diff --git a/pom.xml b/pom.xml
index 9aba7d2..16e63df 100644
--- a/pom.xml
+++ b/pom.xml
@@ -141,7 +141,7 @@
com.ecmsp
protos
- 1.0.0-20251105.185705-41
+ 1.0.0-20251109.095920-47
diff --git a/src/main/java/com/ecmsp/userservice/api/grpc/RoleGrpcMapper.java b/src/main/java/com/ecmsp/userservice/api/grpc/RoleGrpcMapper.java
new file mode 100644
index 0000000..a096dbf
--- /dev/null
+++ b/src/main/java/com/ecmsp/userservice/api/grpc/RoleGrpcMapper.java
@@ -0,0 +1,39 @@
+package com.ecmsp.userservice.api.grpc;
+
+import com.ecmsp.userservice.user.domain.Permission;
+import com.ecmsp.userservice.user.domain.RoleToCreate;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Component
+public class RoleGrpcMapper {
+
+ private final UserGrpcMapper userGrpcMapper;
+
+ public RoleGrpcMapper(UserGrpcMapper userGrpcMapper) {
+ this.userGrpcMapper = userGrpcMapper;
+ }
+
+ public Permission toDomainPermission(String permissionName) {
+ return Permission.valueOf(permissionName);
+ }
+
+ public RoleToCreate toDomainRoleToCreate(com.ecmsp.user.v1.Role protoRole) {
+ Set permissions = protoRole.getPermissionsList().stream()
+ .map(this::toDomainPermission)
+ .collect(Collectors.toSet());
+
+ return new RoleToCreate(protoRole.getName(), permissions);
+ }
+
+ // Delegate to UserGrpcMapper for proto conversions (reuse existing methods)
+ public com.ecmsp.user.v1.Role toProtoRole(com.ecmsp.userservice.user.domain.Role domainRole) {
+ return userGrpcMapper.toProtoRole(domainRole);
+ }
+
+ public String toProtoPermission(Permission permission) {
+ return userGrpcMapper.toProtoPermission(permission);
+ }
+}
diff --git a/src/main/java/com/ecmsp/userservice/api/grpc/UserGrpcMapper.java b/src/main/java/com/ecmsp/userservice/api/grpc/UserGrpcMapper.java
index 202d055..1231171 100644
--- a/src/main/java/com/ecmsp/userservice/api/grpc/UserGrpcMapper.java
+++ b/src/main/java/com/ecmsp/userservice/api/grpc/UserGrpcMapper.java
@@ -1,6 +1,5 @@
package com.ecmsp.userservice.api.grpc;
-import com.ecmsp.user.v1.RoleId;
import com.ecmsp.user.v1.UserId;
import com.ecmsp.userservice.user.domain.Permission;
import com.ecmsp.userservice.user.domain.Role;
@@ -31,7 +30,6 @@ public UserId toProtoUserId(com.ecmsp.userservice.user.domain.UserId domainUserI
public com.ecmsp.user.v1.Role toProtoRole(Role domainRole) {
return com.ecmsp.user.v1.Role.newBuilder()
- .setId(toProtoRoleId(domainRole.id()))
.setName(domainRole.name())
.addAllPermissions(domainRole.permissions().stream()
.map(this::toProtoPermission)
@@ -39,12 +37,6 @@ public com.ecmsp.user.v1.Role toProtoRole(Role domainRole) {
.build();
}
- public RoleId toProtoRoleId(com.ecmsp.userservice.user.domain.RoleId domainRoleId) {
- return RoleId.newBuilder()
- .setValue(domainRoleId.value().toString())
- .build();
- }
-
public String toProtoPermission(Permission permission) {
return permission.name();
}
diff --git a/src/main/java/com/ecmsp/userservice/api/grpc/UserGrpcService.java b/src/main/java/com/ecmsp/userservice/api/grpc/UserGrpcService.java
index a0dc821..3eb8431 100644
--- a/src/main/java/com/ecmsp/userservice/api/grpc/UserGrpcService.java
+++ b/src/main/java/com/ecmsp/userservice/api/grpc/UserGrpcService.java
@@ -1,26 +1,37 @@
package com.ecmsp.userservice.api.grpc;
import com.ecmsp.user.v1.*;
-import com.ecmsp.userservice.user.domain.User;
+import com.ecmsp.userservice.user.domain.Permission;
+import com.ecmsp.userservice.user.domain.RoleFacade;
+import com.ecmsp.userservice.user.domain.RoleToCreate;
import com.ecmsp.userservice.user.domain.UserFacade;
-import com.ecmsp.userservice.user.domain.UserId;
import com.ecmsp.userservice.user.domain.UserView;
import io.grpc.Status;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.Arrays;
import java.util.List;
import java.util.Optional;
+import java.util.Set;
import java.util.stream.Collectors;
@GrpcService
public class UserGrpcService extends UserServiceGrpc.UserServiceImplBase {
+ private static final Logger log = LoggerFactory.getLogger(UserGrpcService.class);
+
private final UserFacade userFacade;
+ private final RoleFacade roleFacade;
private final UserGrpcMapper mapper;
+ private final RoleGrpcMapper roleMapper;
- public UserGrpcService(UserFacade userFacade, UserGrpcMapper mapper) {
+ public UserGrpcService(UserFacade userFacade, RoleFacade roleFacade, UserGrpcMapper mapper, RoleGrpcMapper roleMapper) {
this.userFacade = userFacade;
+ this.roleFacade = roleFacade;
this.mapper = mapper;
+ this.roleMapper = roleMapper;
}
@Override
@@ -29,11 +40,11 @@ public void getUser(GetUserRequest request, StreamObserver resp
com.ecmsp.user.v1.UserId protoUserId = com.ecmsp.user.v1.UserId.newBuilder()
.setValue(request.getUserId())
.build();
- UserId userId = mapper.toDomainUserId(protoUserId);
- Optional userOptional = userFacade.findUserById(userId);
+ com.ecmsp.userservice.user.domain.UserId userId = mapper.toDomainUserId(protoUserId);
+ Optional userOptional = userFacade.findUserById(userId);
if (userOptional.isPresent()) {
- User user = userOptional.get();
+ com.ecmsp.userservice.user.domain.User user = userOptional.get();
UserView userView = new UserView(user.id(), user.login(), user.roles());
com.ecmsp.user.v1.User protoUser = mapper.toProtoUser(userView);
@@ -80,7 +91,7 @@ public void createUser(CreateUserRequest request, StreamObserver responseObserver) {
try {
- UserId userId = mapper.toDomainUserId(request.getUser().getId());
+ com.ecmsp.userservice.user.domain.UserId userId = mapper.toDomainUserId(request.getUser().getId());
String newLogin = request.getUser().getLogin();
if (newLogin == null || newLogin.isBlank()) {
@@ -124,9 +135,9 @@ public void updateUser(UpdateUserRequest request, StreamObserver updatedUserOptional = userFacade.findUserById(userId);
+ Optional updatedUserOptional = userFacade.findUserById(userId);
if (updatedUserOptional.isPresent()) {
- User updatedUser = updatedUserOptional.get();
+ com.ecmsp.userservice.user.domain.User updatedUser = updatedUserOptional.get();
UserView userView = new UserView(updatedUser.id(), updatedUser.login(), updatedUser.roles());
com.ecmsp.user.v1.User protoUser = mapper.toProtoUser(userView);
@@ -158,7 +169,7 @@ public void deleteUser(DeleteUserRequest request, StreamObserver responseObserver) {
- // TODO: Implement role management later
- responseObserver.onError(Status.UNIMPLEMENTED
- .withDescription("Role management not yet implemented")
- .asRuntimeException());
+ try {
+ log.info("Creating role: {}", request.getRole().getName());
+
+ RoleToCreate roleToCreate = roleMapper.toDomainRoleToCreate(request.getRole());
+ com.ecmsp.userservice.user.domain.RoleId roleId = roleFacade.createRole(roleToCreate);
+
+ com.ecmsp.userservice.user.domain.Role createdRole = roleFacade.findRoleById(roleId)
+ .orElseThrow(() -> new IllegalStateException("Role not found after creation"));
+
+ CreateRoleResponse response = CreateRoleResponse.newBuilder()
+ .setRole(roleMapper.toProtoRole(createdRole))
+ .build();
+
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+
+ log.info("Role created successfully: {}", roleId.value());
+ } catch (IllegalArgumentException e) {
+ log.error("Invalid role data: {}", e.getMessage());
+ // Check if it's a duplicate role error
+ if (e.getMessage().contains("already exists")) {
+ responseObserver.onError(Status.ALREADY_EXISTS
+ .withDescription(e.getMessage())
+ .asRuntimeException());
+ } else {
+ responseObserver.onError(Status.INVALID_ARGUMENT
+ .withDescription(e.getMessage())
+ .asRuntimeException());
+ }
+ } catch (Exception e) {
+ log.error("Error creating role", e);
+ responseObserver.onError(Status.INTERNAL
+ .withDescription("Failed to create role: " + e.getMessage())
+ .asRuntimeException());
+ }
}
@Override
public void updateRole(UpdateRoleRequest request, StreamObserver responseObserver) {
- // TODO: Implement role management later
- responseObserver.onError(Status.UNIMPLEMENTED
- .withDescription("Role management not yet implemented")
- .asRuntimeException());
+ try {
+ String roleName = request.getRole().getName();
+ log.info("Updating role: {}", roleName);
+
+ // Get current role by name
+ com.ecmsp.userservice.user.domain.Role currentRole = roleFacade.findRoleByName(roleName)
+ .orElseThrow(() -> new IllegalArgumentException("Role not found: " + roleName));
+
+ // Get the role ID for subsequent operations
+ com.ecmsp.userservice.user.domain.RoleId roleId = currentRole.id();
+
+ // Determine permissions to add and remove
+ Set newPermissions = request.getRole().getPermissionsList().stream()
+ .map(roleMapper::toDomainPermission)
+ .collect(Collectors.toSet());
+
+ Set currentPermissions = currentRole.permissions();
+
+ // Add new permissions
+ newPermissions.stream()
+ .filter(p -> !currentPermissions.contains(p))
+ .forEach(p -> roleFacade.addPermissionToRole(roleId, p));
+
+ // Remove old permissions
+ currentPermissions.stream()
+ .filter(p -> !newPermissions.contains(p))
+ .forEach(p -> roleFacade.removePermissionFromRole(roleId, p));
+
+ // Get updated role
+ com.ecmsp.userservice.user.domain.Role updatedRole = roleFacade.findRoleById(roleId)
+ .orElseThrow(() -> new IllegalStateException("Role not found after update"));
+
+ UpdateRoleResponse response = UpdateRoleResponse.newBuilder()
+ .setRole(roleMapper.toProtoRole(updatedRole))
+ .build();
+
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+
+ log.info("Role updated successfully: {}", roleName);
+ } catch (IllegalArgumentException e) {
+ log.error("Invalid role data: {}", e.getMessage());
+ responseObserver.onError(Status.INVALID_ARGUMENT
+ .withDescription(e.getMessage())
+ .asRuntimeException());
+ } catch (Exception e) {
+ log.error("Error updating role", e);
+ responseObserver.onError(Status.INTERNAL
+ .withDescription("Failed to update role: " + e.getMessage())
+ .asRuntimeException());
+ }
}
@Override
public void deleteRole(DeleteRoleRequest request, StreamObserver responseObserver) {
- // TODO: Implement role management later
- responseObserver.onError(Status.UNIMPLEMENTED
- .withDescription("Role management not yet implemented")
- .asRuntimeException());
+ try {
+ String roleName = request.getRoleId();
+ log.info("Deleting role: {}", roleName);
+
+ roleFacade.deleteRoleByName(roleName);
+
+ DeleteRoleResponse response = DeleteRoleResponse.newBuilder().build();
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+
+ log.info("Role deleted successfully: {}", roleName);
+ } catch (IllegalArgumentException e) {
+ log.error("Invalid role name: {}", e.getMessage());
+ responseObserver.onError(Status.INVALID_ARGUMENT
+ .withDescription(e.getMessage())
+ .asRuntimeException());
+ } catch (Exception e) {
+ log.error("Error deleting role", e);
+ responseObserver.onError(Status.INTERNAL
+ .withDescription("Failed to delete role: " + e.getMessage())
+ .asRuntimeException());
+ }
}
@Override
public void listRoles(ListRolesRequest request, StreamObserver responseObserver) {
- // TODO: Implement role management later
- responseObserver.onError(Status.UNIMPLEMENTED
- .withDescription("Role management not yet implemented")
- .asRuntimeException());
+ try {
+ log.info("Listing all roles");
+
+ List roles = roleFacade.getAllRoles();
+ List protoRoles = roles.stream()
+ .map(roleMapper::toProtoRole)
+ .collect(Collectors.toList());
+
+ ListRolesResponse response = ListRolesResponse.newBuilder()
+ .addAllRoles(protoRoles)
+ .build();
+
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+
+ log.info("Listed {} roles", roles.size());
+ } catch (Exception e) {
+ log.error("Error listing roles", e);
+ responseObserver.onError(Status.INTERNAL
+ .withDescription("Failed to list roles: " + e.getMessage())
+ .asRuntimeException());
+ }
}
@Override
public void assignRoleToUsers(AssignRoleToUsersRequest request, StreamObserver responseObserver) {
- // TODO: Implement role management later
- responseObserver.onError(Status.UNIMPLEMENTED
- .withDescription("Role management not yet implemented")
- .asRuntimeException());
+ try {
+ String roleName = request.getRoleName();
+ log.info("Assigning role {} to {} users", roleName, request.getUserIdsList().size());
+
+ // Verify role exists
+ roleFacade.findRoleByName(roleName)
+ .orElseThrow(() -> new IllegalArgumentException("Role not found: " + roleName));
+
+ // Assign role to each user
+ for (String userIdString : request.getUserIdsList()) {
+ com.ecmsp.userservice.user.domain.UserId userId = new com.ecmsp.userservice.user.domain.UserId(
+ java.util.UUID.fromString(userIdString)
+ );
+ userFacade.assignRoleToUser(userId, roleName);
+ }
+
+ AssignRoleToUsersResponse response = AssignRoleToUsersResponse.newBuilder().build();
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+
+ log.info("Role assigned successfully to {} users", request.getUserIdsList().size());
+ } catch (IllegalArgumentException e) {
+ log.error("Invalid assignment data: {}", e.getMessage());
+ responseObserver.onError(Status.INVALID_ARGUMENT
+ .withDescription(e.getMessage())
+ .asRuntimeException());
+ } catch (Exception e) {
+ log.error("Error assigning role to users", e);
+ responseObserver.onError(Status.INTERNAL
+ .withDescription("Failed to assign role: " + e.getMessage())
+ .asRuntimeException());
+ }
}
@Override
public void removeRoleFromUsers(RemoveRoleFromUsersRequest request, StreamObserver responseObserver) {
- // TODO: Implement role management later
- responseObserver.onError(Status.UNIMPLEMENTED
- .withDescription("Role management not yet implemented")
- .asRuntimeException());
+ try {
+ String roleName = request.getRoleName();
+ log.info("Removing role {} from {} users", roleName, request.getUserIdsList().size());
+
+ // Verify role exists
+ roleFacade.findRoleByName(roleName)
+ .orElseThrow(() -> new IllegalArgumentException("Role not found: " + roleName));
+
+ // Remove role from each user
+ for (String userIdString : request.getUserIdsList()) {
+ com.ecmsp.userservice.user.domain.UserId userId = new com.ecmsp.userservice.user.domain.UserId(
+ java.util.UUID.fromString(userIdString)
+ );
+ userFacade.removeRoleFromUser(userId, roleName);
+ }
+
+ RemoveRoleFromUsersResponse response = RemoveRoleFromUsersResponse.newBuilder().build();
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+
+ log.info("Role removed successfully from {} users", request.getUserIdsList().size());
+ } catch (IllegalArgumentException e) {
+ log.error("Invalid removal data: {}", e.getMessage());
+ responseObserver.onError(Status.INVALID_ARGUMENT
+ .withDescription(e.getMessage())
+ .asRuntimeException());
+ } catch (Exception e) {
+ log.error("Error removing role from users", e);
+ responseObserver.onError(Status.INTERNAL
+ .withDescription("Failed to remove role: " + e.getMessage())
+ .asRuntimeException());
+ }
}
@Override
public void listAllPermissions(ListAllPermissionsRequest request, StreamObserver responseObserver) {
- // TODO: Implement role management later
- responseObserver.onError(Status.UNIMPLEMENTED
- .withDescription("Role management not yet implemented")
- .asRuntimeException());
+ try {
+ log.info("Listing all available permissions");
+
+ List permissions = Arrays.stream(Permission.values())
+ .map(Permission::name)
+ .collect(Collectors.toList());
+
+ ListAllPermissionsResponse response = ListAllPermissionsResponse.newBuilder()
+ .addAllPermissions(permissions)
+ .build();
+
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+
+ log.info("Listed {} permissions", permissions.size());
+ } catch (Exception e) {
+ log.error("Error listing permissions", e);
+ responseObserver.onError(Status.INTERNAL
+ .withDescription("Failed to list permissions: " + e.getMessage())
+ .asRuntimeException());
+ }
}
}
diff --git a/src/main/java/com/ecmsp/userservice/api/rest/UserController.java b/src/main/java/com/ecmsp/userservice/api/rest/UserController.java
index 10297d3..a14584b 100644
--- a/src/main/java/com/ecmsp/userservice/api/rest/UserController.java
+++ b/src/main/java/com/ecmsp/userservice/api/rest/UserController.java
@@ -4,7 +4,6 @@
import com.ecmsp.userservice.api.rest.role.AssignRoleRequest;
import com.ecmsp.userservice.api.rest.role.RoleResponse;
import com.ecmsp.userservice.user.domain.Role;
-import com.ecmsp.userservice.user.domain.RoleId;
import com.ecmsp.userservice.user.domain.UserFacade;
import com.ecmsp.userservice.user.domain.UserId;
import com.ecmsp.userservice.user.domain.UserToCreate;
@@ -38,15 +37,15 @@ public ResponseEntity createUser(@RequestBody UserCreateRequest request) {
public ResponseEntity assignRoleToUser(
@PathVariable UUID userId,
@RequestBody AssignRoleRequest request) {
- userFacade.assignRoleToUser(new UserId(userId), new RoleId(request.roleId()));
+ userFacade.assignRoleToUser(new UserId(userId), request.roleName());
return ResponseEntity.ok().build();
}
- @DeleteMapping("/{userId}/roles/{roleId}")
+ @DeleteMapping("/{userId}/roles/{roleName}")
public ResponseEntity removeRoleFromUser(
@PathVariable UUID userId,
- @PathVariable UUID roleId) {
- userFacade.removeRoleFromUser(new UserId(userId), new RoleId(roleId));
+ @PathVariable String roleName) {
+ userFacade.removeRoleFromUser(new UserId(userId), roleName);
return ResponseEntity.ok().build();
}
diff --git a/src/main/java/com/ecmsp/userservice/api/rest/role/AssignRoleRequest.java b/src/main/java/com/ecmsp/userservice/api/rest/role/AssignRoleRequest.java
index 066b5da..0336f90 100644
--- a/src/main/java/com/ecmsp/userservice/api/rest/role/AssignRoleRequest.java
+++ b/src/main/java/com/ecmsp/userservice/api/rest/role/AssignRoleRequest.java
@@ -1,6 +1,4 @@
package com.ecmsp.userservice.api.rest.role;
-import java.util.UUID;
-
-public record AssignRoleRequest(UUID roleId) {
+public record AssignRoleRequest(String roleName) {
}
diff --git a/src/main/java/com/ecmsp/userservice/api/rest/role/RoleController.java b/src/main/java/com/ecmsp/userservice/api/rest/role/RoleController.java
index a179c24..2663f7e 100644
--- a/src/main/java/com/ecmsp/userservice/api/rest/role/RoleController.java
+++ b/src/main/java/com/ecmsp/userservice/api/rest/role/RoleController.java
@@ -22,6 +22,19 @@ public RoleController(RoleFacade roleFacade) {
this.roleFacade = roleFacade;
}
+ @ExceptionHandler(IllegalArgumentException.class)
+ public ResponseEntity handleIllegalArgumentException(IllegalArgumentException e) {
+ if (e.getMessage().contains("already exists")) {
+ return ResponseEntity.status(HttpStatus.CONFLICT)
+ .body(new ErrorResponse(e.getMessage()));
+ }
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST)
+ .body(new ErrorResponse(e.getMessage()));
+ }
+
+ record ErrorResponse(String message) {
+ }
+
@PostMapping
public ResponseEntity createRole(@RequestBody RoleCreateRequest request) {
RoleToCreate roleToCreate = new RoleToCreate(request.name(), request.permissions());
@@ -39,9 +52,9 @@ public ResponseEntity createRole(@RequestBody RoleCreateRequest re
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}
- @GetMapping("/{roleId}")
- public ResponseEntity getRoleById(@PathVariable UUID roleId) {
- return roleFacade.findRoleById(new RoleId(roleId))
+ @GetMapping("/{roleName}")
+ public ResponseEntity getRoleByName(@PathVariable String roleName) {
+ return roleFacade.findRoleByName(roleName)
.map(role -> new RoleResponse(
role.id().value(),
role.name(),
@@ -64,28 +77,28 @@ public ResponseEntity> getAllRoles() {
return ResponseEntity.ok(roles);
}
- @PostMapping("/{roleId}/permissions")
+ @PostMapping("/{roleName}/permissions")
public ResponseEntity addPermissionToRole(
- @PathVariable UUID roleId,
+ @PathVariable String roleName,
@RequestBody AddPermissionRequest request) {
- roleFacade.addPermissionToRole(new RoleId(roleId), request.permission());
+ roleFacade.addPermissionToRoleByName(roleName, request.permission());
return ResponseEntity.ok().build();
}
- @DeleteMapping("/{roleId}/permissions/{permission}")
+ @DeleteMapping("/{roleName}/permissions/{permission}")
public ResponseEntity removePermissionFromRole(
- @PathVariable UUID roleId,
+ @PathVariable String roleName,
@PathVariable String permission) {
- roleFacade.removePermissionFromRole(
- new RoleId(roleId),
+ roleFacade.removePermissionFromRoleByName(
+ roleName,
com.ecmsp.userservice.user.domain.Permission.valueOf(permission)
);
return ResponseEntity.ok().build();
}
- @DeleteMapping("/{roleId}")
- public ResponseEntity deleteRole(@PathVariable UUID roleId) {
- roleFacade.deleteRole(new RoleId(roleId));
+ @DeleteMapping("/{roleName}")
+ public ResponseEntity deleteRole(@PathVariable String roleName) {
+ roleFacade.deleteRoleByName(roleName);
return ResponseEntity.noContent().build();
}
}
diff --git a/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/DbUserRepository.java b/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/DbUserRepository.java
index ddc439b..9dedf68 100644
--- a/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/DbUserRepository.java
+++ b/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/DbUserRepository.java
@@ -63,4 +63,9 @@ public List findByLoginContaining(String loginFilter) {
public void updateLogin(UserId userId, String newLogin) {
userEntityRepository.updateLogin(userId.value(), newLogin);
}
+
+ @Transactional
+ public void upsert(User user) {
+ userEntityRepository.save(userMapper.toUserEntity(user));
+ }
}
diff --git a/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/RoleEntity.java b/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/RoleEntity.java
index 6cf28ae..8c715f7 100644
--- a/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/RoleEntity.java
+++ b/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/RoleEntity.java
@@ -14,7 +14,7 @@
@NoArgsConstructor
@Entity
@Table(name = "roles")
-class RoleEntity {
+public class RoleEntity {
@Id
@Column(name = "role_id")
diff --git a/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/RoleEntityRepository.java b/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/RoleEntityRepository.java
index 1e8d548..623b3d1 100644
--- a/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/RoleEntityRepository.java
+++ b/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/RoleEntityRepository.java
@@ -5,6 +5,6 @@
import java.util.Optional;
import java.util.UUID;
-interface RoleEntityRepository extends JpaRepository {
+public interface RoleEntityRepository extends JpaRepository {
Optional findByRoleName(String roleName);
}
diff --git a/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/UserEntity.java b/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/UserEntity.java
index 9ebed41..30ceab5 100644
--- a/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/UserEntity.java
+++ b/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/UserEntity.java
@@ -14,7 +14,7 @@
@NoArgsConstructor
@Entity
@Table(name = "users")
-class UserEntity {
+public class UserEntity {
@Id
@Column(name = "user_id")
diff --git a/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/UserEntityRepository.java b/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/UserEntityRepository.java
index 1f0bead..e8ed28f 100644
--- a/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/UserEntityRepository.java
+++ b/src/main/java/com/ecmsp/userservice/user/adapter/repository/db/UserEntityRepository.java
@@ -10,7 +10,7 @@
import java.util.UUID;
@Repository
-interface UserEntityRepository extends JpaRepository {
+public interface UserEntityRepository extends JpaRepository {
@Query("SELECT u FROM UserEntity u WHERE u.login = :login")
Optional findByLogin(String login);
diff --git a/src/main/java/com/ecmsp/userservice/user/config/UserConfig.java b/src/main/java/com/ecmsp/userservice/user/config/UserConfig.java
index 0090dd9..d704b63 100644
--- a/src/main/java/com/ecmsp/userservice/user/config/UserConfig.java
+++ b/src/main/java/com/ecmsp/userservice/user/config/UserConfig.java
@@ -1,5 +1,7 @@
package com.ecmsp.userservice.user.config;
+import com.ecmsp.userservice.user.adapter.repository.db.RoleEntityRepository;
+import com.ecmsp.userservice.user.adapter.repository.db.UserEntityRepository;
import com.ecmsp.userservice.user.domain.RoleRepository;
import com.ecmsp.userservice.user.domain.UserFacade;
import com.ecmsp.userservice.user.domain.UserRepository;
@@ -9,7 +11,7 @@
@Configuration
class UserConfig {
@Bean
- public UserFacade userFacade(UserRepository userRepository, RoleRepository roleRepository){
- return new UserFacade(userRepository, roleRepository);
+ public UserFacade userFacade(UserRepository userRepository, RoleEntityRepository roleEntityRepository, UserEntityRepository userEntityRepository){
+ return new UserFacade(userRepository, roleEntityRepository, userEntityRepository);
}
}
diff --git a/src/main/java/com/ecmsp/userservice/user/domain/RoleFacade.java b/src/main/java/com/ecmsp/userservice/user/domain/RoleFacade.java
index 3562ae9..4dc7d1f 100644
--- a/src/main/java/com/ecmsp/userservice/user/domain/RoleFacade.java
+++ b/src/main/java/com/ecmsp/userservice/user/domain/RoleFacade.java
@@ -12,6 +12,12 @@ public RoleFacade(RoleRepository roleRepository) {
}
public RoleId createRole(RoleToCreate roleToCreate) {
+ // Check if role with this name already exists
+ Optional existingRole = roleRepository.findByName(roleToCreate.name());
+ if (existingRole.isPresent()) {
+ throw new IllegalArgumentException("Role with name '" + roleToCreate.name() + "' already exists");
+ }
+
RoleId roleId = new RoleId(UUID.randomUUID());
Role role = new Role(roleId, roleToCreate.name(), roleToCreate.permissions());
roleRepository.save(role);
@@ -47,4 +53,24 @@ public List getAllRoles() {
public void deleteRole(RoleId roleId) {
roleRepository.delete(roleId);
}
+
+ public void deleteRoleByName(String roleName) {
+ Role role = roleRepository.findByName(roleName)
+ .orElseThrow(() -> new IllegalArgumentException("Role not found: " + roleName));
+ roleRepository.delete(role.id());
+ }
+
+ public void addPermissionToRoleByName(String roleName, Permission permission) {
+ Role role = roleRepository.findByName(roleName)
+ .orElseThrow(() -> new IllegalArgumentException("Role not found: " + roleName));
+ role.addPermission(permission);
+ roleRepository.save(role);
+ }
+
+ public void removePermissionFromRoleByName(String roleName, Permission permission) {
+ Role role = roleRepository.findByName(roleName)
+ .orElseThrow(() -> new IllegalArgumentException("Role not found: " + roleName));
+ role.removePermission(permission);
+ roleRepository.save(role);
+ }
}
diff --git a/src/main/java/com/ecmsp/userservice/user/domain/UserFacade.java b/src/main/java/com/ecmsp/userservice/user/domain/UserFacade.java
index bd52c57..2ac8b51 100644
--- a/src/main/java/com/ecmsp/userservice/user/domain/UserFacade.java
+++ b/src/main/java/com/ecmsp/userservice/user/domain/UserFacade.java
@@ -1,4 +1,8 @@
package com.ecmsp.userservice.user.domain;
+import com.ecmsp.userservice.user.adapter.repository.db.RoleEntity;
+import com.ecmsp.userservice.user.adapter.repository.db.RoleEntityRepository;
+import com.ecmsp.userservice.user.adapter.repository.db.UserEntity;
+import com.ecmsp.userservice.user.adapter.repository.db.UserEntityRepository;
import java.util.HashSet;
import java.util.List;
@@ -8,12 +12,14 @@
public class UserFacade {
private final UserRepository userRepository;
- private final RoleRepository roleRepository;
+ private final RoleEntityRepository roleEntityRepository;
+ private final UserEntityRepository userEntityRepository;
private final PasswordHasher passwordHasher = new PasswordHasher();
- public UserFacade(UserRepository userRepository, RoleRepository roleRepository) {
+ public UserFacade(UserRepository userRepository, RoleEntityRepository roleEntityRepository, UserEntityRepository userEntityRepository) {
this.userRepository = userRepository;
- this.roleRepository = roleRepository;
+ this.roleEntityRepository = roleEntityRepository;
+ this.userEntityRepository = userEntityRepository;
}
public User createUser(UserToCreate userToCreate){
@@ -51,26 +57,22 @@ public List listUsers(String filterLogin) {
return userRepository.findByLoginContaining(filterLogin);
}
- public void assignRoleToUser(UserId userId, RoleId roleId) {
- User user = userRepository.findById(userId)
+ public void assignRoleToUser(UserId userId, String roleName) {
+ UserEntity user = userEntityRepository.findById(userId.value())
.orElseThrow(() -> new IllegalArgumentException("User not found: " + userId));
- Role role = roleRepository.findById(roleId)
- .orElseThrow(() -> new IllegalArgumentException("Role not found: " + roleId));
+ RoleEntity role = roleEntityRepository.findByRoleName(roleName)
+ .orElseThrow(() -> new IllegalArgumentException("Role not found: " + roleName));
- Set updatedRoles = new HashSet<>(user.roles());
- updatedRoles.add(role);
- User updatedUser = new User(user.id(), user.login(), user.passwordHash(), updatedRoles);
- userRepository.save(updatedUser);
+ user.getRoles().add(role);
+ userEntityRepository.save(user);
}
- public void removeRoleFromUser(UserId userId, RoleId roleId) {
- User user = userRepository.findById(userId)
+ public void removeRoleFromUser(UserId userId, String roleName) {
+ UserEntity user = userEntityRepository.findById(userId.value())
.orElseThrow(() -> new IllegalArgumentException("User not found: " + userId));
- Set updatedRoles = new HashSet<>(user.roles());
- updatedRoles.removeIf(role -> role.id().equals(roleId));
- User updatedUser = new User(user.id(), user.login(), user.passwordHash(), updatedRoles);
- userRepository.save(updatedUser);
+ user.getRoles().removeIf(role -> role.getRoleName().equals(roleName));
+ userEntityRepository.save(user);
}
public Set getUserRoles(UserId userId) {
diff --git a/src/main/resources/db/migration/V3__Create_roles_and_permissions.sql b/src/main/resources/db/migration/V3__Create_roles_and_permissions.sql
index 54f67a2..69d5913 100644
--- a/src/main/resources/db/migration/V3__Create_roles_and_permissions.sql
+++ b/src/main/resources/db/migration/V3__Create_roles_and_permissions.sql
@@ -1,23 +1,23 @@
-- Create permissions table
-CREATE TABLE permissions (
+CREATE TABLE IF NOT EXISTS permissions (
permission_name VARCHAR(100) PRIMARY KEY
);
-- Create roles table
-CREATE TABLE roles (
+CREATE TABLE IF NOT EXISTS roles (
role_id UUID PRIMARY KEY,
role_name VARCHAR(100) NOT NULL UNIQUE
);
-- Create role_permissions join table
-CREATE TABLE role_permissions (
+CREATE TABLE IF NOT EXISTS role_permissions (
role_id UUID REFERENCES roles(role_id) ON DELETE CASCADE,
permission_name VARCHAR(100) REFERENCES permissions(permission_name) ON DELETE CASCADE,
PRIMARY KEY (role_id, permission_name)
);
-- Create user_roles join table
-CREATE TABLE user_roles (
+CREATE TABLE IF NOT EXISTS user_roles (
user_id UUID REFERENCES users(user_id) ON DELETE CASCADE,
role_id UUID REFERENCES roles(role_id) ON DELETE CASCADE,
PRIMARY KEY (user_id, role_id)