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
Support swapping default roles #2868
Conversation
The Java checkstyle failed. Please run You can install the pre-commit hooks with |
8e5bf6d
to
9697a5e
Compare
The Java checkstyle failed. Please run You can install the pre-commit hooks with |
cf90559
to
286fde3
Compare
The Java checkstyle failed. Please run You can install the pre-commit hooks with |
7f14cf0
to
57d293c
Compare
0e802e9
to
dc99de8
Compare
@@ -56,11 +59,47 @@ public RoleResourceTest() { | |||
} | |||
|
|||
@Test | |||
void get_queryDefaultRole(TestInfo test) throws IOException { | |||
Role defaultRole = createRolesAndSetDefault(test, 7); | |||
void defaultRole(TestInfo test) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Main test for this feature
@@ -2,5 +2,6 @@ | |||
"name": "DataConsumer", | |||
"displayName": "Data Consumer", | |||
"description": "Users with Data Consumer role use different data assets for their day to day work.", | |||
"deleted": false | |||
"deleted": false, | |||
"default": true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting DataConsumer as default role.
} | ||
EntityRepository<User> userRepository = Entity.getEntityRepository(Entity.USER); | ||
users | ||
.parallelStream() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parallelization to minimize performance impact.
Switching a default role for 100 users takes ~2 seconds on Mattbook Pro
Considered bulk update of relationships in entity_relationship table.
However, this does not capture the change description for the role update for each of the users.
Optimizing for correctness instead of performance for this feature.
try { | ||
return withHref(uriInfo, setFields(JsonUtils.readValue(json, Role.class), fields)); | ||
} catch (IOException e) { | ||
LOG.warn("Could not parse Role from json {}", json); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't happy about hiding this exception.
Replacing the lambda here with simple for loop.
@@ -908,12 +908,12 @@ public EntityUpdater(T original, T updated, Operation operation) { | |||
this.operation = operation; | |||
} | |||
|
|||
public final void update() throws IOException { | |||
public final void update() throws IOException, ParseException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May need to make it throws Exception
in the future.
Going with this for now.
|
||
UPDATE role_entity | ||
SET json = JSON_SET(json, '$.default', FALSE); | ||
|
||
UPDATE role_entity | ||
SET json = JSON_SET(json, '$.default', TRUE) | ||
WHERE name = 'DataConsumer'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set DataConsumer as default for migration purpose.
Pseudocode: ``` A. patchRole(role1, default=True): B. set role1.default = True for all users: add role1 to user.roles C. for role in roles if role != role1: set role.default = False for all users: delete role from user.roles ``` This ensures that changeDescription for the role(s) and user(s) are updated accordingly. Potential optimization: Adding role1 and removing role from user.roles could be considered/implemented as one change. However, increases code complexity.
List<Role> roles = new ArrayList<>(); | ||
for (String roleJson : daoCollection.roleDAO().getDefaultRoles()) { | ||
roles.add(withHref(uriInfo, setFields(JsonUtils.readValue(roleJson, Role.class), fields))); | ||
} | ||
if (roles.size() > 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't we avoid this ever happening when the admin tries to set the default role?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, this PR with DB Transaction while swapping default role prevents getting into a situation where we have multiple default roles.
My testing pattern has been the following:
- Start up OM with DataConsumer as default role
- Set another role R as default role and observe that DataConsumer is no longer default and user relationships have been updated.
- Set DataConsumer as default role and obseve that R is no longer default and user relationships have been updated.
I did a few iterations of these locally with PostMan and ended up converting the logic into a test (RoleResourceTest.defaultRole)
I left the log line as is for detection purpose, in case there are any unforeseeable edge cases being missed out (as the code evolves).
setDefaultToFalse(updatedRole); | ||
} | ||
recordChange("default", origRole.getDefault(), updatedRole.getDefault()); | ||
LOG.info( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets mark this as debug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
1f1517f
to
4eef07c
Compare
// - the previous default role is no longer set as default | ||
// - all users have roles set correctly (only current default role should exist) | ||
for (int i = 0; i < 2; i++) { // Run two iterations for this test. | ||
Role defaultRole = createRolesAndSetDefault(test, 7, i * 10); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This creates a set of 7 arbitrary roles and chooses one at random to be default (code below)
4eef07c
to
4024d10
Compare
List<Role> defaultRoles = getDefaultRoles(null, ROLE_PATCH_FIELDS); | ||
EntityRepository<Role> roleRepository = Entity.getEntityRepository(Entity.ROLE); | ||
// Set default=FALSE for all existing default roles. | ||
for (Role defaultRole : defaultRoles) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There will be only one default role here (at any given point of time) based on how this feature has been implemented.
continue; | ||
} | ||
Role origDefaultRole = roleRepository.get(null, defaultRole.getId().toString(), ROLE_PATCH_FIELDS); | ||
Role updatedDefaultRole = roleRepository.get(null, defaultRole.getId().toString(), ROLE_PATCH_FIELDS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where jsonschema2pojo deep cloning would have helped.
Role origDefaultRole = roleRepository.get(null, defaultRole.getId().toString(), ROLE_PATCH_FIELDS);
Role updatedDefaultRole = origDefaultRole.clone();
joelittlejohn/jsonschema2pojo#230
Resorting to two db calls for now. Need to add an internal utility for cloning entities, or contribute to jsonschema2pojo
[open-metadata-ingestion] Kudos, SonarCloud Quality Gate passed! |
[catalog] Kudos, SonarCloud Quality Gate passed! |
Pseudocode:
This logic ensures that changeDescription for the role(s) and user(s) are updated correctly.
Alternative considered:
Directly updating relationships with bulk sqlbatch update in entity_relationship between user and role to achieve the above.
However, this does not capture change description correctly.
Describe your changes :
See #2460
Type of change :
Frontend Preview (Screenshots) :
For frontend related change, please link screenshots of your changes preview! Optional for backend related changes.
Checklist:
Reviewers