Skip to content
This repository has been archived by the owner on Sep 7, 2021. It is now read-only.

Commit

Permalink
Merge pull request #16 from jhoogstraat/vapor-4.0.1
Browse files Browse the repository at this point in the history
Fixes Corvus for Vapor 4.0.0
  • Loading branch information
PSchmiedmayer authored Apr 10, 2020
2 parents c41fd8b + 48254ea commit b83435c
Show file tree
Hide file tree
Showing 15 changed files with 69 additions and 67 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ let package = Package(
// 💧 A server-side Swift web framework.
.package(
url: "https://github.com/vapor/vapor.git",
from: "4.0.0-rc"
from: "4.0.0"
),

// 💧 Vapor's ORM Framework.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Fluent

/// A protocol that wraps `Vapor`'s `ModelAuthenticatable`
/// for consistency in naming.
public protocol CorvusModelAuthenticatable: ModelAuthenticatable {}
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
import Fluent
import Vapor
import Fluent

// swiftlint:disable identifier_name

/// A protocol that defines bearer authentication tokens, similar to
/// `ModelUserToken`.
public protocol CorvusModelUserToken: CorvusModel {

/// `CorvusModelTokenAuthenticatable`.
public protocol CorvusModelTokenAuthenticatable: CorvusModel, Authenticatable {
/// The `User` type the token belongs to.
associatedtype User: CorvusModel & Authenticatable
/// The `String` value of the token.
var value: String { get set }
/// The `User` associated with the token.
var user: User { get set }
/// A boolean that deletes tokens if they're not in use.
var isValid: Bool { get }
associatedtype User: CorvusModel & Authenticatable

/// The `String` value of the token.
var value: String { get set }

/// The `User` associated with the token.
var user: User { get set }

/// A boolean that deletes tokens if they're not in use.
var isValid: Bool { get }
}

/// An extension to provide a default initializer to tokens so that they can
/// be initialized manually in module code.
extension CorvusModelUserToken {
extension CorvusModelTokenAuthenticatable {

/// Initializes a token.
/// - Parameters:
/// - id: The unique identifier of the token.
Expand All @@ -39,15 +38,15 @@ extension CorvusModelUserToken {
/// An extension to provide an authenticator for the token that can be
/// registered to the `Vapor` application, and field accessors for `value` and
/// `user`.
extension CorvusModelUserToken {
extension CorvusModelTokenAuthenticatable {

/// Provides a `Vapor` authenticator defined below.
public static func authenticator(
database: DatabaseID? = nil
) -> CorvusModelUserTokenAuthenticator<Self> {
CorvusModelUserTokenAuthenticator<Self>(database: database)
) -> CorvusModelTokenAuthenticator<Self> {
CorvusModelTokenAuthenticator<Self>(database: database)
}

/// Provides access to the `value` attribute.
var _$value: Field<String> {
guard let mirror = Mirror(reflecting: self).descendant("_value"),
Expand All @@ -71,16 +70,16 @@ extension CorvusModelUserToken {

/// Provides a `BearerAuthenticator` struct that defines how tokens are
/// authenticated.
public struct CorvusModelUserTokenAuthenticator<T: CorvusModelUserToken>:
public struct CorvusModelTokenAuthenticator<T: CorvusModelTokenAuthenticatable>:
BearerAuthenticator
{

/// The token's user.
public typealias User = T.User

/// The database the token is saved in.
public let database: DatabaseID?

/// Authenticates a token.
/// - Parameters:
/// - bearer: The bearer token passed in the request.
Expand All @@ -89,21 +88,23 @@ BearerAuthenticator
public func authenticate(
bearer: BearerAuthorization,
for request: Request
) -> EventLoopFuture<User?> {
) -> EventLoopFuture<Void> {
let db = request.db(self.database)
return T.query(on: db)
.filter(\._$value == bearer.token)
.first()
.flatMap
{ token -> EventLoopFuture<User?> in
{ token -> EventLoopFuture<Void> in
guard let token = token else {
return request.eventLoop.makeSucceededFuture(nil)
return request.eventLoop.makeSucceededFuture(())
}
guard token.isValid else {
return token.delete(on: db).map { nil }
return token.delete(on: db)
}
request.auth.login(token)
return token._$user.get(on: db).map {
request.auth.login($0)
}
return token._$user.get(on: db)
.map { $0 }
}
}
}
5 changes: 0 additions & 5 deletions Sources/Corvus/Authentication/CorvusModelUser.swift

This file was deleted.

2 changes: 1 addition & 1 deletion Sources/Corvus/Authentication/CorvusToken.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public struct CreateCorvusToken: Migration {

/// An extension to conform to the `CorvusModelUserToken` protocol, which
/// provides functionality to authenticate a token.
extension CorvusToken: CorvusModelUserToken {
extension CorvusToken: CorvusModelTokenAuthenticatable {

/// Prevents tokens from being deleted after authentication.
public var isValid: Bool {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Corvus/Authentication/CorvusUser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public struct CreateCorvusUser: Migration {

/// An extension to conform to the `CorvusModelUser` protocol, which provides
/// functionality to authenticate a user with username and password.
extension CorvusUser: CorvusModelUser {
extension CorvusUser: CorvusModelAuthenticatable {

/// Provides a path to the user's username.
public static let usernameKey = \CorvusUser.$username
Expand Down
4 changes: 2 additions & 2 deletions Sources/Corvus/Endpoints/Groups/BasicAuthGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Fluent

/// A special type of `Group` that protects its `content` with basic
/// authentication for a generic `CorvusModelUser`.
public struct BasicAuthGroup<T: CorvusModelUser>: Endpoint {
public struct BasicAuthGroup<T: CorvusModelAuthenticatable>: Endpoint {

/// An array of `PathComponent` describing the path that the
/// `BasicAuthGroup` extends.
Expand Down Expand Up @@ -44,7 +44,7 @@ public struct BasicAuthGroup<T: CorvusModelUser>: Endpoint {

let guardedRoutesBuilder = groupedRoutesBuilder.grouped([
T.guardMiddleware(),
T.authenticator().middleware()
T.authenticator()
])

content.register(to: guardedRoutesBuilder)
Expand Down
6 changes: 3 additions & 3 deletions Sources/Corvus/Endpoints/Groups/BearerAuthGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import Vapor
import Fluent

/// A special type of `Group` that protects its `content` with bearer token
/// authentication for a generic `CorvusModelUserToken`.
public struct BearerAuthGroup<T: CorvusModelUserToken>: Endpoint {
/// authentication for a generic `CorvusModelTokenAuthenticatable`.
public struct BearerAuthGroup<T: CorvusModelTokenAuthenticatable>: Endpoint {

/// An array of `PathComponent` describing the path that the
/// `BearerAuthGroup` extends.
Expand Down Expand Up @@ -44,7 +44,7 @@ public struct BearerAuthGroup<T: CorvusModelUserToken>: Endpoint {

let guardedRoutesBuilder = groupedRoutesBuilder.grouped([
T.User.guardMiddleware(),
T.authenticator().middleware()
T.authenticator()
])

content.register(to: guardedRoutesBuilder)
Expand Down
9 changes: 5 additions & 4 deletions Sources/Corvus/Endpoints/Login.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import Vapor
import Fluent

/// A class that provides functionality to log in a user with username and
/// password credentials sent in a HTTP POST `Request` and save a token for
/// that user. Needs an object of type `T` which represents the token to be
/// created upon login.
public final class Login<T: CorvusModelUserToken & ResponseEncodable>: Endpoint
where T.User: CorvusModelUser {
public final class Login<
T: CorvusModelTokenAuthenticatable & ResponseEncodable>:
Endpoint where T.User: CorvusModelAuthenticatable {

/// The route for the login functionality
let path: PathComponent
Expand Down Expand Up @@ -42,7 +43,7 @@ where T.User: CorvusModelUser {
/// about the HTTP route leading to the current component.
public func register(to routes: RoutesBuilder) {
let guardedRoutesBuilder = routes.grouped(
T.User.authenticator().middleware()
T.User.authenticator()
)

guardedRoutesBuilder.post(path, use: handler)
Expand Down
4 changes: 2 additions & 2 deletions Sources/Corvus/Endpoints/Modifiers/AuthModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Fluent
/// allows Corvus to chain modifiers, as it gets treated as any other struct
/// conforming to `AuthEndpoint`. Requires an object `T` that represents the
/// user to authorize.
public final class AuthModifier<Q: AuthEndpoint, T: CorvusModelUser>:
public final class AuthModifier<Q: AuthEndpoint, T: CorvusModelAuthenticatable>:
AuthEndpoint {

/// The return type for the `.handler()` modifier.
Expand Down Expand Up @@ -109,7 +109,7 @@ extension AuthEndpoint {
/// - Parameter user: A `KeyPath` to the related user property.
/// - Returns: An instance of a `AuthModifier` with the supplied `KeyPath`
/// to the user.
public func auth<T: CorvusModelUser>(
public func auth<T: CorvusModelAuthenticatable>(
_ user: AuthModifier<Self, T>.UserKeyPath
) -> AuthModifier<Self, T> {
AuthModifier(self, user: user)
Expand Down
4 changes: 2 additions & 2 deletions Sources/Corvus/Endpoints/Modifiers/UserAuthModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Fluent
/// That allows Corvus to chain modifiers, as it gets treated as any other
/// struct conforming to `AuthEndpoint`.
public final class UserAuthModifier<Q: AuthEndpoint>: AuthEndpoint
where Q.QuerySubject: CorvusModelUser {
where Q.QuerySubject: CorvusModelAuthenticatable {

/// The return type for the `.handler()` modifier.
public typealias Element = Q.Element
Expand Down Expand Up @@ -78,7 +78,7 @@ where Q.QuerySubject: CorvusModelUser {

/// An extension that adds the `.userAuth()` modifier to components conforming
/// to `AuthEndpoint`.
extension AuthEndpoint where Self.QuerySubject: CorvusModelUser {
extension AuthEndpoint where Self.QuerySubject: CorvusModelAuthenticatable {

/// A modifier used to make sure components only authorize requests where
/// the supplied `CorvusUser` is actually related to the `QuerySubject`.
Expand Down
2 changes: 1 addition & 1 deletion Sources/Corvus/Endpoints/User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Fluent

/// A class that contains Create, Read, Update and Delete functionality for a
/// generic type `T` representing a user object.
public final class User<T: CorvusModelUser & CorvusModel>: Endpoint {
public final class User<T: CorvusModelAuthenticatable & CorvusModel>: Endpoint {

/// The route path to the parameters.
let pathComponents: [PathComponent]
Expand Down
22 changes: 11 additions & 11 deletions Tests/CorvusTests/AuthenticationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ final class AuthenticationTests: XCTestCase {
let basicAuthenticatorTest = BasicAuthenticatorTest()

app.databases.use(.sqlite(.memory), as: .test, isDefault: true)
app.middleware.use(CorvusUser.authenticator().middleware())
app.middleware.use(CorvusUser.authenticator())
app.migrations.add(CreateAccount())
app.migrations.add(CreateCorvusUser())

Expand Down Expand Up @@ -85,7 +85,7 @@ final class AuthenticationTests: XCTestCase {
let basicAuthenticatorTest = BasicAuthenticatorTest()

app.databases.use(.sqlite(.memory), as: .test, isDefault: true)
app.middleware.use(CorvusUser.authenticator().middleware())
app.middleware.use(CorvusUser.authenticator())
app.migrations.add(CreateAccount())
app.migrations.add(CreateCorvusUser())

Expand Down Expand Up @@ -141,8 +141,8 @@ final class AuthenticationTests: XCTestCase {
let bearerAuthenticatorTest = BearerAuthenticatorTest()

app.databases.use(.sqlite(.memory), as: .test, isDefault: true)
app.middleware.use(CorvusToken.authenticator().middleware())
app.middleware.use(CorvusUser.authenticator().middleware())
app.middleware.use(CorvusToken.authenticator())
app.middleware.use(CorvusUser.authenticator())
app.migrations.add(CreateAccount())
app.migrations.add(CreateCorvusUser())
app.migrations.add(CreateCorvusToken())
Expand Down Expand Up @@ -216,7 +216,7 @@ final class AuthenticationTests: XCTestCase {
let bearerAuthenticatorTest = BearerAuthenticatorTest()

app.databases.use(.sqlite(.memory), as: .test, isDefault: true)
app.middleware.use(CorvusToken.authenticator().middleware())
app.middleware.use(CorvusToken.authenticator())
app.migrations.add(CreateAccount())
app.migrations.add(CreateCorvusUser())
app.migrations.add(CreateCorvusToken())
Expand Down Expand Up @@ -262,8 +262,8 @@ final class AuthenticationTests: XCTestCase {
let authModifierTest = AuthModifierTest()

app.databases.use(.sqlite(.memory), as: .test, isDefault: true)
app.middleware.use(CorvusToken.authenticator().middleware())
app.middleware.use(CorvusUser.authenticator().middleware())
app.middleware.use(CorvusToken.authenticator())
app.middleware.use(CorvusUser.authenticator())
app.migrations.add(CreateSecureAccount())
app.migrations.add(CreateCorvusUser())
app.migrations.add(CreateCorvusToken())
Expand Down Expand Up @@ -392,8 +392,8 @@ final class AuthenticationTests: XCTestCase {
let authModifierTest = AuthModifierTest()

app.databases.use(.sqlite(.memory), as: .test, isDefault: true)
app.middleware.use(CustomToken.authenticator().middleware())
app.middleware.use(CustomUser.authenticator().middleware())
app.middleware.use(CustomToken.authenticator())
app.middleware.use(CustomUser.authenticator())
app.migrations.add(CreateCustomAccount())
app.migrations.add(CreateCustomUser())
app.migrations.add(CreateCustomToken())
Expand Down Expand Up @@ -516,8 +516,8 @@ final class AuthenticationTests: XCTestCase {
let userAuthModifierTest = UserAuthModifierTest()

app.databases.use(.sqlite(.memory), as: .test, isDefault: true)
app.middleware.use(CorvusToken.authenticator().middleware())
app.middleware.use(CorvusUser.authenticator().middleware())
app.middleware.use(CorvusToken.authenticator())
app.middleware.use(CorvusUser.authenticator())
app.migrations.add(CreateSecureAccount())
app.migrations.add(CreateCorvusUser())
app.migrations.add(CreateCorvusToken())
Expand Down
2 changes: 1 addition & 1 deletion Tests/CorvusTests/Models/CustomToken.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Corvus
import Foundation
import Fluent

public final class CustomToken: CorvusModelUserToken {
public final class CustomToken: CorvusModelTokenAuthenticatable {

public static let schema = "custom_tokens"

Expand Down
4 changes: 2 additions & 2 deletions Tests/CorvusTests/Models/CustomUser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Fluent
import Vapor
import Foundation

public final class CustomUser: CorvusModel {
public final class CustomUser: CorvusModel, Authenticatable {

public static let schema = "custom_users"

Expand Down Expand Up @@ -62,7 +62,7 @@ public struct CreateCustomUser: Migration {
}
}

extension CustomUser: CorvusModelUser {
extension CustomUser: CorvusModelAuthenticatable {

public static let usernameKey = \CustomUser.$username

Expand Down

0 comments on commit b83435c

Please sign in to comment.