Check if username/email is taken in registration
This commit is contained in:
parent
1eab86489b
commit
694743e3f2
1 changed files with 77 additions and 65 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue