init projects

This commit is contained in:
2026-06-17 18:58:41 +03:00
parent 8543c4e241
commit 21a768edd5
505 changed files with 19998 additions and 93 deletions
+2
View File
@@ -0,0 +1,2 @@
/build
/bin
+8
View File
@@ -0,0 +1,8 @@
plugins {
alias(libs.plugins.convention.jvm)
alias(libs.plugins.convention.koin)
}
dependencies {
implementation(libs.java.jwt)
implementation(libs.logback.classic)
}
@@ -0,0 +1,10 @@
package ru.shadowsparky.backend
import org.koin.core.annotation.ComponentScan
import org.koin.core.annotation.Configuration
import org.koin.core.annotation.Module
@Module
@ComponentScan
@Configuration
class BackendCommon
@@ -0,0 +1,11 @@
package ru.shadowsparky.backend.data
import org.koin.core.annotation.Single
@Single
class EnvFetcher {
fun get(key: String, default: String = ""): String {
val value = System.getenv(key)
return value?.ifEmpty { default } ?: default
}
}
@@ -0,0 +1,33 @@
package ru.shadowsparky.backend.data
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import org.koin.core.annotation.Single
import ru.shadowsparky.backend.domain.JwtInfo
import ru.shadowsparky.backend.domain.LOGIN_NAME
import ru.shadowsparky.backend.domain.USER_ID_ARG
import java.util.Date
import java.util.concurrent.TimeUnit
@Single
class JwtPreparer(
private val jwtInfo: JwtInfo,
private val envFetcher: EnvFetcher
) {
private val tokenTimeInMinutes = envFetcher.get("JWT_DURATION", "30").toLong()
fun prepare(
login: String,
userId: Long
): String {
val exp = Date(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(tokenTimeInMinutes))
val token = JWT.create()
.withAudience(jwtInfo.audience)
.withIssuer(jwtInfo.issuer)
.withClaim(LOGIN_NAME, login)
.withClaim(USER_ID_ARG, userId)
.withSubject(userId.toString())
.withExpiresAt(exp)
.sign(Algorithm.HMAC512(jwtInfo.secret))
return token
}
}
@@ -0,0 +1,20 @@
package ru.shadowsparky.backend.data
import org.koin.core.annotation.Single
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@Single
class Logger {
private val loggers = hashMapOf<String, Logger>()
fun info(tag: String, message: String) = obtainLogger(tag).info(message)
fun debug(tag: String, message: String) = obtainLogger(tag).debug(message)
fun error(tag: String, e: Exception) = obtainLogger(tag).error("error occurred", e)
private fun obtainLogger(tag: String): Logger {
loggers[tag]?.let { return it }
loggers[tag] = LoggerFactory.getLogger(tag)
return loggers[tag]!!
}
}
@@ -0,0 +1,20 @@
package ru.shadowsparky.backend.data
import org.koin.core.annotation.Single
@Single
class StringFetcher {
fun get(resource: StringResource): String {
return resource.message
}
}
enum class StringResource(val message: String) {
UNKNOWN_USER("Пользователь не найден или неверный пароль"),
INVALID_PASSWORD("Вы ввели неверный пароль"),
NO_CHANGES_PASS("Старый и новый пароль должны отличаться"),
USER_BLOCKED("Пользователь заблокирован"),
REG_BLOCKED("Регистрация недоступна. Доступ по приглашениям."),
ALREADY_REGISTERED("Пользователь уже существует"),
VIDEO_NOT_FOUND("Видео не найдено.")
}
@@ -0,0 +1,27 @@
package ru.shadowsparky.backend.data
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import com.auth0.jwt.interfaces.DecodedJWT
import org.koin.core.annotation.Factory
import ru.shadowsparky.backend.domain.JwtInfo
import ru.shadowsparky.backend.domain.LOGIN_NAME
import ru.shadowsparky.backend.domain.LoginVerifier
@Factory
class TokenVerifier(
private val jwtInfo: JwtInfo,
private val loginVerifier: LoginVerifier
) {
val verifier = JWT.require(Algorithm.HMAC512(jwtInfo.secret))
.withAudience(jwtInfo.audience)
.withIssuer(jwtInfo.issuer)
.build()
suspend fun verify(token: String): DecodedJWT {
val jwt = verifier.verify(token)
loginVerifier.verify(jwt.getClaim(LOGIN_NAME).asString())
return jwt
}
}
@@ -0,0 +1,8 @@
package ru.shadowsparky.backend.domain
data class JwtInfo(
val secret: String,
val issuer: String,
val audience: String,
val realm: String
)
@@ -0,0 +1,10 @@
package ru.shadowsparky.backend.domain
interface LoginVerifier {
suspend fun verify(login: String)
}
const val LOGIN_NAME = "login"
const val USER_ID_ARG = "user_id"
const val INVALID_TOKEN_MSG = "Был передан неправильный токен"
@@ -0,0 +1,3 @@
package ru.shadowsparky.backend.domain
class VerifyTokenException(override val message: String?) : IllegalStateException()