diff --git a/komga/src/main/kotlin/org/gotson/komga/infrastructure/security/SecurityConfiguration.kt b/komga/src/main/kotlin/org/gotson/komga/infrastructure/security/SecurityConfiguration.kt index 32591887c..08c3185cf 100644 --- a/komga/src/main/kotlin/org/gotson/komga/infrastructure/security/SecurityConfiguration.kt +++ b/komga/src/main/kotlin/org/gotson/komga/infrastructure/security/SecurityConfiguration.kt @@ -87,7 +87,9 @@ class SecurityConfiguration( "/js/**", "/favicon.ico", "/", - "/index.html") + "/index.html", + "/api/v1/claim" + ) } @Bean diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/ClaimController.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/ClaimController.kt new file mode 100644 index 000000000..b52dc24b2 --- /dev/null +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/ClaimController.kt @@ -0,0 +1,42 @@ +package org.gotson.komga.interfaces.rest + +import org.gotson.komga.domain.model.UserRoles +import org.gotson.komga.infrastructure.security.KomgaPrincipal +import org.gotson.komga.infrastructure.security.KomgaUserDetailsLifecycle +import org.gotson.komga.interfaces.rest.dto.toDto +import org.springframework.context.annotation.Profile +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.springframework.security.core.userdetails.User +import org.springframework.validation.annotation.Validated +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestHeader +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController +import org.springframework.web.server.ResponseStatusException +import javax.validation.constraints.Email +import javax.validation.constraints.NotBlank + +@Profile("claim") +@RestController +@RequestMapping("api/v1/claim", produces = [MediaType.APPLICATION_JSON_VALUE]) +@Validated +class ClaimController( + private val userDetailsLifecycle: KomgaUserDetailsLifecycle +) { + @PostMapping + fun claimAdmin( + @Email @RequestHeader("X-Komga-Email") email: String, + @NotBlank @RequestHeader("X-Komga-Password") password: String + ): UserDto { + if (userDetailsLifecycle.countUsers() > 0) + throw ResponseStatusException(HttpStatus.BAD_REQUEST, "This server has already been claimed") + + return (userDetailsLifecycle.createUser( + User.withUsername(email) + .password(password) + .roles(UserRoles.ADMIN.name) + .build()) as KomgaPrincipal + ).toDto() + } +} diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/UserController.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/UserController.kt index a98f80ad5..52d19da88 100644 --- a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/UserController.kt +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/UserController.kt @@ -7,6 +7,7 @@ import org.gotson.komga.domain.persistence.LibraryRepository import org.gotson.komga.infrastructure.security.KomgaPrincipal import org.gotson.komga.infrastructure.security.KomgaUserDetailsLifecycle import org.gotson.komga.infrastructure.security.UserEmailAlreadyExistsException +import org.gotson.komga.interfaces.rest.dto.toDto import org.springframework.data.repository.findByIdOrNull import org.springframework.http.HttpStatus import org.springframework.http.MediaType @@ -104,13 +105,6 @@ data class UserDto( val roles: List ) -fun KomgaUser.toDto() = - UserDto( - id = id, - email = email, - roles = roles.map { it.name } - ) - data class UserWithSharedLibrariesDto( val id: Long, val email: String, @@ -133,8 +127,6 @@ fun KomgaUser.toWithSharedLibrariesDto() = sharedLibraries = sharedLibraries.map { SharedLibraryDto(it.id, it.name) } ) -fun KomgaPrincipal.toDto() = user.toDto() - data class UserCreationDto( @get:Email val email: String, @get:NotBlank val password: String, diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/UserDto.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/UserDto.kt new file mode 100644 index 000000000..39a927c9d --- /dev/null +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/UserDto.kt @@ -0,0 +1,14 @@ +package org.gotson.komga.interfaces.rest.dto + +import org.gotson.komga.domain.model.KomgaUser +import org.gotson.komga.infrastructure.security.KomgaPrincipal +import org.gotson.komga.interfaces.rest.UserDto + +fun KomgaUser.toDto() = + UserDto( + id = id, + email = email, + roles = roles.map { it.name } + ) + +fun KomgaPrincipal.toDto() = user.toDto() diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/scheduler/InitialUserController.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/scheduler/InitialUserController.kt index 380e23b95..e4cbd54b2 100644 --- a/komga/src/main/kotlin/org/gotson/komga/interfaces/scheduler/InitialUserController.kt +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/scheduler/InitialUserController.kt @@ -15,7 +15,7 @@ import org.springframework.stereotype.Controller private val logger = KotlinLogging.logger {} -@Profile("dev", "prod") +@Profile("(dev | prod) & !claim") @Controller class InitialUserController( private val userDetailsLifecycle: KomgaUserDetailsLifecycle,