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); } }