Skip to content

Commit 0880718

Browse files
AYS-308 | An active user has been deactivated (#366)
Co-authored-by: MenekseYuncu <baioretto66@gmail.com>
1 parent 0d1aa26 commit 0880718

File tree

6 files changed

+329
-3
lines changed

6 files changed

+329
-3
lines changed

src/main/java/org/ays/auth/controller/AysUserController.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,32 @@ public AysResponse<Void> update(@PathVariable @UUID final String id,
144144
* @param id The UUID of the user to be activated.
145145
* @return An {@link AysResponse} indicating the success of the operation.
146146
*/
147-
@PatchMapping("user/{id}/activate")
147+
@PatchMapping("/user/{id}/activate")
148148
@PreAuthorize("hasAnyAuthority('user:update')")
149149
public AysResponse<Void> activate(@PathVariable @UUID final String id) {
150150
userUpdateService.activate(id);
151151
return AysResponse.SUCCESS;
152152
}
153153

154154

155+
/**
156+
* PATCH /user/{id}/passivate : Passivates (deactivates) a user account with the given ID.
157+
* <p>
158+
* This endpoint is protected and requires the caller to have the authority
159+
* 'user:update'. The user ID must be a valid UUID.
160+
* </p>
161+
*
162+
* @param id The UUID of the user to be passivated.
163+
* @return An {@link AysResponse} indicating the success of the operation.
164+
*/
165+
@PatchMapping("/user/{id}/passivate")
166+
@PreAuthorize("hasAnyAuthority('user:update')")
167+
public AysResponse<Void> passivate(@PathVariable @UUID final String id) {
168+
userUpdateService.passivate(id);
169+
return AysResponse.SUCCESS;
170+
}
171+
172+
155173
/**
156174
* DELETE /user/{id} : Deletes a user account with the given ID.
157175
* <p>

src/main/java/org/ays/auth/service/AysUserUpdateService.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.ays.auth.service;
22

33
import org.ays.auth.model.request.AysUserUpdateRequest;
4+
import org.ays.auth.util.exception.AysUserNotActiveException;
45
import org.ays.auth.util.exception.AysUserNotExistByIdException;
56
import org.ays.auth.util.exception.AysUserNotPassiveException;
67

@@ -21,10 +22,19 @@ public interface AysUserUpdateService {
2122
*
2223
* @param id The unique identifier of the user to be activated.
2324
* @throws AysUserNotExistByIdException if a user with the given ID does not exist.
24-
* @throws AysUserNotPassiveException if the user is not in a passive state.
25+
* @throws AysUserNotPassiveException if the user is not in a passive state.
2526
*/
2627
void activate(String id);
2728

29+
/**
30+
* Passivates (deactivates) a user by ID if the user is currently active.
31+
*
32+
* @param id The unique identifier of the user to be passivated.
33+
* @throws AysUserNotExistByIdException if a user with the given ID does not exist.
34+
* @throws AysUserNotActiveException if the user is not in an active state.
35+
*/
36+
void passivate(String id);
37+
2838
/**
2939
* Deletes a user by its unique identifier.
3040
*

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.ays.auth.util.exception.AysUserAlreadyExistsByEmailAddressException;
1616
import org.ays.auth.util.exception.AysUserAlreadyExistsByPhoneNumberException;
1717
import org.ays.auth.util.exception.AysUserIsNotActiveOrPassiveException;
18+
import org.ays.auth.util.exception.AysUserNotActiveException;
1819
import org.ays.auth.util.exception.AysUserNotExistByIdException;
1920
import org.ays.auth.util.exception.AysUserNotPassiveException;
2021
import org.ays.common.model.AysPhoneNumber;
@@ -85,7 +86,7 @@ public void update(final String id,
8586
*
8687
* @param id The unique identifier of the user to be activated.
8788
* @throws AysUserNotExistByIdException if a user with the given ID does not exist.
88-
* @throws AysUserNotPassiveException if the user is not in a passive state and cannot be activated.
89+
* @throws AysUserNotPassiveException if the user is not in a passive state and cannot be activated.
8990
*/
9091
@Override
9192
public void activate(String id) {
@@ -102,6 +103,29 @@ public void activate(String id) {
102103
userSavePort.save(user);
103104
}
104105

106+
/**
107+
* Passivates (deactivates) a user by ID if the user is currently active.
108+
* This method retrieves the user by the provided ID and deactivates the user.
109+
*
110+
* @param id The unique identifier of the user to be passivated.
111+
* @throws AysUserNotExistByIdException if a user with the given ID does not exist.
112+
* @throws AysUserNotActiveException if the user is not in an active state and cannot be passivated.
113+
*/
114+
@Override
115+
public void passivate(String id) {
116+
117+
final AysUser user = userReadPort.findById(id)
118+
.filter(userFromDatabase -> identity.getInstitutionId().equals(userFromDatabase.getInstitution().getId()))
119+
.orElseThrow(() -> new AysUserNotExistByIdException(id));
120+
121+
if (!user.isActive()) {
122+
throw new AysUserNotActiveException(id);
123+
}
124+
125+
user.passivate();
126+
userSavePort.save(user);
127+
}
128+
105129

106130
/**
107131
* Deletes a user account by its ID.

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

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,4 +798,82 @@ void givenUserDelete_whenUserUnauthorized_thenReturnAccessDeniedException() thro
798798
.delete(Mockito.anyString());
799799
}
800800

801+
802+
@Test
803+
void givenValidId_whenPassivateUser_thenReturnSuccess() throws Exception {
804+
805+
// Given
806+
String mockId = "894dcc5d-31cc-4704-9f0a-627ac7da517d";
807+
808+
// When
809+
Mockito.doNothing()
810+
.when(userUpdateService)
811+
.passivate(Mockito.anyString());
812+
813+
// Then
814+
String endpoint = BASE_PATH.concat("/user/").concat(mockId).concat("/passivate");
815+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
816+
.patch(endpoint, mockAdminToken.getAccessToken());
817+
818+
AysResponse<Void> mockResponse = AysResponseBuilder.SUCCESS;
819+
820+
aysMockMvc.perform(mockHttpServletRequestBuilder, mockResponse)
821+
.andExpect(AysMockResultMatchersBuilders.status()
822+
.isOk())
823+
.andExpect(AysMockResultMatchersBuilders.response()
824+
.doesNotExist());
825+
826+
// Verify
827+
Mockito.verify(userUpdateService, Mockito.times(1))
828+
.passivate(Mockito.anyString());
829+
}
830+
831+
@ParameterizedTest
832+
@ValueSource(strings = {
833+
"A",
834+
"493268349068342"
835+
})
836+
void givenInvalidUserId_whenIdNotValid_thenReturnValidationErrorForPassivate(String invalidId) throws Exception {
837+
838+
// Then
839+
String endpoint = BASE_PATH.concat("/user/").concat(invalidId).concat("/passivate");
840+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
841+
.patch(endpoint, mockAdminToken.getAccessToken());
842+
843+
AysErrorResponse mockErrorResponse = AysErrorBuilder.VALIDATION_ERROR;
844+
845+
aysMockMvc.perform(mockHttpServletRequestBuilder, mockErrorResponse)
846+
.andExpect(AysMockResultMatchersBuilders.status()
847+
.isBadRequest())
848+
.andExpect(AysMockResultMatchersBuilders.subErrors()
849+
.isNotEmpty());
850+
851+
// Verify
852+
Mockito.verify(userUpdateService, Mockito.never())
853+
.passivate(Mockito.anyString());
854+
}
855+
856+
@Test
857+
void givenValidUserId_whenUserUnauthorized_thenReturnAccessDeniedException() throws Exception {
858+
859+
// Given
860+
String mockId = "333aec72-ecd8-49fc-86f5-2b5458871edb";
861+
862+
// Then
863+
String endpoint = BASE_PATH.concat("/user/").concat(mockId).concat("/passivate");
864+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
865+
.patch(endpoint, mockUserToken.getAccessToken());
866+
867+
AysErrorResponse mockErrorResponse = AysErrorBuilder.FORBIDDEN;
868+
869+
aysMockMvc.perform(mockHttpServletRequestBuilder, mockErrorResponse)
870+
.andExpect(AysMockResultMatchersBuilders.status()
871+
.isForbidden())
872+
.andExpect(AysMockResultMatchersBuilders.response()
873+
.doesNotExist());
874+
875+
// Verify
876+
Mockito.verify(userUpdateService, Mockito.never())
877+
.passivate(Mockito.anyString());
878+
}
801879
}

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

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ void givenValidIdAndUserUpdateRequest_whenUserUpdated_thenReturnSuccess() throws
373373
Assertions.assertNotNull(userFromDatabase.get().getUpdatedAt());
374374
}
375375

376+
376377
@Test
377378
void givenValidId_whenActivateUser_thenReturnSuccess() throws Exception {
378379

@@ -469,4 +470,49 @@ void givenValidId_whenUserDeleted_thenReturnSuccess() throws Exception {
469470
Assertions.assertEquals(AysUserStatus.DELETED, userFromDatabase.get().getStatus());
470471
}
471472

473+
474+
@Test
475+
void givenValidId_whenPassivateUser_thenReturnSuccess() throws Exception {
476+
477+
// Initialize
478+
Institution institution = new InstitutionBuilder()
479+
.withId(AysValidTestData.Admin.INSTITUTION_ID)
480+
.build();
481+
482+
List<AysRole> roles = roleReadPort.findAllActivesByInstitutionId(institution.getId());
483+
484+
AysUser user = userSavePort.save(
485+
new AysUserBuilder()
486+
.withId(AysRandomUtil.generateUUID())
487+
.withValidValues()
488+
.withRoles(roles)
489+
.withInstitution(institution)
490+
.withStatus(AysUserStatus.ACTIVE)
491+
.build()
492+
);
493+
494+
// Given
495+
String id = user.getId();
496+
497+
// Then
498+
String endpoint = BASE_PATH.concat("/user/").concat(id).concat("/passivate");
499+
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
500+
.patch(endpoint, adminToken.getAccessToken());
501+
502+
AysResponse<Void> mockResponse = AysResponseBuilder.SUCCESS;
503+
504+
aysMockMvc.perform(mockHttpServletRequestBuilder, mockResponse)
505+
.andExpect(AysMockResultMatchersBuilders.status()
506+
.isOk())
507+
.andExpect(AysMockResultMatchersBuilders.response()
508+
.doesNotExist());
509+
510+
// Verify
511+
Optional<AysUser> userFromDatabase = userReadPort.findById(user.getId());
512+
513+
Assertions.assertTrue(userFromDatabase.isPresent());
514+
Assertions.assertEquals(userFromDatabase.get().getId(), user.getId());
515+
Assertions.assertEquals(AysUserStatus.PASSIVE, userFromDatabase.get().getStatus());
516+
}
517+
472518
}

0 commit comments

Comments
 (0)