Skip to content

Commit

Permalink
feat: complete translation service implementation on daemon
Browse files Browse the repository at this point in the history
  • Loading branch information
d1snin committed Aug 27, 2023
1 parent c28c0f7 commit fdaf46e
Show file tree
Hide file tree
Showing 25 changed files with 561 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package dev.d1s.beam.bundle.route

import dev.d1s.beam.commons.validation.Regex as CommonRegex
import dev.d1s.beam.commons.Regex as CommonRegex

object Paths {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@
* limitations under the License.
*/

package dev.d1s.beam.daemon.database
package dev.d1s.beam.commons

import org.koin.core.context.GlobalContext
import org.ktorm.database.Database
import org.ktorm.database.Transaction
public object GlobalTranslation {

private val database by lazy {
GlobalContext.get().get<Database>()
}
public const val TEST_LOCATION: TextLocation = "test"

suspend fun <T> transaction(block: suspend (Transaction) -> T): T =
database.useTransaction { transaction ->
block(transaction)
}
public val Locations: List<TextLocation> = listOf(TEST_LOCATION)

public val Default: Translation = Translation(
space = null,
languageCode = "en",
languageName = "English",
translations = mapOf(
TEST_LOCATION to "test translation"
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public object Paths {
public const val DELETE_BLOCK: String = "/blocks/{$ID_PARAMETER}"

public const val POST_TRANSLATION: String = "/translations"
public const val GET_TRANSLATION: String = "/translations/${LANGUAGE_CODE_PARAMETER}"
public const val GET_TRANSLATION: String = "/translations/{$LANGUAGE_CODE_PARAMETER}"
public const val GET_TRANSLATIONS: String = "/translations"
public const val PUT_TRANSLATION: String = "/translations/${LANGUAGE_CODE_PARAMETER}"
public const val DELETE_TRANSLATION: String = "/translations/${LANGUAGE_CODE_PARAMETER}"
public const val PUT_TRANSLATION: String = "/translations/{$LANGUAGE_CODE_PARAMETER}"
public const val DELETE_TRANSLATION: String = "/translations/{$LANGUAGE_CODE_PARAMETER}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package dev.d1s.beam.commons.validation
package dev.d1s.beam.commons

import kotlin.text.Regex

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,22 @@ package dev.d1s.beam.commons

import kotlinx.serialization.Serializable

public typealias TranslationQualifier = String

public typealias Template = String

public typealias LanguageCode = String
public typealias LanguageName = String

public typealias TextLocation = String

public typealias TranslatedText = String

public typealias TranslationMap = Map<TextLocation, TranslatedText>

public fun TranslationQualifier(spaceId: SpaceId?, languageCode: LanguageCode): TranslationQualifier =
(spaceId?.let { "$it-" } ?: "") + languageCode

public sealed interface AbstractTranslation {

public val languageCode: LanguageCode
Expand All @@ -36,7 +45,7 @@ public sealed interface AbstractTranslation {

@Serializable
public data class Translation(
val space: SpaceId,
val space: SpaceId?,
override val languageCode: LanguageCode,
override val languageName: LanguageName,
override val translations: TranslationMap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public typealias ContentEntityTypeName = String
public typealias ContentEntityParameterName = String
public typealias ContentEntityParameterValue = String
public typealias ContentEntityParameters = Map<ContentEntityParameterName, ContentEntityParameterValue>
public typealias ContentEntityParameter = Map.Entry<ContentEntityParameterName, ContentEntityParameterValue>

@Serializable
public data class ContentEntity(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ public sealed class ContentEntityTypeDefinition(public val name: ContentEntityTy
required: Boolean = false,
translatable: Boolean = false
): ContentEntityParameterDefinition =
ContentEntityParameterDefinition(name, required, translatable)
ContentEntityParameterDefinition(name, required, translatable).also {
internalParameters += it
}
}

public data object VoidContentEntityTypeDefinition : ContentEntityTypeDefinition(name = "void") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package dev.d1s.beam.commons.event

import dev.d1s.beam.commons.BlockId
import dev.d1s.beam.commons.SpaceId
import dev.d1s.beam.commons.TranslationQualifier
import dev.d1s.ktor.events.commons.EventReference
import dev.d1s.ktor.events.commons.ref

Expand All @@ -27,11 +28,19 @@ public object EventReferences {

public val blockCreated: EventReference = ref("block-created")

public val translationCreated: EventReference = ref("translation-created")

public fun spaceUpdated(id: SpaceId? = null): EventReference = ref("space-updated", id)

public fun spaceRemoved(id: SpaceId? = null): EventReference = ref("space-removed", id)

public fun blockUpdated(id: BlockId? = null): EventReference = ref("block-updated", id)

public fun blockRemoved(id: BlockId? = null): EventReference = ref("block-removed", id)

public fun translationUpdated(qualifier: TranslationQualifier? = null): EventReference =
ref("translation-updated", qualifier)

public fun translationRemoved(qualifier: TranslationQualifier? = null): EventReference =
ref("translation-removed", qualifier)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package dev.d1s.beam.commons.validation

import dev.d1s.beam.commons.Metadata
import dev.d1s.beam.commons.MetadataEntry
import dev.d1s.beam.commons.Regex
import dev.d1s.exkt.konform.matches
import io.konform.validation.Validation
import io.konform.validation.jsonschema.maxItems
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package dev.d1s.beam.commons.validation

import dev.d1s.beam.commons.ModifiedRootSpace
import dev.d1s.beam.commons.ModifiedSpace
import dev.d1s.beam.commons.Regex
import dev.d1s.beam.commons.SpaceSlug
import dev.d1s.exkt.konform.matches
import io.konform.validation.Validation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package dev.d1s.beam.commons.validation

import dev.d1s.beam.commons.AbstractTranslation
import dev.d1s.beam.commons.Regex
import dev.d1s.beam.commons.TextLocation
import dev.d1s.beam.commons.TranslatedText
import dev.d1s.exkt.konform.matches
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class TranslationDtoConverter : DtoConverter<TranslationEntity, Translation>, Ko
override suspend fun convertToDto(entity: TranslationEntity) =
entity.run {
Translation(
space.id.toString(),
space?.id?.toString(),
languageCode,
requireNotNull(languageName) { "Language name is required in DTO" },
translations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import org.koin.core.component.inject
import org.ktorm.database.Database
import org.ktorm.dsl.and
import org.ktorm.dsl.eq
import org.ktorm.dsl.isNull
import org.ktorm.entity.add
import org.ktorm.entity.filter
import org.ktorm.entity.find
Expand All @@ -35,10 +36,10 @@ interface TranslationRepository {

suspend fun addTranslation(translation: TranslationEntity): Result<TranslationEntity>

suspend fun findTranslationsBySpace(space: SpaceEntity): Result<TranslationEntities>
suspend fun findTranslationsBySpace(space: SpaceEntity?): Result<TranslationEntities>

suspend fun findTranslationBySpaceAndLanguageCode(
space: SpaceEntity,
space: SpaceEntity?,
languageCode: LanguageCode
): Result<TranslationEntity>

Expand All @@ -54,25 +55,28 @@ class DefaultTranslationRepository : TranslationRepository, KoinComponent {
override suspend fun addTranslation(translation: TranslationEntity): Result<TranslationEntity> =
withIoCatching {
translation.apply {
setId()
database.translations.add(this)
}
}

override suspend fun findTranslationsBySpace(space: SpaceEntity): Result<TranslationEntities> =
override suspend fun findTranslationsBySpace(space: SpaceEntity?): Result<TranslationEntities> =
withIoCatching {
database.translations.filter {
it.spaceId eq space.id
database.translations.filter { translation ->
makeBinaryExpression(translation, space)
}.toList()
}

override suspend fun findTranslationBySpaceAndLanguageCode(
space: SpaceEntity,
space: SpaceEntity?,
languageCode: LanguageCode
): Result<TranslationEntity> =
withIoCatching {
database.translations.find {
(it.spaceId eq space.id) and (it.languageCode eq languageCode)
} ?: error("Translation not found by space ${space.id} and language code '$languageCode'")
database.translations.find { translation ->
val spaceMatches = makeBinaryExpression(translation, space)

spaceMatches and (translation.languageCode eq languageCode)
} ?: error("Translation not found by space ${space?.id} and language code '$languageCode'")
}

override suspend fun updateTranslation(translation: TranslationEntity): Result<TranslationEntity> =
Expand All @@ -87,4 +91,9 @@ class DefaultTranslationRepository : TranslationRepository, KoinComponent {
translation.delete()
Unit
}

private fun makeBinaryExpression(translation: Translations, space: SpaceEntity?) =
space?.let {
translation.spaceId eq it.id
} ?: translation.spaceId.isNull()
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ package dev.d1s.beam.daemon.database

import dev.d1s.beam.commons.TranslationMap
import dev.d1s.beam.daemon.entity.TranslationEntity
import dev.d1s.exkt.ktorm.UuidIdentifiedEntities
import org.ktorm.jackson.json
import org.ktorm.schema.Table
import org.ktorm.schema.text
import org.ktorm.schema.uuid

object Translations : Table<TranslationEntity>(tableName = "translation") {
@Suppress("unused")
object Translations : UuidIdentifiedEntities<TranslationEntity>(tableName = "translation") {

val spaceId = uuid("space_id").references(Spaces) {
it.space
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ package dev.d1s.beam.daemon.entity
import dev.d1s.beam.commons.LanguageCode
import dev.d1s.beam.commons.LanguageName
import dev.d1s.beam.commons.TranslationMap
import dev.d1s.exkt.ktorm.UuidIdentified
import org.ktorm.entity.Entity

typealias TranslationEntities = List<TranslationEntity>

interface TranslationEntity : Entity<TranslationEntity> {
interface TranslationEntity : UuidIdentified<TranslationEntity> {

var space: SpaceEntity
var space: SpaceEntity?

var languageCode: LanguageCode

Expand All @@ -37,4 +38,4 @@ interface TranslationEntity : Entity<TranslationEntity> {
}

val TranslationEntity.asString
get() = "TranslationEntity{space = ${space.id}, languageCode = $languageCode, languageName = $languageName}"
get() = "TranslationEntity{languageCode = $languageCode, languageName = $languageName}"
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import dev.d1s.beam.daemon.exception.ForbiddenException
import dev.d1s.beam.daemon.service.AuthService
import dev.d1s.beam.daemon.service.TranslationService
import dev.d1s.beam.daemon.util.requiredLanguageCodeParameter
import dev.d1s.beam.daemon.util.requiredSpaceIdQueryParameter
import dev.d1s.beam.daemon.util.spaceIdQueryParameter
import dev.d1s.exkt.ktor.server.koin.configuration.Route
import io.ktor.http.*
import io.ktor.server.application.*
Expand All @@ -44,11 +44,13 @@ class DeleteTranslationRoute : Route, KoinComponent {
override fun Routing.apply() {
authenticate {
delete(Paths.DELETE_TRANSLATION) {
val spaceId = call.requiredSpaceIdQueryParameter
val spaceId = call.spaceIdQueryParameter
val languageCode = call.requiredLanguageCodeParameter

val spaceModificationAllowed = authService.isSpaceModificationAllowed(call.jwtSubject, spaceId)
.getOrThrow()
val spaceModificationAllowed = authService.isSpaceModificationAllowed(
call.jwtSubject,
spaceId ?: TranslationService.GLOBAL_TRANSLATION_PERMITTED_SPACE
).getOrThrow()

if (spaceModificationAllowed) {
translationService.removeTranslation(spaceId, languageCode).getOrThrow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import dev.d1s.beam.daemon.entity.TranslationEntity
import dev.d1s.beam.daemon.exception.ForbiddenException
import dev.d1s.beam.daemon.service.AuthService
import dev.d1s.beam.daemon.service.TranslationService
import dev.d1s.beam.daemon.util.requiredSpaceIdQueryParameter
import dev.d1s.beam.daemon.util.spaceIdQueryParameter
import dev.d1s.exkt.dto.DtoConverter
import dev.d1s.exkt.dto.requiredDto
import dev.d1s.exkt.ktor.server.koin.configuration.Route
Expand Down Expand Up @@ -57,11 +57,13 @@ class PostTranslationRoute : Route, KoinComponent {
val body = call.receive<TranslationModification>()
validateTranslation(body)

val spaceId = call.requiredSpaceIdQueryParameter
val spaceId = call.spaceIdQueryParameter

val spaceModificationAllowed =
authService.isSpaceModificationAllowed(call.jwtSubject, spaceId)
.getOrThrow()
authService.isSpaceModificationAllowed(
call.jwtSubject,
spaceId ?: TranslationService.GLOBAL_TRANSLATION_PERMITTED_SPACE
).getOrThrow()

if (spaceModificationAllowed) {
val translation = translationModificationDtoConverter.convertToEntity(body)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class PutTranslationRoute : Route, KoinComponent {
val spaceModificationAllowed =
authService.isSpaceModificationAllowed(
call.jwtSubject,
spaceId ?: TranslationService.GLOBAL_SPACE_IDENTIFIER
spaceId ?: TranslationService.GLOBAL_TRANSLATION_PERMITTED_SPACE
).getOrThrow()

if (spaceModificationAllowed) {
Expand Down
Loading

0 comments on commit fdaf46e

Please sign in to comment.