@@ -19,12 +19,11 @@ import ru.soune.nocopy.dto.file.ChunkUploadResponse;
|
||||
import ru.soune.nocopy.dto.file.CompleteUploadResponse;
|
||||
import ru.soune.nocopy.dto.file.FileEntityResponse;
|
||||
import ru.soune.nocopy.dto.file.UploadProgress;
|
||||
import ru.soune.nocopy.entity.user.AuthToken;
|
||||
import ru.soune.nocopy.entity.file.FileStatus;
|
||||
import ru.soune.nocopy.entity.file.UploadStatus;
|
||||
import ru.soune.nocopy.exception.*;
|
||||
import ru.soune.nocopy.handler.*;
|
||||
import ru.soune.nocopy.service.auth.AuthService;
|
||||
import ru.soune.nocopy.service.register.AuthService;
|
||||
import ru.soune.nocopy.service.file.FileEntityService;
|
||||
import ru.soune.nocopy.service.file.FileUploadService;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import ru.soune.nocopy.dto.BaseResponse;
|
||||
import ru.soune.nocopy.dto.MessageCode;
|
||||
import ru.soune.nocopy.dto.TokenProcessRequest;
|
||||
import ru.soune.nocopy.exception.NotFoundAuthToken;
|
||||
import ru.soune.nocopy.service.auth.AuthService;
|
||||
import ru.soune.nocopy.service.register.AuthService;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import ru.soune.nocopy.exception.*;
|
||||
import ru.soune.nocopy.handler.validator.FileUploadRequestValidator;
|
||||
import ru.soune.nocopy.repository.AuthTokenRepository;
|
||||
import ru.soune.nocopy.repository.FileUploadSessionRepository;
|
||||
import ru.soune.nocopy.service.auth.AuthService;
|
||||
import ru.soune.nocopy.service.register.AuthService;
|
||||
import ru.soune.nocopy.service.file.FileUploadService;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -33,16 +33,16 @@ public class LogoutRequestHandler implements RequestHandler {
|
||||
LogoutRequest logoutRequest = objectMapper.convertValue(request.getMessageBody(), LogoutRequest.class);
|
||||
|
||||
Optional<AuthToken> opToken = authTokenRepository.findByToken(logoutRequest.getToken());
|
||||
Optional<User> user = userRepository.findByEmail(logoutRequest.getEmail());
|
||||
User user = userRepository.findByEmail(logoutRequest.getEmail());
|
||||
|
||||
if (opToken.isEmpty() || user.isEmpty()) {
|
||||
if (opToken.isEmpty() || user == null) {
|
||||
throw new NotValidFieldException("User with email or token not found",
|
||||
new BaseResponse(request.getMsgId(), MessageCode.AUTH_EMAIL_OR_TOKEN_NOT_FOUND.getCode(),
|
||||
MessageCode.AUTH_EMAIL_OR_TOKEN_NOT_FOUND.getDescription(),
|
||||
new LogoutRequest(logoutRequest.getEmail(), logoutRequest.getToken())));
|
||||
}
|
||||
|
||||
if (!Objects.equals(opToken.get().getUser().getId(), user.get().getId())) {
|
||||
if (!Objects.equals(opToken.get().getUser().getId(), user.getId())) {
|
||||
throw new NotValidFieldException("User token mismatch with user",
|
||||
new BaseResponse(request.getMsgId(), MessageCode.AUTH_TOKEN_MISMATCH.getCode(),
|
||||
MessageCode.AUTH_TOKEN_MISMATCH.getDescription(),
|
||||
|
||||
@@ -51,7 +51,7 @@ public class VerifyRegisterUserHandler implements RequestHandler {
|
||||
User user = userRepository.findById(userId)
|
||||
.orElseThrow(() -> new UserNotFoundException("User not found with id: " + userId));
|
||||
|
||||
Optional<AuthToken> userAuthTokens = authTokenRepository.findByUserIdAndIsActive(userId, false);
|
||||
Optional<AuthToken> userAuthTokens = authTokenRepository.findByUserId(userId);
|
||||
|
||||
AuthToken authToken = userAuthTokens.isEmpty() ? authService.generateAuthToken(user): userAuthTokens.get();
|
||||
|
||||
|
||||
@@ -14,4 +14,5 @@ public interface AuthTokenRepository extends JpaRepository<AuthToken, Long> {
|
||||
Optional<AuthToken> findByLastUsedAtBefore(LocalDateTime lastUsedAt);
|
||||
Optional<AuthToken> findByToken(String token);
|
||||
Optional<AuthToken> findByUserIdAndIsActive(Long userId, boolean isActive);
|
||||
Optional<AuthToken> findByUserId(Long userId);
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
package ru.soune.nocopy.service.register;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.soune.nocopy.dto.*;
|
||||
import ru.soune.nocopy.dto.register.LoginAnswer;
|
||||
import ru.soune.nocopy.dto.register.LoginRequest;
|
||||
import ru.soune.nocopy.dto.register.RegRequest;
|
||||
import ru.soune.nocopy.entity.user.AuthToken;
|
||||
import ru.soune.nocopy.entity.user.User;
|
||||
import ru.soune.nocopy.exception.NotValidFieldException;
|
||||
import ru.soune.nocopy.repository.AuthTokenRepository;
|
||||
import ru.soune.nocopy.repository.UserRepository;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AuthService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
private final AuthTokenRepository authTokenRepository;
|
||||
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
private final SecureRandom secureRandom = new SecureRandom();
|
||||
|
||||
@Transactional
|
||||
public AuthToken register(RegRequest registerRequest) {
|
||||
User user = new User();
|
||||
user.setFullName(registerRequest.getFullName());
|
||||
user.setEmail(registerRequest.getEmail());
|
||||
user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
|
||||
|
||||
if (registerRequest.getCompanyName() != null) {
|
||||
user.setCompany(registerRequest.getCompanyName());
|
||||
}
|
||||
|
||||
if (registerRequest.getPhone() != null) {
|
||||
user.setPhone(registerRequest.getPhone());
|
||||
}
|
||||
|
||||
User savedUser = userRepository.save(user);
|
||||
|
||||
AuthToken authToken = genereateAuthToken(savedUser);
|
||||
|
||||
return authTokenRepository.save(authToken);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public AuthToken login(LoginRequest request) {
|
||||
User user = userRepository.findByEmail(request.getEmail());
|
||||
|
||||
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
|
||||
LoginAnswer loginAnswer = new LoginAnswer();
|
||||
loginAnswer.setFieldErrors(Arrays.asList(Map.of("password", request.getPassword())));
|
||||
|
||||
throw new NotValidFieldException("Invalid password", new BaseResponse(20003,
|
||||
MessageCode.AUTH_PASSWORD_NOT_MATCHES.getCode(),
|
||||
MessageCode.AUTH_PASSWORD_NOT_MATCHES.getDescription(), loginAnswer));
|
||||
}
|
||||
|
||||
user.setLastLoginAt(LocalDateTime.now());
|
||||
User savedUser = userRepository.save(user);
|
||||
|
||||
AuthToken authToken = new AuthToken();
|
||||
authToken.setToken(generateAuthToken());
|
||||
authToken.setUser(savedUser);
|
||||
|
||||
return authTokenRepository.save(authToken);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void logout(String token) {
|
||||
authTokenRepository.findByToken(token)
|
||||
.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() {
|
||||
byte[] bytes = new byte[32];
|
||||
secureRandom.nextBytes(bytes);
|
||||
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.soune.nocopy.entity.AuthToken;
|
||||
import ru.soune.nocopy.entity.user.AuthToken;
|
||||
import ru.soune.nocopy.repository.AuthTokenRepository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package ru.soune.nocopy.service.register;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.soune.nocopy.dto.*;
|
||||
import ru.soune.nocopy.dto.register.LoginAnswer;
|
||||
import ru.soune.nocopy.dto.register.LoginRequest;
|
||||
import ru.soune.nocopy.dto.register.RegRequest;
|
||||
import ru.soune.nocopy.entity.user.AuthToken;
|
||||
import ru.soune.nocopy.entity.user.User;
|
||||
import ru.soune.nocopy.exception.NotFoundAuthToken;
|
||||
import ru.soune.nocopy.exception.NotValidFieldException;
|
||||
import ru.soune.nocopy.repository.AuthTokenRepository;
|
||||
import ru.soune.nocopy.repository.UserRepository;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AuthService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
private final AuthTokenRepository authTokenRepository;
|
||||
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
private final SecureRandom secureRandom = new SecureRandom();
|
||||
|
||||
@Transactional
|
||||
public AuthToken register(RegRequest registerRequest) {
|
||||
User user = new User();
|
||||
user.setFullName(registerRequest.getFullName());
|
||||
user.setEmail(registerRequest.getEmail());
|
||||
user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
|
||||
|
||||
if (registerRequest.getCompanyName() != null) {
|
||||
user.setCompany(registerRequest.getCompanyName());
|
||||
}
|
||||
|
||||
if (registerRequest.getPhone() != null) {
|
||||
user.setPhone(registerRequest.getPhone());
|
||||
}
|
||||
|
||||
User savedUser = userRepository.save(user);
|
||||
|
||||
AuthToken authToken = genereateAuthToken(savedUser);
|
||||
|
||||
return authTokenRepository.save(authToken);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long useUserAuthToken(String token) {
|
||||
if (token == null || token.isBlank()) {
|
||||
throw new NotFoundAuthToken("Token is required");
|
||||
}
|
||||
|
||||
if (token.startsWith("Bearer ")) {
|
||||
token = token.replace("Bearer ", "");
|
||||
}
|
||||
|
||||
AuthToken authToken = authTokenRepository.findByToken(token)
|
||||
.orElseThrow(() -> new NotFoundAuthToken("Token not found"));
|
||||
authToken.setLastUsedAt(LocalDateTime.now());
|
||||
authToken.setExpiresAt(LocalDateTime.now().plusHours(1));
|
||||
|
||||
authTokenRepository.save(authToken);
|
||||
|
||||
return authToken.getUser().getId();
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public AuthToken login(LoginRequest request) {
|
||||
User user = userRepository.findByEmail(request.getEmail());
|
||||
|
||||
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
|
||||
LoginAnswer loginAnswer = new LoginAnswer();
|
||||
loginAnswer.setFieldErrors(Arrays.asList(Map.of("password", request.getPassword())));
|
||||
|
||||
throw new NotValidFieldException("Invalid password", new BaseResponse(20003,
|
||||
MessageCode.AUTH_PASSWORD_NOT_MATCHES.getCode(),
|
||||
MessageCode.AUTH_PASSWORD_NOT_MATCHES.getDescription(), loginAnswer));
|
||||
}
|
||||
|
||||
user.setLastLoginAt(LocalDateTime.now());
|
||||
User savedUser = userRepository.save(user);
|
||||
|
||||
AuthToken authToken = new AuthToken();
|
||||
authToken.setToken(generateAuthToken());
|
||||
authToken.setUser(savedUser);
|
||||
|
||||
return authTokenRepository.save(authToken);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void logout(String token) {
|
||||
authTokenRepository.findByToken(token)
|
||||
.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() {
|
||||
byte[] bytes = new byte[32];
|
||||
secureRandom.nextBytes(bytes);
|
||||
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
package ru.soune.nocopy.service.user;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.soune.nocopy.dto.user.UserContentRequest;
|
||||
import ru.soune.nocopy.dto.user.UserContentUpdateRequest;
|
||||
import ru.soune.nocopy.entity.file.FileType;
|
||||
import ru.soune.nocopy.entity.user.User;
|
||||
import ru.soune.nocopy.entity.user.UserContent;
|
||||
import ru.soune.nocopy.exception.ContentNotFoundException;
|
||||
import ru.soune.nocopy.exception.UserNotFoundException;
|
||||
import ru.soune.nocopy.mapper.UserContentMapper;
|
||||
import ru.soune.nocopy.repository.UserContentRepository;
|
||||
import ru.soune.nocopy.repository.UserRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class UserContentService {
|
||||
|
||||
private final UserContentRepository userContentRepository;
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
private final UserContentMapper userContentMapper;
|
||||
|
||||
public List<UserContent> findByUser(long userId) {
|
||||
return userContentRepository.findByUserId(userId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public UserContent addUserContent(UserContentRequest userContentRequest) {
|
||||
UserContent userContent = new UserContent();
|
||||
|
||||
Optional<User> byEmail = userRepository.findByEmail(userContentRequest.userEmail());
|
||||
User user = byEmail.orElseThrow(() -> new UserNotFoundException(userContentRequest.userEmail()));
|
||||
|
||||
userContent.setUser(user);
|
||||
userContent.setFilename(userContentRequest.fileName());
|
||||
userContent.setFileExtension(userContentRequest.fileExtension());
|
||||
userContent.setFilePath(userContentRequest.filePath());
|
||||
userContent.setFileType(FileType.valueOf(userContentRequest.fileType()));
|
||||
userContent.setOriginalFilename(userContentRequest.originalFilename());
|
||||
userContent.setProtectionLevel(userContentRequest.protectionLevel());
|
||||
userContent.setFileSize(userContentRequest.fileSize());
|
||||
|
||||
//TODO add
|
||||
// @Column(name = "protection_hash", length = 64)
|
||||
// private String protectionHash;
|
||||
// @Column(name = "watermark_id", length = 50)
|
||||
// private String watermarkId;
|
||||
|
||||
return userContentRepository.save(userContent);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public UserContent updateUserContent(UserContentUpdateRequest userContentRequest) {
|
||||
UserContent entity = userContentRepository.findById(userContentRequest.id())
|
||||
.orElseThrow(() -> new ContentNotFoundException("Content not found with: " + userContentRequest.id()));
|
||||
|
||||
userContentMapper.updateEntityFromDto(userContentRequest, entity);
|
||||
|
||||
return userContentRepository.save(entity);
|
||||
}
|
||||
|
||||
public void deleteUserContent(long userContentId) {
|
||||
userContentRepository.deleteById(userContentId);
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package ru.soune.nocopy.service;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import ru.soune.nocopy.dto.register.LoginRequest;
|
||||
import ru.soune.nocopy.entity.user.AuthToken;
|
||||
import ru.soune.nocopy.entity.user.User;
|
||||
import ru.soune.nocopy.exception.NotValidationPasswordException;
|
||||
import ru.soune.nocopy.exception.UserNotFoundException;
|
||||
import ru.soune.nocopy.repository.AuthTokenRepository;
|
||||
import ru.soune.nocopy.repository.UserRepository;
|
||||
import ru.soune.nocopy.service.register.AuthService;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class AuthServiceTest {
|
||||
|
||||
@Mock
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Mock
|
||||
private AuthTokenRepository authTokenRepository;
|
||||
|
||||
@Mock
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Mock
|
||||
private MessageSource messageSource;
|
||||
|
||||
@InjectMocks
|
||||
private AuthService authService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
void login_success() {
|
||||
LoginRequest request = new LoginRequest("test@mail.com", "password");
|
||||
|
||||
User user = new User();
|
||||
user.setId(1L);
|
||||
user.setEmail("test@mail.com");
|
||||
user.setPassword("encoded_pass");
|
||||
|
||||
when(userRepository.findByEmail("test@mail.com"))
|
||||
.thenReturn(Optional.of(user));
|
||||
when(passwordEncoder.matches("password", "encoded_pass"))
|
||||
.thenReturn(true);
|
||||
when(authTokenRepository.save(any(AuthToken.class)))
|
||||
.thenAnswer(invocation -> invocation.getArgument(0));
|
||||
|
||||
AuthToken token = authService.login(request);
|
||||
|
||||
assertNotNull(token);
|
||||
assertNotNull(token.getToken());
|
||||
// assertEquals(user.getTokens().get(0), token.getUser());
|
||||
|
||||
ArgumentCaptor<AuthToken> captor = ArgumentCaptor.forClass(AuthToken.class);
|
||||
verify(authTokenRepository).save(captor.capture());
|
||||
|
||||
// assertEquals(user, captor.getValue().getUser());
|
||||
assertNotNull(captor.getValue().getToken());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void login_userNotFound() {
|
||||
LoginRequest request = new LoginRequest("missing@mail.com", "pwd");
|
||||
|
||||
when(userRepository.findByEmail("missing@mail.com")).thenReturn(Optional.empty());
|
||||
|
||||
assertThrows(UserNotFoundException.class, () -> authService.login(request));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void login_invalidPassword() {
|
||||
LoginRequest request = new LoginRequest("test@mail.com", "wrong");
|
||||
|
||||
User user = new User();
|
||||
user.setEmail("test@mail.com");
|
||||
user.setPassword("encoded_pass");
|
||||
|
||||
when(userRepository.findByEmail("test@mail.com")).thenReturn(Optional.of(user));
|
||||
when(passwordEncoder.matches("wrong", "encoded_pass")).thenReturn(false);
|
||||
|
||||
assertThrows(NotValidationPasswordException.class, () -> authService.login(request));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user