diff --git a/server/src/main/java/com/objectcomputing/checkins/services/permissions/Permission.java b/server/src/main/java/com/objectcomputing/checkins/services/permissions/Permission.java index 40d95edb63..98d8ce70af 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/permissions/Permission.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/permissions/Permission.java @@ -1,8 +1,11 @@ package com.objectcomputing.checkins.services.permissions; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.annotation.JsonCreator; import io.micronaut.core.annotation.Introspected; @Introspected +@JsonSerialize(using = PermissionSerializer.class) public enum Permission { CAN_VIEW_FEEDBACK_REQUEST("View feedback requests", "Feedback"), CAN_CREATE_FEEDBACK_REQUEST("Create feedback requests", "Feedback"), @@ -33,7 +36,6 @@ public enum Permission { this.category = category; } - public String getDescription() { return description; } @@ -41,5 +43,16 @@ public String getDescription() { public String getCategory() { return category; } + + // Use the fromName method as @JsonCreator + @JsonCreator + public static Permission fromName(String name) { + for (Permission permission : values()) { + if (permission.name().equalsIgnoreCase(name)) { + return permission; + } + } + throw new UnsupportedOperationException(String.format("Unknown permission: '%s'", name)); + } } diff --git a/server/src/main/java/com/objectcomputing/checkins/services/permissions/PermissionDTO.java b/server/src/main/java/com/objectcomputing/checkins/services/permissions/PermissionDTO.java new file mode 100644 index 0000000000..d17fef92c8 --- /dev/null +++ b/server/src/main/java/com/objectcomputing/checkins/services/permissions/PermissionDTO.java @@ -0,0 +1,68 @@ +package com.objectcomputing.checkins.services.permissions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.micronaut.core.annotation.Introspected; + +import java.util.Objects; + +@Introspected +public class PermissionDTO { + + private String permission; + private String description; + + public PermissionDTO() {} + + public PermissionDTO(String permission, String description, String category) { + this.permission = permission; + this.description = description; + this.category = category; + } + + private String category; + + public PermissionDTO(Permission permission) { + this.permission = permission.name(); + this.description = permission.getDescription(); + this.category = permission.getCategory(); + } + + public String getPermission() { + return permission; + } + + public void setPermission(String permission) { + this.permission = permission; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PermissionDTO that = (PermissionDTO) o; + return Objects.equals(permission, that.permission) && Objects.equals(description, that.description) && Objects.equals(category, that.category); + } + + @Override + public int hashCode() { + return Objects.hash(permission, description, category); + } +} + diff --git a/server/src/main/java/com/objectcomputing/checkins/services/permissions/PermissionSerializer.java b/server/src/main/java/com/objectcomputing/checkins/services/permissions/PermissionSerializer.java new file mode 100644 index 0000000000..af407b65d6 --- /dev/null +++ b/server/src/main/java/com/objectcomputing/checkins/services/permissions/PermissionSerializer.java @@ -0,0 +1,31 @@ +package com.objectcomputing.checkins.services.permissions; + +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +public class PermissionSerializer extends StdSerializer { + + public PermissionSerializer() { + super(Permission.class); + } + + public PermissionSerializer(Class t) { + super(t); + } + + public void serialize( + Permission permission, JsonGenerator generator, SerializerProvider provider) + throws IOException { + generator.writeStartObject(); + generator.writeFieldName("permission"); + generator.writeString(permission.name()); + generator.writeFieldName("description"); + generator.writeString(permission.getDescription()); + generator.writeFieldName("category"); + generator.writeString(permission.getCategory()); + generator.writeEndObject(); + } +} \ No newline at end of file diff --git a/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionController.java b/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionController.java index 03e6b2449e..6c53b79c3f 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionController.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionController.java @@ -1,6 +1,5 @@ package com.objectcomputing.checkins.services.role.role_permissions; -; import com.objectcomputing.checkins.services.permissions.Permission; import com.objectcomputing.checkins.services.permissions.RequiredPermission; import io.micronaut.http.HttpResponse; @@ -57,10 +56,10 @@ public Mono>> getAllRolePermission @RequiredPermission(Permission.CAN_ASSIGN_ROLE_PERMISSIONS) @Post("/") - public Mono> save(@Body @Valid RolePermissionDTO rolePermission) { - return Mono.fromCallable(() -> rolePermissionServices.save(rolePermission.getRoleId(), rolePermission.getPermissionId())) + public Mono> save(@Body @Valid RolePermissionDTO rolePermission) { + return Mono.fromCallable(() -> rolePermissionServices.save(rolePermission.getRoleId(), Permission.fromName(rolePermission.getPermission()))) .publishOn(Schedulers.fromExecutor(eventLoopGroup)) - .map(savedRolePermission -> (HttpResponse) HttpResponse + .map(savedRolePermission -> (HttpResponse) HttpResponse .created(fromEntity(savedRolePermission))) .subscribeOn(scheduler); } @@ -69,12 +68,12 @@ public Mono> save(@Body @Valid RolePermissionDTO @Delete("/") public Mono> delete(@Body RolePermissionDTO dto) { - return Mono.fromRunnable(() -> rolePermissionServices.delete(dto.getRoleId(), dto.getPermissionId())) + return Mono.fromRunnable(() -> rolePermissionServices.delete(dto.getRoleId(), Permission.fromName(dto.getPermission()))) .publishOn(Schedulers.fromExecutor(eventLoopGroup)) .subscribeOn(scheduler).thenReturn(HttpResponse.ok()); } - private RolePermissionDTO fromEntity(RolePermission rolePermission) { - return new RolePermissionDTO(rolePermission.getRoleId(), rolePermission.getPermission()); + private RolePermissionResponseDTO fromEntity(RolePermission rolePermission) { + return new RolePermissionResponseDTO(rolePermission.getRoleId(), rolePermission.getPermission()); } } diff --git a/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionDTO.java b/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionDTO.java index d62041282c..ac9f997e84 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionDTO.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionDTO.java @@ -1,6 +1,7 @@ package com.objectcomputing.checkins.services.role.role_permissions; import com.objectcomputing.checkins.services.permissions.Permission; +import com.objectcomputing.checkins.services.permissions.PermissionDTO; import io.micronaut.core.annotation.Introspected; import io.swagger.v3.oas.annotations.media.Schema; @@ -14,12 +15,12 @@ public class RolePermissionDTO { @Schema(description = "id of the role", required = true) private UUID roleId; - @Schema(description = "id of the permission", required = true) - private Permission permissionId; + @Schema(description = "the permission", required = true) + private String permission; - public RolePermissionDTO(UUID roleId, Permission permissionId) { + public RolePermissionDTO(UUID roleId, Permission permission) { this.roleId = roleId; - this.permissionId = permissionId; + this.permission = permission.name(); } public UUID getRoleId() { @@ -30,19 +31,19 @@ public void setRoleId(UUID roleId) { this.roleId = roleId; } - public Permission getPermissionId() { - return permissionId; + public String getPermission() { + return permission; } - public void setPermissionId(Permission permissionId) { - this.permissionId = permissionId; + public void setPermission(String permission) { + this.permission = permission; } @Override public String toString() { final StringBuilder sb = new StringBuilder("RolePermissionCreateDTO{"); sb.append("roleId=").append(roleId); - sb.append(", permissionId=").append(permissionId); + sb.append(", permission=").append(permission); sb.append('}'); return sb.toString(); } diff --git a/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionResponseDTO.java b/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionResponseDTO.java new file mode 100644 index 0000000000..384872c162 --- /dev/null +++ b/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionResponseDTO.java @@ -0,0 +1,49 @@ +package com.objectcomputing.checkins.services.role.role_permissions; + +import com.objectcomputing.checkins.services.permissions.Permission; +import io.micronaut.core.annotation.Introspected; +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.validation.constraints.NotNull; +import java.util.UUID; + +@Introspected +public class RolePermissionResponseDTO { + + @NotNull + @Schema(description = "id of the role", required = true) + private UUID roleId; + + @Schema(description = "the permission", required = true) + private Permission permission; + + public RolePermissionResponseDTO(UUID roleId, Permission permission) { + this.roleId = roleId; + this.permission = permission; + } + + public UUID getRoleId() { + return roleId; + } + + public void setRoleId(UUID roleId) { + this.roleId = roleId; + } + + public Permission getPermission() { + return permission; + } + + public void setPermission(Permission permission) { + this.permission = permission; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("RolePermissionCreateDTO{"); + sb.append("roleId=").append(roleId); + sb.append(", permission=").append(permission); + sb.append('}'); + return sb.toString(); + } +} diff --git a/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionServicesImpl.java b/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionServicesImpl.java index 6d2df5f73e..2a274d5453 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionServicesImpl.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionServicesImpl.java @@ -1,6 +1,7 @@ package com.objectcomputing.checkins.services.role.role_permissions; import com.objectcomputing.checkins.services.permissions.Permission; +import com.objectcomputing.checkins.services.permissions.PermissionDTO; import com.objectcomputing.checkins.services.permissions.PermissionServices; import com.objectcomputing.checkins.services.role.Role; import com.objectcomputing.checkins.services.role.RoleServices; @@ -45,7 +46,7 @@ public List findAll() { rolePermissionsResponseDTO.setRoleId(role.getId()); rolePermissionsResponseDTO.setRole(role.getRole()); rolePermissionsResponseDTO.setDescription(role.getDescription()); - rolePermissionsResponseDTO.setPermissions(permissionsAssociatedWithRole); + rolePermissionsResponseDTO.setPermissions(permissionsAssociatedWithRole.stream().map((Permission permission) -> new PermissionDTO(permission)).collect(Collectors.toList())); roleInfo.add(rolePermissionsResponseDTO); } diff --git a/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionsResponseDTO.java b/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionsResponseDTO.java index 8a6036d6ab..dde0e95280 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionsResponseDTO.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionsResponseDTO.java @@ -1,6 +1,7 @@ package com.objectcomputing.checkins.services.role.role_permissions; import com.objectcomputing.checkins.services.permissions.Permission; +import com.objectcomputing.checkins.services.permissions.PermissionDTO; import io.micronaut.core.annotation.Introspected; import io.micronaut.core.annotation.Nullable; import io.swagger.v3.oas.annotations.media.Schema; @@ -16,7 +17,7 @@ public class RolePermissionsResponseDTO { @Schema(description = "id of the role", required = true) private UUID roleId; - @NotNull + @Nullable @Schema(description = "The name of the role", required = true) private String role; @@ -26,7 +27,7 @@ public class RolePermissionsResponseDTO { @NotNull @Schema(description = "List of Permissions associated with this role", required = true) - private List permissions; + private List permissions; public UUID getRoleId() { return roleId; @@ -36,11 +37,12 @@ public void setRoleId(UUID roleId) { this.roleId = roleId; } + @Nullable public String getRole() { return role; } - public void setRole(String role) { + public void setRole(@Nullable String role) { this.role = role; } @@ -53,11 +55,11 @@ public void setDescription(@Nullable String description) { this.description = description; } - public List getPermissions() { + public List getPermissions() { return permissions; } - public void setPermissions(List permissions) { + public void setPermissions(List permissions) { this.permissions = permissions; } diff --git a/server/src/test/java/com/objectcomputing/checkins/services/permissions/PermissionsControllerTest.java b/server/src/test/java/com/objectcomputing/checkins/services/permissions/PermissionsControllerTest.java index d0139bde81..6fe5c434ad 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/permissions/PermissionsControllerTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/permissions/PermissionsControllerTest.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -42,12 +43,12 @@ void testGetAllPermissionsEnsureAlphabeticalOrder() { MemberProfile user = createADefaultMemberProfile(); assignMemberRole(user); - List expected = List.of(Permission.values()); + List expected = List.of(Permission.values()).stream().map((permission) -> new PermissionDTO(permission)).collect(Collectors.toList()); final HttpRequest request = HttpRequest. GET("/OrderByPermission").basicAuth(user.getWorkEmail(), RoleType.Constants.MEMBER_ROLE); - final HttpResponse> response = - client.toBlocking().exchange(request, Argument.listOf(Permission.class)); + final HttpResponse> response = + client.toBlocking().exchange(request, Argument.listOf(PermissionDTO.class)); assertEquals(HttpStatus.OK, response.getStatus()); assertTrue(response.getBody().isPresent()); @@ -74,12 +75,12 @@ void testGetAllPermissions() { MemberProfile user = createADefaultMemberProfile(); assignMemberRole(user); - List expected = List.of(Permission.values()); + List expected = List.of(Permission.values()).stream().map((permission) -> new PermissionDTO(permission)).collect(Collectors.toList()); final HttpRequest request = HttpRequest. GET("/").basicAuth(user.getWorkEmail(), RoleType.Constants.MEMBER_ROLE); - final HttpResponse> response = - client.toBlocking().exchange(request, Argument.listOf(Permission.class)); + final HttpResponse> response = + client.toBlocking().exchange(request, Argument.listOf(PermissionDTO.class)); assertEquals(HttpStatus.OK, response.getStatus()); assertTrue(response.getBody().isPresent()); @@ -87,7 +88,7 @@ void testGetAllPermissions() { } @Test - void getAllPermissionsnIsNotAuthenticatedThrowsError() { + void getAllPermissionsIsNotAuthenticatedThrowsError() { final HttpRequest request = HttpRequest.GET("/"); HttpClientResponseException responseException = assertThrows(HttpClientResponseException.class, diff --git a/server/src/test/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionsControllerTest.java b/server/src/test/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionsControllerTest.java index ceddc24f0f..f24813bc75 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionsControllerTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/role/role_permissions/RolePermissionsControllerTest.java @@ -7,6 +7,7 @@ import com.objectcomputing.checkins.services.fixture.RoleFixture; import com.objectcomputing.checkins.services.memberprofile.MemberProfile; import com.objectcomputing.checkins.services.permissions.Permission; +import com.objectcomputing.checkins.services.permissions.PermissionDTO; import com.objectcomputing.checkins.services.role.Role; import com.objectcomputing.checkins.services.role.RoleType; import io.micronaut.core.type.Argument; @@ -53,7 +54,6 @@ void testGetAllRolePermissions() { final HttpResponse> response = client.toBlocking().exchange(request, Argument.listOf(RolePermissionsResponseDTO.class)); - assertEquals(HttpStatus.OK, response.getStatus()); assertTrue(response.getBody().isPresent()); @@ -62,9 +62,9 @@ void testGetAllRolePermissions() { assertEquals(adminRole.getRole(), actual.get(0).getRole()); assertNotNull(actual.get(0).getDescription()); assertEquals(19, actual.get(0).getPermissions().size()); - List assigned = actual.get(0).getPermissions(); + List assigned = actual.get(0).getPermissions(); for(Permission permission: adminPermissions) { - Permission stored = permission; + PermissionDTO stored = new PermissionDTO(permission); assertTrue(assigned.contains(stored)); } } diff --git a/web-ui/src/components/menu/Menu.test.jsx b/web-ui/src/components/menu/Menu.test.jsx index b4eae5c7b5..f7ac807dc6 100644 --- a/web-ui/src/components/menu/Menu.test.jsx +++ b/web-ui/src/components/menu/Menu.test.jsx @@ -30,7 +30,7 @@ const adminState = { workEmail: "test@tester.com", }, role: ["MEMBER", "ADMIN"], - permissions: ["CAN_VIEW_SKILLS_REPORT"], + permissions: [{permission:"CAN_VIEW_SKILLS_REPORT"}], imageUrl: "https://upload.wikimedia.org/wikipedia/commons/7/74/SNL_MrBill_Doll.jpg", }, diff --git a/web-ui/src/context/selectors.js b/web-ui/src/context/selectors.js index ea11c22c87..8b72128ec8 100644 --- a/web-ui/src/context/selectors.js +++ b/web-ui/src/context/selectors.js @@ -43,12 +43,12 @@ export const selectIsAdmin = createSelector( export const selectHasPermissionAssignmentPermission = createSelector( selectUserProfile, (userProfile) => - userProfile && userProfile.role && userProfile.permissions.some((p) => p.length > 0 && p.includes("CAN_ASSIGN_ROLE_PERMISSIONS")) + userProfile && userProfile.role && userProfile.permissions.some((p) => p?.permission?.includes("CAN_ASSIGN_ROLE_PERMISSIONS")) ); export const selectHasReportPermission = createSelector( selectUserProfile, - (userProfile) => userProfile && userProfile.role && userProfile.permissions.some((p) => p.length > 0 && p.includes("REPORT")) + (userProfile) => userProfile && userProfile.role && userProfile.permissions.some((p) => p?.permission?.includes("REPORT")) ); diff --git a/web-ui/src/pages/PermissionsPage.jsx b/web-ui/src/pages/PermissionsPage.jsx index 3c27c371e7..8be201b0b7 100644 --- a/web-ui/src/pages/PermissionsPage.jsx +++ b/web-ui/src/pages/PermissionsPage.jsx @@ -50,7 +50,11 @@ const PermissionEditor = ({ ); }; -const isPermissionEnabled = (rolePermissions, permission) => rolePermissions.some((current) => current.id === permission.id); +const isPermissionEnabled = (rolePermissions, permission) => { + return rolePermissions.some((current) => { + return current.permission === permission.permission; + }); +} const EditPermissionsPage = () => { const { state } = useContext(AppContext); @@ -102,7 +106,7 @@ const EditPermissionsPage = () => { }; const addPermissionForRole = async (role, permission) => { - let newSchema = { roleId: role.id, permissionId: permission.id }; + let newSchema = { roleId: role.id, permission: permission.permission }; let res = await postRolePermission(newSchema, csrf); const snackPayload = res.error ? { severity: "warning", toast: `Problem adding ${permission.description} to ${role.role}` } @@ -114,7 +118,7 @@ const EditPermissionsPage = () => { }; const deletePermissionForRole = async (role, permission) => { - let newSchema = { roleId: role.id, permissionId: permission.id }; + let newSchema = { roleId: role.id, permission: permission.permission }; let res = await deleteRolePermission(newSchema, csrf); const snackPayload = res.error ? { severity: "warning", toast: `Problem deleting ${permission.description} from ${role.role}` } @@ -162,7 +166,7 @@ const EditPermissionsPage = () => {

{category?.category}:

{ category?.permissions?.map((permission)=> (