From 0a3245ddf958a7921b3460e7027d24acbf33118c Mon Sep 17 00:00:00 2001 From: grimsi <9295182+grimsi@users.noreply.github.com> Date: Sun, 8 Sep 2024 20:54:31 +0200 Subject: [PATCH] Implement dynamic config management Start implementation of library management --- .../de/grimsi/gameyfin/GameyfinApplication.kt | 2 + .../gameyfin/config/ConfigController.kt | 28 ++++ .../grimsi/gameyfin/config/ConfigProperty.kt | 38 +++++ .../grimsi/gameyfin/config/ConfigService.kt | 133 ++++++++++++++++++ .../gameyfin/config/entities/ConfigEntry.kt | 19 +++ .../config/persistence/ConfigRepository.kt | 6 + .../gameyfin/libraries/LibraryEndpoint.kt | 18 +++ .../gameyfin/libraries/LibraryService.kt | 26 ++++ .../gameyfin/libraries/entities/Library.kt | 15 ++ .../persistence/LibraryRepository.kt | 6 + .../grimsi/gameyfin/{config => meta}/Roles.kt | 2 +- .../{config => meta}/SecurityConfig.kt | 2 +- .../de/grimsi/gameyfin/meta/WebConfig.kt | 14 ++ .../annotations/DynamicAccessInterceptor.kt | 38 +++++ .../meta/annotations/DynamicPublicAccess.kt | 14 ++ .../grimsi/gameyfin/setup/SetupDataLoader.kt | 2 +- .../de/grimsi/gameyfin/setup/SetupEndpoint.kt | 14 +- .../de/grimsi/gameyfin/setup/SetupService.kt | 2 +- .../grimsi/gameyfin/system/SystemEndpoint.kt | 2 +- .../de/grimsi/gameyfin/users/RoleService.kt | 2 +- .../de/grimsi/gameyfin/users/UserEndpoint.kt | 16 +-- .../de/grimsi/gameyfin/users/UserService.kt | 8 +- .../users/dto/{UserInfo.kt => UserInfoDto.kt} | 2 +- ...Registration.kt => UserRegistrationDto.kt} | 2 +- .../users/util/UserDetailsExtensions.kt | 2 +- 25 files changed, 385 insertions(+), 28 deletions(-) create mode 100644 src/main/kotlin/de/grimsi/gameyfin/config/ConfigController.kt create mode 100644 src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperty.kt create mode 100644 src/main/kotlin/de/grimsi/gameyfin/config/ConfigService.kt create mode 100644 src/main/kotlin/de/grimsi/gameyfin/config/entities/ConfigEntry.kt create mode 100644 src/main/kotlin/de/grimsi/gameyfin/config/persistence/ConfigRepository.kt create mode 100644 src/main/kotlin/de/grimsi/gameyfin/libraries/LibraryEndpoint.kt create mode 100644 src/main/kotlin/de/grimsi/gameyfin/libraries/LibraryService.kt create mode 100644 src/main/kotlin/de/grimsi/gameyfin/libraries/entities/Library.kt create mode 100644 src/main/kotlin/de/grimsi/gameyfin/libraries/persistence/LibraryRepository.kt rename src/main/kotlin/de/grimsi/gameyfin/{config => meta}/Roles.kt (92%) rename src/main/kotlin/de/grimsi/gameyfin/{config => meta}/SecurityConfig.kt (98%) create mode 100644 src/main/kotlin/de/grimsi/gameyfin/meta/WebConfig.kt create mode 100644 src/main/kotlin/de/grimsi/gameyfin/meta/annotations/DynamicAccessInterceptor.kt create mode 100644 src/main/kotlin/de/grimsi/gameyfin/meta/annotations/DynamicPublicAccess.kt rename src/main/kotlin/de/grimsi/gameyfin/users/dto/{UserInfo.kt => UserInfoDto.kt} (83%) rename src/main/kotlin/de/grimsi/gameyfin/users/dto/{UserRegistration.kt => UserRegistrationDto.kt} (77%) diff --git a/src/main/kotlin/de/grimsi/gameyfin/GameyfinApplication.kt b/src/main/kotlin/de/grimsi/gameyfin/GameyfinApplication.kt index baa1b18..bf71a00 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/GameyfinApplication.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/GameyfinApplication.kt @@ -2,9 +2,11 @@ package de.grimsi.gameyfin import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication +import org.springframework.transaction.annotation.EnableTransactionManagement @SpringBootApplication +@EnableTransactionManagement class GameyfinApplication fun main(args: Array) { diff --git a/src/main/kotlin/de/grimsi/gameyfin/config/ConfigController.kt b/src/main/kotlin/de/grimsi/gameyfin/config/ConfigController.kt new file mode 100644 index 0000000..8d04ae5 --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/config/ConfigController.kt @@ -0,0 +1,28 @@ +package de.grimsi.gameyfin.config + +import com.vaadin.hilla.Endpoint +import de.grimsi.gameyfin.meta.Roles +import jakarta.annotation.security.RolesAllowed + +@Endpoint +@RolesAllowed(Roles.Names.SUPERADMIN, Roles.Names.ADMIN) +class ConfigController( + private val appConfigService: ConfigService +) { + + fun getConfig(key: String): String { + return appConfigService.getConfigValue(key) + } + + fun setConfig(config: Pair) { + appConfigService.setConfigValue(config.first, config.second) + } + + fun resetConfig(key: String) { + appConfigService.resetConfigValue(key) + } + + fun deleteConfig(key: String) { + appConfigService.deleteConfig(key) + } +} diff --git a/src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperty.kt b/src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperty.kt new file mode 100644 index 0000000..c06e4e8 --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperty.kt @@ -0,0 +1,38 @@ +package de.grimsi.gameyfin.config + +import java.io.Serializable +import kotlin.reflect.KClass + +sealed class ConfigProperty(val type: KClass, val key: String, val default: T? = null) { + + /** Libraries */ + // Allow access to game libraries without login + data object LibraryAllowPublicAccess : + ConfigProperty(Boolean::class, "library.allow-public-access", false) + + // Enable automatic library scanning using file system watchers + data object LibraryEnableFilesystemWatcher : + ConfigProperty(Boolean::class, "library.scan.enable-filesystem-watcher", true) + + // Enable periodic refresh of video game meta-data and set the schedule (default is once per week) + data object LibraryMetadataUpdateEnabled : + ConfigProperty(Boolean::class, "library.metadata.update.enabled", true) + + data object LibraryMetadataUpdateSchedule : + ConfigProperty(String::class, "library.metadata.update.schedule", "0 0 * * 0") + + /** User management */ + // Allow new users to sign up by themselves + data object UsersAllowNewSignUps : ConfigProperty(Boolean::class, "users.sign-ups.allow", false) + + // If an administrator needs to confirm new sign-ups before they are allowed to log in + data object UsersConfirmNewSignUps : + ConfigProperty(Boolean::class, "users.sign-ups.confirm", false) + + /** Notifications */ + // Settings for the mail server used by Gameyfin to send notifications + data object NotificationsEmailHost : ConfigProperty(String::class, "notifications.email.host") + data object NotificationsEmailPort : ConfigProperty(String::class, "notifications.email.port") + data object NotificationsEmailUsername : ConfigProperty(String::class, "notifications.email.username") + data object NotificationsEmailPassword : ConfigProperty(String::class, "notifications.email.password") +} \ No newline at end of file diff --git a/src/main/kotlin/de/grimsi/gameyfin/config/ConfigService.kt b/src/main/kotlin/de/grimsi/gameyfin/config/ConfigService.kt new file mode 100644 index 0000000..388ceaf --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/config/ConfigService.kt @@ -0,0 +1,133 @@ +package de.grimsi.gameyfin.config + +import de.grimsi.gameyfin.config.entities.ConfigEntry +import de.grimsi.gameyfin.config.persistence.ConfigRepository +import jakarta.transaction.Transactional +import org.springframework.stereotype.Service +import java.io.Serializable +import kotlin.reflect.safeCast + +@Service +@Transactional +class ConfigService( + private val appConfigRepository: ConfigRepository +) { + + /** + * Get the current value of a config property in a type-safe way. + * Used internally. + * + * @param configProperty: The config property containing necessary type information + * @return The current value if set or the default value + * @throws IllegalArgumentException if no value is set and no default value exists + */ + fun getConfigValue(configProperty: ConfigProperty): T { + val appConfig = appConfigRepository.findById(configProperty.key).orElse(null) + return if (appConfig != null) { + getValue(appConfig.value, configProperty) + } else { + configProperty.default ?: throw IllegalArgumentException("No value found for key: ${configProperty.key}") + } + } + + /** + * Get the current value of a config property in a *not* type-safe way. + * Used for the external API. + * + * @param key: The key of the config property + * @return The current value if set or the default value + * @throws IllegalArgumentException if no value is set and no default value exists + */ + fun getConfigValue(key: String): String { + val configProperty = findConfigProperty(key) + val appConfig = appConfigRepository.findById(configProperty.key).orElse(null) + + return if (appConfig != null) { + getValue(appConfig.value, configProperty).toString() + } else { + configProperty.default?.toString() + ?: throw IllegalArgumentException("No value found for key: ${configProperty.key}") + } + } + + /** + * Set the value for a specified key. + * Checks if the value can be cast to the type defined for the config property. + * + * @param key: Key of the target config property + * @param value: Value to set the config property to + * @throws IllegalArgumentException if the value can't be cast to the type defined for the config property + */ + fun setConfigValue(key: String, value: T) { + val configKey = findConfigProperty(key) + + if (configKey.type.safeCast(value) == null) { + throw IllegalArgumentException("Type mismatch for key: ${configKey.key}") + } + + val appConfig = ConfigEntry(configKey.key, value.toString()) + appConfigRepository.save(appConfig) + } + + /** + * Reset a given config property to its default value if it has a default value. + * Otherwise, delete the config key from the database. + * + * @param key: Key of the config property + */ + fun resetConfigValue(key: String) { + val configKey = findConfigProperty(key) + + if (configKey.default == null) { + deleteConfig(key) + return + } + + val appConfig = appConfigRepository.findById(configKey.key).orElse(null) + if (appConfig != null) { + appConfig.value = configKey.default.toString() + appConfigRepository.save(appConfig) + } + } + + /** + * Remove a config property from the database + * + * @param key: Key of the config property + */ + fun deleteConfig(key: String) { + val configKey = findConfigProperty(key) + appConfigRepository.deleteById(configKey.key) + } + + /** + * Get the value of the config property in a type-safe way. + */ + @Suppress("UNCHECKED_CAST") + private fun getValue(value: String, configProperty: ConfigProperty): T { + return when (configProperty.type) { + String::class -> value as T + Boolean::class -> value.toBoolean() as T + Number::class -> value.toInt() as T + Float::class -> value.toFloat() as T + else -> { + throw RuntimeException("Unknown config type ${configProperty.type}: '$value' for key ${configProperty.key}") + } + } + } + + /** + * Returns a config property + */ + private fun findConfigProperty(key: String): ConfigProperty<*> { + // Use reflection to get all objects defined within ConfigKey + val configProperties = ConfigProperty::class.sealedSubclasses.flatMap { subclass -> + subclass.objectInstance?.let { listOf(it) } ?: listOf() + } + + // Find the matching config key based on the string key + return configProperties.find { it.key == key } + ?: throw IllegalArgumentException("Unknown configuration key: $key") + } +} + diff --git a/src/main/kotlin/de/grimsi/gameyfin/config/entities/ConfigEntry.kt b/src/main/kotlin/de/grimsi/gameyfin/config/entities/ConfigEntry.kt new file mode 100644 index 0000000..557eefb --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/config/entities/ConfigEntry.kt @@ -0,0 +1,19 @@ +package de.grimsi.gameyfin.config.entities + +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Id +import jakarta.persistence.Table +import jakarta.validation.constraints.NotNull + +@Entity +@Table(name = "app_config") +class ConfigEntry( + @Id + @NotNull + @Column(unique = true) + val key: String, + + @NotNull + var value: String +) \ No newline at end of file diff --git a/src/main/kotlin/de/grimsi/gameyfin/config/persistence/ConfigRepository.kt b/src/main/kotlin/de/grimsi/gameyfin/config/persistence/ConfigRepository.kt new file mode 100644 index 0000000..d69fc3b --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/config/persistence/ConfigRepository.kt @@ -0,0 +1,6 @@ +package de.grimsi.gameyfin.config.persistence + +import de.grimsi.gameyfin.config.entities.ConfigEntry +import org.springframework.data.jpa.repository.JpaRepository + +interface ConfigRepository : JpaRepository diff --git a/src/main/kotlin/de/grimsi/gameyfin/libraries/LibraryEndpoint.kt b/src/main/kotlin/de/grimsi/gameyfin/libraries/LibraryEndpoint.kt new file mode 100644 index 0000000..36eeab3 --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/libraries/LibraryEndpoint.kt @@ -0,0 +1,18 @@ +package de.grimsi.gameyfin.libraries + +import com.vaadin.hilla.Endpoint +import de.grimsi.gameyfin.libraries.entities.Library +import de.grimsi.gameyfin.meta.Roles +import jakarta.annotation.security.RolesAllowed + +@Endpoint +class LibraryEndpoint( + private val libraryService: LibraryService +) { + @RolesAllowed(Roles.Names.SUPERADMIN, Roles.Names.ADMIN) + fun getAllLibraries(): Collection { + return libraryService.getAllLibraries() + } + + +} \ No newline at end of file diff --git a/src/main/kotlin/de/grimsi/gameyfin/libraries/LibraryService.kt b/src/main/kotlin/de/grimsi/gameyfin/libraries/LibraryService.kt new file mode 100644 index 0000000..9d6c073 --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/libraries/LibraryService.kt @@ -0,0 +1,26 @@ +package de.grimsi.gameyfin.libraries + +import de.grimsi.gameyfin.libraries.entities.Library +import de.grimsi.gameyfin.libraries.persistence.LibraryRepository +import org.springframework.stereotype.Service + +@Service +class LibraryService( + private val libraryRepository: LibraryRepository +) { + fun createLibrary(library: Library): Library { + return libraryRepository.save(library) + } + + fun getAllLibraries(): Collection { + return libraryRepository.findAll() + } + + fun deleteLibrary(library: Library) { + libraryRepository.delete(library) + } + + fun updateLibrary(library: Library) { + libraryRepository.save(library) + } +} \ No newline at end of file diff --git a/src/main/kotlin/de/grimsi/gameyfin/libraries/entities/Library.kt b/src/main/kotlin/de/grimsi/gameyfin/libraries/entities/Library.kt new file mode 100644 index 0000000..de3e636 --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/libraries/entities/Library.kt @@ -0,0 +1,15 @@ +package de.grimsi.gameyfin.libraries.entities + +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id + +@Entity +class Library( + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + var id: Long? = null, + + var path: String +) \ No newline at end of file diff --git a/src/main/kotlin/de/grimsi/gameyfin/libraries/persistence/LibraryRepository.kt b/src/main/kotlin/de/grimsi/gameyfin/libraries/persistence/LibraryRepository.kt new file mode 100644 index 0000000..3a9bca2 --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/libraries/persistence/LibraryRepository.kt @@ -0,0 +1,6 @@ +package de.grimsi.gameyfin.libraries.persistence + +import de.grimsi.gameyfin.libraries.entities.Library +import org.springframework.data.jpa.repository.JpaRepository + +interface LibraryRepository : JpaRepository \ No newline at end of file diff --git a/src/main/kotlin/de/grimsi/gameyfin/config/Roles.kt b/src/main/kotlin/de/grimsi/gameyfin/meta/Roles.kt similarity index 92% rename from src/main/kotlin/de/grimsi/gameyfin/config/Roles.kt rename to src/main/kotlin/de/grimsi/gameyfin/meta/Roles.kt index 8667e77..b575c5d 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/config/Roles.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/meta/Roles.kt @@ -1,4 +1,4 @@ -package de.grimsi.gameyfin.config +package de.grimsi.gameyfin.meta enum class Roles(val roleName: String) { SUPERADMIN(Names.SUPERADMIN), diff --git a/src/main/kotlin/de/grimsi/gameyfin/config/SecurityConfig.kt b/src/main/kotlin/de/grimsi/gameyfin/meta/SecurityConfig.kt similarity index 98% rename from src/main/kotlin/de/grimsi/gameyfin/config/SecurityConfig.kt rename to src/main/kotlin/de/grimsi/gameyfin/meta/SecurityConfig.kt index 6ff2c70..d1cd233 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/config/SecurityConfig.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/meta/SecurityConfig.kt @@ -1,4 +1,4 @@ -package de.grimsi.gameyfin.config +package de.grimsi.gameyfin.meta import com.vaadin.flow.spring.security.VaadinWebSecurity import org.springframework.context.annotation.Bean diff --git a/src/main/kotlin/de/grimsi/gameyfin/meta/WebConfig.kt b/src/main/kotlin/de/grimsi/gameyfin/meta/WebConfig.kt new file mode 100644 index 0000000..d0896e6 --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/meta/WebConfig.kt @@ -0,0 +1,14 @@ +package de.grimsi.gameyfin.meta + +import de.grimsi.gameyfin.meta.annotations.DynamicAccessInterceptor +import org.springframework.context.annotation.Configuration +import org.springframework.web.servlet.config.annotation.InterceptorRegistry +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer + +@Configuration +class WebConfig(val dynamicAccessInterceptor: DynamicAccessInterceptor) : WebMvcConfigurer { + + override fun addInterceptors(registry: InterceptorRegistry) { + registry.addInterceptor(dynamicAccessInterceptor) + } +} diff --git a/src/main/kotlin/de/grimsi/gameyfin/meta/annotations/DynamicAccessInterceptor.kt b/src/main/kotlin/de/grimsi/gameyfin/meta/annotations/DynamicAccessInterceptor.kt new file mode 100644 index 0000000..bbd37c6 --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/meta/annotations/DynamicAccessInterceptor.kt @@ -0,0 +1,38 @@ +package de.grimsi.gameyfin.meta.annotations + +import de.grimsi.gameyfin.config.ConfigProperty +import de.grimsi.gameyfin.config.ConfigService +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import org.springframework.stereotype.Component +import org.springframework.web.method.HandlerMethod +import org.springframework.web.servlet.HandlerInterceptor + +@Component +class DynamicAccessInterceptor( + private val configService: ConfigService +) : HandlerInterceptor { + + override fun preHandle( + request: HttpServletRequest, + response: HttpServletResponse, + handler: Any + ): Boolean { + val handlerMethod = (handler as? HandlerMethod) ?: return true + val method = handlerMethod.method + + // Check if method is annotated with @DynamicPublicAccess + if (method.isAnnotationPresent(DynamicPublicAccess::class.java)) { + // Check if user is authenticated or public access is enabled + if (request.userPrincipal != null || configService.getConfigValue(ConfigProperty.LibraryAllowPublicAccess)) { + return true + } + + // Deny access if user is not logged in and public access is disabled + response.status = HttpServletResponse.SC_UNAUTHORIZED + return false + } + + return true + } +} diff --git a/src/main/kotlin/de/grimsi/gameyfin/meta/annotations/DynamicPublicAccess.kt b/src/main/kotlin/de/grimsi/gameyfin/meta/annotations/DynamicPublicAccess.kt new file mode 100644 index 0000000..ff88cb4 --- /dev/null +++ b/src/main/kotlin/de/grimsi/gameyfin/meta/annotations/DynamicPublicAccess.kt @@ -0,0 +1,14 @@ +package de.grimsi.gameyfin.meta.annotations + +import kotlin.annotation.AnnotationRetention.RUNTIME +import kotlin.annotation.AnnotationTarget.FUNCTION + +/** + * This annotation is used on endpoint methods which can be switched between publicly accessible and + * only accessible for registered users. + * One example would be the main library view. + */ + +@Target(FUNCTION) +@Retention(RUNTIME) +annotation class DynamicPublicAccess \ No newline at end of file diff --git a/src/main/kotlin/de/grimsi/gameyfin/setup/SetupDataLoader.kt b/src/main/kotlin/de/grimsi/gameyfin/setup/SetupDataLoader.kt index fe263a9..91ae929 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/setup/SetupDataLoader.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/setup/SetupDataLoader.kt @@ -1,6 +1,6 @@ package de.grimsi.gameyfin.setup -import de.grimsi.gameyfin.config.Roles +import de.grimsi.gameyfin.meta.Roles import de.grimsi.gameyfin.users.UserService import de.grimsi.gameyfin.users.entities.Role import de.grimsi.gameyfin.users.entities.User diff --git a/src/main/kotlin/de/grimsi/gameyfin/setup/SetupEndpoint.kt b/src/main/kotlin/de/grimsi/gameyfin/setup/SetupEndpoint.kt index 180981b..e9c0be1 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/setup/SetupEndpoint.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/setup/SetupEndpoint.kt @@ -1,14 +1,14 @@ package de.grimsi.gameyfin.setup import com.vaadin.flow.server.auth.AnonymousAllowed -import de.grimsi.gameyfin.config.Roles -import de.grimsi.gameyfin.users.RoleService -import de.grimsi.gameyfin.users.UserService -import de.grimsi.gameyfin.users.dto.UserInfo -import de.grimsi.gameyfin.users.dto.UserRegistration -import de.grimsi.gameyfin.users.entities.User import com.vaadin.hilla.Endpoint import com.vaadin.hilla.exception.EndpointException +import de.grimsi.gameyfin.meta.Roles +import de.grimsi.gameyfin.users.RoleService +import de.grimsi.gameyfin.users.UserService +import de.grimsi.gameyfin.users.dto.UserInfoDto +import de.grimsi.gameyfin.users.dto.UserRegistrationDto +import de.grimsi.gameyfin.users.entities.User @Endpoint class SetupEndpoint( @@ -22,7 +22,7 @@ class SetupEndpoint( } @AnonymousAllowed - fun registerSuperAdmin(superAdminRegistration: UserRegistration): UserInfo { + fun registerSuperAdmin(superAdminRegistration: UserRegistrationDto): UserInfoDto { if (setupService.isSetupCompleted()) throw EndpointException("Setup already completed") val user = User( diff --git a/src/main/kotlin/de/grimsi/gameyfin/setup/SetupService.kt b/src/main/kotlin/de/grimsi/gameyfin/setup/SetupService.kt index 74a6139..d0cb2bb 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/setup/SetupService.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/setup/SetupService.kt @@ -1,6 +1,6 @@ package de.grimsi.gameyfin.setup -import de.grimsi.gameyfin.config.Roles +import de.grimsi.gameyfin.meta.Roles import de.grimsi.gameyfin.users.RoleService import de.grimsi.gameyfin.users.UserService import de.grimsi.gameyfin.users.entities.User diff --git a/src/main/kotlin/de/grimsi/gameyfin/system/SystemEndpoint.kt b/src/main/kotlin/de/grimsi/gameyfin/system/SystemEndpoint.kt index badad50..69061f4 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/system/SystemEndpoint.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/system/SystemEndpoint.kt @@ -1,7 +1,7 @@ package de.grimsi.gameyfin.system -import de.grimsi.gameyfin.config.Roles import com.vaadin.hilla.Endpoint +import de.grimsi.gameyfin.meta.Roles import jakarta.annotation.security.RolesAllowed @Endpoint diff --git a/src/main/kotlin/de/grimsi/gameyfin/users/RoleService.kt b/src/main/kotlin/de/grimsi/gameyfin/users/RoleService.kt index 374de42..37f1cb4 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/users/RoleService.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/users/RoleService.kt @@ -1,6 +1,6 @@ package de.grimsi.gameyfin.users -import de.grimsi.gameyfin.config.Roles +import de.grimsi.gameyfin.meta.Roles import de.grimsi.gameyfin.users.entities.Role import de.grimsi.gameyfin.users.persistence.RoleRepository import jakarta.transaction.Transactional diff --git a/src/main/kotlin/de/grimsi/gameyfin/users/UserEndpoint.kt b/src/main/kotlin/de/grimsi/gameyfin/users/UserEndpoint.kt index 70339bc..5753735 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/users/UserEndpoint.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/users/UserEndpoint.kt @@ -1,10 +1,10 @@ package de.grimsi.gameyfin.users -import de.grimsi.gameyfin.config.Roles -import de.grimsi.gameyfin.users.dto.UserInfo -import de.grimsi.gameyfin.users.dto.UserRegistration -import de.grimsi.gameyfin.users.entities.User import com.vaadin.hilla.Endpoint +import de.grimsi.gameyfin.meta.Roles +import de.grimsi.gameyfin.users.dto.UserInfoDto +import de.grimsi.gameyfin.users.dto.UserRegistrationDto +import de.grimsi.gameyfin.users.entities.User import jakarta.annotation.security.PermitAll import org.springframework.security.core.Authentication import org.springframework.security.core.GrantedAuthority @@ -16,19 +16,19 @@ class UserEndpoint( ) { @PermitAll - fun getUserInfo(): UserInfo { + fun getUserInfo(): UserInfoDto { val auth: Authentication = SecurityContextHolder.getContext().authentication val authorities: List = auth.authorities.map { g: GrantedAuthority -> g.authority } - return UserInfo(username = auth.name, roles = authorities) + return UserInfoDto(username = auth.name, roles = authorities) } @PermitAll - fun registerUser(registration: UserRegistration): UserInfo { + fun registerUser(registration: UserRegistrationDto): UserInfoDto { val user: User = registerUser(registration, listOf(Roles.USER)) return userService.toUserInfo(user) } - private fun registerUser(registration: UserRegistration, roles: List): User { + private fun registerUser(registration: UserRegistrationDto, roles: List): User { val user = User( username = registration.username, password = registration.password, diff --git a/src/main/kotlin/de/grimsi/gameyfin/users/UserService.kt b/src/main/kotlin/de/grimsi/gameyfin/users/UserService.kt index 59ee4de..ef488ed 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/users/UserService.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/users/UserService.kt @@ -1,7 +1,7 @@ package de.grimsi.gameyfin.users -import de.grimsi.gameyfin.config.Roles -import de.grimsi.gameyfin.users.dto.UserInfo +import de.grimsi.gameyfin.meta.Roles +import de.grimsi.gameyfin.users.dto.UserInfoDto import de.grimsi.gameyfin.users.entities.Role import de.grimsi.gameyfin.users.entities.User import de.grimsi.gameyfin.users.persistence.UserRepository @@ -50,8 +50,8 @@ class UserService( return userRepository.save(user) } - fun toUserInfo(user: User): UserInfo { - return UserInfo( + fun toUserInfo(user: User): UserInfoDto { + return UserInfoDto( username = user.username, email = user.email, roles = user.roles.map { r -> r.rolename } diff --git a/src/main/kotlin/de/grimsi/gameyfin/users/dto/UserInfo.kt b/src/main/kotlin/de/grimsi/gameyfin/users/dto/UserInfoDto.kt similarity index 83% rename from src/main/kotlin/de/grimsi/gameyfin/users/dto/UserInfo.kt rename to src/main/kotlin/de/grimsi/gameyfin/users/dto/UserInfoDto.kt index 55212f8..4c4e956 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/users/dto/UserInfo.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/users/dto/UserInfoDto.kt @@ -1,6 +1,6 @@ package de.grimsi.gameyfin.users.dto -data class UserInfo( +data class UserInfoDto( val username: String, val email: String? = null, val roles: List diff --git a/src/main/kotlin/de/grimsi/gameyfin/users/dto/UserRegistration.kt b/src/main/kotlin/de/grimsi/gameyfin/users/dto/UserRegistrationDto.kt similarity index 77% rename from src/main/kotlin/de/grimsi/gameyfin/users/dto/UserRegistration.kt rename to src/main/kotlin/de/grimsi/gameyfin/users/dto/UserRegistrationDto.kt index cc7ccfa..fcc95dc 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/users/dto/UserRegistration.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/users/dto/UserRegistrationDto.kt @@ -1,6 +1,6 @@ package de.grimsi.gameyfin.users.dto -data class UserRegistration( +data class UserRegistrationDto( val username: String, val password: String, val email: String diff --git a/src/main/kotlin/de/grimsi/gameyfin/users/util/UserDetailsExtensions.kt b/src/main/kotlin/de/grimsi/gameyfin/users/util/UserDetailsExtensions.kt index 57940e9..2fb3bbe 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/users/util/UserDetailsExtensions.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/users/util/UserDetailsExtensions.kt @@ -3,7 +3,7 @@ package de.grimsi.gameyfin.users.util -import de.grimsi.gameyfin.config.Roles +import de.grimsi.gameyfin.meta.Roles import org.springframework.security.core.userdetails.UserDetails fun UserDetails.hasRole(role: Roles): Boolean {