diff --git a/api-gateway/src/main/resources/static/index.html b/api-gateway/src/main/resources/static/index.html
index 311e4f68b7..684cee39f2 100755
--- a/api-gateway/src/main/resources/static/index.html
+++ b/api-gateway/src/main/resources/static/index.html
@@ -198,6 +198,12 @@
+
+
+
+
+
+
diff --git a/api-gateway/src/main/resources/static/scripts/app.js b/api-gateway/src/main/resources/static/scripts/app.js
index 5974f59b8d..daf9660120 100644
--- a/api-gateway/src/main/resources/static/scripts/app.js
+++ b/api-gateway/src/main/resources/static/scripts/app.js
@@ -12,7 +12,7 @@ const petClinicApp = angular.module('petClinicApp', [
'ui.router', 'layoutNav', 'layoutFooter', 'layoutWelcome', 'ownerList', 'ownerDetails', 'ownerForm', 'ownerRegister', 'petRegister', 'petForm'
, 'visits', 'visit', 'visitList' , 'vetList','vetForm','vetDetails', 'billForm', 'billUpdateForm', 'loginForm', 'rolesDetails', 'signupForm', 'productDetailsInfo',
'billDetails', 'billsByOwnerId', 'billHistory','billsByVetId','inventoryList', 'inventoryForm', 'productForm','inventoryProductList', 'inventoryUpdateForm', 'productUpdateForm',
- 'verification' , 'adminPanel','resetPwdForm','forgotPwdForm','petTypeList', 'petDetails','userDetails','managerForm']);
+ 'verification' , 'adminPanel','resetPwdForm','forgotPwdForm','petTypeList', 'petDetails','userDetails','managerForm','userModule']);
diff --git a/api-gateway/src/main/resources/static/scripts/auth/admin-panel/admin-panel.template.html b/api-gateway/src/main/resources/static/scripts/auth/admin-panel/admin-panel.template.html
index 9724f37d14..1cd6933c8d 100644
--- a/api-gateway/src/main/resources/static/scripts/auth/admin-panel/admin-panel.template.html
+++ b/api-gateway/src/main/resources/static/scripts/auth/admin-panel/admin-panel.template.html
@@ -12,6 +12,7 @@
Users
Username |
Email |
+ Role |
Options |
@@ -23,8 +24,15 @@ Users
{{user.email}} |
+
+
+
+ {{ role.name }},
+
+ |
+
|
diff --git a/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.component.js b/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.component.js
new file mode 100644
index 0000000000..c2726d3ee9
--- /dev/null
+++ b/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.component.js
@@ -0,0 +1,10 @@
+'use strict';
+
+angular.module('userModule')
+ .component('updateUserRoleComponent', {
+ templateUrl: 'scripts/auth/update-role-form/role-update.template.html',
+ controller: 'UpdateUserRoleController',
+ bindings: {
+ userId: '<'
+ }
+ });
\ No newline at end of file
diff --git a/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.config.js b/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.config.js
new file mode 100644
index 0000000000..af5abd257f
--- /dev/null
+++ b/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.config.js
@@ -0,0 +1,16 @@
+'use strict';
+
+angular.module('userModule', ['ui.router'])
+ .config(['$stateProvider', function($stateProvider) {
+ $stateProvider
+ .state('updateUserRole', {
+ parent: 'app',
+ url: '/users/:userId/updateRole',
+ component: 'updateUserRoleComponent',
+ resolve: {
+ userId: ['$stateParams', function($stateParams) {
+ return $stateParams.userId;
+ }]
+ }
+ });
+ }]);
\ No newline at end of file
diff --git a/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.controller.js b/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.controller.js
new file mode 100644
index 0000000000..753496bb79
--- /dev/null
+++ b/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.controller.js
@@ -0,0 +1,56 @@
+'use strict';
+
+angular.module('userModule')
+ .controller('UpdateUserRoleController', ['$scope', '$http', 'UserService', '$state', function($scope, $http, UserService, $state) {
+ var ctrl = this; // Capture the controller instance
+
+ $scope.roles = UserService.getAvailableRoles();
+ $scope.selectedRole = {};
+
+ // Use $onInit lifecycle hook to set $scope.userId
+ ctrl.$onInit = function() {
+ $scope.userId = ctrl.userId;
+ };
+
+ $scope.selectedRoles = {};
+
+ $scope.updateRole = function() {
+ var rolesList = [];
+ for (var role in $scope.selectedRoles) {
+ if ($scope.selectedRoles[role]) {
+ rolesList.push(role);
+ }
+ }
+
+ if (rolesList.length === 0) {
+ alert('Please select at least one role.');
+ return;
+ }
+
+ if (rolesList.length > 1) {
+ alert('Please select only one role.');
+ return;
+ }
+
+ var rolesChangeRequest = {
+ roles: rolesList
+ };
+
+ // Send the PATCH request
+ $http({
+ method: 'PATCH',
+ url: 'api/gateway/users/' + $scope.userId,
+ data: rolesChangeRequest,
+ headers: {
+ 'Content-Type': 'application/json',
+ // Add token headers if needed
+ }
+ })
+ .then(function successCallback(response) {
+ alert('Roles updated successfully!');
+ $state.go('AdminPanel');
+ }, function errorCallback(response) {
+ alert('Failed to update roles. ' + response.data.message);
+ });
+ };
+ }]);
diff --git a/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.service.js b/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.service.js
new file mode 100644
index 0000000000..fbf12f6add
--- /dev/null
+++ b/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.service.js
@@ -0,0 +1,8 @@
+'use strict';
+
+angular.module('userModule').service('UserService', [function() {
+ this.getAvailableRoles = function() {
+ return ['ADMIN', 'VET', 'OWNER'];
+ };
+
+}]);
\ No newline at end of file
diff --git a/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.template.html b/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.template.html
new file mode 100644
index 0000000000..be352a7b03
--- /dev/null
+++ b/api-gateway/src/main/resources/static/scripts/auth/update-role-form/role-update.template.html
@@ -0,0 +1,12 @@
+Update User Role
+
diff --git a/auth-service/src/main/java/com/petclinic/authservice/businesslayer/UserService.java b/auth-service/src/main/java/com/petclinic/authservice/businesslayer/UserService.java
index 8c391b806e..4928b32f37 100644
--- a/auth-service/src/main/java/com/petclinic/authservice/businesslayer/UserService.java
+++ b/auth-service/src/main/java/com/petclinic/authservice/businesslayer/UserService.java
@@ -63,5 +63,5 @@ public interface UserService {
void updatePassword(String newPassword, String token);
void processResetPassword(UserResetPwdWithTokenRequestModel resetRequest);
- UserPasswordLessDTO updateUserRole(String id, RolesChangeRequestDTO roles, String token);
+ UserPasswordLessDTO updateUserRole(String userId, RolesChangeRequestDTO roles, String token);
}
diff --git a/auth-service/src/main/java/com/petclinic/authservice/datalayer/user/UserRepo.java b/auth-service/src/main/java/com/petclinic/authservice/datalayer/user/UserRepo.java
index 2f86e56833..10a830a499 100644
--- a/auth-service/src/main/java/com/petclinic/authservice/datalayer/user/UserRepo.java
+++ b/auth-service/src/main/java/com/petclinic/authservice/datalayer/user/UserRepo.java
@@ -26,7 +26,6 @@
public interface UserRepo extends JpaRepository {
Optional findByEmail(String email);
- User findUserById(long id);
Optional findByUsername(String username);
diff --git a/auth-service/src/main/java/com/petclinic/authservice/presentationlayer/User/RolesChangeRequestDTO.java b/auth-service/src/main/java/com/petclinic/authservice/presentationlayer/User/RolesChangeRequestDTO.java
index afde7a6c0e..7c59f390a5 100644
--- a/auth-service/src/main/java/com/petclinic/authservice/presentationlayer/User/RolesChangeRequestDTO.java
+++ b/auth-service/src/main/java/com/petclinic/authservice/presentationlayer/User/RolesChangeRequestDTO.java
@@ -6,11 +6,12 @@
import lombok.NoArgsConstructor;
import java.util.List;
+import java.util.Set;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true)
public class RolesChangeRequestDTO {
- List roles;
+ Set roles;
}
diff --git a/auth-service/src/test/java/com/petclinic/authservice/presentationlayer/User/UserControllerIntegrationTest.java b/auth-service/src/test/java/com/petclinic/authservice/presentationlayer/User/UserControllerIntegrationTest.java
index 455d4cd37d..a4020e1b1c 100644
--- a/auth-service/src/test/java/com/petclinic/authservice/presentationlayer/User/UserControllerIntegrationTest.java
+++ b/auth-service/src/test/java/com/petclinic/authservice/presentationlayer/User/UserControllerIntegrationTest.java
@@ -26,10 +26,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
-import java.util.Base64;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
import java.util.stream.Collectors;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@@ -648,7 +645,7 @@ void deleteUser_ShouldThrowNotFoundException(){
@Test
void updateUserRole_validUserId() {
RolesChangeRequestDTO updatedUser = RolesChangeRequestDTO.builder()
- .roles(Collections.singletonList("OWNER"))
+ .roles(Collections.singleton("OWNER"))
.build();
String token = jwtTokenUtil.generateToken(userRepo.findAll().get(0));
@@ -666,16 +663,19 @@ void updateUserRole_validUserId() {
.value(dto -> {
assertNotNull(dto);
List actualRoleNames = dto.getRoles().stream()
- .map(Role::getName) // Assuming the Role object has a getName() method
+ .map(Role::getName)
.toList();
- assertEquals(updatedUser.getRoles(), actualRoleNames);
+
+ Set actualRolesSet = new HashSet<>(actualRoleNames);
+
+ assertEquals(updatedUser.getRoles(), actualRolesSet);
});
}
@Test
void updateUserRole_InvalidUserId() {
RolesChangeRequestDTO updatedUser = RolesChangeRequestDTO.builder()
- .roles(Collections.singletonList("OWNER"))
+ .roles(Collections.singleton("OWNER"))
.build();
String token = jwtTokenUtil.generateToken(userRepo.findAll().get(0));
String invalidUserId = "invalidId";
@@ -694,7 +694,7 @@ void updateUserRole_InvalidUserId() {
@Test
void updateUserRole_NoCookie() {
RolesChangeRequestDTO updatedUser = RolesChangeRequestDTO.builder()
- .roles(Collections.singletonList("OWNER"))
+ .roles(Collections.singleton("OWNER"))
.build();
webTestClient
@@ -711,7 +711,7 @@ void updateUserRole_NoCookie() {
void updateUserRole_cannotChangeOwnRoles() {
String userId = "validUserId";
RolesChangeRequestDTO updatedUser = RolesChangeRequestDTO.builder()
- .roles(Collections.singletonList("OWNER"))
+ .roles(Collections.singleton("OWNER"))
.build();
String token = jwtTokenUtil.generateToken(userRepo.findAll().get(0));
@@ -730,7 +730,7 @@ void updateUserRole_cannotChangeOwnRoles() {
@Test
void updateUserRole_invalidRole() {
RolesChangeRequestDTO updatedUser = RolesChangeRequestDTO.builder()
- .roles(Collections.singletonList("NOT_OWNER"))
+ .roles(Collections.singleton("NOT_OWNER"))
.build();
String token = jwtTokenUtil.generateToken(userRepo.findAll().get(0));