mirror of
https://github.com/gotson/komga.git
synced 2025-12-21 07:56:57 +01:00
fix: better email validation
rejects email address where domain has no extension related to #434
This commit is contained in:
parent
8c034035a0
commit
97871f7fbc
6 changed files with 90 additions and 12 deletions
|
|
@ -11,7 +11,7 @@ const val ROLE_FILE_DOWNLOAD = "FILE_DOWNLOAD"
|
|||
const val ROLE_PAGE_STREAMING = "PAGE_STREAMING"
|
||||
|
||||
data class KomgaUser(
|
||||
@Email
|
||||
@Email(regexp = ".+@.+\\..+")
|
||||
@NotBlank
|
||||
val email: String,
|
||||
@NotBlank
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class ClaimController(
|
|||
|
||||
@PostMapping
|
||||
fun claimAdmin(
|
||||
@Email @RequestHeader("X-Komga-Email") email: String,
|
||||
@Email(regexp = ".+@.+\\..+") @RequestHeader("X-Komga-Email") email: String,
|
||||
@NotBlank @RequestHeader("X-Komga-Password") password: String
|
||||
): UserDto {
|
||||
if (userDetailsLifecycle.countUsers() > 0)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
package org.gotson.komga.interfaces.rest
|
||||
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler
|
||||
import org.springframework.web.bind.annotation.ResponseBody
|
||||
import org.springframework.web.bind.annotation.ResponseStatus
|
||||
import javax.validation.ConstraintViolationException
|
||||
|
||||
@ControllerAdvice
|
||||
class ErrorHandlingControllerAdvice {
|
||||
@ExceptionHandler(ConstraintViolationException::class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ResponseBody
|
||||
fun onConstraintValidationException(
|
||||
e: ConstraintViolationException
|
||||
): ValidationErrorResponse =
|
||||
ValidationErrorResponse(
|
||||
e.constraintViolations.map { Violation(it.propertyPath.toString(), it.message) }
|
||||
)
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException::class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ResponseBody
|
||||
fun onMethodArgumentNotValidException(
|
||||
e: MethodArgumentNotValidException
|
||||
): ValidationErrorResponse =
|
||||
ValidationErrorResponse(
|
||||
e.bindingResult.fieldErrors.map { Violation(it.field, it.defaultMessage) }
|
||||
)
|
||||
}
|
||||
|
||||
data class ValidationErrorResponse(
|
||||
val violations: List<Violation> = emptyList()
|
||||
)
|
||||
|
||||
data class Violation(
|
||||
val fieldName: String? = null,
|
||||
val message: String? = null
|
||||
)
|
||||
|
|
@ -45,7 +45,7 @@ fun KomgaUser.toWithSharedLibrariesDto() =
|
|||
)
|
||||
|
||||
data class UserCreationDto(
|
||||
@get:Email val email: String,
|
||||
@get:Email(regexp = ".+@.+\\..+") val email: String,
|
||||
@get:NotBlank val password: String,
|
||||
val roles: List<String> = emptyList()
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
package org.gotson.komga.interfaces.rest
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.ValueSource
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.test.context.ActiveProfiles
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.post
|
||||
|
||||
@ExtendWith(SpringExtension::class)
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc(printOnlyOnFailure = false)
|
||||
@ActiveProfiles("test")
|
||||
class ClaimControllerTest(
|
||||
@Autowired private val mockMvc: MockMvc
|
||||
|
||||
) {
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = ["user", "user@domain"])
|
||||
fun `given unclaimed server when claiming with invalid email address then returns bad request`(email: String) {
|
||||
val password = "password"
|
||||
|
||||
mockMvc.post("/api/v1/claim") {
|
||||
header("X-Komga-Email", email)
|
||||
header("X-Komga-Password", password)
|
||||
}.andExpect {
|
||||
status { isBadRequest() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package org.gotson.komga.interfaces.rest
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.gotson.komga.domain.model.ROLE_ADMIN
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.ValueSource
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
|
|
@ -9,26 +11,27 @@ import org.springframework.http.MediaType
|
|||
import org.springframework.test.context.ActiveProfiles
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.patch
|
||||
import org.springframework.test.web.servlet.post
|
||||
|
||||
@ExtendWith(SpringExtension::class)
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc(printOnlyOnFailure = false)
|
||||
@ActiveProfiles("demo", "test")
|
||||
@ActiveProfiles("test")
|
||||
class UserControllerTest(
|
||||
@Autowired private val mockMvc: MockMvc
|
||||
|
||||
) {
|
||||
@Test
|
||||
@WithMockCustomUser
|
||||
fun `given demo profile is active when a user tries to update its password via api then returns forbidden`() {
|
||||
val jsonString = """{"password":"new"}"""
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = ["user", "user@domain"])
|
||||
@WithMockCustomUser(roles = [ROLE_ADMIN])
|
||||
fun `when creating a user with invalid email then returns bad request`(email: String) {
|
||||
val jsonString = """{"email":"$email","password":"password"}"""
|
||||
|
||||
mockMvc.patch("/api/v1/users/me/password") {
|
||||
mockMvc.post("/api/v1/users") {
|
||||
contentType = MediaType.APPLICATION_JSON
|
||||
content = jsonString
|
||||
}.andExpect {
|
||||
status { isForbidden() }
|
||||
status { isBadRequest() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue