diff --git a/pom.xml b/pom.xml index 7cea613..165aeda 100755 --- a/pom.xml +++ b/pom.xml @@ -70,6 +70,13 @@ commons-lang3 3.7 + + + org.mockito + mockito-all + 1.9.5 + test + diff --git a/src/main/java/org/codiki/account/AccountController.java b/src/main/java/org/codiki/account/AccountController.java index 373b8fa..67a65ec 100755 --- a/src/main/java/org/codiki/account/AccountController.java +++ b/src/main/java/org/codiki/account/AccountController.java @@ -87,4 +87,10 @@ public class AccountController { public UserDTO signin(@RequestBody final UserDTO pUser, final HttpServletResponse pResponse) throws IOException { return accountService.signin(pUser, pResponse); } + + @PutMapping("/") + public void update(@RequestBody final UserDTO pUser, final HttpServletRequest pRequest, + final HttpServletResponse pResponse) throws IOException { + accountService.updateUser(pUser, pRequest, pResponse); + } } diff --git a/src/main/java/org/codiki/account/AccountService.java b/src/main/java/org/codiki/account/AccountService.java index cf9aa96..c921696 100755 --- a/src/main/java/org/codiki/account/AccountService.java +++ b/src/main/java/org/codiki/account/AccountService.java @@ -140,4 +140,32 @@ public class AccountService { return new UserDTO(user); } + + public void updateUser(final UserDTO pUser, final HttpServletRequest pRequest, + final HttpServletResponse pResponse) throws IOException { + final Optional connectedUserOpt = tokenService.getAuthenticatedUserByToken(pRequest); + if(connectedUserOpt.isPresent()) { + final User connectedUser = connectedUserOpt.get(); + + final Optional userFromDb = userRepository.findByEmail(pUser.getEmail()); + + /* + * If a user is returned by the repository, that's the email adress is used, but + * if it is not the same as the connected user, that's the email adress + * corresponds to another user. So a 409 error is sent. Otherwise, if no user is + * returned by the repository, that's the email adress is free to be used. So, + * user can change him email adress. + */ + if(userFromDb.isPresent() && !connectedUser.getEmail().equals(userFromDb.get().getEmail())) { + pResponse.sendError(HttpServletResponse.SC_CONFLICT); + } else { + connectedUser.setName(pUser.getName()); + connectedUser.setEmail(pUser.getEmail()); + + userRepository.save(connectedUser); + } + } else { + pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); + } + } } diff --git a/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.html b/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.html index cc50d1b..0113bcb 100755 --- a/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.html +++ b/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.html @@ -7,7 +7,7 @@ alt="Card image cap" mdbTooltip="Modifier mon image de profil" placement="bottom"> -
+
+ required />
@@ -32,15 +32,25 @@ #email="ngModel" data-error="Veuillez saisir votre adresse email" data-sucess="" - required disabled /> + required />
+
+
+

{{modelError}}

+
+
+
+
+

{{result}}

+
+
Annuler
diff --git a/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.ts b/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.ts index b085096..307630d 100755 --- a/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.ts +++ b/src/main/ts/src/app/account-settings/profil-edition/profil-edition.component.ts @@ -10,7 +10,7 @@ import { environment } from '../../../environments/environment'; selector: 'app-profil-edition', templateUrl: './profil-edition.component.html', styles: [` - .card-body { + #form { padding-bottom: 10px; } @@ -21,6 +21,13 @@ import { environment } from '../../../environments/environment'; #profil-image { cursor: pointer; } + + #resultMsg, #errorMsg { + max-height: 0; + overflow: hidden; + transition: max-height 0.5s ease-out; + margin: 0; + } `] }) export class ProfilEditionComponent implements OnInit { @@ -69,6 +76,24 @@ export class ProfilEditionComponent implements OnInit { } onSubmit(): void { - // TODO + this.profilEditionService.updateUser(this.model).subscribe(() => { + this.setMessage('Modification enregistrée.', false); + }, error => { + this.setMessage('L\'adresse mail saisie n\'est pas disponible.', true); + }); + } + + setMessage(message: string, error: boolean): void { + this[error ? 'modelError' : 'result'] = message; + + const resultMsgDiv = document.getElementById(error ? 'errorMsg' : 'resultMsg'); + resultMsgDiv.style.maxHeight = '64px'; + + setTimeout(() => { + resultMsgDiv.style.maxHeight = '0px'; + setTimeout(() => { + this[error ? 'modelError' : 'result'] = undefined; + }, 550); + }, 3000); } } diff --git a/src/main/ts/src/app/account-settings/profil-edition/profil-edition.service.ts b/src/main/ts/src/app/account-settings/profil-edition/profil-edition.service.ts index b5a2635..1a0e14e 100755 --- a/src/main/ts/src/app/account-settings/profil-edition/profil-edition.service.ts +++ b/src/main/ts/src/app/account-settings/profil-edition/profil-edition.service.ts @@ -2,8 +2,10 @@ import { Injectable } from '@angular/core'; import {HttpClient, HttpRequest, HttpEvent} from '@angular/common/http'; import {Observable} from 'rxjs/Observable'; import { environment } from '../../../environments/environment'; +import { User } from '../../core/entities'; const IMAGES_URL = environment.apiUrl + '/api/images'; +const ACCOUNT_URL = environment.apiUrl + '/api/account'; @Injectable() export class ProfilEditionService { @@ -21,4 +23,8 @@ export class ProfilEditionService { } )); } + + updateUser(user: User): Observable { + return this.http.put(`${ACCOUNT_URL}/`, user); + } } diff --git a/src/test/java/org/codiki/account/AccountServiceTest.java b/src/test/java/org/codiki/account/AccountServiceTest.java new file mode 100644 index 0000000..d592710 --- /dev/null +++ b/src/test/java/org/codiki/account/AccountServiceTest.java @@ -0,0 +1,125 @@ +package org.codiki.account; + +import java.io.IOException; +import java.util.Optional; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.codiki.core.entities.dto.UserDTO; +import org.codiki.core.entities.persistence.User; +import org.codiki.core.repositories.UserRepository; +import org.codiki.core.security.TokenService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class AccountServiceTest { + + @InjectMocks + private AccountService service; + + @Mock + private UserRepository repository; + + @Mock + private TokenService tokenService; + + @Mock + private HttpServletRequest request; + + @Mock + private HttpServletResponse response; + + @Before + public void before() { + MockitoAnnotations.initMocks(AccountServiceTest.class); + } + + private Optional buildUser() { + final User u = new User(); + u.setId(1L); + u.setName("name"); + u.setEmail("test@test.te"); + return Optional.of(u); + } + + @Test + public void test_updateUser_ok_diff_name() throws IOException { + final UserDTO userDto = new UserDTO(); + userDto.setName("anotherName"); + userDto.setEmail("test@test.te"); + + final Optional connectedUser = buildUser(); + final Optional userFromDb = buildUser(); + + Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser); + Mockito.when(repository.findByEmail(Mockito.anyString())).thenReturn(userFromDb); + + service.updateUser(userDto, request, response); + Mockito.verify(response, Mockito.times(0)).sendError(Mockito.anyInt()); + } + + @Test + public void test_updateUser_ok_diff_email() throws IOException { + final UserDTO userDto = new UserDTO(); + userDto.setName("name"); + userDto.setEmail("autre_adresse@test.te"); + + final Optional connectedUser = buildUser(); + final Optional userFromDb = buildUser(); + + Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser); + Mockito.when(repository.findByEmail(Mockito.anyString())).thenReturn(userFromDb); + + service.updateUser(userDto, request, response); + Mockito.verify(response, Mockito.times(0)).sendError(Mockito.anyInt()); + } + + @Test + public void test_updateUser_ok_diff_all() throws IOException { + final UserDTO userDto = new UserDTO(); + userDto.setName("anotherName"); + userDto.setEmail("another_adress@test.te"); + + final Optional connectedUser = buildUser(); + final Optional userFromDb = buildUser(); + + Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser); + Mockito.when(repository.findByEmail(Mockito.anyString())).thenReturn(userFromDb); + + service.updateUser(userDto, request, response); + Mockito.verify(response, Mockito.times(0)).sendError(Mockito.anyInt()); + } + + @Test + public void test_updateUser_error_email() throws IOException { + final UserDTO userDto = new UserDTO(); + userDto.setName("name"); + userDto.setEmail("test@test.te"); + + final Optional connectedUser = buildUser(); + final Optional userFromDb = buildUser(); + userFromDb.get().setEmail("another_adress@test.te"); + + Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser); + Mockito.when(repository.findByEmail(Mockito.anyString())).thenReturn(userFromDb); + + service.updateUser(userDto, request, response); + Mockito.verify(response, Mockito.times(1)).sendError(Mockito.anyInt()); + } + + @Test + public void test_updateUser_error_disconnected() throws IOException { + Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(Optional.empty()); + + service.updateUser(null, request, response); + Mockito.verify(response, Mockito.times(1)).sendError(Mockito.anyInt()); + } +}