Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

console - log relevant information in home, user and logs page #2777

Merged
merged 56 commits into from
Jan 21, 2020

Conversation

Gaetanbrl
Copy link
Contributor

@Gaetanbrl Gaetanbrl commented Oct 16, 2019

Link to #2267 .

Display logs detail by click to get log relevant information in admin log.

Thank you in advance for review.
@fvanderbiest @landryb @tonio @RemiDesgrange

@landryb landryb added this to the 19.09 milestone Oct 17, 2019
@landryb landryb added this to In progress in CRAIG via automation Oct 17, 2019
@landryb
Copy link
Member

landryb commented Oct 17, 2019

Can we take #2267 (comment) into account ? once the changed field is added to the schema, i think it's hard to migrate its type/size to something else, so might aswell get it large from the start.

Apparently (per https://thoughts-on-java.org/mapping-blobs-and-clobs-with-hibernate-and-jpa/)there are two ways, using the Clob java type instead of String, or just annotate the property and keep using String.

I tried adding @Lob annotion on the changed definition, dropped the changed column in the db with varchar type, it was recreated by hibernate as text type in the DB - modifying an attr on a user works (ie json contains {"new":"editoraaa","field":"description","old":"editor","type":"Attribute was changed for a user"}) but strangely the json is not directly readable in the database field (there's 733070 in the field for that record ?). - and here i will stop poking at this since im no java hell expert.

@Gaetanbrl
Copy link
Contributor Author

Can we take #2267 (comment) into account ?

Unfortunately, we can't take it into account now. I can open a new issue to keep this in mind.

I tried adding @lob annotion on the changed definition

Thank you, hope we can do that soon...

@fvanderbiest fvanderbiest modified the milestones: 19.09, 19.12 Oct 22, 2019
@landryb
Copy link
Member

landryb commented Nov 13, 2019

Ahem... gentle review poke ? :)

@Gaetanbrl
Copy link
Contributor Author

need to manage conflict / rebase again ...

@RemiDesgrange
Copy link
Contributor

Can you make the integration test pass ? Thanks.

@Gaetanbrl
Copy link
Contributor Author

Can you make the integration test pass ? Thanks.

Yes, we can @RemiDesgrange. As said before :

need to manage conflict / rebase

@pierrejego
Copy link
Member

There are three integration tests on attributes deletion for orgs which failed for the moment. I am trying to find out why.
We can delete those attributes in real GUI, without errors.

@pierrejego
Copy link
Member

Can we take #2267 (comment) into account ? once the changed field is added to the schema, i think it's hard to migrate its type/size to something else, so might aswell get it large from the start.

Apparently (per https://thoughts-on-java.org/mapping-blobs-and-clobs-with-hibernate-and-jpa/)there are two ways, using the Clob java type instead of String, or just annotate the property and keep using String.

I tried adding @Lob annotion on the changed definition, dropped the changed column in the db with varchar type, it was recreated by hibernate as text type in the DB - modifying an attr on a user works (ie json contains {"new":"editoraaa","field":"description","old":"editor","type":"Attribute was changed for a user"}) but strangely the json is not directly readable in the database field (there's 733070 in the field for that record ?). - and here i will stop poking at this since im no java hell expert.

Last error in integration test was due to attributed changed size. (char varying 255) to small to set all information. If an error occurs when trying to save in database, en Error log is provided in trace, and changed value contains. JSon "error": "Error while inserting admin log in database, see admin log file"

I agree with you @landryb , we should change to Lob, but I am not sure how to do it correctly.

I have added @lob annotation to "changed" attribut from class "AdminLogEntry", this work perfectly for me;
I saw that update is set in webmvc-config.xml so table should be updated at startup , but It could be complicated to reinstall previous version if needed.

Tell me if I need to do something else to take type change to Log into account.

@landryb
Copy link
Member

landryb commented Nov 15, 2019

I agree with you @landryb , we should change to Lob, but I am not sure how to do it correctly.

I have added @lob annotation to "changed" attribut from class "AdminLogEntry", this work perfectly for me;
I saw that update is set in webmvc-config.xml so table should be updated at startup , but It could be complicated to reinstall previous version if needed.

Tell me if I need to do something else to take type change to Log into account.

I'm no java expert wrt this, but we shouldnt care about 'reinstall previous version if needed', no release was made with changed as varchar; that was only temporary during dev in a separate branch, so there's no compat to keep.

What i found strange was not having the plain text value in the database field....

@pierrejego
Copy link
Member

I need to make more test before review

@pierrejego
Copy link
Member

Ok I have done more test.
1 - New instance OK
2 - migration from exisiting instance KO,
hibernate does not change type automaticlly if there is date in it (not on my server), so we will need to Drop previous table, OR make an manual ALTER TABLE Script before migration. Where should I put this type of script from version migration ?

Otherwise it's ready for review @RemiDesgrange :) thanks

@landryb
Copy link
Member

landryb commented Nov 15, 2019

as discussed over the phone we dont need to care about the varchar->lob migration since the changed field is a new field :)

@RemiDesgrange
Copy link
Contributor

The migration should go here (but ping @pmauduit anyway), you should not use Lob to store json in database. Georchestra didn't choose the best opensource database out there to end up usng the DB like if it was MySQL :-) . I am not blaming you for this choice. But using lob (so storing binary) is the not a good idea, because we won't be able to request the JSON from SQL. So every people that build tools around georchestra won't able to just query the data and use it. With JSON type you can. If using JSONB, you can even put indexes on json keys !

Ok solution time: you should pass a JSONObject to AdminLogEntry.

This will allow you to remove codes that convert back and forth from String to JSON

@fvanderbiest
Copy link
Member

The migration should go here

Rather https://github.com/georchestra/georchestra/tree/master/migrations/19.12 (the directory does not exist yet, feel free to create it)

@landryb
Copy link
Member

landryb commented Nov 18, 2019

Nice, didnt know that json & jsonb were native postgresql data types.

As for the migration, i'm still not sure there should be one, as we're only adding a new field to an existing table, and from my understanding hibernate will create the field if it doesnt exist, so there should be no need for an sql snippet ?

@cmangeat cmangeat self-requested a review November 19, 2019 14:16
Copy link
Contributor

@cmangeat cmangeat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we (@cmangeat & @pmauduit) will discuss more precisely (and conceptually) afterwards, current review comments aim at earning lisibility for further improvments proposals.

Conceptually, here are a summary so far:

  • Sometimes the logging logic is made onto the controllers, sometimes in the DAO. Our opinion is that it might not be the right place to hook (either in the controller nor in the DAO), this leads to duplicating code in both places. This is probably not the role of the DAO to log, and it should stick with LDAP accesses or so.
  • To complete the previous point: We were thinking about a "ogc-server-statistics"-like approach with log.info() using the logging framework instead.
  • The PR replaces the LogDAO by a LogUtils class, and unset the LogDAO from the tests. Integrating a new class is OK, but why not having set a LogUtils in the test classes instead of leaving the field unset ? This leads to unecessary if (logUtils != null) in the actual code.
  • There is a private field added to the UsersController class which is problematic, as it can lead to race conditions in case of several requests are made simultaneously on the same controller, the controller is supposed to be reentrant. There is another place in the code where such an error is made, we will comment accordingly.
  • We were wondering if we could avoid the long series of "if" statements to check what and where the objects have been modified, we don't have any clue so far.
  • Sometimes the log statement is made before the actual modification is made onto the LDAP, sometimes after. We think that it would be more relevant to always log after the modification has been made.
  • As already reported by @rémiDesgrange, we think that using a more convenient type in the postgresql could simplify queries, as using BLOB type makes it complicated to request against.


@Autowired
private AdminLogDao logDao;
private Boolean isPendingChanged;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code ?

public void setLogDao(AdminLogDao logDao) {
this.logDao = logDao;
public void setPendingChanged(Boolean isPendingChanged) {
this.isPendingChanged = isPendingChanged;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code ?

@@ -217,9 +205,14 @@ public synchronized void update(Account account, Account modified, String origin
if (hasUserDnChanged(account, modified)) {
ldapTemplate.rename(buildUserDn(account), buildUserDn(modified));
}
this.setPendingChanged(this.hasUserPendingChanged(account, modified));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code ?

update(modified, originLogin);
}

public boolean hasUserPendingChanged(Account account, Account modified) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code ?

AdminLogEntry log = new AdminLogEntry(originLogin, user.getUid(), logType, new Date());
this.logDao.save(log);
// Add log entry when role was added
if (originLogin != null && logUtils != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logUtils cant be null ?

if (auth != null && auth.getName() != null && target != null) {
String admin = auth.getName();
// case where we don't need to log changes
if (values == null || values.isEmpty()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copying null in null, is not a trouble, if values is empty() can be managed at worst in the constructor.

public AdminLogEntry createLog(String target, AdminLogType type, String values) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();

AdminLogEntry log = new AdminLogEntry();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be done later.

try {
logDao.save(log);
} catch (DataIntegrityViolationException divex) {
// Value could be to large for field size
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case value should be trimmed ? no relying on an exception to be thrown ?

}
} else {
LOG.info("Authentification Security Context is null.");
log = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return null, see "condition reversion" comment.

/**
* Full creation by log details creation and log creation directly.
*
* @param target String
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure these comments help

@fvanderbiest fvanderbiest changed the title log relevant information in home, user and logs page console - log relevant information in home, user and logs page Nov 22, 2019
@tonio
Copy link
Contributor

tonio commented Nov 29, 2019

For the frontend side:

Architecture

  • There is a lot of code duplication. The whole log table should be a shared configurable component, instantiated in the 3 places it is used (It's possible to get inspiration from the stats component, shared in home page & stats tabs).

  • Moreover, having a seperate template would make it more readable. There's also too much logic in the template that should be moved to the component.

UX

  • There's in my opinion a suboptimal use of available space: last column with change token is not very useful, for most of the logs, details can be displayed directly like:
    Screenshot from 2019-11-29 11-00-11

  • The breadcrumb which only displayed on item opening is quite confusing (hidden on global view). I think user shouldn't have to leave the list to see log detail. For the longest (ie: message), it could be displayed in a tooltip.
    Screenshot from 2019-11-29 11-24-52

Data

  • Editing multiples fields at once should end in a single log entry, otherwise logs are spammed with quite duplicated entries:
    Screenshot from 2019-11-29 13-20-02

Conclusion

There's at least a refactoring to share the component to be done before going deeper in the review. UX can be discussed but should be simplified in my point of view.

@landryb
Copy link
Member

landryb commented Nov 29, 2019

UX

* There's in my opinion a suboptimal use of available space: last column with change token is not very useful, for most of the logs, details can be displayed directly
  ![Screenshot from 2019-11-29 11-00-11](https://user-images.githubusercontent.com/21686/69867978-bfce5e80-12a8-11ea-9c2f-365b1f84efd8.png)

right now we have the 'correct' amount of details given the available space in most cases, can you detail examples you have in mind where the displayed info is not useful enough ?

Data

* Editing multiples fields at once should end in a single log entry, otherwise logs are spammed with quite duplicated entries:
  ![Screenshot from 2019-11-29 13-20-02](https://user-images.githubusercontent.com/21686/69868805-2c4a5d00-12ab-11ea-8c76-01edbee66afa.png)

That was a design choice in conjunction with what happens in the backend. IIrc it was a bit too complicated to "merge" changes happening at the same time, but if it needs to be revisited then so be it. How would you display all user-related changes in a single line ?

@landryb
Copy link
Member

landryb commented Dec 6, 2019

what's the status of the PR now ? being rewritten ? reviews adressed ?

@pierrejego
Copy link
Member

The migration should go here (but ping @pmauduit anyway), you should not use Lob to store json in database. Georchestra didn't choose the best opensource database out there to end up usng the DB like if it was MySQL :-) . I am not blaming you for this choice. But using lob (so storing binary) is the not a good idea, because we won't be able to request the JSON from SQL. So every people that build tools around georchestra won't able to just query the data and use it. With JSON type you can. If using JSONB, you can even put indexes on json keys !

Ok solution time: you should pass a JSONObject to AdminLogEntry.

This will allow you to remove codes that convert back and forth from String to JSON

Hello, there are no simple way to store Java JsonObject to JsonB postgresql type.
Hibernate does not have OOB support for jsonb type in postgres.

What is the best option :

1 - do we use an external librairie ? Like this example https://vladmihalcea.com/how-to-map-json-objects-using-generic-hibernate-types/

2 -Or to we keep @lob like it is already existing in console

but only change type to JsonObject to at least avoid conversion.

3 - Or perhaps a another idea ?

Regards

@Gaetanbrl
Copy link
Contributor Author

need more tests (specific with logo action).

@Gaetanbrl
Copy link
Contributor Author

As I said - Need more test => To finish correctly :)

@Gaetanbrl
Copy link
Contributor Author

missing comma

Wich line please ?

@Gaetanbrl
Copy link
Contributor Author

actually after looking at the context, i think it should be 'added to user' and 'removed from user' since the username is put next to it, and 'custom role FOO added to user bar'/'system role FOO removed from user bar' reads better than 'custom role FOO added for this user bar'/'system role FOO removed for this user bar'

engrish, do you spik it ? ;)

Not cool ! :) I will check traductions ;)

@landryb
Copy link
Member

landryb commented Jan 21, 2020

In some cases, hovering over an action label for the first time showed true for the tooltip, then if a second later i hover again on the same label it shows the correct label in the tooltip. caching issue ? lookup issue ?

@Gaetanbrl
Copy link
Contributor Author

Gaetanbrl commented Jan 21, 2020

In some cases, hovering over an action label for the first time showed true for the tooltip, then if a second later i hover again on the same label it shows the correct label in the tooltip. caching issue ? lookup issue ?

Already catched in the UI 1.0.

If you over on html parent, you get "true", else you get info. I check that.

@Gaetanbrl
Copy link
Contributor Author

Unless you have no info, you get "true" in some case... not good!

@Gaetanbrl
Copy link
Contributor Author

I hope you have a spanish speaker ;)

@landryb
Copy link
Member

landryb commented Jan 21, 2020

Fwiw, i think i've tested lots of cases, i'm struggling to see the console in the fr locale (cf #2890) but for me the PR is +1 at this point.

@fvanderbiest
Copy link
Member

fvanderbiest commented Jan 21, 2020

I hope you have a spanish speaker ;)

We do :-) ping @severo

One last thing Gaetan, can you import all translations into the spanish and other translation files (even if the translations are not done - ie in english) : this will allow translators to do their job. Thanks.
I usually use meld to do this.

@Gaetanbrl
Copy link
Contributor Author

can you import all translations into the spanish and other translation files

Yes.

I usually use meld to do this.

New for me, but seems great !

@Gaetanbrl
Copy link
Contributor Author

@fvanderbiest it's good for you (last commits) ?

@fvanderbiest
Copy link
Member

This looks good. Thanks.
If you're done with it, I'll add translations as far as I can go and then let's merge \o/

@Gaetanbrl
Copy link
Contributor Author

and then let's merge

😵 😵 \o/

@fvanderbiest fvanderbiest merged commit 825622e into georchestra:master Jan 21, 2020
CRAIG automation moved this from Reviewer approved to Done Jan 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
CRAIG
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

7 participants