refactor
This commit is contained in:
@@ -29,9 +29,8 @@ dependencies {
|
||||
implementation(libs.exposed)
|
||||
implementation(libs.exposed.dao)
|
||||
implementation(libs.exposed.jdbc)
|
||||
implementation(libs.migration)
|
||||
implementation(libs.postgres)
|
||||
implementation(libs.koin)
|
||||
implementation(libs.koin.logger)
|
||||
implementation(libs.random)
|
||||
implementation(libs.otp)
|
||||
implementation(libs.kdf)
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
kotlin = "2.2.10"
|
||||
ktor = "3.2.3"
|
||||
exposed = "0.60.0"
|
||||
migration = "1.0.0"
|
||||
postgres = "42.7.5"
|
||||
koin = "4.1.0"
|
||||
random = "1.0.0"
|
||||
otp = "1.1.1"
|
||||
kdf = "1.0.3"
|
||||
@@ -30,11 +30,9 @@ ktor-server-validation = { module = "io.ktor:ktor-server-request-validation", ve
|
||||
exposed = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" }
|
||||
exposed-dao = { module = "org.jetbrains.exposed:exposed-dao", version.ref = "exposed" }
|
||||
exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" }
|
||||
migration = { module = "com.infendro:ktor-migration", version.ref = "migration" }
|
||||
postgres = { module = "org.postgresql:postgresql", version.ref = "postgres" }
|
||||
|
||||
koin = { module = "io.insert-koin:koin-ktor", version.ref = "koin" }
|
||||
koin-logger = { module = "io.insert-koin:koin-logger-slf4j", version.ref = "koin" }
|
||||
|
||||
random = { module = "com.infendro:random", version.ref = "random" }
|
||||
otp = { module = "com.infendro:otp", version.ref = "otp" }
|
||||
kdf = { module = "com.infendro:kdf", version.ref = "kdf" }
|
||||
|
||||
@@ -9,8 +9,6 @@ fun main(
|
||||
) = EngineMain.main(args)
|
||||
|
||||
fun Application.module() {
|
||||
configureDependencyInjection()
|
||||
|
||||
configureDatabase()
|
||||
|
||||
configureSerialization()
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
package com.infendro.account.config
|
||||
|
||||
import com.infendro.account.model.Role
|
||||
import com.infendro.account.model.entity.MigrationTable
|
||||
import com.infendro.account.model.migration
|
||||
import com.infendro.account.model.repository.AccountRepository
|
||||
import com.infendro.account.util.SecureHasher
|
||||
import com.infendro.migration.Migration
|
||||
import io.ktor.server.application.*
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.SchemaUtils
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.koin.ktor.ext.inject
|
||||
|
||||
fun Application.configureDatabase() {
|
||||
val config = environment.config.database
|
||||
@@ -19,19 +15,11 @@ fun Application.configureDatabase() {
|
||||
user = config.username,
|
||||
password = config.password,
|
||||
)
|
||||
migrate()
|
||||
}
|
||||
|
||||
fun Application.migrate() {
|
||||
transaction {
|
||||
SchemaUtils.create(MigrationTable)
|
||||
}
|
||||
|
||||
val accounts by inject<AccountRepository>()
|
||||
|
||||
migration("initial") {
|
||||
exec(
|
||||
"""
|
||||
install(Migration) {
|
||||
migration("initial") {
|
||||
exec(
|
||||
"""
|
||||
CREATE TABLE access
|
||||
(
|
||||
id BIGSERIAL
|
||||
@@ -68,16 +56,17 @@ fun Application.migrate() {
|
||||
NOT NULL
|
||||
);
|
||||
""".trimIndent()
|
||||
)
|
||||
)
|
||||
|
||||
accounts.insert {
|
||||
val salt = SecureHasher.generateSalt()
|
||||
AccountRepository.insert {
|
||||
val salt = SecureHasher.generateSalt()
|
||||
|
||||
this.username = "infendro"
|
||||
this.passwordHash = SecureHasher.hash("password", salt)
|
||||
this.passwordSalt = salt
|
||||
this.secret = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA===="
|
||||
this.role = Role.OWNER
|
||||
this.username = "infendro"
|
||||
this.passwordHash = SecureHasher.hash("password", salt)
|
||||
this.passwordSalt = salt
|
||||
this.secret = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA===="
|
||||
this.role = Role.OWNER
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.infendro.account.config
|
||||
|
||||
import com.infendro.account.model.repository.AccessRepository
|
||||
import com.infendro.account.model.repository.AccountRepository
|
||||
import com.infendro.account.model.repository.MigrationRepository
|
||||
import com.infendro.account.model.repository.SessionRepository
|
||||
import com.infendro.account.service.AccessService
|
||||
import com.infendro.account.service.AccountService
|
||||
import com.infendro.account.service.RoleService
|
||||
import com.infendro.account.service.SessionService
|
||||
import io.ktor.server.application.*
|
||||
import org.koin.core.module.dsl.singleOf
|
||||
import org.koin.dsl.module
|
||||
import org.koin.ktor.plugin.Koin
|
||||
import org.koin.logger.slf4jLogger
|
||||
|
||||
fun Application.configureDependencyInjection() {
|
||||
install(Koin) {
|
||||
slf4jLogger()
|
||||
modules(module)
|
||||
}
|
||||
}
|
||||
|
||||
private val module = module {
|
||||
singleOf(::MigrationRepository)
|
||||
singleOf(::AccessRepository)
|
||||
singleOf(::AccountRepository)
|
||||
singleOf(::SessionRepository)
|
||||
|
||||
singleOf(::AccessService)
|
||||
singleOf(::AccountService)
|
||||
singleOf(::RoleService)
|
||||
singleOf(::SessionService)
|
||||
}
|
||||
@@ -7,15 +7,12 @@ import com.infendro.account.model.entity.SessionEntity
|
||||
import com.infendro.account.model.entity.SessionTable
|
||||
import com.infendro.account.model.repository.SessionRepository
|
||||
import com.infendro.account.util.Hasher
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.auth.Authentication
|
||||
import io.ktor.server.auth.session
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.sessions.*
|
||||
import kotlin.time.Duration.Companion.days
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.koin.ktor.ext.inject
|
||||
import kotlin.time.Duration.Companion.days
|
||||
|
||||
@Serializable
|
||||
data class AuthenticationSession(
|
||||
@@ -46,9 +43,7 @@ fun Application.configureSecurity() {
|
||||
install(Authentication) {
|
||||
session<AuthenticationSession> {
|
||||
validate { authenticationSession ->
|
||||
val sessionRepository by inject<SessionRepository>()
|
||||
|
||||
val session = sessionRepository
|
||||
val session = SessionRepository
|
||||
.singleOrNull { SessionTable.tokenHash eq Hasher.hash(authenticationSession.token) }
|
||||
?: return@validate null
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.infendro.account.model
|
||||
|
||||
import com.infendro.account.model.entity.MigrationTable
|
||||
import com.infendro.account.model.repository.MigrationRepository
|
||||
import io.ktor.server.application.*
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.Transaction
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.koin.ktor.ext.inject
|
||||
|
||||
fun Application.migration(
|
||||
name: String,
|
||||
block: Transaction.() -> Unit,
|
||||
) {
|
||||
val migrations by inject<MigrationRepository>()
|
||||
|
||||
migrations
|
||||
.singleOrNull { MigrationTable.name eq name }
|
||||
?.run { return }
|
||||
|
||||
transaction {
|
||||
try {
|
||||
block()
|
||||
log.info("""Migration "$name" successful""")
|
||||
} catch (e: Exception) {
|
||||
log.error("""Migration "$name" failed""")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
migrations.insert {
|
||||
this.name = name
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.infendro.account.model.entity
|
||||
|
||||
import org.jetbrains.exposed.dao.LongEntity
|
||||
import org.jetbrains.exposed.dao.LongEntityClass
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import org.jetbrains.exposed.dao.id.LongIdTable
|
||||
|
||||
object MigrationTable : LongIdTable("migration", "id") {
|
||||
val name = text("name")
|
||||
}
|
||||
|
||||
class MigrationEntity(id: EntityID<Long>) : LongEntity(id) {
|
||||
companion object : LongEntityClass<MigrationEntity>(MigrationTable)
|
||||
|
||||
var name by MigrationTable.name
|
||||
}
|
||||
@@ -2,4 +2,4 @@ package com.infendro.account.model.repository
|
||||
|
||||
import com.infendro.account.model.entity.AccessEntity
|
||||
|
||||
class AccessRepository : Repository<AccessEntity>(AccessEntity)
|
||||
object AccessRepository : Repository<AccessEntity>(AccessEntity)
|
||||
|
||||
@@ -2,4 +2,4 @@ package com.infendro.account.model.repository
|
||||
|
||||
import com.infendro.account.model.entity.AccountEntity
|
||||
|
||||
class AccountRepository : Repository<AccountEntity>(AccountEntity)
|
||||
object AccountRepository : Repository<AccountEntity>(AccountEntity)
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.infendro.account.model.repository
|
||||
|
||||
import com.infendro.account.model.entity.MigrationEntity
|
||||
|
||||
class MigrationRepository : Repository<MigrationEntity>(MigrationEntity)
|
||||
@@ -50,8 +50,8 @@ abstract class Repository<ENTITY : LongEntity>(
|
||||
|
||||
fun exists(
|
||||
where: Op<Boolean>,
|
||||
): Boolean {
|
||||
return all(where).isNotEmpty()
|
||||
): Boolean = transaction {
|
||||
entityClass.find(where).any()
|
||||
}
|
||||
|
||||
fun exists(
|
||||
|
||||
@@ -2,4 +2,4 @@ package com.infendro.account.model.repository
|
||||
|
||||
import com.infendro.account.model.entity.SessionEntity
|
||||
|
||||
class SessionRepository : Repository<SessionEntity>(SessionEntity)
|
||||
object SessionRepository : Repository<SessionEntity>(SessionEntity)
|
||||
|
||||
@@ -3,15 +3,12 @@ package com.infendro.account.routing
|
||||
import com.infendro.account.config.AuthenticationPrincipal
|
||||
import com.infendro.account.service.AccessService
|
||||
import io.ktor.http.HttpStatusCode.Companion.OK
|
||||
import io.ktor.resources.Resource
|
||||
import io.ktor.server.auth.authenticate
|
||||
import io.ktor.server.auth.principal
|
||||
import io.ktor.server.resources.delete
|
||||
import io.ktor.server.resources.get
|
||||
import io.ktor.resources.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.resources.*
|
||||
import io.ktor.server.resources.post
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.Routing
|
||||
import org.koin.ktor.ext.inject
|
||||
|
||||
@Resource("/access")
|
||||
private class Access {
|
||||
@@ -28,20 +25,18 @@ private class Access {
|
||||
}
|
||||
|
||||
fun Routing.access() {
|
||||
val accessService by inject<AccessService>()
|
||||
|
||||
authenticate {
|
||||
post<Access> {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
|
||||
accessService.post(principal)
|
||||
AccessService.post(principal)
|
||||
.also { call.respond(it) }
|
||||
}
|
||||
|
||||
get<Access.All> {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
|
||||
accessService.getAll(principal)
|
||||
AccessService.getAll(principal)
|
||||
.also { call.respond(it) }
|
||||
}
|
||||
|
||||
@@ -49,7 +44,7 @@ fun Routing.access() {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
val id = resource.id
|
||||
|
||||
accessService.deleteId(principal, id)
|
||||
AccessService.deleteId(principal, id)
|
||||
call.respond(OK)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import io.ktor.server.resources.put
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.Routing
|
||||
import io.ktor.server.sessions.*
|
||||
import org.koin.ktor.ext.inject
|
||||
|
||||
@Resource("/account")
|
||||
private class Account {
|
||||
@@ -71,12 +70,10 @@ private class Account {
|
||||
}
|
||||
|
||||
fun Routing.account() {
|
||||
val accountService by inject<AccountService>()
|
||||
|
||||
post<Account> {
|
||||
val request = call.receive<PostAccountRequest>()
|
||||
|
||||
accountService.post(request)
|
||||
AccountService.post(request)
|
||||
.also { call.respond(it) }
|
||||
}
|
||||
|
||||
@@ -84,21 +81,21 @@ fun Routing.account() {
|
||||
get<Account.All> {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
|
||||
accountService.getAll(principal)
|
||||
AccountService.getAll(principal)
|
||||
.also { call.respond(it) }
|
||||
}
|
||||
|
||||
get<Account.Current> {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
|
||||
accountService.getCurrent(principal)
|
||||
AccountService.getCurrent(principal)
|
||||
.also { call.respond(it) }
|
||||
}
|
||||
|
||||
delete<Account.Current> {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
|
||||
accountService.deleteCurrent(principal)
|
||||
AccountService.deleteCurrent(principal)
|
||||
call.respond(OK)
|
||||
}
|
||||
|
||||
@@ -106,7 +103,7 @@ fun Routing.account() {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
val request = call.receive<PutAccountCurrentUsernameRequest>()
|
||||
|
||||
accountService.putCurrentUsername(principal, call.sessions, request)
|
||||
AccountService.putCurrentUsername(principal, call.sessions, request)
|
||||
call.respond(OK)
|
||||
}
|
||||
|
||||
@@ -114,7 +111,7 @@ fun Routing.account() {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
val request = call.receive<PutAccountCurrentPasswordRequest>()
|
||||
|
||||
accountService.putCurrentPassword(principal, call.sessions, request)
|
||||
AccountService.putCurrentPassword(principal, call.sessions, request)
|
||||
call.respond(OK)
|
||||
}
|
||||
|
||||
@@ -122,14 +119,14 @@ fun Routing.account() {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
val request = call.receive<PostAccountCurrentSecretRequest>()
|
||||
|
||||
accountService.postCurrentSecret(principal, call.sessions, request)
|
||||
AccountService.postCurrentSecret(principal, call.sessions, request)
|
||||
.also { call.respond(it) }
|
||||
}
|
||||
|
||||
get<Account.Current.Session.All> {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
|
||||
accountService.getCurrentSessionAll(principal)
|
||||
AccountService.getCurrentSessionAll(principal)
|
||||
.also { call.respond(it) }
|
||||
}
|
||||
|
||||
@@ -137,7 +134,7 @@ fun Routing.account() {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
val id = resource.id
|
||||
|
||||
accountService.deleteCurrentSessionId(principal, call.sessions, id)
|
||||
AccountService.deleteCurrentSessionId(principal, call.sessions, id)
|
||||
call.respond(OK)
|
||||
}
|
||||
|
||||
@@ -145,7 +142,7 @@ fun Routing.account() {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
val id = resource.id
|
||||
|
||||
accountService.deleteId(principal, id)
|
||||
AccountService.deleteId(principal, id)
|
||||
call.respond(OK)
|
||||
}
|
||||
|
||||
@@ -154,7 +151,7 @@ fun Routing.account() {
|
||||
val id = resource.parent.id
|
||||
val request = call.receive<PutAccountIdRoleRequest>()
|
||||
|
||||
accountService.putIdRole(principal, id, request)
|
||||
AccountService.putIdRole(principal, id, request)
|
||||
call.respond(OK)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package com.infendro.account.routing
|
||||
|
||||
import com.infendro.account.service.RoleService
|
||||
import io.ktor.resources.Resource
|
||||
import io.ktor.server.resources.get
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.routing.Routing
|
||||
import org.koin.ktor.ext.inject
|
||||
import io.ktor.resources.*
|
||||
import io.ktor.server.resources.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
@Resource("/role")
|
||||
private class Role {
|
||||
@@ -16,10 +15,8 @@ private class Role {
|
||||
}
|
||||
|
||||
fun Routing.role() {
|
||||
val roleService by inject<RoleService>()
|
||||
|
||||
get<Role.All> {
|
||||
roleService.getAll()
|
||||
RoleService.getAll()
|
||||
.also { call.respond(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,14 @@ import com.infendro.account.config.AuthenticationPrincipal
|
||||
import com.infendro.account.dto.request.PostSessionRequest
|
||||
import com.infendro.account.service.SessionService
|
||||
import io.ktor.http.HttpStatusCode.Companion.OK
|
||||
import io.ktor.resources.Resource
|
||||
import io.ktor.server.auth.authenticate
|
||||
import io.ktor.server.auth.principal
|
||||
import io.ktor.server.request.receive
|
||||
import io.ktor.server.resources.delete
|
||||
import io.ktor.server.resources.get
|
||||
import io.ktor.resources.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.resources.*
|
||||
import io.ktor.server.resources.post
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.Routing
|
||||
import io.ktor.server.sessions.sessions
|
||||
import org.koin.ktor.ext.inject
|
||||
import io.ktor.server.sessions.*
|
||||
|
||||
@Resource("/session")
|
||||
private class Session {
|
||||
@@ -36,12 +33,10 @@ private class Session {
|
||||
}
|
||||
|
||||
fun Routing.session() {
|
||||
val sessionService by inject<SessionService>()
|
||||
|
||||
post<Session> {
|
||||
val request = call.receive<PostSessionRequest>()
|
||||
|
||||
sessionService.post(call.sessions, request)
|
||||
SessionService.post(call.sessions, request)
|
||||
call.respond(OK)
|
||||
}
|
||||
|
||||
@@ -49,7 +44,7 @@ fun Routing.session() {
|
||||
get<Session.All> {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
|
||||
sessionService.getAll(principal)
|
||||
SessionService.getAll(principal)
|
||||
.also { call.respond(it) }
|
||||
}
|
||||
|
||||
@@ -57,21 +52,21 @@ fun Routing.session() {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
val id = resource.id
|
||||
|
||||
sessionService.deleteId(principal, id)
|
||||
SessionService.deleteId(principal, id)
|
||||
call.respond(OK)
|
||||
}
|
||||
|
||||
get<Session.Current> {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
|
||||
sessionService.getCurrent(principal)
|
||||
SessionService.getCurrent(principal)
|
||||
.also { call.respond(it) }
|
||||
}
|
||||
|
||||
delete<Session.Current> {
|
||||
val principal = call.principal<AuthenticationPrincipal>()!!
|
||||
|
||||
sessionService.deleteCurrent(principal, call.sessions)
|
||||
SessionService.deleteCurrent(principal, call.sessions)
|
||||
call.respond(OK)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,7 @@ import com.infendro.account.util.Hasher
|
||||
import com.infendro.account.util.TokenGenerator
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
|
||||
class AccessService(
|
||||
private val accessRepository: AccessRepository,
|
||||
) {
|
||||
object AccessService {
|
||||
fun post(
|
||||
principal: AuthenticationPrincipal,
|
||||
): PostAccessResponse {
|
||||
@@ -23,7 +21,7 @@ class AccessService(
|
||||
throw ForbiddenException()
|
||||
|
||||
val token = TokenGenerator.generate()
|
||||
accessRepository.insert {
|
||||
AccessRepository.insert {
|
||||
this.tokenHash = Hasher.hash(token)
|
||||
}
|
||||
|
||||
@@ -38,7 +36,7 @@ class AccessService(
|
||||
if (principal.role != OWNER)
|
||||
throw ForbiddenException()
|
||||
|
||||
return accessRepository
|
||||
return AccessRepository
|
||||
.all()
|
||||
.map { it.toResponse() }
|
||||
}
|
||||
@@ -50,10 +48,10 @@ class AccessService(
|
||||
if (principal.role != OWNER)
|
||||
throw ForbiddenException()
|
||||
|
||||
val access = accessRepository
|
||||
val access = AccessRepository
|
||||
.singleOrNull { AccessTable.id eq id }
|
||||
?: throw NotFoundException()
|
||||
|
||||
accessRepository.delete(access)
|
||||
AccessRepository.delete(access)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,26 +20,22 @@ import com.infendro.account.util.SecureHasher
|
||||
import io.ktor.server.sessions.*
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
|
||||
class AccountService(
|
||||
private val accessRepository: AccessRepository,
|
||||
private val accountRepository: AccountRepository,
|
||||
private val sessionRepository: SessionRepository,
|
||||
) {
|
||||
object AccountService {
|
||||
fun post(
|
||||
request: PostAccountRequest,
|
||||
): PostAccountResponse {
|
||||
val access = accessRepository
|
||||
val access = AccessRepository
|
||||
.singleOrNull { AccessTable.tokenHash eq Hasher.hash(request.access.token) }
|
||||
?: throw UnauthorizedException()
|
||||
|
||||
accountRepository
|
||||
AccountRepository
|
||||
.singleOrNull { AccountTable.username eq request.username }
|
||||
?.run { throw ConflictException() }
|
||||
|
||||
accessRepository.delete(access)
|
||||
AccessRepository.delete(access)
|
||||
|
||||
val secret = OTP.generateSecret()
|
||||
accountRepository.insert {
|
||||
AccountRepository.insert {
|
||||
val salt = SecureHasher.generateSalt()
|
||||
|
||||
this.username = request.username
|
||||
@@ -60,7 +56,7 @@ class AccountService(
|
||||
if (principal.role != OWNER)
|
||||
throw ForbiddenException()
|
||||
|
||||
return accountRepository
|
||||
return AccountRepository
|
||||
.all()
|
||||
.map(AccountEntity::toResponse)
|
||||
}
|
||||
@@ -77,7 +73,7 @@ class AccountService(
|
||||
if (principal.role == OWNER)
|
||||
throw ForbiddenException()
|
||||
|
||||
accountRepository.delete(principal.account)
|
||||
AccountRepository.delete(principal.account)
|
||||
}
|
||||
|
||||
fun putCurrentUsername(
|
||||
@@ -88,10 +84,10 @@ class AccountService(
|
||||
if (!OTP.verify(principal.account.secret, request.otp))
|
||||
throw UnauthorizedException()
|
||||
|
||||
accountRepository.update(principal.account) {
|
||||
AccountRepository.update(principal.account) {
|
||||
this.username = request.username
|
||||
}
|
||||
sessionRepository.delete(principal.account.sessions())
|
||||
SessionRepository.delete(principal.account.sessions())
|
||||
|
||||
sessions.clear<AuthenticationSession>()
|
||||
}
|
||||
@@ -104,13 +100,13 @@ class AccountService(
|
||||
if (!OTP.verify(principal.account.secret, request.otp))
|
||||
throw UnauthorizedException()
|
||||
|
||||
accountRepository.update(principal.account) {
|
||||
AccountRepository.update(principal.account) {
|
||||
val salt = SecureHasher.generateSalt()
|
||||
|
||||
this.passwordHash = SecureHasher.hash(request.password, salt)
|
||||
this.passwordSalt = salt
|
||||
}
|
||||
sessionRepository.delete(principal.account.sessions())
|
||||
SessionRepository.delete(principal.account.sessions())
|
||||
|
||||
sessions.clear<AuthenticationSession>()
|
||||
}
|
||||
@@ -124,10 +120,10 @@ class AccountService(
|
||||
throw UnauthorizedException()
|
||||
|
||||
val secret = OTP.generateSecret()
|
||||
accountRepository.update(principal.account) {
|
||||
AccountRepository.update(principal.account) {
|
||||
this.secret = secret
|
||||
}
|
||||
sessionRepository.delete(principal.account.sessions())
|
||||
SessionRepository.delete(principal.account.sessions())
|
||||
|
||||
sessions.clear<AuthenticationSession>()
|
||||
|
||||
@@ -148,14 +144,14 @@ class AccountService(
|
||||
sessions: CurrentSession,
|
||||
id: Long,
|
||||
) {
|
||||
val session = sessionRepository
|
||||
val session = SessionRepository
|
||||
.singleOrNull { SessionTable.id eq id }
|
||||
?: throw NotFoundException()
|
||||
|
||||
if (session.account().id != principal.account.id)
|
||||
throw ForbiddenException()
|
||||
|
||||
sessionRepository.delete(session)
|
||||
SessionRepository.delete(session)
|
||||
|
||||
if (session.id == principal.session.id)
|
||||
sessions.clear<AuthenticationSession>()
|
||||
@@ -165,14 +161,14 @@ class AccountService(
|
||||
principal: AuthenticationPrincipal,
|
||||
id: Long,
|
||||
) {
|
||||
val account = accountRepository
|
||||
val account = AccountRepository
|
||||
.singleOrNull { AccountTable.id eq id }
|
||||
?: throw NotFoundException()
|
||||
|
||||
if (account.role !in principal.role.children)
|
||||
throw ForbiddenException()
|
||||
|
||||
accountRepository.delete(account)
|
||||
AccountRepository.delete(account)
|
||||
}
|
||||
|
||||
fun putIdRole(
|
||||
@@ -180,7 +176,7 @@ class AccountService(
|
||||
id: Long,
|
||||
request: PutAccountIdRoleRequest,
|
||||
) {
|
||||
val account = accountRepository
|
||||
val account = AccountRepository
|
||||
.singleOrNull { AccountTable.id eq id }
|
||||
?: throw NotFoundException()
|
||||
|
||||
@@ -190,7 +186,7 @@ class AccountService(
|
||||
if (request.role !in principal.role.children)
|
||||
throw ForbiddenException()
|
||||
|
||||
accountRepository.update(account) {
|
||||
AccountRepository.update(account) {
|
||||
role = request.role
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.infendro.account.dto.response.RoleResponse
|
||||
import com.infendro.account.dto.response.toResponse
|
||||
import com.infendro.account.model.Role
|
||||
|
||||
class RoleService {
|
||||
object RoleService {
|
||||
fun getAll(): List<RoleResponse> {
|
||||
return Role.ALL
|
||||
.map(Role::toResponse)
|
||||
|
||||
@@ -22,15 +22,12 @@ import io.ktor.server.sessions.*
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList
|
||||
|
||||
class SessionService(
|
||||
private val accountRepository: AccountRepository,
|
||||
private val sessionRepository: SessionRepository,
|
||||
) {
|
||||
object SessionService {
|
||||
fun post(
|
||||
sessions: CurrentSession,
|
||||
request: PostSessionRequest,
|
||||
) {
|
||||
val account = accountRepository
|
||||
val account = AccountRepository
|
||||
.singleOrNull { AccountTable.username eq request.username }
|
||||
?: throw NotFoundException()
|
||||
|
||||
@@ -41,7 +38,7 @@ class SessionService(
|
||||
throw UnauthorizedException()
|
||||
|
||||
val token = TokenGenerator.generate()
|
||||
sessionRepository.insert {
|
||||
SessionRepository.insert {
|
||||
this.tokenHash = Hasher.hash(token)
|
||||
this.account = account
|
||||
}
|
||||
@@ -57,7 +54,7 @@ class SessionService(
|
||||
if (principal.role == USER)
|
||||
throw ForbiddenException()
|
||||
|
||||
return accountRepository
|
||||
return AccountRepository
|
||||
.all { AccountTable.role inList principal.role.children }
|
||||
.flatMap { it.sessions() }
|
||||
.map(SessionEntity::toResponse)
|
||||
@@ -70,14 +67,14 @@ class SessionService(
|
||||
if (principal.role == USER)
|
||||
throw ForbiddenException()
|
||||
|
||||
val session = sessionRepository
|
||||
val session = SessionRepository
|
||||
.singleOrNull { SessionTable.id eq id }
|
||||
?: throw NotFoundException()
|
||||
|
||||
if (session.account().role !in principal.role.children)
|
||||
throw ForbiddenException()
|
||||
|
||||
sessionRepository.delete(session)
|
||||
SessionRepository.delete(session)
|
||||
}
|
||||
|
||||
fun getCurrent(
|
||||
@@ -90,7 +87,7 @@ class SessionService(
|
||||
principal: AuthenticationPrincipal,
|
||||
sessions: CurrentSession,
|
||||
) {
|
||||
sessionRepository.delete(principal.session)
|
||||
SessionRepository.delete(principal.session)
|
||||
|
||||
sessions.clear<AuthenticationSession>()
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import com.infendro.kdf.PBKDF2
|
||||
import com.infendro.random.PRNG
|
||||
|
||||
object SecureHasher {
|
||||
private val kdf = PBKDF2(SHA256)
|
||||
private val random = PRNG.HMAC
|
||||
private val kdf = PBKDF2(SHA256)
|
||||
|
||||
fun hash(
|
||||
value: String,
|
||||
|
||||
Reference in New Issue
Block a user