Add password reset model

This commit is contained in:
Christoph Hagen 2022-10-11 12:04:15 +02:00
parent e49cc9cb91
commit 16ab0fd6d3
4 changed files with 83 additions and 0 deletions

View File

@ -0,0 +1,18 @@
import FluentSQLiteDriver
struct PasswordResetMigration: Migration {
func prepare(on database: FluentSQLiteDriver.Database) -> EventLoopFuture<Void> {
database.schema(PasswordReset.schema)
.id()
.field(PasswordReset.Key.user.key, .uuid, .required, .references(User.schema, .id))
.unique(on: PasswordReset.Key.user.key)
.field(PasswordReset.Key.token.key, .string, .required)
.field(PasswordReset.Key.expiry.key, .date, .required)
.create()
}
func revert(on database: FluentSQLiteDriver.Database) -> EventLoopFuture<Void> {
database.schema(PasswordReset.schema).delete()
}
}

View File

@ -0,0 +1,60 @@
import Foundation
import FluentSQLiteDriver
import Crypto
private extension FieldProperty {
convenience init(_ key: PasswordReset.Key) {
self.init(key: key.key)
}
}
private extension ParentProperty {
convenience init(_ key: PasswordReset.Key) {
self.init(key: key.key)
}
}
extension PasswordReset.Key {
var key: FieldKey {
.init(stringLiteral: rawValue)
}
}
final class PasswordReset: Model {
/// The name of the SQLite table
static let schema = "reset"
enum Key: String {
case id = "id"
case user = "user"
case token = "token"
case expiry = "expiry"
}
/// The unique identifier for the reset request
@ID(key: .id)
var id: UUID?
/// The user associated with the reset request
@Parent(.user)
var user: User
/// The random reset token issued with the email
@Field(.token)
var resetToken: String
/// The time when the reset token expires and can't be used anymore
@Field(.expiry)
var expiryDate: Date
init() { }
/// Creates a new password reset.
init(id: UUID? = nil, user: User) {
self.id = id
self.user = user
self.resetToken = .newToken()
self.expiryDate = Date().addingTimeInterval(15*60)
}
}

View File

@ -52,6 +52,10 @@ final class User: Model {
@OptionalParent(.table) @OptionalParent(.table)
var table: Table? var table: Table?
/// The optional password reset request associated with this user
@OptionalChild(for: \.$user)
var resetRequest: PasswordReset?
init() { } init() { }
/// Creates a new user. /// Creates a new user.

View File

@ -28,6 +28,7 @@ public func configure(_ app: Application) throws {
app.databases.use(.sqlite(.file(dbFile)), as: .sqlite) app.databases.use(.sqlite(.file(dbFile)), as: .sqlite)
} }
app.migrations.add(UserTableMigration()) app.migrations.add(UserTableMigration())
app.migrations.add(PasswordResetMigration())
try app.autoMigrate().wait() try app.autoMigrate().wait()