login fix and spaces creation
This commit is contained in:
@@ -30,18 +30,19 @@ class AuthController(
|
|||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
suspend fun login(@RequestBody request: AuthRequest): Map<String, String> {
|
suspend fun login(@RequestBody request: AuthRequest): Map<String, String> {
|
||||||
return authService.login(request.username, request.password)
|
val token = authService.login(request.username, request.password)
|
||||||
.map { token -> mapOf("token" to token) }.awaitFirst()
|
return mapOf("token" to token)
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/register")
|
@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)
|
return authService.register(request.username, request.password, request.firstName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/tgLogin")
|
@PostMapping("/tgLogin")
|
||||||
fun tgLogin(@RequestHeader("X-Tg-Id") tgId: String): Mono<Map<String, String>> {
|
suspend fun tgLogin(@RequestHeader("X-Tg-Id") tgId: String): Map<String, String> {
|
||||||
return authService.tgLogin(tgId).map { token -> mapOf("token" to token) }
|
val token = authService.tgLogin(tgId)
|
||||||
|
return mapOf("token" to token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package space.luminic.budgerapp.services
|
package space.luminic.budgerapp.services
|
||||||
|
|
||||||
import kotlinx.coroutines.reactive.awaitFirstOrNull
|
import kotlinx.coroutines.reactive.awaitFirstOrNull
|
||||||
|
import kotlinx.coroutines.reactor.awaitSingle
|
||||||
|
import kotlinx.coroutines.reactor.awaitSingleOrNull
|
||||||
import org.springframework.cache.annotation.Cacheable
|
import org.springframework.cache.annotation.Cacheable
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
@@ -22,72 +25,66 @@ class AuthService(
|
|||||||
private val jwtUtil: JWTUtil,
|
private val jwtUtil: JWTUtil,
|
||||||
private val userService: UserService
|
private val userService: UserService
|
||||||
|
|
||||||
) {
|
) {
|
||||||
private val passwordEncoder = BCryptPasswordEncoder()
|
private val passwordEncoder = BCryptPasswordEncoder()
|
||||||
|
|
||||||
fun login(username: String, password: String): Mono<String> {
|
suspend fun login(username: String, password: String): String {
|
||||||
return userRepository.findByUsername(username)
|
val user = userRepository.findByUsername(username).awaitFirstOrNull()
|
||||||
.flatMap { user ->
|
?: throw UsernameNotFoundException("Пользователь не найден")
|
||||||
if (passwordEncoder.matches(password, user.password)) {
|
return if (passwordEncoder.matches(password, user.password)) {
|
||||||
val token = jwtUtil.generateToken(user.username!!)
|
val token = jwtUtil.generateToken(user.username!!)
|
||||||
val expireAt = Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 10)
|
val expireAt = Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 10)
|
||||||
tokenService.saveToken(
|
tokenService.saveToken(
|
||||||
token = token,
|
token = token,
|
||||||
username = username,
|
username = username,
|
||||||
expiresAt = LocalDateTime.ofInstant(
|
expiresAt = LocalDateTime.ofInstant(
|
||||||
expireAt.toInstant(),
|
expireAt.toInstant(),
|
||||||
ZoneId.systemDefault()
|
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
|
|
||||||
} // Сохранение нового пользователя
|
|
||||||
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
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")
|
@Cacheable(cacheNames = ["tokens"], key = "#token")
|
||||||
suspend fun isTokenValid(token: String): User {
|
suspend fun isTokenValid(token: String): User {
|
||||||
val tokenDetails = tokenService.getToken(token).awaitFirstOrNull() ?: throw AuthException("Invalid token")
|
val tokenDetails = tokenService.getToken(token).awaitFirstOrNull() ?: throw AuthException("Токен не валиден")
|
||||||
when {
|
when {
|
||||||
tokenDetails.status == TokenStatus.ACTIVE && tokenDetails.expiresAt.isAfter(LocalDateTime.now()) -> {
|
tokenDetails.status == TokenStatus.ACTIVE && tokenDetails.expiresAt.isAfter(LocalDateTime.now()) -> {
|
||||||
return userService.getByUserNameWoPass(tokenDetails.username)
|
return userService.getByUserNameWoPass(tokenDetails.username)
|
||||||
@@ -95,7 +92,7 @@ class AuthService(
|
|||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
tokenService.revokeToken(tokenDetails.token)
|
tokenService.revokeToken(tokenDetails.token)
|
||||||
throw AuthException("Token expired or inactive")
|
throw AuthException("Токен истек или не валиден")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import kotlinx.coroutines.coroutineScope
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.reactive.awaitFirst
|
import kotlinx.coroutines.reactive.awaitFirst
|
||||||
import kotlinx.coroutines.reactive.awaitFirstOrNull
|
import kotlinx.coroutines.reactive.awaitFirstOrNull
|
||||||
|
import kotlinx.coroutines.reactive.awaitLast
|
||||||
import kotlinx.coroutines.reactive.awaitSingle
|
import kotlinx.coroutines.reactive.awaitSingle
|
||||||
import kotlinx.coroutines.reactor.awaitSingleOrNull
|
import kotlinx.coroutines.reactor.awaitSingleOrNull
|
||||||
import org.bson.Document
|
import org.bson.Document
|
||||||
@@ -18,6 +19,7 @@ import space.luminic.budgerapp.configs.AuthException
|
|||||||
import space.luminic.budgerapp.models.*
|
import space.luminic.budgerapp.models.*
|
||||||
import space.luminic.budgerapp.repos.*
|
import space.luminic.budgerapp.repos.*
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneId
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -92,7 +94,8 @@ class SpaceService(
|
|||||||
username = userDoc.getString("username"),
|
username = userDoc.getString("username"),
|
||||||
firstName = userDoc.getString("firstName")
|
firstName = userDoc.getString("firstName")
|
||||||
)
|
)
|
||||||
}.toMutableList()
|
}.toMutableList(),
|
||||||
|
createdAt = doc.getDate("createdAt").toInstant().atZone(ZoneId.systemDefault()).toLocalDate()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.awaitFirst()
|
}.awaitFirst()
|
||||||
@@ -120,7 +123,7 @@ class SpaceService(
|
|||||||
.map { category ->
|
.map { category ->
|
||||||
category.copy(id = null, space = savedSpace) // Создаем новую копию
|
category.copy(id = null, space = savedSpace) // Создаем новую копию
|
||||||
}
|
}
|
||||||
categoryRepo.saveAll(categories).awaitSingle()
|
categoryRepo.saveAll(categories).awaitLast()
|
||||||
savedSpace
|
savedSpace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package space.luminic.budgerapp.services
|
package space.luminic.budgerapp.services
|
||||||
|
|
||||||
|
import kotlinx.coroutines.reactor.awaitSingle
|
||||||
import org.springframework.cache.annotation.CacheEvict
|
import org.springframework.cache.annotation.CacheEvict
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
@@ -12,14 +13,14 @@ import java.time.LocalDateTime
|
|||||||
class TokenService(private val tokenRepository: TokenRepo) {
|
class TokenService(private val tokenRepository: TokenRepo) {
|
||||||
|
|
||||||
@CacheEvict("tokens", allEntries = true)
|
@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(
|
val newToken = Token(
|
||||||
token = token,
|
token = token,
|
||||||
username = username,
|
username = username,
|
||||||
issuedAt = LocalDateTime.now(),
|
issuedAt = LocalDateTime.now(),
|
||||||
expiresAt = expiresAt
|
expiresAt = expiresAt
|
||||||
)
|
)
|
||||||
return tokenRepository.save(newToken)
|
return tokenRepository.save(newToken).awaitSingle()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getToken(token: String): Mono<Token> {
|
fun getToken(token: String): Mono<Token> {
|
||||||
|
|||||||
@@ -24,14 +24,6 @@ class JWTUtil(private val tokenService: TokenService) {
|
|||||||
.setExpiration(expireAt) // 10 дней
|
.setExpiration(expireAt) // 10 дней
|
||||||
.signWith(key)
|
.signWith(key)
|
||||||
.compact()
|
.compact()
|
||||||
tokenService.saveToken(
|
|
||||||
token,
|
|
||||||
username,
|
|
||||||
LocalDateTime.from(
|
|
||||||
expireAt.toInstant().atZone(ZoneId.systemDefault())
|
|
||||||
.toLocalDateTime()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return token
|
return token
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user