Skip to content

Instantly share code, notes, and snippets.

@Higher08
Created February 14, 2022 16:22
Show Gist options
  • Save Higher08/31eef9524a9a231c73ff470a7870c9f9 to your computer and use it in GitHub Desktop.
Save Higher08/31eef9524a9a231c73ff470a7870c9f9 to your computer and use it in GitHub Desktop.
//
// ModelCredentialsAuthenticatable.swift
//
//
// Created by Dmytro on 12.02.2022.
//
import Vapor
import Bridges
public protocol ModelCredentialsAuthenticatable: Table, Authenticatable {
static var usernameKey: KeyPath<Self, Column<String>> { get }
static var passwordHashKey: KeyPath<Self, Column<String>> { get }
func verify(password: String) throws -> Bool
}
extension ModelCredentialsAuthenticatable {
public static func credentialsAuthenticator(
database: DatabaseIdentifier
) -> Authenticator {
ModelCredentialsAuthenticator<Self>(database: database)
}
var _$username: Column<String> {
self[keyPath: Self.usernameKey]
}
var _$passwordHash: Column<String> {
self[keyPath: Self.passwordHashKey]
}
}
public struct ModelCredentials: Content {
public let username: String
public let password: String
public init(username: String, password: String) {
self.username = username
self.password = password
}
}
private struct ModelCredentialsAuthenticator<User>: CredentialsAuthenticator
where User: ModelCredentialsAuthenticatable
{
typealias Credentials = ModelCredentials
public let database: DatabaseIdentifier
func authenticate(credentials: ModelCredentials, for request: Request) -> EventLoopFuture<Void> {
User.query(on: database, on: request)
.where(\User._$username == credentials.username)
.first()
.flatMapThrowing
{
guard let user = $0 else {
return
}
guard try user.verify(password: credentials.password) else {
return
}
request.auth.login(user)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment