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
|
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 {
|
func deletePlayer(named name: PlayerName, in database: Database) async throws {
|
||||||
let user = try await user(named: name, in: database)
|
let user = try await user(named: name, in: database)
|
||||||
try await tables.leaveTable(player: user, in: database)
|
try await tables.leaveTable(player: user, in: database)
|
||||||
|
@ -83,6 +83,29 @@ func requestPlayerPasswordReset(_ app: Application) {
|
|||||||
return .ok
|
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.
|
Delete a player.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user