diff --git a/core/src/main/java/space/shefer/receipt/platform/core/entity/UserProfile.java b/core/src/main/java/space/shefer/receipt/platform/core/entity/UserProfile.java index 6d066cf..f4f953b 100644 --- a/core/src/main/java/space/shefer/receipt/platform/core/entity/UserProfile.java +++ b/core/src/main/java/space/shefer/receipt/platform/core/entity/UserProfile.java @@ -26,6 +26,12 @@ public class UserProfile extends BaseUuidIdEntity { @Column(name = "access_token") private String accessToken; + @Column(name = "name") + private String name; + + @Column(name = "email") + private String email; + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/dto/FnsLoginResponse.kt b/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/dto/FnsLoginResponse.kt new file mode 100644 index 0000000..af647e9 --- /dev/null +++ b/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/dto/FnsLoginResponse.kt @@ -0,0 +1,9 @@ +package space.shefer.receipt.fnssdk.dto + + +class FnsLoginResponse { + + lateinit var email: String + lateinit var name: String + +} diff --git a/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/excepion/FnsException.kt b/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/excepion/FnsException.kt index aa30dab..6124a84 100644 --- a/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/excepion/FnsException.kt +++ b/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/excepion/FnsException.kt @@ -11,3 +11,23 @@ class ReceiptNotFoundException(val fn: String, val fd: String, val fp: String) @ResponseStatus(code = HttpStatus.FORBIDDEN) class AuthorizationFailedException(login: String, cause: Throwable? = null) : FnsException("Login with phone $login failed", cause) + +@ResponseStatus(code = HttpStatus.CONFLICT) +class UserAlreadyExistsException(userName: String) + : FnsException("This user $userName exists") + +@ResponseStatus(code = HttpStatus.BAD_REQUEST) +class IncorrectEmailException(email: String) + : FnsException("Object didn't pass validation for format email: $email") + +@ResponseStatus(code = HttpStatus.BAD_REQUEST) +class IncorrectPhoneException(phone: String) + : FnsException("Phone $phone is incorrect") + +@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR) +class UnexpectedHttpException() + : FnsException("Unexpected error") + +@ResponseStatus(code = HttpStatus.NOT_FOUND) +class ErrorToken() + : FnsException("Token not found") diff --git a/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/service/ResponseErrorHandleFNS.kt b/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/service/ResponseErrorHandleFNS.kt new file mode 100644 index 0000000..8d0f01b --- /dev/null +++ b/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/service/ResponseErrorHandleFNS.kt @@ -0,0 +1,17 @@ +package space.shefer.receipt.fnssdk.service + +import org.springframework.http.client.ClientHttpResponse +import org.springframework.web.client.ResponseErrorHandler +import java.io.IOException + +class ResponseErrorHandleFNS : ResponseErrorHandler { + + @Throws(IOException::class) + override fun handleError(httpResponse: ClientHttpResponse) { + + } + + override fun hasError(response: ClientHttpResponse): Boolean { + return false + } +} diff --git a/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/webclient/FnsReceiptWebClient.kt b/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/webclient/FnsReceiptWebClient.kt index 6a0ced2..420fe8e 100644 --- a/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/webclient/FnsReceiptWebClient.kt +++ b/fns-sdk/src/main/kotlin/space/shefer/receipt/fnssdk/webclient/FnsReceiptWebClient.kt @@ -9,7 +9,9 @@ import org.springframework.stereotype.Component import org.springframework.web.client.HttpClientErrorException import org.springframework.web.client.HttpServerErrorException import org.springframework.web.client.RestTemplate -import space.shefer.receipt.fnssdk.excepion.AuthorizationFailedException +import space.shefer.receipt.fnssdk.dto.FnsLoginResponse +import space.shefer.receipt.fnssdk.excepion.* +import space.shefer.receipt.fnssdk.service.ResponseErrorHandleFNS import java.net.URI import java.util.* @@ -46,7 +48,6 @@ class FnsReceiptWebClient { return null } - fun getReceiptExists(fn: String, fd: String, fp: String, time: String, money: Float): Boolean { val moneyForUrl: Int = (money * 100).toInt() val uri = "$HOST/v1/ofds/*/inns/*/fss/$fn/operations/1/tickets/$fd?fiscalSign=$fp&date=$time&sum=$moneyForUrl" @@ -66,7 +67,6 @@ class FnsReceiptWebClient { throw e } - return responseEntity.statusCode == HttpStatus.NO_CONTENT } @@ -84,25 +84,42 @@ class FnsReceiptWebClient { fun signUp(email: String, name: String, phone: String) { val headers = HttpHeaders() headers.add("Content-Type", "application/json; charset=UTF-8") - RestTemplate().exchange( + val restTemplate = RestTemplate() + restTemplate.errorHandler = ResponseErrorHandleFNS() + val responseEntity = restTemplate.exchange( URI("$HOST/v1/mobile/users/signup"), HttpMethod.POST, HttpEntity("""{"email":"$email","name":"$name","phone":"$phone"}""", headers), String::class.java ) + if (responseEntity.statusCode == HttpStatus.NO_CONTENT) { + return + } + if (responseEntity.statusCode == HttpStatus.CONFLICT && responseEntity.body.toString() == "user exists") { + throw UserAlreadyExistsException(name); + } else if (responseEntity.statusCode == HttpStatus.BAD_REQUEST + && responseEntity.body.toString().contains("Object didn't pass validation for format email")) { + throw IncorrectEmailException(email); + } else if (responseEntity.statusCode == HttpStatus.INTERNAL_SERVER_ERROR + && responseEntity.body.toString() == "failed with code 20101") { + throw IncorrectPhoneException(phone) + } else { + throw UnexpectedHttpException() + } + } - fun login(login: String, password: String) { + fun login(phone: String, password: String): FnsLoginResponse? { val headers = HttpHeaders() headers.add("Content-Type", "application/json; charset=UTF-8") headers.add("Authorization", getAuthHeader(login, password)) try { - RestTemplate().exchange( + return RestTemplate().exchange( URI("$HOST/v1/mobile/users/login"), HttpMethod.GET, HttpEntity(headers), - String::class.java - ) + FnsLoginResponse::class.java + ).body } catch (e: HttpClientErrorException.Forbidden) { throw AuthorizationFailedException(login, e) } diff --git a/rest-api/src/main/java/space/shefer/receipt/rest/controller/UserController.java b/rest-api/src/main/java/space/shefer/receipt/rest/controller/UserController.java index a27f447..076dc51 100644 --- a/rest-api/src/main/java/space/shefer/receipt/rest/controller/UserController.java +++ b/rest-api/src/main/java/space/shefer/receipt/rest/controller/UserController.java @@ -1,17 +1,26 @@ package space.shefer.receipt.rest.controller; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.lang.Nullable; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.HttpClientErrorException; +import space.shefer.receipt.fnssdk.excepion.ErrorToken; import space.shefer.receipt.fnssdk.webclient.FnsReceiptWebClient; import space.shefer.receipt.platform.core.entity.UserProfile; import space.shefer.receipt.platform.core.service.UserProfileService; import space.shefer.receipt.rest.dto.UserLoginDto; import space.shefer.receipt.rest.dto.UserPasswordRestoreDto; import space.shefer.receipt.rest.dto.UserSignUpDto; +import space.shefer.receipt.rest.service.FnsUserService; +import org.springframework.web.client.HttpClientErrorException; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; @RestController @@ -19,23 +28,33 @@ public class UserController { private final FnsReceiptWebClient fnsReceiptWebClient; private final UserProfileService userProfileService; + private final FnsUserService fnsUserService; @Autowired - public UserController(FnsReceiptWebClient fnsReceiptWebClient, UserProfileService userProfileService) { + public UserController(FnsReceiptWebClient fnsReceiptWebClient, UserProfileService userProfileService, FnsUserService fnsUserService) { this.fnsReceiptWebClient = fnsReceiptWebClient; this.userProfileService = userProfileService; + this.fnsUserService = fnsUserService; } @RequestMapping(value = "/login", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE) public String login(@RequestBody UserLoginDto userLoginDto) { - fnsReceiptWebClient.login(userLoginDto.getPhone(), userLoginDto.getPassword()); + fnsUserService.login(userLoginDto); UserProfile userProfile = userProfileService.createOrUpdate(userLoginDto.getPhone(), userLoginDto.getPassword()); return userProfile.getAccessToken(); } @RequestMapping(value = "/signUp", method = RequestMethod.POST) public void signUp(@RequestBody UserSignUpDto userSignUpDto) { - fnsReceiptWebClient.signUp(userSignUpDto.getEmail(), userSignUpDto.getName(), userSignUpDto.getPhone()); + fnsUserService.signUp(userSignUpDto); + } + + @RequestMapping(value = "/users/me", method = RequestMethod.GET) + public UserSignUpDto getInfoByToken(@Nullable @RequestHeader("Authorization") String authHeader) { + if (authHeader != null) { + return fnsUserService.getUserByToken(getTokenFromAuthHeader(authHeader)); + } + throw new ErrorToken(); } @RequestMapping(value = "/passwordRestore", method = RequestMethod.POST) @@ -43,5 +62,8 @@ public void passwordRestore(@RequestBody UserPasswordRestoreDto userPasswordRest fnsReceiptWebClient.passwordRestore(userPasswordRestoreDto.getPhone()); } + public String getTokenFromAuthHeader(String authHeader) { + return authHeader.substring(authHeader.indexOf(" ") + 1); + } } diff --git a/rest-api/src/main/java/space/shefer/receipt/rest/service/FnsUserService.java b/rest-api/src/main/java/space/shefer/receipt/rest/service/FnsUserService.java new file mode 100644 index 0000000..984781f --- /dev/null +++ b/rest-api/src/main/java/space/shefer/receipt/rest/service/FnsUserService.java @@ -0,0 +1,62 @@ +package space.shefer.receipt.rest.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import space.shefer.receipt.fnssdk.dto.FnsLoginResponse; +import space.shefer.receipt.fnssdk.webclient.FnsReceiptWebClient; +import space.shefer.receipt.platform.core.entity.UserProfile; +import space.shefer.receipt.platform.core.repository.UserProfileRepository; +import space.shefer.receipt.rest.dto.UserLoginDto; +import space.shefer.receipt.rest.dto.UserSignUpDto; + +@Service +public class FnsUserService { + + private final UserProfileRepository userProfileRepository; + private final FnsReceiptWebClient fnsReceiptWebClient; + + @Autowired + public FnsUserService(UserProfileRepository userProfileRepository, FnsReceiptWebClient fnsReceiptWebClient) { + this.userProfileRepository = userProfileRepository; + this.fnsReceiptWebClient = fnsReceiptWebClient; + } + + public void signUp(UserSignUpDto userSignUpDto) { + fnsReceiptWebClient.signUp(userSignUpDto.getEmail(), userSignUpDto.getName(), userSignUpDto.getPhone()); + } + + public UserSignUpDto getUserByToken(String authHeader) { + UserProfile userProfile = userProfileRepository.getByAccessToken(authHeader); + if (userProfile == null) { + return null; + } + UserSignUpDto userSignUpDto = new UserSignUpDto(); + userSignUpDto.setEmail(userProfile.getEmail()); + userSignUpDto.setName(userProfile.getName()); + userSignUpDto.setPhone(userProfile.getPhone()); + return userSignUpDto; + } + + public void login(UserLoginDto userLoginDto) { + FnsLoginResponse responseEntity = fnsReceiptWebClient.login(userLoginDto.getPhone(), userLoginDto.getPassword()); + if (responseEntity != null) { + UserProfile userProfile = userProfileRepository.getByPhone(userLoginDto.getPhone()); + if (userProfile != null) { + if (!userProfile.getEmail().equals(responseEntity.email) || (!userProfile.getName().equals(responseEntity.name))) { + userProfile.setName(responseEntity.getName()); + userProfile.setEmail(responseEntity.getEmail()); + userProfileRepository.save(userProfile); + } + } + else { + UserProfile newUserProfile = new UserProfile(); + newUserProfile.setPhone(userLoginDto.getPhone()); + newUserProfile.setEmail(responseEntity.email); + newUserProfile.setName(responseEntity.name); + newUserProfile.setPassword(userLoginDto.getPassword()); + userProfileRepository.save(newUserProfile); + } + } + } + +}