Skip to content

Commit b0c4ae7

Browse files
authored
DMP-3819 Update POST /admin/users to disallow duplicate email address (#3040)
1 parent e0e1f22 commit b0c4ae7

File tree

7 files changed

+82
-22
lines changed

7 files changed

+82
-22
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package uk.gov.hmcts.darts.common.repository;
2+
3+
import org.junit.jupiter.api.BeforeEach;
4+
import org.junit.jupiter.api.Test;
5+
import org.mockito.Mockito;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.test.context.bean.override.mockito.MockitoBean;
8+
import uk.gov.hmcts.darts.authorisation.api.AuthorisationApi;
9+
import uk.gov.hmcts.darts.authorisation.component.UserIdentity;
10+
import uk.gov.hmcts.darts.common.entity.UserAccountEntity;
11+
import uk.gov.hmcts.darts.testutils.PostgresIntegrationBase;
12+
import uk.gov.hmcts.darts.testutils.stubs.SuperAdminUserStub;
13+
14+
import java.util.List;
15+
16+
import static org.junit.jupiter.api.Assertions.assertEquals;
17+
18+
class UserAccountRepositoryIntTest extends PostgresIntegrationBase {
19+
20+
@Autowired
21+
private UserAccountRepository userAccountRepository;
22+
23+
@Autowired
24+
private SuperAdminUserStub superAdminUserStub;
25+
26+
@MockitoBean
27+
private AuthorisationApi authorisationApi;
28+
29+
@MockitoBean
30+
private UserIdentity userIdentity;
31+
32+
private UserAccountEntity integrationTestUser;
33+
34+
@BeforeEach
35+
void setUp() {
36+
integrationTestUser = dartsDatabase.getUserAccountStub().getIntegrationTestUserAccountEntity();
37+
Mockito.when(authorisationApi.getCurrentUser()).thenReturn(integrationTestUser);
38+
}
39+
40+
@Test
41+
void findByEmailAddressIgnoreCase_shouldReturnExpectedUserAccount_whenItExistsIgnoringCase() {
42+
superAdminUserStub.givenUserIsAuthorised(userIdentity);
43+
String userEmail = "[email protected]";
44+
45+
List<UserAccountEntity> foundUsers = userAccountRepository.findByEmailAddressIgnoreCase(userEmail);
46+
47+
assertEquals(1, foundUsers.size());
48+
assertEquals(integrationTestUser.getEmailAddress(), foundUsers.get(0).getEmailAddress());
49+
}
50+
}

src/integrationTest/java/uk/gov/hmcts/darts/usermanagement/controller/PostUserIntTest.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
1414
import org.springframework.transaction.PlatformTransactionManager;
1515
import org.springframework.transaction.support.TransactionTemplate;
16+
import uk.gov.hmcts.darts.audio.model.Problem;
1617
import uk.gov.hmcts.darts.authorisation.api.AuthorisationApi;
1718
import uk.gov.hmcts.darts.authorisation.component.UserIdentity;
1819
import uk.gov.hmcts.darts.common.entity.SecurityGroupEntity;
1920
import uk.gov.hmcts.darts.common.entity.UserAccountEntity;
2021
import uk.gov.hmcts.darts.testutils.IntegrationBase;
2122
import uk.gov.hmcts.darts.testutils.stubs.SuperAdminUserStub;
23+
import uk.gov.hmcts.darts.usermanagement.exception.UserManagementError;
2224

2325
import java.io.UnsupportedEncodingException;
2426
import java.util.List;
@@ -72,7 +74,7 @@ void setUp() {
7274
}
7375

7476
@Test
75-
void createUserShouldSucceedWhenProvidedWithValidValuesForMinimumRequiredFields() throws Exception {
77+
void createUser_ShouldSucceed_WhenProvidedWithValidValuesForMinimumRequiredFields() throws Exception {
7678
superAdminUserStub.givenUserIsAuthorised(userIdentity);
7779

7880
MockHttpServletRequestBuilder request = buildRequest()
@@ -118,7 +120,7 @@ void createUserShouldSucceedWhenProvidedWithValidValuesForMinimumRequiredFields(
118120
}
119121

120122
@Test
121-
void createUserShouldSucceedWhenProvidedWithValidValuesForAllFields() throws Exception {
123+
void createUser_ShouldSucceed_WhenProvidedWithValidValuesForAllFields() throws Exception {
122124
superAdminUserStub.givenUserIsAuthorised(userIdentity);
123125

124126
MockHttpServletRequestBuilder request = buildRequest()
@@ -174,7 +176,7 @@ void createUserShouldSucceedWhenProvidedWithValidValuesForAllFields() throws Exc
174176
}
175177

176178
@Test
177-
void createUserShouldFailWhenRequiredFieldsAreMissing() throws Exception {
179+
void createUser_ShouldFail_WhenRequiredFieldsAreMissing() throws Exception {
178180
superAdminUserStub.givenUserIsAuthorised(userIdentity);
179181

180182
MockHttpServletRequestBuilder request = buildRequest()
@@ -193,7 +195,7 @@ void createUserShouldFailWhenRequiredFieldsAreMissing() throws Exception {
193195
}
194196

195197
@Test
196-
void createUserShouldSucceedWhenProvidedWithAUserEmailAddressThatMatchesAnExistingDisabledAccount() throws Exception {
198+
void createUser_ShouldFail_WhenProvidedWithAUserEmailAddressThatMatchesAnExistingDisabledAccount() throws Exception {
197199
superAdminUserStub.givenUserIsAuthorised(userIdentity);
198200

199201
UserAccountEntity userAccountEntity = new UserAccountEntity();
@@ -211,12 +213,18 @@ void createUserShouldSucceedWhenProvidedWithAUserEmailAddressThatMatchesAnExisti
211213
"email_address": "[email protected]"
212214
}
213215
""");
214-
mockMvc.perform(request)
215-
.andExpect(status().isCreated());
216+
MvcResult mvcResult = mockMvc.perform(request)
217+
.andExpect(status().isConflict()).andReturn();
218+
String actualJson = mvcResult.getResponse().getContentAsString();
219+
220+
Problem problem = objectMapper.readValue(actualJson, Problem.class);
221+
assertEquals(UserManagementError.DUPLICATE_EMAIL.getType(), problem.getType().toString());
222+
assertEquals(UserManagementError.DUPLICATE_EMAIL.getTitle(), problem.getTitle());
223+
assertEquals("User with email [email protected] already exists", problem.getDetail());
216224
}
217225

218226
@Test
219-
void createUserShouldFailWhenProvidedWithASecurityGroupThatDoesntExist() throws Exception {
227+
void createUser_ShouldFail_WhenProvidedWithASecurityGroupThatDoesntExist() throws Exception {
220228
superAdminUserStub.givenUserIsAuthorised(userIdentity);
221229

222230
MockHttpServletRequestBuilder request = buildRequest()
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
4444

4545
@AutoConfigureMockMvc
46-
class UserControllerTest extends IntegrationBase {
46+
class UserControllerIntTest extends IntegrationBase {
4747

4848
private static final String ENDPOINT_URL = "/admin/users/";
4949

@@ -325,8 +325,7 @@ void testActivateModifyUserWithSuperAdminAndFailWithNoFullNameAndNoEmailAddress(
325325
// add user to the super admin group
326326
Optional<SecurityGroupEntity> groupEntity
327327
= securityGroupRepository.findByGroupNameIgnoreCase(SecurityGroupEnum.SUPER_ADMIN.getName());
328-
329-
328+
330329
userAccountEntity.getSecurityGroupEntities().add(groupEntity.get());
331330
userAccountEntity = dartsDatabaseStub.save(userAccountEntity);
332331

src/main/java/uk/gov/hmcts/darts/common/repository/UserAccountRepository.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ AND securityRole.id IN (:roleIds)
6262
""")
6363
Optional<UserAccountEntity> findByRoleAndUserId(Integer securityRoleId, Integer userId);
6464

65-
List<UserAccountEntity> findByEmailAddressIgnoreCaseAndActive(String emailAddress, Boolean active);
66-
6765
List<UserAccountEntity> findByEmailAddressIgnoreCase(String emailAddress);
6866

6967
@Modifying

src/main/java/uk/gov/hmcts/darts/usermanagement/service/impl/UserManagementServiceImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ private List<Long> updateEntity(UserPatch userPatch, UserAccountEntity userAccou
194194
if (active != null) {
195195
userAccountEntity.setActive(active);
196196

197-
// if we are disabling the use then disable the transcriptions
197+
// if we are disabling the user then disable the transcriptions
198198
// and remove user from security groups
199199
if (active.equals(Boolean.FALSE)) {
200200
unassignUserFromGroupsTheyArePartOf(userAccountEntity);

src/main/java/uk/gov/hmcts/darts/usermanagement/service/validation/UserEmailValidator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public void validate(User user) {
2424
String.format("Invalid email format {%s}", user.getEmailAddress()));
2525
}
2626

27-
userAccountRepository.findByEmailAddressIgnoreCaseAndActive(user.getEmailAddress(), true)
27+
userAccountRepository.findByEmailAddressIgnoreCase(user.getEmailAddress())
2828
.stream().findFirst()
2929
.ifPresent(existingUser -> {
3030
throw new DartsApiException(

src/test/java/uk/gov/hmcts/darts/usermanagement/service/impl/UserEmailValidatorTest.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import org.junit.jupiter.api.BeforeEach;
44
import org.junit.jupiter.api.Test;
55
import org.junit.jupiter.api.extension.ExtendWith;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.ValueSource;
68
import org.mockito.Mock;
79
import org.mockito.junit.jupiter.MockitoExtension;
810
import uk.gov.hmcts.darts.common.entity.UserAccountEntity;
@@ -36,19 +38,22 @@ void setUp() {
3638
}
3739

3840
@Test
39-
void doesNotThrowExceptionIfEmailNotCurrentlyAssociatedWithActiveUser() {
40-
when(userAccountRepository.findByEmailAddressIgnoreCaseAndActive(NEW_EMAIL_ADDRESS, true))
41+
void validate_doesNotThrowException_whenEmailNotCurrentlyAssociatedWithAnyUser() {
42+
when(userAccountRepository.findByEmailAddressIgnoreCase(NEW_EMAIL_ADDRESS))
4143
.thenReturn(Collections.emptyList());
4244

4345
userEmailValidator.validate(someUserWithEmail(NEW_EMAIL_ADDRESS));
4446

4547
assertThatNoException().isThrownBy(() -> userEmailValidator.validate(someUserWithEmail(NEW_EMAIL_ADDRESS)));
4648
}
4749

48-
@Test
49-
void throwsExceptionIfEmailAlreadyAssociatedWithActiveUser() {
50-
when(userAccountRepository.findByEmailAddressIgnoreCaseAndActive(EXISTING_EMAIL_ADDRESS, true))
51-
.thenReturn(List.of(someUserAccountWithEmail(EXISTING_EMAIL_ADDRESS)));
50+
@ParameterizedTest
51+
@ValueSource(strings = {"true", "false"})
52+
void validate_throwsException_whenEmailAlreadyAssociatedWithExistingUser(boolean isActive) {
53+
UserAccountEntity existingUser = someUserAccountWithEmail(EXISTING_EMAIL_ADDRESS);
54+
existingUser.setActive(isActive);
55+
when(userAccountRepository.findByEmailAddressIgnoreCase(EXISTING_EMAIL_ADDRESS))
56+
.thenReturn(List.of(existingUser));
5257

5358
User user = someUserWithEmail(EXISTING_EMAIL_ADDRESS);
5459
assertThatThrownBy(() -> userEmailValidator.validate(user))
@@ -58,7 +63,7 @@ void throwsExceptionIfEmailAlreadyAssociatedWithActiveUser() {
5863
}
5964

6065
@Test
61-
void throwsExceptionIfEmailAddressHasNoDomain() {
66+
void validate_throwsException_whenEmailAddressHasNoDomain() {
6267

6368
User user = someUserWithEmail(EMAIL_ADDRESS_NO_DOMAIN);
6469
assertThatThrownBy(() -> userEmailValidator.validate(user))
@@ -68,7 +73,7 @@ void throwsExceptionIfEmailAddressHasNoDomain() {
6873
}
6974

7075
@Test
71-
void throwsExceptionIfEmailAddressHasNoUser() {
76+
void validate_throwsException_whenEmailAddressHasNoUser() {
7277

7378
User user = someUserWithEmail(EMAIL_ADDRESS_NO_USER);
7479
assertThatThrownBy(() -> userEmailValidator.validate(user))

0 commit comments

Comments
 (0)