scheduling

This commit is contained in:
Vladimir Voronin
2025-01-07 13:31:08 +03:00
parent 8b440ad9e8
commit 84f61532d0
5 changed files with 73 additions and 29 deletions

View File

@@ -1,19 +1,18 @@
package space.luminic.budgerapp package space.luminic.budgerapp
import com.interaso.webpush.VapidKeys
//import org.apache.tomcat.util.codec.binary.Base64.encodeBase64
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication import org.springframework.boot.runApplication
import org.springframework.cache.annotation.EnableCaching import org.springframework.cache.annotation.EnableCaching
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories import org.springframework.data.mongodb.repository.config.EnableMongoRepositories
import org.springframework.scheduling.annotation.EnableAsync import org.springframework.scheduling.annotation.EnableAsync
import org.springframework.web.reactive.config.EnableWebFlux import org.springframework.scheduling.annotation.EnableScheduling
import java.security.Security
import java.util.TimeZone import java.util.TimeZone
@SpringBootApplication @SpringBootApplication
@EnableCaching @EnableCaching
@EnableAsync @EnableAsync
@EnableScheduling
@EnableMongoRepositories(basePackages = ["space.luminic.budgerapp.repos"]) @EnableMongoRepositories(basePackages = ["space.luminic.budgerapp.repos"])
class BudgerAppApplication class BudgerAppApplication

View File

@@ -14,7 +14,7 @@ data class PushMessage(
val title: String, val title: String,
val body: String, val body: String,
val icon: String? = null, val icon: String? = null,
val budge: String? = null, val badge: String? = null,
val url: String? = null val url: String? = null
) )

View File

@@ -5,10 +5,8 @@ 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
import space.luminic.budgerapp.configs.AuthException import space.luminic.budgerapp.configs.AuthException
import space.luminic.budgerapp.models.Token
import space.luminic.budgerapp.models.TokenStatus import space.luminic.budgerapp.models.TokenStatus
import space.luminic.budgerapp.models.User import space.luminic.budgerapp.models.User
import space.luminic.budgerapp.repos.TokenRepo
import space.luminic.budgerapp.repos.UserRepo import space.luminic.budgerapp.repos.UserRepo
import space.luminic.budgerapp.utils.JWTUtil import space.luminic.budgerapp.utils.JWTUtil
import java.time.LocalDateTime import java.time.LocalDateTime
@@ -19,7 +17,7 @@ import java.util.Date
@Service @Service
class AuthService( class AuthService(
private val userRepository: UserRepo, private val userRepository: UserRepo,
private val tokenRepo: TokenRepo, private val tokenService: TokenService,
private val jwtUtil: JWTUtil private val jwtUtil: JWTUtil
) { ) {
@@ -31,18 +29,14 @@ class AuthService(
if (passwordEncoder.matches(password, user.password)) { 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)
tokenRepo.save( tokenService.saveToken(
Token(
token = token, token = token,
username = username, username = username,
issuedAt = LocalDateTime.now(),
expiresAt = LocalDateTime.ofInstant( expiresAt = LocalDateTime.ofInstant(
expireAt.toInstant(), expireAt.toInstant(),
ZoneId.systemDefault() ZoneId.systemDefault()
) )
) ).thenReturn(token)
)
.thenReturn(token)
} else { } else {
Mono.error(AuthException("Invalid credentials")) Mono.error(AuthException("Invalid credentials"))
} }
@@ -51,16 +45,21 @@ class AuthService(
@Cacheable("tokens") @Cacheable("tokens")
fun isTokenValid(token: String): Mono<User> { fun isTokenValid(token: String): Mono<User> {
// print("checking token: $token") return tokenService.getToken(token)
return tokenRepo.findByToken(token) .flatMap { tokenDetails ->
.flatMap { when {
if (it.status == TokenStatus.ACTIVE && tokenDetails.status == TokenStatus.ACTIVE && tokenDetails.expiresAt.isAfter(LocalDateTime.now()) -> {
it.expiresAt.isAfter(LocalDateTime.now()) userRepository.findByUsername(tokenDetails.username)
) { .switchIfEmpty(Mono.error(AuthException("User not found for token")))
userRepository.findByUsername(it.username)
} else {
Mono.error(AuthException("Token expired"))
} }
}.switchIfEmpty(Mono.error(AuthException("User not found")))
else -> {
tokenService.revokeToken(token)
.then(Mono.error(AuthException("Token expired or inactive")))
} }
} }
}
.switchIfEmpty(Mono.error(AuthException("Token not found")))
}
}

View File

@@ -21,6 +21,10 @@ class TokenService(private val tokenRepository: TokenRepo) {
return tokenRepository.save(newToken) return tokenRepository.save(newToken)
} }
fun getToken(token: String): Mono<Token> {
return tokenRepository.findByToken(token)
}
@CacheEvict("tokens", allEntries = true) @CacheEvict("tokens", allEntries = true)
fun revokeToken(token: String): Mono<Void> { fun revokeToken(token: String): Mono<Void> {
return tokenRepository.findByToken(token) return tokenRepository.findByToken(token)

View File

@@ -0,0 +1,42 @@
package space.luminic.budgerapp.utils
import org.slf4j.LoggerFactory
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component
import space.luminic.budgerapp.models.PushMessage
import space.luminic.budgerapp.services.SubscriptionService
import space.luminic.budgerapp.services.TokenService
@Component
class ScheduledTasks(private val subscriptionService: SubscriptionService,
private val tokenService: TokenService) {
private val logger = LoggerFactory.getLogger(ScheduledTasks::class.java)
@Scheduled(cron = "0 30 19 * * *")
fun sendNotificationOfMoneyFilling() {
subscriptionService.sendToAll(
PushMessage(
title = "Время заполнять траты!🤑",
body = "Проверь все ли траты внесены!",
icon = "/apple-touch-icon.png",
badge = "/apple-touch-icon.png",
url = "https://luminic.space/transactions/create"
)
).doOnNext { responses ->
responses.forEach { response ->
logger.info("Уведомление отправлено: $response")
}
}.subscribe(
{ logger.info("Все уведомления отправлены.") },
{ error -> logger.error("Ошибка при отправке уведомлений: ${error.message}", error) }
)
}
@Scheduled(cron = "0 0 0 * * *")
fun deleteExpiredTokens() {
tokenService.deleteExpiredTokens()
}
}