Add password reset model
This commit is contained in:
parent
e49cc9cb91
commit
16ab0fd6d3
18
Sources/App/Model/Migrations/PasswordResetMigration.swift
Normal file
18
Sources/App/Model/Migrations/PasswordResetMigration.swift
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
60
Sources/App/Model/PasswordReset.swift
Normal file
60
Sources/App/Model/PasswordReset.swift
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user