Skip to content

Issue/628#681

Merged
mhdirkse merged 71 commits intomasterfrom
issue/628
Apr 10, 2026
Merged

Issue/628#681
mhdirkse merged 71 commits intomasterfrom
issue/628

Conversation

@mhdirkse
Copy link
Copy Markdown
Member

No description provided.

@mhdirkse mhdirkse marked this pull request as ready for review March 23, 2026 13:18
@mhdirkse
Copy link
Copy Markdown
Member Author

@mhdirkse mhdirkse requested a review from nielsm5 March 23, 2026 15:01
Comment on lines +123 to +124
} catch(HttpInternalServerErrorException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is very strange? Why not use an ExceptionHandler ?
The whole point of the ExceptionHandlers is to uniformly handle all exceptions of a certain type.
If you're going to catch all exceptions, why throw them in the first place?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I intend to introduce exception handlers in a later PR. My aim with this PR is to pass a user role to the frontend and to make a start to make the UI role-dependent.

Comment on lines +80 to +93
String result = null;
// When authorization is disabled, isUserInRole() always returns true.
// Therefore we have to check for the most powerful rule first.
if (isUserInRoles(testerRoles)) {
result = TestToolApiImpl.TESTER;
} else if (isUserInRoles(dataAdminRoles)) {
result = TestToolApiImpl.DATA_ADMIN;
} else if(isUserInRoles(observerRoles)) {
result = TestToolApiImpl.OBSERVER;
} else {
result = TestToolApiImpl.NO_AUTHORIZATION;
}
log.info("Tell frontend that user is in role [{}]", result);
return result;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A user can have multiple roles, why not return all authorities? At least create a mechanism both implementations can use to map the roles...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The trouble is that with JAX-RS it is not so easy to get the user role. We have two tools:

  • We have a method isUserInRoles() that receives a list of roles and that returns true if the user is in a role from the list.
  • From Spring we get variables that hold cumulative lists of roles. testerRoles = IbisTester, dataAdminRoles = IbisDataAdmin, IbisAdmin, IbisTester and observerRoles = IbisObserver, IbisDataAdmin, IbisAdmin, IbisTester.

To get as close as possible to a single role, we must group the roles by distinguishing role. We can calculate that IbisTester < IbisTester, IbisDataAdmin, IbisAdmin < IbisTester, IbisDataAdmin, IbisAdmin, IbisObserver. Then we can use isUserInRole() to return either {IbisTester} or {IbisDataAdmin, IbisAdmin} or {IbisObserver}. Then we can have common logic to produce a result from one of IbisTester, {IbisTester}, IbisDataAdmin, IbisAdmin, {IbisDataAdmin, IbisAdmin}, IbisObserver and {IbisObserver}.

Complicated as this logic may be, it is possible to write unit tests for it. Although we produce more complex code than the code you reviewed, it is probably more trustworthy.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Niels, we discussed this orally. Now I understand. I think this PR does it the right way now.

log.error("Cannot read properties from existing classpath resource test.properties");
return result;
}
String uiTestModeStr = props.getProperty("ladybug.ui.test.mode");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You could just use @Value("hier") instead of creating your own properties parser...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Then I need a class with annotation @propertysource to read my test.properties file. That file is optional - these are properties to make Ladybug behave in ways that are not relevant for real users. I am going to add properties here to let the backend throw fake exceptions. Within the @propertysource annotation I need to set ignoreResourceNotFound=true. But then I cannot inject values so easily with the @value annotation. When the property is not found, I get ${the.property} as value when the property name is the.property. I think the current approach is more appropriate. Less risk to introduce Spring configurations that may jeopardize other parts of Ladybug or the FF!.

Comment on lines +51 to +53
public static final class TestProperties {
private @Getter @Setter UI_TEST_MODE uiTestMode = UI_TEST_MODE.DEFAULT;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why do you have a class with only 1 field? Why not just use the field directly?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I will add the logic for fake exceptions here instead of hard coding whether to throw fake exceptions or not. Then that logic is not temporary anymore.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done that.

if (!StringUtils.isEmpty(transformation)) {
map.put(KEY_TRANSFORMATION, transformation);
}
map.put("uiTestMode", testProperties.getUiTestMode().toString().toLowerCase());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please use enum.name()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It is in a bean now. Te enum value is put in the JSON automatically.

@if (activeTab === GLOBAL) {
<div class="form-group">
<label>Report generator</label>
<label>Report generator{{ optionalNotAuthorized() }}</label>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why don't you just disable the field with a tooltip that the user doesn't have the required roles?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

@mhdirkse mhdirkse marked this pull request as draft April 2, 2026 16:58
@mhdirkse
Copy link
Copy Markdown
Member Author

mhdirkse commented Apr 2, 2026

I am busy processing review comments. I need to push to save my work. As it is now it is not ready for merging.

@mhdirkse
Copy link
Copy Markdown
Member Author

mhdirkse commented Apr 2, 2026

I am busy extending the PR with extra Cypress tests for authorization. I will enable authorization with and without using the test mode. Without the test mode we login as observer and check that the control about the report generator is disabled - no option anymore to enable / disable the report generator except back to default. With the test mode and as observer, we try to disable the report generator and check that we get a toast originating from a backend error.

@mhdirkse
Copy link
Copy Markdown
Member Author

mhdirkse commented Apr 3, 2026

@mhdirkse
Copy link
Copy Markdown
Member Author

mhdirkse commented Apr 3, 2026

See https://github.com/wearefrank/ladybug/actions/runs/23955165018 for the tests with the FF!. I may put this to ready for review before the tests will have finished.

@mhdirkse mhdirkse marked this pull request as ready for review April 3, 2026 17:26
@mhdirkse mhdirkse requested a review from nielsm5 April 3, 2026 17:26
Copy link
Copy Markdown
Contributor

@nielsm5 nielsm5 left a comment

Choose a reason for hiding this comment

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

Je gebruikt de testmode nu niet meer maar het zit er wel in. Zelf denk ik dat het handiger is zaken uit de codebase te houden wanneer deze niets toevoegen. (Behalve als je andere plannen hebt. Maar dan zou het eigenlijk in een los pr moeten 😉.)

@mhdirkse mhdirkse merged commit 7163921 into master Apr 10, 2026
12 of 15 checks passed
@mhdirkse mhdirkse deleted the issue/628 branch April 10, 2026 08:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants