Add route to update password with email token
This commit is contained in:
parent
4e9675c284
commit
ff916945df
@ -114,7 +114,42 @@ final class SQLiteDatabase {
|
||||
/**
|
||||
Change the password of a user with a recovery token
|
||||
|
||||
Possible errors:
|
||||
- `404`: Reset token not found or expired
|
||||
*/
|
||||
func updatePassword(password: String, forResetToken token: String, in database: Database) async throws {
|
||||
// 1. Find and validate the reset request
|
||||
let reset: PasswordReset? = try await PasswordReset.query(on: database)
|
||||
.filter(\.$resetToken == token)
|
||||
.first()
|
||||
guard let reset else {
|
||||
throw Abort(.expectationFailed)
|
||||
}
|
||||
guard reset.expiryDate.timeIntervalSinceNow > 0 else {
|
||||
throw Abort(.expectationFailed)
|
||||
}
|
||||
|
||||
// 2. Update the user password
|
||||
let user = try await reset.$user.get(on: database)
|
||||
user.passwordHash = password
|
||||
try await user.save(on: database)
|
||||
|
||||
// 3. Delete the reset request
|
||||
try await PasswordReset
|
||||
.query(on: database)
|
||||
.filter(\.$resetToken == token)
|
||||
.delete()
|
||||
}
|
||||
|
||||
func passwordHashForExistingPlayer(named name: PlayerName, in database: Database) async throws -> PasswordHash {
|
||||
try await User
|
||||
.query(on: database)
|
||||
.filter(\.$name == name)
|
||||
.first()
|
||||
.unwrap(or: Abort(.notFound))
|
||||
.passwordHash
|
||||
}
|
||||
|
||||
func deletePlayer(named name: PlayerName, in database: Database) async throws {
|
||||
let user = try await user(named: name, in: database)
|
||||
try await tables.leaveTable(player: user, in: database)
|
||||
|
@ -83,6 +83,29 @@ func requestPlayerPasswordReset(_ app: Application) {
|
||||
return .ok
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Use a token from a password reset email to change the password.
|
||||
|
||||
Headers:
|
||||
- `token`: The one-time recovery token
|
||||
- `password`: The new password for the user
|
||||
|
||||
Possible responses:
|
||||
- `200`: Success, password changed
|
||||
- `400`: Missing token or password header
|
||||
- `404`: Player name not found or no email registered
|
||||
- `424`: Password could not be hashed
|
||||
*/
|
||||
func resetPlayerPasswordWithEmailToken(_ app: Application) {
|
||||
app.post("player", "reset") { req async throws -> HTTPResponseStatus in
|
||||
let token = try req.header(.token)
|
||||
let hash = try req.hashedPassword() // errors: 400, 424
|
||||
try await server.updatePassword(password: hash, forResetToken: token, in: req.db)
|
||||
return .ok
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Delete a player.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user