Adds validation and error handling to signup

This commit is contained in:
2025-12-05 00:15:20 -06:00
parent 8b808bfd34
commit 302feeab1e
6 changed files with 30 additions and 3 deletions

View File

@@ -28,12 +28,14 @@ repositories {
dependencies { dependencies {
val mysqlConnectorJ = "9.5.0" val mysqlConnectorJ = "9.5.0"
val commonsValidator = "1.10.1"
implementation("org.springframework.boot:spring-boot-starter-actuator") implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("com.mysql:mysql-connector-j:${mysqlConnectorJ}") implementation("com.mysql:mysql-connector-j:${mysqlConnectorJ}")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("commons-validator:commons-validator:${commonsValidator}")
developmentOnly("org.springframework.boot:spring-boot-devtools") developmentOnly("org.springframework.boot:spring-boot-devtools")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor") annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
testImplementation("org.springframework.boot:spring-boot-starter-actuator-test") testImplementation("org.springframework.boot:spring-boot-starter-actuator-test")

View File

@@ -3,6 +3,7 @@ package net.halfbinary.scavengerhuntapi.controller
import net.halfbinary.scavengerhuntapi.model.converter.toDomain import net.halfbinary.scavengerhuntapi.model.converter.toDomain
import net.halfbinary.scavengerhuntapi.model.request.HunterSignupRequest import net.halfbinary.scavengerhuntapi.model.request.HunterSignupRequest
import net.halfbinary.scavengerhuntapi.service.SignupService import net.halfbinary.scavengerhuntapi.service.SignupService
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController import org.springframework.web.bind.annotation.RestController
@@ -10,7 +11,13 @@ import org.springframework.web.bind.annotation.RestController
@RestController @RestController
class SignupController(private val signupService: SignupService) { class SignupController(private val signupService: SignupService) {
@PostMapping("/signup") @PostMapping("/signup")
fun hunterSignup(@RequestBody body: HunterSignupRequest) { fun hunterSignup(@RequestBody body: HunterSignupRequest): ResponseEntity<Any> {
signupService.createNewHunter(body.toDomain()) try {
signupService.createNewHunter(body.toDomain())
return ResponseEntity.ok().build()
} catch (e: RuntimeException) {
return ResponseEntity.badRequest().body(e.message)
}
} }
} }

View File

@@ -0,0 +1,3 @@
package net.halfbinary.scavengerhuntapi.error.exception
class InvalidEmailException(email: String): RuntimeException("The email ${email} is not valid.")

View File

@@ -0,0 +1,3 @@
package net.halfbinary.scavengerhuntapi.error.exception
class PreexistingAccountException: RuntimeException("An account with that email already exists.")

View File

@@ -6,4 +6,7 @@ import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
@Repository @Repository
interface HunterRepository : JpaRepository<HunterRecord, HunterId> interface HunterRepository : JpaRepository<HunterRecord, HunterId>
interface HunterRepository : JpaRepository<HunterRecord, HunterId> {
fun findByEmail(email: String): HunterRecord?
}

View File

@@ -1,13 +1,22 @@
package net.halfbinary.scavengerhuntapi.service package net.halfbinary.scavengerhuntapi.service
import net.halfbinary.scavengerhuntapi.error.exception.InvalidEmailException
import net.halfbinary.scavengerhuntapi.error.exception.PreexistingAccountException
import net.halfbinary.scavengerhuntapi.model.converter.toRecord import net.halfbinary.scavengerhuntapi.model.converter.toRecord
import net.halfbinary.scavengerhuntapi.model.domain.Hunter import net.halfbinary.scavengerhuntapi.model.domain.Hunter
import net.halfbinary.scavengerhuntapi.repository.HunterRepository import net.halfbinary.scavengerhuntapi.repository.HunterRepository
import org.apache.commons.validator.routines.EmailValidator
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@Service @Service
class SignupService(private val hunterRepository: HunterRepository) { class SignupService(private val hunterRepository: HunterRepository) {
fun createNewHunter(hunter: Hunter) { fun createNewHunter(hunter: Hunter) {
if (!EmailValidator.getInstance().isValid(hunter.email)) {
throw InvalidEmailException(hunter.email)
}
if (hunterRepository.findByEmail(hunter.email) != null) {
throw PreexistingAccountException()
}
hunterRepository.save(hunter.toRecord()) hunterRepository.save(hunter.toRecord())
} }
} }