Check if username/email is taken in registration

This commit is contained in:
William Brawner 2023-06-17 10:13:32 -06:00
parent 1eab86489b
commit 694743e3f2

View file

@ -16,25 +16,25 @@ import io.ktor.server.routing.*
import java.time.Instant import java.time.Instant
fun Application.userRoutes( fun Application.userRoutes(
emailService: EmailService, emailService: EmailService,
passwordResetRepository: PasswordResetRepository, passwordResetRepository: PasswordResetRepository,
permissionRepository: PermissionRepository, permissionRepository: PermissionRepository,
sessionRepository: SessionRepository, sessionRepository: SessionRepository,
userRepository: UserRepository userRepository: UserRepository
) { ) {
routing { routing {
route("/api/users") { route("/api/users") {
post("/login") { post("/login") {
val request = call.receive<LoginRequest>() val request = call.receive<LoginRequest>()
val user = val user =
userRepository.findAll(nameOrEmail = request.username, password = request.password.hash()) userRepository.findAll(nameOrEmail = request.username, password = request.password.hash())
.firstOrNull() .firstOrNull()
?: userRepository.findAll(nameOrEmail = request.username, password = request.password.hash()) ?: userRepository.findAll(nameOrEmail = request.username, password = request.password.hash())
.firstOrNull() .firstOrNull()
?: run { ?: run {
errorResponse(HttpStatusCode.Unauthorized, "Invalid credentials") errorResponse(HttpStatusCode.Unauthorized, "Invalid credentials")
return@post return@post
} }
val session = sessionRepository.save(Session(userId = user.id)) val session = sessionRepository.save(Session(userId = user.id))
call.respond(session.asResponse()) call.respond(session.asResponse())
} }
@ -49,14 +49,26 @@ fun Application.userRoutes(
errorResponse(HttpStatusCode.BadRequest, "Password must not be null or blank") errorResponse(HttpStatusCode.BadRequest, "Password must not be null or blank")
return@post return@post
} }
val existingUser = userRepository.findAll(nameOrEmail = request.username).firstOrNull()
?: request.email?.let {
return@let if (it.isBlank()) {
null
} else {
userRepository.findAll(nameOrEmail = it).firstOrNull()
}
}
existingUser?.let {
errorResponse(HttpStatusCode.BadRequest, "Username or email already taken")
return@post
}
call.respond( call.respond(
userRepository.save( userRepository.save(
User( User(
name = request.username, name = request.username,
password = request.password.hash(), password = request.password.hash(),
email = request.email email = if (request.email.isNullOrBlank()) null else request.email
) )
).asResponse() ).asResponse()
) )
} }
@ -68,20 +80,20 @@ fun Application.userRoutes(
return@get return@get
} }
permissionRepository.findAll( permissionRepository.findAll(
budgetIds = call.request.queryParameters.getAll("budgetId") budgetIds = call.request.queryParameters.getAll("budgetId")
).mapNotNull { ).mapNotNull {
userRepository.findAll(ids = listOf(it.userId)) userRepository.findAll(ids = listOf(it.userId))
.firstOrNull() .firstOrNull()
?.asResponse() ?.asResponse()
}.run { call.respond(this) } }.run { call.respond(this) }
} }
get("/{id}") { get("/{id}") {
userRepository.findAll(ids = call.parameters.getAll("id")) userRepository.findAll(ids = call.parameters.getAll("id"))
.firstOrNull() .firstOrNull()
?.asResponse() ?.asResponse()
?.let { call.respond(it) } ?.let { call.respond(it) }
?: errorResponse(HttpStatusCode.NotFound) ?: errorResponse(HttpStatusCode.NotFound)
} }
post { post {
@ -95,13 +107,13 @@ fun Application.userRoutes(
return@post return@post
} }
call.respond( call.respond(
userRepository.save( userRepository.save(
User( User(
name = request.username, name = request.username,
password = request.password, password = request.password,
email = request.email email = request.email
) )
).asResponse() ).asResponse()
) )
} }
@ -114,17 +126,17 @@ fun Application.userRoutes(
return@put return@put
} }
call.respond( call.respond(
userRepository.save( userRepository.save(
userRepository.findAll(ids = call.parameters.getAll("id")) userRepository.findAll(ids = call.parameters.getAll("id"))
.first() .first()
.run { .run {
copy( copy(
name = request.username ?: name, name = request.username ?: name,
password = request.password?.hash() ?: password, password = request.password?.hash() ?: password,
email = request.email ?: email email = request.email ?: email
) )
} }
).asResponse() ).asResponse()
) )
} }
@ -150,12 +162,12 @@ fun Application.userRoutes(
post { post {
val request = call.receive<ResetPasswordRequest>() val request = call.receive<ResetPasswordRequest>()
userRepository.findAll(nameOrEmail = request.username) userRepository.findAll(nameOrEmail = request.username)
.firstOrNull() .firstOrNull()
?.let { ?.let {
val email = it.email ?: return@let val email = it.email ?: return@let
val passwordResetToken = passwordResetRepository.save(PasswordResetToken(userId = it.id)) val passwordResetToken = passwordResetRepository.save(PasswordResetToken(userId = it.id))
emailService.sendPasswordResetEmail(passwordResetToken, email) emailService.sendPasswordResetEmail(passwordResetToken, email)
} }
call.respond(HttpStatusCode.Accepted) call.respond(HttpStatusCode.Accepted)
} }
} }
@ -164,25 +176,25 @@ fun Application.userRoutes(
post { post {
val request = call.receive<PasswordResetRequest>() val request = call.receive<PasswordResetRequest>()
val passwordResetToken = passwordResetRepository.findAll(listOf(request.token)) val passwordResetToken = passwordResetRepository.findAll(listOf(request.token))
.firstOrNull() .firstOrNull()
?: run { ?: run {
errorResponse(HttpStatusCode.Unauthorized, "Invalid token") errorResponse(HttpStatusCode.Unauthorized, "Invalid token")
return@post return@post
} }
if (passwordResetToken.expiration.isBefore(Instant.now())) { if (passwordResetToken.expiration.isBefore(Instant.now())) {
errorResponse(HttpStatusCode.Unauthorized, "Token expired") errorResponse(HttpStatusCode.Unauthorized, "Token expired")
return@post return@post
} }
userRepository.findAll(listOf(passwordResetToken.userId)) userRepository.findAll(listOf(passwordResetToken.userId))
.firstOrNull() .firstOrNull()
?.let { ?.let {
userRepository.save(it.copy(password = request.password.hash())) userRepository.save(it.copy(password = request.password.hash()))
passwordResetRepository.delete(passwordResetToken) passwordResetRepository.delete(passwordResetToken)
} }
?: run { ?: run {
errorResponse(HttpStatusCode.InternalServerError, "Invalid token") errorResponse(HttpStatusCode.InternalServerError, "Invalid token")
return@post return@post
} }
call.respond(HttpStatusCode.NoContent) call.respond(HttpStatusCode.NoContent)
} }
} }