UserService.kt
- package delta.codecharacter.server.user
- import delta.codecharacter.dtos.CompleteProfileRequestDto
- import delta.codecharacter.dtos.RegisterUserRequestDto
- import delta.codecharacter.dtos.UpdatePasswordRequestDto
- import delta.codecharacter.server.exception.CustomException
- import delta.codecharacter.server.user.activate_user.ActivateUserService
- import delta.codecharacter.server.user.public_user.PublicUserService
- import delta.codecharacter.server.user.rating_history.RatingHistoryService
- import org.springframework.beans.factory.annotation.Autowired
- import org.springframework.context.annotation.Lazy
- import org.springframework.dao.DuplicateKeyException
- import org.springframework.http.HttpStatus
- import org.springframework.security.core.authority.SimpleGrantedAuthority
- import org.springframework.security.core.userdetails.UserDetailsService
- import org.springframework.security.core.userdetails.UsernameNotFoundException
- import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
- import org.springframework.stereotype.Service
- import java.util.Optional
- import java.util.UUID
- @Service
- class UserService(
- @Autowired private val userRepository: UserRepository,
- @Autowired private val publicUserService: PublicUserService,
- @Autowired private val ratingHistoryService: RatingHistoryService,
- @Autowired private val activateUserService: ActivateUserService
- ) : UserDetailsService {
- @Lazy @Autowired private lateinit var passwordEncoder: BCryptPasswordEncoder
- override fun loadUserByUsername(email: String?): UserEntity {
- if (email == null) {
- throw UsernameNotFoundException("User not found")
- }
- val user = userRepository.findFirstByEmail(email)
- if (user.isEmpty) {
- throw UsernameNotFoundException("User not found")
- } else if (!user.get().isEnabled) {
- throw CustomException(HttpStatus.UNAUTHORIZED, "Email not verified")
- } else if (!user.get().isAccountNonExpired) {
- throw CustomException(HttpStatus.UNAUTHORIZED, "Account expired")
- } else {
- return user.get()
- }
- }
- private fun createUserWithPassword(userId: UUID, password: String, email: String) {
- val user =
- UserEntity(
- id = userId,
- password = passwordEncoder.encode(password),
- email = email,
- loginType = LoginType.PASSWORD,
- isProfileComplete = true,
- isEnabled = false,
- isAccountNonExpired = true,
- isAccountNonLocked = true,
- isCredentialsNonExpired = true,
- userAuthorities = mutableListOf(SimpleGrantedAuthority("ROLE_USER"))
- )
- userRepository.save(user)
- }
- fun createUserWithOAuth(email: String, oauthProvider: LoginType): UserEntity {
- val userId = UUID.randomUUID()
- val user =
- UserEntity(
- id = userId,
- password = passwordEncoder.encode(UUID.randomUUID().toString()),
- email = email,
- loginType = oauthProvider,
- isProfileComplete = false,
- isEnabled = true,
- isAccountNonExpired = true,
- isAccountNonLocked = true,
- isCredentialsNonExpired = true,
- userAuthorities = mutableListOf(SimpleGrantedAuthority("ROLE_USER_INCOMPLETE_PROFILE"))
- )
- ratingHistoryService.create(userId)
- return userRepository.save(user)
- }
- fun getUserByEmail(email: String): Optional<UserEntity> {
- return userRepository.findFirstByEmail(email)
- }
- fun updateUserPassword(userId: UUID, password: String) {
- val user = userRepository.findById(userId).get()
- userRepository.save(user.copy(password = passwordEncoder.encode(password)))
- }
- fun verifyUserPassword(userId: UUID, password: String): Boolean {
- val user = userRepository.findById(userId)
- return passwordEncoder.matches(password, user.get().password)
- }
- fun updatePassword(userId: UUID, updatePasswordRequestDto: UpdatePasswordRequestDto) {
- val (oldPassword, password, passwordConfirmation) = updatePasswordRequestDto
- if (password != passwordConfirmation) {
- throw CustomException(HttpStatus.BAD_REQUEST, "Passwords do not match")
- }
- if (verifyUserPassword(userId, oldPassword)) {
- val user = userRepository.findById(userId).get()
- userRepository.save(user.copy(password = passwordEncoder.encode(password)))
- } else {
- throw CustomException(HttpStatus.BAD_REQUEST, "Old password is incorrect")
- }
- }
- fun registerUser(registerUserRequestDto: RegisterUserRequestDto) {
- val (username, name, email, password, passwordConfirmation, country, college, avatarId) =
- registerUserRequestDto
- if (password != passwordConfirmation) {
- throw CustomException(
- HttpStatus.BAD_REQUEST, "Password and password confirmation don't match"
- )
- }
- if (!publicUserService.isUsernameUnique(username)) {
- throw CustomException(HttpStatus.BAD_REQUEST, "Username already taken")
- }
- val userId = UUID.randomUUID()
- try {
- createUserWithPassword(userId, password, email)
- publicUserService.create(userId, username, name, country, college, avatarId)
- ratingHistoryService.create(userId)
- activateUserService.sendActivationToken(userId, name, email)
- } catch (duplicateError: DuplicateKeyException) {
- throw CustomException(HttpStatus.BAD_REQUEST, "Username/Email already exists")
- }
- }
- fun activateUser(userId: UUID, token: String) {
- activateUserService.processActivationToken(userId, token)
- val user = userRepository.findFirstById((userId)).get()
- val activatedUser = user.copy(isEnabled = true)
- userRepository.save(activatedUser)
- }
- fun completeUserProfile(userId: UUID, completeProfileRequestDto: CompleteProfileRequestDto) {
- val (username, name, country, college, avatarId) = completeProfileRequestDto
- val user = userRepository.findFirstById(userId).get()
- publicUserService.create(userId, username, name, country, college, avatarId)
- userRepository.save(
- user.copy(
- isProfileComplete = true,
- userAuthorities = mutableListOf(SimpleGrantedAuthority("ROLE_USER"))
- )
- )
- }
- }