diff --git a/src/main/kotlin/io/visus/demos/kotlinapi/config/SecurityConfig.kt b/src/main/kotlin/io/visus/demos/kotlinapi/config/SecurityConfig.kt index 363eb2b..c3b9717 100644 --- a/src/main/kotlin/io/visus/demos/kotlinapi/config/SecurityConfig.kt +++ b/src/main/kotlin/io/visus/demos/kotlinapi/config/SecurityConfig.kt @@ -73,7 +73,6 @@ class SecurityConfig( "/v1/health", "/v1/auth/login", "/v1/auth/refresh", - "/v1/auth/register", ).permitAll() .anyExchange() .authenticated() diff --git a/src/main/kotlin/io/visus/demos/kotlinapi/controller/AdminController.kt b/src/main/kotlin/io/visus/demos/kotlinapi/controller/AdminController.kt new file mode 100644 index 0000000..75c9048 --- /dev/null +++ b/src/main/kotlin/io/visus/demos/kotlinapi/controller/AdminController.kt @@ -0,0 +1,61 @@ +package io.visus.demos.kotlinapi.controller + +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.media.Content +import io.swagger.v3.oas.annotations.media.Schema +import io.swagger.v3.oas.annotations.responses.ApiResponse +import io.swagger.v3.oas.annotations.responses.ApiResponses +import io.swagger.v3.oas.annotations.security.SecurityRequirement +import io.swagger.v3.oas.annotations.tags.Tag +import io.visus.demos.kotlinapi.api.ApiVersion +import io.visus.demos.kotlinapi.api.contracts.ErrorResponse +import io.visus.demos.kotlinapi.api.contracts.RegisterRequest +import io.visus.demos.kotlinapi.api.contracts.RegisterResponse +import io.visus.demos.kotlinapi.domain.service.AuthService +import jakarta.validation.Valid +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RestController + +@RestController +@ApiVersion(version = 1) +@Tag(name = "Admin", description = "Endpoints for admin operations") +class AdminController( + private val authService: AuthService, +) { + @PostMapping("/admin/users", produces = [MediaType.APPLICATION_JSON_VALUE]) + @PreAuthorize("hasRole('ROLE_ADMIN')") + @Operation( + summary = "Register new user", + description = "Creates a new user account (Admin only)", + security = [SecurityRequirement(name = "bearerAuth")], + ) + @ApiResponses( + value = [ + ApiResponse( + responseCode = "201", + description = "User successfully registered", + content = [Content(schema = Schema(implementation = RegisterResponse::class))], + ), + ApiResponse( + responseCode = "400", + description = "Invalid request payload", + content = [Content(schema = Schema(implementation = ErrorResponse::class))], + ), + ApiResponse( + responseCode = "403", + description = "Forbidden, admin role required", + content = [Content(schema = Schema(implementation = ErrorResponse::class))], + ), + ], + ) + suspend fun register( + @Valid @RequestBody request: RegisterRequest, + ): ResponseEntity { + val user = authService.register(request.email, request.password) + return ResponseEntity.status(201).body(user) + } +} diff --git a/src/main/kotlin/io/visus/demos/kotlinapi/controller/AuthController.kt b/src/main/kotlin/io/visus/demos/kotlinapi/controller/AuthController.kt index c1a85b5..4ebc1e6 100644 --- a/src/main/kotlin/io/visus/demos/kotlinapi/controller/AuthController.kt +++ b/src/main/kotlin/io/visus/demos/kotlinapi/controller/AuthController.kt @@ -12,8 +12,6 @@ import io.visus.demos.kotlinapi.api.contracts.AuthResponse import io.visus.demos.kotlinapi.api.contracts.ErrorResponse import io.visus.demos.kotlinapi.api.contracts.LoginRequest import io.visus.demos.kotlinapi.api.contracts.RefreshTokenRequest -import io.visus.demos.kotlinapi.api.contracts.RegisterRequest -import io.visus.demos.kotlinapi.api.contracts.RegisterResponse import io.visus.demos.kotlinapi.domain.exception.InvalidTokenException import io.visus.demos.kotlinapi.domain.model.User import io.visus.demos.kotlinapi.domain.service.AuthService @@ -130,30 +128,4 @@ class AuthController( return ResponseEntity.ok(response) } - @PostMapping("/auth/register", produces = [MediaType.APPLICATION_JSON_VALUE]) - @Operation( - summary = "Register new user", - description = "Creates a new user account", - security = [], - ) - @ApiResponses( - value = [ - ApiResponse( - responseCode = "201", - description = "User successfully registered", - content = [Content(schema = Schema(implementation = RegisterResponse::class))], - ), - ApiResponse( - responseCode = "400", - description = "Invalid request payload", - content = [Content(schema = Schema(implementation = ErrorResponse::class))], - ), - ], - ) - suspend fun register( - @Valid @RequestBody request: RegisterRequest, - ): ResponseEntity { - val user = authService.register(request.email, request.password) - return ResponseEntity.status(201).body(user) - } }