login fix and spaces creation

This commit is contained in:
xds
2025-03-06 18:55:12 +03:00
parent 3b9f0e566c
commit 98263732ca
5 changed files with 71 additions and 77 deletions

View File

@@ -30,18 +30,19 @@ class AuthController(
@PostMapping("/login")
suspend fun login(@RequestBody request: AuthRequest): Map<String, String> {
return authService.login(request.username, request.password)
.map { token -> mapOf("token" to token) }.awaitFirst()
val token = authService.login(request.username, request.password)
return mapOf("token" to token)
}
@PostMapping("/register")
fun register(@RequestBody request: RegisterRequest): Mono<User> {
suspend fun register(@RequestBody request: RegisterRequest): User {
return authService.register(request.username, request.password, request.firstName)
}
@PostMapping("/tgLogin")
fun tgLogin(@RequestHeader("X-Tg-Id") tgId: String): Mono<Map<String, String>> {
return authService.tgLogin(tgId).map { token -> mapOf("token" to token) }
suspend fun tgLogin(@RequestHeader("X-Tg-Id") tgId: String): Map<String, String> {
val token = authService.tgLogin(tgId)
return mapOf("token" to token)
}

View File

@@ -1,7 +1,10 @@
package space.luminic.budgerapp.services
import kotlinx.coroutines.reactive.awaitFirstOrNull
import kotlinx.coroutines.reactor.awaitSingle
import kotlinx.coroutines.reactor.awaitSingleOrNull
import org.springframework.cache.annotation.Cacheable
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
@@ -22,72 +25,66 @@ class AuthService(
private val jwtUtil: JWTUtil,
private val userService: UserService
) {
) {
private val passwordEncoder = BCryptPasswordEncoder()
fun login(username: String, password: String): Mono<String> {
return userRepository.findByUsername(username)
.flatMap { user ->
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 = LocalDateTime.ofInstant(
expireAt.toInstant(),
ZoneId.systemDefault()
)
).thenReturn(token)
} else {
Mono.error(AuthException("Invalid credentials"))
}
}
}
fun tgLogin(tgId: String): Mono<String> {
return userRepository.findByTgId(tgId)
.switchIfEmpty(Mono.error(AuthException("Invalid credentials")))
.flatMap { user ->
println("here")
val token = jwtUtil.generateToken(user.username!!)
val expireAt = Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 10)
tokenService.saveToken(
token = token,
username = user.username,
expiresAt = LocalDateTime.ofInstant(
expireAt.toInstant(),
ZoneId.systemDefault()
)
).thenReturn(token)
}
}
fun register(username: String, password: String, firstName: String): Mono<User> {
return userRepository.findByUsername(username)
.flatMap<User> { Mono.error(IllegalArgumentException("User with username '$username' already exists")) } // Ошибка, если пользователь уже существует
.switchIfEmpty(
Mono.defer {
val newUser = User(
username = username,
password = passwordEncoder.encode(password), // Шифрование пароля
firstName = firstName,
roles = mutableListOf("USER")
)
userRepository.save(newUser).map { user ->
user.password = null
user
} // Сохранение нового пользователя
}
suspend fun login(username: String, password: String): String {
val user = userRepository.findByUsername(username).awaitFirstOrNull()
?: 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 = LocalDateTime.ofInstant(
expireAt.toInstant(),
ZoneId.systemDefault()
)
)
token
} else {
throw IllegalArgumentException("Ошибка логина или пароля")
}
}
suspend fun tgLogin(tgId: String): String {
val user =
userRepository.findByTgId(tgId).awaitSingleOrNull() ?: throw UsernameNotFoundException("Пользователь не найден")
val token = jwtUtil.generateToken(user.username!!)
val expireAt = Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 10)
tokenService.saveToken(
token = token,
username = user.username,
expiresAt = LocalDateTime.ofInstant(
expireAt.toInstant(),
ZoneId.systemDefault()
)
)
return token
}
suspend fun register(username: String, password: String, firstName: String): User {
val user = userRepository.findByUsername(username).awaitSingleOrNull()
if (user == null) {
var newUser = User(
username = username,
password = passwordEncoder.encode(password), // Шифрование пароля
firstName = firstName,
roles = mutableListOf("USER")
)
newUser = userRepository.save(newUser).awaitSingle()
newUser.password = null
return newUser
} else throw IllegalArgumentException("Пользователь уже зарегистрирован")
}
@Cacheable(cacheNames = ["tokens"], key = "#token")
suspend fun isTokenValid(token: String): User {
val tokenDetails = tokenService.getToken(token).awaitFirstOrNull() ?: throw AuthException("Invalid token")
suspend fun isTokenValid(token: String): User {
val tokenDetails = tokenService.getToken(token).awaitFirstOrNull() ?: throw AuthException("Токен не валиден")
when {
tokenDetails.status == TokenStatus.ACTIVE && tokenDetails.expiresAt.isAfter(LocalDateTime.now()) -> {
return userService.getByUserNameWoPass(tokenDetails.username)
@@ -95,7 +92,7 @@ class AuthService(
else -> {
tokenService.revokeToken(tokenDetails.token)
throw AuthException("Token expired or inactive")
throw AuthException("Токен истек или не валиден")
}
}
}

View File

@@ -4,6 +4,7 @@ import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.reactive.awaitFirst
import kotlinx.coroutines.reactive.awaitFirstOrNull
import kotlinx.coroutines.reactive.awaitLast
import kotlinx.coroutines.reactive.awaitSingle
import kotlinx.coroutines.reactor.awaitSingleOrNull
import org.bson.Document
@@ -18,6 +19,7 @@ import space.luminic.budgerapp.configs.AuthException
import space.luminic.budgerapp.models.*
import space.luminic.budgerapp.repos.*
import java.time.LocalDateTime
import java.time.ZoneId
import java.util.UUID
@Service
@@ -92,7 +94,8 @@ class SpaceService(
username = userDoc.getString("username"),
firstName = userDoc.getString("firstName")
)
}.toMutableList()
}.toMutableList(),
createdAt = doc.getDate("createdAt").toInstant().atZone(ZoneId.systemDefault()).toLocalDate()
)
}
}.awaitFirst()
@@ -120,7 +123,7 @@ class SpaceService(
.map { category ->
category.copy(id = null, space = savedSpace) // Создаем новую копию
}
categoryRepo.saveAll(categories).awaitSingle()
categoryRepo.saveAll(categories).awaitLast()
savedSpace
}

View File

@@ -1,5 +1,6 @@
package space.luminic.budgerapp.services
import kotlinx.coroutines.reactor.awaitSingle
import org.springframework.cache.annotation.CacheEvict
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
@@ -12,14 +13,14 @@ import java.time.LocalDateTime
class TokenService(private val tokenRepository: TokenRepo) {
@CacheEvict("tokens", allEntries = true)
fun saveToken(token: String, username: String, expiresAt: LocalDateTime): Mono<Token> {
suspend fun saveToken(token: String, username: String, expiresAt: LocalDateTime): Token {
val newToken = Token(
token = token,
username = username,
issuedAt = LocalDateTime.now(),
expiresAt = expiresAt
)
return tokenRepository.save(newToken)
return tokenRepository.save(newToken).awaitSingle()
}
fun getToken(token: String): Mono<Token> {

View File

@@ -24,14 +24,6 @@ class JWTUtil(private val tokenService: TokenService) {
.setExpiration(expireAt) // 10 дней
.signWith(key)
.compact()
tokenService.saveToken(
token,
username,
LocalDateTime.from(
expireAt.toInstant().atZone(ZoneId.systemDefault())
.toLocalDateTime()
)
)
return token
}