Skip to content
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

feat(AUTH-CPC-755): Add More Roles Front End #573

Merged
merged 7 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions api-gateway/src/main/resources/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@
<script src="scripts/pet-type-list/pet-type-list.controller.js"></script>
<script src="scripts/pet-type-list/pet-type-list.component.js"></script>

<script src="scripts/auth/update-role-form/role-update.config.js"></script>
<script src="scripts/auth/update-role-form/role-update.service.js"></script>
<script src="scripts/auth/update-role-form/role-update.controller.js"></script>
<script src="scripts/auth/update-role-form/role-update.component.js"></script>



<script src="scripts/pet-details/pet-details.js"></script>
<script src="scripts/pet-details/pet-details.controller.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion api-gateway/src/main/resources/static/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -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']);



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ <h2 class="admin-panel">Users</h2>
<tr>
<th>Username</th>
<th>Email</th>
<th>Role</th>
<th>Options</th>
</tr>
</thead>
Expand All @@ -23,8 +24,15 @@ <h2 class="admin-panel">Users</h2>
</a>
</td>
<td>{{user.email}}</td>
<td>
<!-- Using a nested ng-repeat to loop over each role in the user.roles array -->
<span ng-repeat="role in user.roles">
{{ role.name }}<span ng-if="!$last">, </span>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this doing ? Is it reading from the fetched user ?

</span>
</td>
<td>
<input class="add-vet-button btn btn-success" type="button" value="Delete" ng-click="removeUser(user.userId)"/>
<button class="btn btn-warning" ui-sref="updateUserRole({ userId: user.userId })">Update Role</button>
</td>
</tr>

Expand Down
Original file line number Diff line number Diff line change
@@ -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: '<'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this doing ?

}
});
Original file line number Diff line number Diff line change
@@ -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;
}]
}
});
}]);
Original file line number Diff line number Diff line change
@@ -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;
}
Comment on lines +30 to +33
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use radio buttons instead of this bloated logic ?


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);
});
};
}]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dylan recently added his inventory manger story so I would recommend adding Inventory Manager as a role if you have the time.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict';

angular.module('userModule').service('UserService', [function() {
this.getAvailableRoles = function() {
return ['ADMIN', 'VET', 'OWNER'];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these values not fetched from the database, what happens if a new role is added ? For example I added the inventory manager ?

Comment on lines +1 to +5
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this normally work with the default preexisting roles? New ones would prove to be an issue no?

};

}]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<h2>Update User Role</h2>
<form style="background-color: #f5f5f5; padding: 20px; border-radius: 10px; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);">
<div class="form-group">
<label>Select Role:</label>
<div ng-repeat="role in roles" class="form-check">
<input type="checkbox" class="form-check-input" id="{{role}}" ng-model="selectedRoles[role]" ng-true-value="'{{role}}'" ng-false-value="undefined">
<label class="form-check-label" for="{{role}}">{{role}}</label>
</div>
</div>
Comment on lines +6 to +9
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we using checkboxes ? Radio buttons would fit better since we would want to choose only one role.

<button type="button" class="btn btn-warning" ng-click="updateRole()">Update Roles</button>
<a ui-sref="AdminPanel" class="btn btn-secondary">Cancel</a>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@
public interface UserRepo extends JpaRepository<User, Long> {

Optional<User> findByEmail(String email);
User findUserById(long id);

Optional<User> findByUsername(String username);

//Optional<User> findByUserId(String userId);
Optional<User> findById(String userId);

Check warning on line 33 in auth-service/src/main/java/com/petclinic/authservice/datalayer/user/UserRepo.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Spring Data repository method parameters errors

Expected parameter types: **long**
Optional<User> findOptionalUserByUserIdentifier_UserId(String userId);

User findUserByUserIdentifier_UserId(String userId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

Check warning on line 8 in auth-service/src/main/java/com/petclinic/authservice/presentationlayer/User/RolesChangeRequestDTO.java

View workflow job for this annotation

GitHub Actions / Qodana for JVM

Unused import

Unused import `import java.util.List;`
import java.util.Set;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true)
public class RolesChangeRequestDTO {
List<String> roles;
Set<String> roles;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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));

Expand All @@ -666,16 +663,19 @@ void updateUserRole_validUserId() {
.value(dto -> {
assertNotNull(dto);
List<String> actualRoleNames = dto.getRoles().stream()
.map(Role::getName) // Assuming the Role object has a getName() method
.map(Role::getName)
.toList();
assertEquals(updatedUser.getRoles(), actualRoleNames);

Set<String> 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";
Expand All @@ -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
Expand All @@ -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));
Expand All @@ -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));

Expand Down
Loading