Skip to content

Commit 899a0a2

Browse files
authored
AYS-517 | Role and Permission Relations Have Been Optimized for Working Less Queries (#392)
1 parent 1770df4 commit 899a0a2

File tree

5 files changed

+103
-64
lines changed

5 files changed

+103
-64
lines changed

src/main/java/org/ays/auth/model/AysRole.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import org.ays.institution.model.Institution;
1010

1111
import java.util.List;
12+
import java.util.Set;
13+
import java.util.stream.Collectors;
1214

1315
/**
1416
* Represents a role entity in the system.
@@ -58,6 +60,25 @@ public boolean isDeleted() {
5860
}
5961

6062

63+
/**
64+
* Updates the role with the provided information.
65+
* This method updates the role's name and permissions based on the provided values.
66+
*
67+
* @param name The new name of the role.
68+
* @param permissionIds The IDs of the permissions to be assigned to the role.
69+
* @param updatedUser The user who is updating the role.
70+
*/
71+
public void update(final String name,
72+
final Set<String> permissionIds,
73+
final String updatedUser) {
74+
75+
this.name = name;
76+
this.permissions = permissionIds.stream()
77+
.map(roleId -> AysPermission.builder().id(roleId).build())
78+
.collect(Collectors.toList());
79+
this.updatedUser = updatedUser;
80+
}
81+
6182
/**
6283
* Activates the role by setting its status to {@link AysRoleStatus#ACTIVE}.
6384
* This method should be called when the role needs to be marked as active in the system.

src/main/java/org/ays/auth/model/entity/AysRoleEntity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import org.ays.common.model.entity.BaseEntity;
2424
import org.ays.institution.model.entity.InstitutionEntity;
2525

26-
import java.util.List;
26+
import java.util.Set;
2727

2828
/**
2929
* Entity class representing a role within the application, extending from {@link BaseEntity}.
@@ -65,6 +65,6 @@ public class AysRoleEntity extends BaseEntity {
6565
joinColumns = @JoinColumn(name = "ROLE_ID"),
6666
inverseJoinColumns = @JoinColumn(name = "PERMISSION_ID")
6767
)
68-
private List<AysPermissionEntity> permissions;
68+
private Set<AysPermissionEntity> permissions;
6969

7070
}

src/main/java/org/ays/auth/service/impl/AysRoleUpdateServiceImpl.java

Lines changed: 66 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import java.util.List;
2424
import java.util.Set;
25+
import java.util.stream.Collectors;
2526

2627
/**
2728
* Service implementation for updating roles.
@@ -62,19 +63,78 @@ public void update(final String id,
6263
.filter(roleFromDatabase -> identity.getInstitutionId().equals(roleFromDatabase.getInstitution().getId()))
6364
.orElseThrow(() -> new AysRoleNotExistByIdException(id));
6465

65-
if (!role.getName().equals(updateRequest.getName())) {
66+
final boolean isRoleNameChanged = !role.getName().equals(updateRequest.getName());
67+
if (isRoleNameChanged) {
6668
this.checkExistingRoleNameByWithoutId(id, updateRequest.getName());
6769
}
6870

69-
final List<AysPermission> permissions = this.checkExistingPermissionsAndGet(updateRequest.getPermissionIds());
70-
71-
role.setName(updateRequest.getName());
72-
role.setPermissions(permissions);
73-
role.setUpdatedUser(identity.getUserId());
71+
final Set<String> existingPermissionIds = role.getPermissions().stream()
72+
.map(AysPermission::getId)
73+
.collect(Collectors.toSet());
74+
final boolean permissionsChanged = !existingPermissionIds.equals(updateRequest.getPermissionIds());
75+
if (permissionsChanged) {
76+
this.validatePermissions(updateRequest.getPermissionIds());
77+
}
7478

79+
role.update(
80+
updateRequest.getName(),
81+
updateRequest.getPermissionIds(),
82+
identity.getUserId()
83+
);
7584
roleSavePort.save(role);
7685
}
7786

87+
/**
88+
* Checks the existence of another role with the same name, excluding the current role ID.
89+
*
90+
* @param id The ID of the role being updated.
91+
* @param name The name to check for uniqueness.
92+
* @throws AysRoleAlreadyExistsByNameException if a role with the same name already exists, excluding the current role ID.
93+
*/
94+
private void checkExistingRoleNameByWithoutId(final String id, final String name) {
95+
roleReadPort.findByName(name)
96+
.filter(role -> !id.equals(role.getId()))
97+
.ifPresent(role -> {
98+
throw new AysRoleAlreadyExistsByNameException(name);
99+
});
100+
}
101+
102+
/**
103+
* Validates the specified permission IDs and checks user authorization.
104+
* <p>
105+
* This method verifies if all permission IDs exist in the system and checks if the user
106+
* has appropriate access level for super permissions. Only super admin users can assign
107+
* super permissions.
108+
* </p>
109+
*
110+
* @param permissionIds the set of permission IDs to validate
111+
* @throws AysPermissionNotExistException if any of the specified permissions do not exist
112+
* @throws AysUserNotSuperAdminException if a non-super admin user attempts to assign super permissions
113+
*/
114+
private void validatePermissions(final Set<String> permissionIds) {
115+
116+
final List<AysPermission> permissions = permissionReadPort.findAllByIds(permissionIds);
117+
118+
if (permissions.size() != permissionIds.size()) {
119+
120+
final List<String> notExistsPermissionIds = permissionIds.stream()
121+
.filter(permissionId -> permissions.stream()
122+
.noneMatch(permissionEntity -> permissionEntity.getId().equals(permissionId)))
123+
.toList();
124+
125+
throw new AysPermissionNotExistException(notExistsPermissionIds);
126+
}
127+
128+
if (identity.isSuperAdmin()) {
129+
return;
130+
}
131+
132+
boolean haveSuperPermissions = permissions.stream().anyMatch(AysPermission::isSuper);
133+
if (haveSuperPermissions) {
134+
throw new AysUserNotSuperAdminException(identity.getUserId());
135+
}
136+
}
137+
78138

79139
/**
80140
* Activates an existing role.
@@ -163,54 +223,4 @@ public void delete(final String id) {
163223
roleSavePort.save(role);
164224
}
165225

166-
167-
/**
168-
* Checks the existence of another role with the same name, excluding the current role ID.
169-
*
170-
* @param id The ID of the role being updated.
171-
* @param name The name to check for uniqueness.
172-
* @throws AysRoleAlreadyExistsByNameException if a role with the same name already exists, excluding the current role ID.
173-
*/
174-
private void checkExistingRoleNameByWithoutId(final String id, final String name) {
175-
roleReadPort.findByName(name)
176-
.filter(role -> !id.equals(role.getId()))
177-
.ifPresent(role -> {
178-
throw new AysRoleAlreadyExistsByNameException(name);
179-
});
180-
}
181-
182-
/**
183-
* Checks the existence of permissions based on the provided permission IDs.
184-
* Verifies if all permission IDs exist and validates super admin restrictions.
185-
*
186-
* @param permissionIds the set of permission IDs to check
187-
* @return the list of permissions corresponding to the provided IDs
188-
* @throws AysPermissionNotExistException if any of the permission IDs do not exist
189-
* @throws AysUserNotSuperAdminException if the current user is not authorized to assign super permissions
190-
*/
191-
private List<AysPermission> checkExistingPermissionsAndGet(final Set<String> permissionIds) {
192-
final List<AysPermission> permissions = permissionReadPort.findAllByIds(permissionIds);
193-
194-
if (permissions.size() != permissionIds.size()) {
195-
196-
final List<String> notExistsPermissionIds = permissionIds.stream()
197-
.filter(permissionId -> permissions.stream()
198-
.noneMatch(permissionEntity -> permissionEntity.getId().equals(permissionId)))
199-
.toList();
200-
201-
throw new AysPermissionNotExistException(notExistsPermissionIds);
202-
}
203-
204-
if (identity.isSuperAdmin()) {
205-
return permissions;
206-
}
207-
208-
boolean haveSuperPermissions = permissions.stream().anyMatch(AysPermission::isSuper);
209-
if (haveSuperPermissions) {
210-
throw new AysUserNotSuperAdminException(identity.getUserId());
211-
}
212-
213-
return permissions;
214-
}
215-
216226
}

src/test/java/org/ays/auth/controller/AysRoleEndToEndTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ void givenValidIdAndRoleUpdateRequest_whenRequestHasSuperPermissionsAndUserIsNot
583583
.withValidValues()
584584
.withoutId()
585585
.withName(AysRandomUtil.generateText(10))
586-
.withPermissions(permissions)
586+
.withPermissions(List.of(permissions.get(0)))
587587
.withInstitution(new InstitutionBuilder().withId(AysValidTestData.Admin.INSTITUTION_ID).build())
588588
.build()
589589
);

src/test/java/org/ays/auth/model/entity/AysRoleEntityBuilder.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import org.ays.common.util.AysRandomUtil;
77
import org.ays.institution.model.entity.InstitutionEntity;
88

9-
import java.util.List;
9+
import java.util.Set;
1010

1111
public class AysRoleEntityBuilder extends TestDataBuilder<AysRoleEntity> {
1212

@@ -15,10 +15,18 @@ public AysRoleEntityBuilder() {
1515
}
1616

1717
public AysRoleEntityBuilder withValidValues() {
18-
List<AysPermissionEntity> permissionEntities = List.of(
19-
new AysPermissionEntityBuilder().withValidValues().build(),
20-
new AysPermissionEntityBuilder().withValidValues().withName("institution:page").withCategory(AysPermissionCategory.PAGE).build()
18+
19+
Set<AysPermissionEntity> permissionEntities = Set.of(
20+
new AysPermissionEntityBuilder()
21+
.withValidValues()
22+
.build(),
23+
new AysPermissionEntityBuilder()
24+
.withValidValues()
25+
.withName("institution:page")
26+
.withCategory(AysPermissionCategory.PAGE)
27+
.build()
2128
);
29+
2230
return this
2331
.withId(AysRandomUtil.generateUUID())
2432
.withName("admin")
@@ -41,7 +49,7 @@ public AysRoleEntityBuilder withStatus(AysRoleStatus status) {
4149
return this;
4250
}
4351

44-
public AysRoleEntityBuilder withPermissions(List<AysPermissionEntity> permissionEntities) {
52+
public AysRoleEntityBuilder withPermissions(Set<AysPermissionEntity> permissionEntities) {
4553
data.setPermissions(permissionEntities);
4654
return this;
4755
}

0 commit comments

Comments
 (0)