128 lines
4.7 KiB
Kotlin
128 lines
4.7 KiB
Kotlin
package space.luminic.finance.services
|
|
|
|
import org.springframework.cache.annotation.Cacheable
|
|
import org.springframework.security.core.context.SecurityContextHolder
|
|
import org.springframework.security.core.userdetails.UsernameNotFoundException
|
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
|
import org.springframework.stereotype.Service
|
|
import space.luminic.finance.configs.AuthException
|
|
import space.luminic.finance.dtos.UserDTO
|
|
import space.luminic.finance.models.NotFoundException
|
|
import space.luminic.finance.models.Token
|
|
import space.luminic.finance.models.User
|
|
import space.luminic.finance.repos.UserRepo
|
|
import space.luminic.finance.utils.JWTUtil
|
|
import java.time.Instant
|
|
import java.util.*
|
|
|
|
|
|
@Service
|
|
class AuthService(
|
|
private val userRepo: UserRepo,
|
|
private val tokenService: TokenService,
|
|
private val jwtUtil: JWTUtil,
|
|
private val userService: UserService,
|
|
|
|
) {
|
|
private val passwordEncoder = BCryptPasswordEncoder()
|
|
|
|
fun getSecurityUser(): User {
|
|
val securityContextHolder = SecurityContextHolder.getContext()
|
|
?: throw AuthException("Authentication failed")
|
|
val authentication = securityContextHolder.authentication
|
|
|
|
val username = authentication.name
|
|
// Получаем пользователя по имени
|
|
return userService.getById(username.toInt())
|
|
}
|
|
|
|
fun getSecurityUserId(): Int {
|
|
val securityContextHolder = SecurityContextHolder.getContext()
|
|
?: throw AuthException("Authentication failed")
|
|
val authentication = securityContextHolder.authentication
|
|
|
|
val username = authentication.name
|
|
// Получаем пользователя по имени
|
|
return username.toInt()
|
|
}
|
|
|
|
fun login(username: String, password: String): String {
|
|
val user = userRepo.findByUsername(username)
|
|
?: throw UsernameNotFoundException("Пользователь не найден")
|
|
return if (passwordEncoder.matches(password, user.password)) {
|
|
val token = jwtUtil.generateToken(user.username)
|
|
val expireAt = Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 10)
|
|
tokenService.saveToken(
|
|
token = token,
|
|
username = username,
|
|
expiresAt = expireAt.toInstant()
|
|
)
|
|
token
|
|
} else {
|
|
throw IllegalArgumentException("Ошибка логина или пароля")
|
|
}
|
|
}
|
|
|
|
fun tgAuth(tgUser: UserDTO.TelegramAuthDTO): String {
|
|
val user: User = try {
|
|
tgLogin(tgUser.id!!)
|
|
} catch (e: NotFoundException) {
|
|
registerTg(tgUser)
|
|
}
|
|
val token = jwtUtil.generateToken(user.username)
|
|
val expireAt = Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 10)
|
|
tokenService.saveToken(
|
|
token = token,
|
|
username = user.username,
|
|
expiresAt = expireAt.toInstant()
|
|
)
|
|
return token
|
|
}
|
|
|
|
fun registerTg(tgUser: UserDTO.TelegramAuthDTO): User {
|
|
val user = User(
|
|
username = tgUser.username ?: UUID.randomUUID().toString().split('-')[0],
|
|
firstName = tgUser.first_name ?: UUID.randomUUID().toString().split('-')[0],
|
|
tgId = tgUser.id,
|
|
tgUserName = tgUser.username,
|
|
photoUrl = tgUser.photo_url,
|
|
roles = mutableListOf("USER")
|
|
)
|
|
return userRepo.create(user)
|
|
}
|
|
|
|
fun tgLogin(tgId: Long): User {
|
|
return userRepo.findByTgId(tgId) ?: throw NotFoundException("User with provided TG id $tgId not found")
|
|
}
|
|
|
|
fun register(username: String, password: String, firstName: String): User {
|
|
val user = userRepo.findByUsername(username)
|
|
if (user == null) {
|
|
var newUser = User(
|
|
username = username,
|
|
password = passwordEncoder.encode(password), // Шифрование пароля
|
|
firstName = firstName,
|
|
roles = mutableListOf("USER")
|
|
)
|
|
newUser = userRepo.create(newUser)
|
|
return newUser
|
|
} else throw IllegalArgumentException("Пользователь уже зарегистрирован")
|
|
}
|
|
|
|
|
|
@Cacheable(cacheNames = ["tokens"], key = "#token")
|
|
fun isTokenValid(token: String): User {
|
|
val tokenDetails = tokenService.getToken(token)
|
|
when {
|
|
tokenDetails.status == Token.TokenStatus.ACTIVE && tokenDetails.expiresAt.isAfter(Instant.now()) -> {
|
|
return tokenDetails.user
|
|
}
|
|
|
|
else -> {
|
|
tokenService.revokeToken(tokenDetails.token)
|
|
throw AuthException("Токен истек или не валиден")
|
|
}
|
|
}
|
|
}
|
|
|
|
} |