Skip to content

Conversation

@0xTim
Copy link
Member

@0xTim 0xTim commented Dec 4, 2020

Improves the experience for users writing web applications. Adds a ModelCredentialsAuthenticator to automatically conform Model types to CredentialsAuthenticatable and provide a middleware to use.

This can be used when logging in users via a web form, as shown in the tests. This also backfills some tests for ModelSessionAuthenticatable.

Also fixes a bug where the SessionAuthenticator was not using the provided DatabaseID

Resolves #710
Resolves #701

Docs here vapor/docs#576

@0xTim 0xTim requested a review from gwynne December 4, 2020 14:14
@0xTim 0xTim added the semver-minor Contains new APIs label Dec 4, 2020
@0xTim 0xTim requested a review from siemensikkema December 5, 2020 09:39
public let database: DatabaseID?

func authenticate(credentials: ModelCredentials, for request: Request) -> EventLoopFuture<Void> {
User.query(on: request.db(self.database)).filter(\._$username == credentials.username).first().flatMapThrowing { foundUser in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, since this is a default implementation that a lot of people will end up using, we should do something like this:

    .all()
    .flatMapThrowing {
#if DEBUG
        assert($0.count <= 1 , "Usernames must be unique in your database")
#else
        guard $0.count <= 1 else throw Abort(.conflict, reason: "Found more than one matching user")
#endif
        return $0.first
    }

I'd hate for it to turn into another potential footgun for the unsuspecting 😕. Granted, this would only catch the case where someone actually did end up with multiple of the same username, but at least it's something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given this affects all of the authenticators, we should probably do that as a separate PR


func authenticate(sessionID: User.SessionID, for request: Request) -> EventLoopFuture<Void> {
User.find(sessionID, on: request.db).map {
User.find(sessionID, on: request.db(self.databaseID)).map {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ouch, I don't like that this was missing at all 😕

@0xTim 0xTim merged commit 855cd81 into master Dec 8, 2020
@0xTim 0xTim deleted the credentials-model branch December 8, 2020 09:56
@tanner0101
Copy link
Member

These changes are now available in 4.1.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver-minor Contains new APIs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fluent should provide a ModelCredentialsAuthenticatable protocol sessionAuthenticator ignores databaseID

3 participants