Files
antifed/backend/src/main/kotlin/services/Action.kt
T

166 lines
5.1 KiB
Kotlin

package dev.svitan.services
import io.ktor.server.plugins.NotFoundException
import kotlinx.serialization.Serializable
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.transaction
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.UUID
enum class ActionKind {
TEXT, SCRIPT;
companion object {
fun from(it: String): ActionKind {
return when (it.lowercase()) {
"text" -> TEXT
"script" -> SCRIPT
else -> throw IllegalArgumentException("Invalid action kind: $it")
}
}
}
override fun toString(): String {
return super.toString().lowercase()
}
}
@Serializable
data class ActionDTO(
val id: String,
val name: String,
val kind: ActionKind,
val source: String,
val authId: String,
val createdAt: String,
val updatedAt: String
)
@Serializable
data class NewActionDTO(
val name: String,
val kind: String,
val source: String,
val authId: String
)
@Serializable
data class UpdateActionDTO(
val name: String?,
val kind: String?,
val source: String?
)
@Serializable
data class RunActionDTO(
val pin: String,
val key: String
)
class ActionService {
object Actions : Table("actions") {
val id = uuid("id").autoGenerate()
val name = text("name").uniqueIndex()
val kind = text("kind")
val aSource = text("source") // `source` is another property
val auth = uuid("auth_id").references(AuthService.Auths.id)
val createdAt = text("created_at")
val updatedAt = text("updated_at")
override val primaryKey = PrimaryKey(id)
}
companion object {
fun init() {
transaction {
SchemaUtils.create(Actions)
}
}
fun create(action: NewActionDTO): UUID {
val id = transaction {
val now = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
val authId = UUID.fromString(action.authId)
AuthService.read(authId) ?: throw NotFoundException("auth not found")
Actions.insert {
it[name] = action.name
it[kind] = ActionKind.from(action.kind).toString()
it[aSource] = if (action.kind == ActionKind.SCRIPT.toString()) "" else action.source
it[auth] = authId
it[createdAt] = now
it[updatedAt] = now
}[Actions.id]
}
if (action.kind == ActionKind.SCRIPT.toString()) {
ExecutorService.writeFile(id, action.source)
}
return id
}
fun read(id: UUID): ActionDTO? = transaction {
Actions.selectAll()
.where { Actions.id eq id }
.map {
ActionDTO(
it[Actions.id].toString(),
it[Actions.name],
ActionKind.from(it[Actions.kind]),
it[Actions.aSource],
it[Actions.auth].toString(),
it[Actions.createdAt],
it[Actions.updatedAt]
)
}.singleOrNull()
}
fun readAll(): List<ActionDTO> = transaction {
Actions.selectAll().map {
ActionDTO(
it[Actions.id].toString(),
it[Actions.name],
ActionKind.from(it[Actions.kind]),
it[Actions.aSource],
it[Actions.auth].toString(),
it[Actions.createdAt],
it[Actions.updatedAt]
)
}
}
fun update(id: UUID, action: UpdateActionDTO) {
val oldAction = read(id) ?: throw NotFoundException("action not found")
transaction {
val now = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
Actions.update({ Actions.id eq id }) {
if (action.name != null) it[name] = action.name
if (action.kind != null) it[kind] = ActionKind.from(action.kind).toString()
if (action.source != null) it[aSource] = action.source
it[updatedAt] = now
}
}
if (action.kind == ActionKind.SCRIPT.toString() && action.source != null) {
ExecutorService.writeFile(id, action.source)
} else if (action.kind == ActionKind.TEXT.toString() && oldAction.kind == ActionKind.SCRIPT) {
ExecutorService.deleteFile(id)
}
}
fun delete(id: UUID) {
val action = read(id) ?: throw NotFoundException("action not found")
transaction {
Actions.deleteWhere { Actions.id eq id }
}
if (action.kind == ActionKind.SCRIPT) {
ExecutorService.deleteFile(id)
}
}
}
}