NCBACK-33 #16
@@ -34,7 +34,7 @@ public class UserController {
|
|||||||
@GetMapping("/all")
|
@GetMapping("/all")
|
||||||
public ResponseEntity<List<UserDTO>> getAllUsers() {
|
public ResponseEntity<List<UserDTO>> getAllUsers() {
|
||||||
List<UserDTO> allUsers = userRepository.findAll().stream()
|
List<UserDTO> allUsers = userRepository.findAll().stream()
|
||||||
.map(u -> new UserDTO(u.getFullName(), u.getCompany(), u.getEmail(), u.getIsActive(),
|
.map(u -> new UserDTO(u.getFullName(), u.getCompany(), u.getEmail(), u.isActive(),
|
||||||
u.getPhone(), u.getGenderType(),
|
u.getPhone(), u.getGenderType(),
|
||||||
u.getBirthday(), u.getCreatedAt(), u.getSubscriptionType()))
|
u.getBirthday(), u.getCreatedAt(), u.getSubscriptionType()))
|
||||||
.toList();
|
.toList();
|
||||||
@@ -52,19 +52,19 @@ public class UserController {
|
|||||||
AuthToken authToken = tokenOptional.orElseThrow(() -> new NotFoundAuthToken("Token: " + token + "not found"));
|
AuthToken authToken = tokenOptional.orElseThrow(() -> new NotFoundAuthToken("Token: " + token + "not found"));
|
||||||
|
|
||||||
if (authToken != null) {
|
if (authToken != null) {
|
||||||
Optional<User> user = userRepository.findByEmail(email);
|
User user = userRepository.findByEmail(email);
|
||||||
//TODO add mapper
|
//TODO add mapper
|
||||||
if (user.isPresent()) {
|
if (user != null) {
|
||||||
UserDTO userDTO = userMapper.toDTO(user.get());
|
UserDTO userDTO = userMapper.toDTO(user);
|
||||||
userDTO.setEmail(email);
|
userDTO.setEmail(email);
|
||||||
userDTO.setFullName(user.get().getFullName());
|
userDTO.setFullName(user.getFullName());
|
||||||
userDTO.setCompany(user.get().getCompany());
|
userDTO.setCompany(user.getCompany());
|
||||||
userDTO.setPhone(user.get().getPhone());
|
userDTO.setPhone(user.getPhone());
|
||||||
userDTO.setGenderType(user.get().getGenderType());
|
userDTO.setGenderType(user.getGenderType());
|
||||||
userDTO.setBirthday(user.get().getBirthday());
|
userDTO.setBirthday(user.getBirthday());
|
||||||
userDTO.setCreatedAt(user.get().getCreatedAt());
|
userDTO.setCreatedAt(user.getCreatedAt());
|
||||||
userDTO.setSubscriptionType(user.get().getSubscriptionType());
|
userDTO.setSubscriptionType(user.getSubscriptionType());
|
||||||
userDTO.setActive(user.get().getIsActive());
|
userDTO.setActive(user.isActive());
|
||||||
|
|
||||||
return ResponseEntity.ok(userDTO);
|
return ResponseEntity.ok(userDTO);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ public enum MessageCode {
|
|||||||
REG_EMAIL_OR_PHONE_EXISTS(1, "Email or phone already registered"),
|
REG_EMAIL_OR_PHONE_EXISTS(1, "Email or phone already registered"),
|
||||||
INVALID_FIELD(2, "Invalid field"),
|
INVALID_FIELD(2, "Invalid field"),
|
||||||
INVALID_TOKEN(2, "Invalid token"),
|
INVALID_TOKEN(2, "Invalid token"),
|
||||||
|
TOKEN_IS_ALIVE(2, "Token is alive"),
|
||||||
INVALID_ACTION(2, "Invalid action"),
|
INVALID_ACTION(2, "Invalid action"),
|
||||||
FILE_UPLOAD_ERROR(2, "File upload error"),
|
FILE_UPLOAD_ERROR(2, "File upload error"),
|
||||||
FILE_DOWNLOAD_ERROR(2, "File download error"),
|
FILE_DOWNLOAD_ERROR(2, "File download error"),
|
||||||
|
USER_NOT_VERIFIED(2, "User not verified"),
|
||||||
FILE_DOWNLOAD_ERROR_NOT_CORRECT_FIELD(2, "Not correct field"),
|
FILE_DOWNLOAD_ERROR_NOT_CORRECT_FIELD(2, "Not correct field"),
|
||||||
IMAGE_FOUND_ERROR(2, "Image found error"),
|
IMAGE_FOUND_ERROR(2, "Image found error"),
|
||||||
INVALID_JSON_BODY(2, "Invalid fields in JSON object"),
|
INVALID_JSON_BODY(2, "Invalid fields in JSON object"),
|
||||||
|
|||||||
@@ -13,5 +13,9 @@ import java.util.Map;
|
|||||||
public class LoginAnswer {
|
public class LoginAnswer {
|
||||||
private String Token;
|
private String Token;
|
||||||
|
|
||||||
|
private boolean isActive;
|
||||||
|
|
||||||
|
private boolean isVerified;
|
||||||
|
|
||||||
private List<Map<String, String>> fieldErrors;
|
private List<Map<String, String>> fieldErrors;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,5 +13,9 @@ import java.util.Map;
|
|||||||
public class RegAnswer {
|
public class RegAnswer {
|
||||||
private String Token;
|
private String Token;
|
||||||
|
|
||||||
|
private boolean isActive;
|
||||||
|
|
||||||
|
private boolean isVerified;
|
||||||
|
|
||||||
private List<Map<String, String>> fieldErrors;
|
private List<Map<String, String>> fieldErrors;
|
||||||
}
|
}
|
||||||
@@ -14,4 +14,7 @@ public class VerifyUserRequest {
|
|||||||
|
|
||||||
@JsonProperty("user_id")
|
@JsonProperty("user_id")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
|
@JsonProperty("resend")
|
||||||
|
private Integer resend;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,4 +28,8 @@ public class EmailVerificationToken {
|
|||||||
|
|
||||||
@Column(name = "created_at", nullable = false)
|
@Column(name = "created_at", nullable = false)
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
public boolean isExpired() {
|
||||||
|
return LocalDateTime.now().isAfter(expiresAt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class User {
|
|||||||
private LocalDateTime lastLoginAt;
|
private LocalDateTime lastLoginAt;
|
||||||
|
|
||||||
@Column(name = "is_active")
|
@Column(name = "is_active")
|
||||||
private Boolean isActive = false;
|
private boolean isActive = false;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
|
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ import ru.soune.nocopy.dto.*;
|
|||||||
import ru.soune.nocopy.dto.register.LoginAnswer;
|
import ru.soune.nocopy.dto.register.LoginAnswer;
|
||||||
import ru.soune.nocopy.dto.register.LoginRequest;
|
import ru.soune.nocopy.dto.register.LoginRequest;
|
||||||
import ru.soune.nocopy.entity.user.AuthToken;
|
import ru.soune.nocopy.entity.user.AuthToken;
|
||||||
|
import ru.soune.nocopy.entity.user.User;
|
||||||
import ru.soune.nocopy.exception.NotValidFieldException;
|
import ru.soune.nocopy.exception.NotValidFieldException;
|
||||||
import ru.soune.nocopy.repository.UserRepository;
|
import ru.soune.nocopy.repository.UserRepository;
|
||||||
import ru.soune.nocopy.service.register.AuthService;
|
import ru.soune.nocopy.service.register.AuthService;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -25,8 +27,9 @@ public class LoginRequestHandler implements RequestHandler {
|
|||||||
@Override
|
@Override
|
||||||
public BaseResponse handle(BaseRequest request) {
|
public BaseResponse handle(BaseRequest request) {
|
||||||
LoginRequest loginRequest = objectMapper.convertValue(request.getMessageBody(), LoginRequest.class);
|
LoginRequest loginRequest = objectMapper.convertValue(request.getMessageBody(), LoginRequest.class);
|
||||||
|
User user = userRepository.findByEmail(loginRequest.getEmail());
|
||||||
|
|
||||||
if (!userRepository.existsByEmail(loginRequest.getEmail())) {
|
if (user != null) {
|
||||||
LoginAnswer loginAnswer = new LoginAnswer();
|
LoginAnswer loginAnswer = new LoginAnswer();
|
||||||
loginAnswer.setFieldErrors(Arrays.asList(Map.of("email", loginRequest.getEmail())));
|
loginAnswer.setFieldErrors(Arrays.asList(Map.of("email", loginRequest.getEmail())));
|
||||||
|
|
||||||
@@ -35,6 +38,17 @@ public class LoginRequestHandler implements RequestHandler {
|
|||||||
MessageCode.AUTH_EMAIL_NOT_FOUND.getDescription(), loginAnswer));
|
MessageCode.AUTH_EMAIL_NOT_FOUND.getDescription(), loginAnswer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!user.isActive() && !user.isEmailVerified()) {
|
||||||
|
LoginAnswer loginAnswer = new LoginAnswer();
|
||||||
|
|
||||||
|
loginAnswer.setFieldErrors(Arrays.asList(Map.of(
|
||||||
|
"verified", String.valueOf(user.isEmailVerified()),
|
||||||
|
"isActive", String.valueOf(user.isActive()))));
|
||||||
|
|
||||||
|
return new BaseResponse(request.getMsgId(), MessageCode.USER_NOT_VERIFIED.getCode(),
|
||||||
|
MessageCode.USER_NOT_VERIFIED.getDescription(), loginAnswer);
|
||||||
|
}
|
||||||
|
|
||||||
AuthToken authToken = authService.login(loginRequest);
|
AuthToken authToken = authService.login(loginRequest);
|
||||||
|
|
||||||
LoginAnswer loginAnswer = new LoginAnswer();
|
LoginAnswer loginAnswer = new LoginAnswer();
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ public class RegRequestHandler implements RequestHandler {
|
|||||||
|
|
||||||
RegAnswer regAnswer = new RegAnswer();
|
RegAnswer regAnswer = new RegAnswer();
|
||||||
regAnswer.setToken(authToken.getToken());
|
regAnswer.setToken(authToken.getToken());
|
||||||
|
regAnswer.setVerified(false);
|
||||||
|
regAnswer.setActive(false);
|
||||||
|
|
||||||
return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
|
return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
|
||||||
MessageCode.SUCCESS.getDescription(), regAnswer);
|
MessageCode.SUCCESS.getDescription(), regAnswer);
|
||||||
|
|||||||
@@ -11,10 +11,14 @@ import ru.soune.nocopy.dto.register.RegAnswer;
|
|||||||
import ru.soune.nocopy.dto.register.VerifyUserRequest;
|
import ru.soune.nocopy.dto.register.VerifyUserRequest;
|
||||||
import ru.soune.nocopy.entity.user.AuthToken;
|
import ru.soune.nocopy.entity.user.AuthToken;
|
||||||
import ru.soune.nocopy.entity.user.EmailVerificationToken;
|
import ru.soune.nocopy.entity.user.EmailVerificationToken;
|
||||||
|
import ru.soune.nocopy.entity.user.User;
|
||||||
import ru.soune.nocopy.exception.NotValidFieldException;
|
import ru.soune.nocopy.exception.NotValidFieldException;
|
||||||
import ru.soune.nocopy.exception.TokenNotFoundException;
|
import ru.soune.nocopy.exception.UserNotFoundException;
|
||||||
import ru.soune.nocopy.repository.AuthTokenRepository;
|
import ru.soune.nocopy.repository.AuthTokenRepository;
|
||||||
import ru.soune.nocopy.repository.EmailVerificationTokenRepository;
|
import ru.soune.nocopy.repository.EmailVerificationTokenRepository;
|
||||||
|
import ru.soune.nocopy.repository.UserRepository;
|
||||||
|
import ru.soune.nocopy.service.mail.EmailService;
|
||||||
|
import ru.soune.nocopy.service.register.AuthService;
|
||||||
import ru.soune.nocopy.service.user.UserService;
|
import ru.soune.nocopy.service.user.UserService;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -24,45 +28,91 @@ import java.util.Optional;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class VerifyRegisterUserHandler implements RequestHandler {
|
public class VerifyRegisterUserHandler implements RequestHandler {
|
||||||
|
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
private final EmailVerificationTokenRepository emailVerificationTokenRepository;
|
private final EmailVerificationTokenRepository emailVerificationTokenRepository;
|
||||||
|
|
||||||
|
private final EmailService emailService;
|
||||||
|
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
|
|
||||||
private final AuthTokenRepository authTokenRepository;
|
private final AuthTokenRepository authTokenRepository;
|
||||||
|
|
||||||
|
private final AuthService authService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseResponse handle(BaseRequest request) {
|
public BaseResponse handle(BaseRequest request) {
|
||||||
VerifyUserRequest verifyUserRequest = objectMapper.convertValue(request.getMessageBody(),
|
VerifyUserRequest verifyUserRequest = objectMapper.convertValue(request.getMessageBody(), VerifyUserRequest.class);
|
||||||
VerifyUserRequest.class);
|
|
||||||
|
|
||||||
String verifyToken = verifyUserRequest.getVerifyToken();
|
|
||||||
Long userId = verifyUserRequest.getUserId();
|
Long userId = verifyUserRequest.getUserId();
|
||||||
|
|
||||||
EmailVerificationToken emailVerificationToken =
|
User user = userRepository.findById(userId)
|
||||||
emailVerificationTokenRepository.findByUserIdAndToken(userId, verifyToken);
|
.orElseThrow(() -> new UserNotFoundException("User not found with id: " + userId));
|
||||||
|
|
||||||
if (emailVerificationToken == null) {
|
Optional<AuthToken> userAuthTokens = authTokenRepository.findByUserIdAndIsActive(userId, false);
|
||||||
throw new NotValidFieldException("Token was incorrected:" + verifyToken,
|
|
||||||
new BaseResponse(request.getMsgId(), MessageCode.INVALID_TOKEN.getCode(),
|
AuthToken authToken = userAuthTokens.isEmpty() ? authService.generateAuthToken(user): userAuthTokens.get();
|
||||||
MessageCode.INVALID_TOKEN.getDescription(), Map.of(
|
|
||||||
"userId", userId,
|
if (verifyUserRequest.getResend() != null && verifyUserRequest.getResend() == 1) {
|
||||||
"token", verifyToken)));
|
return handleResend(request, user, authToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
userService.activateAndVerifyUser(userId);
|
return handleVerify(request, user, authToken, verifyUserRequest.getVerifyToken());
|
||||||
emailVerificationTokenRepository.delete(emailVerificationToken);
|
}
|
||||||
|
|
||||||
Optional<AuthToken> byUserIdAndIsActive = authTokenRepository.findByUserIdAndIsActive(userId, true);
|
private BaseResponse handleResend(BaseRequest request, User user, AuthToken authToken) {
|
||||||
AuthToken authToken = byUserIdAndIsActive.orElseThrow(() ->
|
|
||||||
new TokenNotFoundException("Token not found with user id: " + userId));
|
EmailVerificationToken token = emailVerificationTokenRepository.findByUserId(user.getId());
|
||||||
|
|
||||||
|
if (token != null && !token.isExpired()) {
|
||||||
|
emailService.sendVerificationEmail(user, token.getToken());
|
||||||
|
|
||||||
|
log.info("Verification token resent for user {}", user.getEmail());
|
||||||
|
return successResponse(request, authToken, "Verification code has been resent", false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token != null) {
|
||||||
|
emailVerificationTokenRepository.delete(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
EmailVerificationToken newToken = emailService.createEmailVerificationToken(authToken);
|
||||||
|
|
||||||
|
emailService.sendVerificationEmail(user, newToken.getToken());
|
||||||
|
|
||||||
|
log.info("New verification token generated for user {}", user.getEmail());
|
||||||
|
|
||||||
|
return successResponse(request, authToken, "New verification code has been sent",
|
||||||
|
false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private BaseResponse handleVerify(BaseRequest request, User user, AuthToken authToken, String providedToken) {
|
||||||
|
|
||||||
|
EmailVerificationToken token = emailVerificationTokenRepository.findByUserIdAndToken(user.getId(), providedToken);
|
||||||
|
|
||||||
|
if (token == null || token.isExpired()) {
|
||||||
|
throw new NotValidFieldException("Invalid or expired token",
|
||||||
|
new BaseResponse(request.getMsgId(), MessageCode.INVALID_TOKEN.getCode(),
|
||||||
|
MessageCode.INVALID_TOKEN.getDescription(), Map.of("userId", user.getId())));
|
||||||
|
}
|
||||||
|
|
||||||
|
User updateUser = userService.activateAndVerifyUser(user.getId());
|
||||||
|
emailVerificationTokenRepository.delete(token);
|
||||||
|
|
||||||
|
return successResponse(request, authToken, MessageCode.SUCCESS.getDescription(), updateUser.isActive(),
|
||||||
|
updateUser.isEmailVerified());
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaseResponse successResponse(BaseRequest request, AuthToken authToken, String message, boolean isActive,
|
||||||
|
boolean isVerified) {
|
||||||
|
|
||||||
RegAnswer regAnswer = new RegAnswer();
|
RegAnswer regAnswer = new RegAnswer();
|
||||||
regAnswer.setToken(authToken.getToken());
|
regAnswer.setToken(authToken.getToken());
|
||||||
|
regAnswer.setVerified(isVerified);
|
||||||
|
regAnswer.setActive(isActive);
|
||||||
|
|
||||||
return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
|
return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), message, regAnswer);
|
||||||
MessageCode.SUCCESS.getDescription(), regAnswer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,4 +11,5 @@ public interface EmailVerificationTokenRepository extends JpaRepository<EmailVer
|
|||||||
Optional<EmailVerificationToken> findByToken(String token);
|
Optional<EmailVerificationToken> findByToken(String token);
|
||||||
EmailVerificationToken findByUserIdAndToken(Long userId, String token);
|
EmailVerificationToken findByUserIdAndToken(Long userId, String token);
|
||||||
List<EmailVerificationToken> findByExpiresAtBefore(LocalDateTime expiresAtBefore);
|
List<EmailVerificationToken> findByExpiresAtBefore(LocalDateTime expiresAtBefore);
|
||||||
|
EmailVerificationToken findByUserId(Long userId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import ru.soune.nocopy.entity.user.User;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface UserRepository extends JpaRepository<User, Long> {
|
public interface UserRepository extends JpaRepository<User, Long> {
|
||||||
Optional<User> findByEmail(String email);
|
User findByEmail(String email);
|
||||||
boolean existsByEmail(String email);
|
boolean existsByEmail(String email);
|
||||||
boolean existsByPhone(@Size(min = 11, max = 14) String phone);
|
boolean existsByPhone(@Size(min = 11, max = 14) String phone);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,17 +50,14 @@ public class AuthService {
|
|||||||
|
|
||||||
User savedUser = userRepository.save(user);
|
User savedUser = userRepository.save(user);
|
||||||
|
|
||||||
AuthToken authToken = new AuthToken();
|
AuthToken authToken = genereateAuthToken(savedUser);
|
||||||
authToken.setToken(generateAuthToken());
|
|
||||||
authToken.setUser(savedUser);
|
|
||||||
|
|
||||||
return authTokenRepository.save(authToken);
|
return authTokenRepository.save(authToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public AuthToken login(LoginRequest request) {
|
public AuthToken login(LoginRequest request) {
|
||||||
Optional<User> userOpt = userRepository.findByEmail(request.getEmail());
|
User user = userRepository.findByEmail(request.getEmail());
|
||||||
User user = userOpt.get();
|
|
||||||
|
|
||||||
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
|
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
|
||||||
LoginAnswer loginAnswer = new LoginAnswer();
|
LoginAnswer loginAnswer = new LoginAnswer();
|
||||||
@@ -87,6 +84,18 @@ public class AuthService {
|
|||||||
.ifPresent(authTokenRepository::delete);
|
.ifPresent(authTokenRepository::delete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AuthToken generateAuthToken(User user) {
|
||||||
|
return authTokenRepository.save(genereateAuthToken(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuthToken genereateAuthToken(User user) {
|
||||||
|
AuthToken authToken = new AuthToken();
|
||||||
|
authToken.setToken(generateAuthToken());
|
||||||
|
authToken.setUser(user);
|
||||||
|
|
||||||
|
return authToken;
|
||||||
|
}
|
||||||
|
|
||||||
private String generateAuthToken() {
|
private String generateAuthToken() {
|
||||||
byte[] bytes = new byte[32];
|
byte[] bytes = new byte[32];
|
||||||
secureRandom.nextBytes(bytes);
|
secureRandom.nextBytes(bytes);
|
||||||
|
|||||||
@@ -47,13 +47,13 @@ public class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void activateAndVerifyUser(long userId) {
|
public User activateAndVerifyUser(long userId) {
|
||||||
Optional<User> users = userRepository.findById(userId);
|
Optional<User> users = userRepository.findById(userId);
|
||||||
User user = users.orElseThrow(() -> new UserNotFoundException("User not found with id: " + userId));
|
User user = users.orElseThrow(() -> new UserNotFoundException("User not found with id: " + userId));
|
||||||
user.setIsActive(true);
|
user.setActive(true);
|
||||||
user.setEmailVerified(true);
|
user.setEmailVerified(true);
|
||||||
|
|
||||||
userRepository.save(user);
|
return userRepository.save(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateUserFromRequest(User user, UserRequest request) {
|
private void updateUserFromRequest(User user, UserRequest request) {
|
||||||
|
|||||||
Reference in New Issue
Block a user