import { Authenticatable, AuthenticatableCredentials, AuthenticatableIdentifier, AuthenticatableRepository, } from '../types' import {Awaitable, Maybe} from '../../util' import {ORMUser} from './ORMUser' import {Container, Inject, Injectable} from '../../di' import {AuthenticatableAlreadyExistsError} from '../AuthenticatableAlreadyExistsError' /** * A user repository implementation that looks up users stored in the database. */ @Injectable() export class ORMUserRepository extends AuthenticatableRepository { @Inject('injector') protected readonly injector!: Container /** Look up the user by their username. */ getByIdentifier(id: AuthenticatableIdentifier): Awaitable> { return ORMUser.query() .where('username', '=', id) .first() } /** * Try to look up a user by the credentials provided. * If a securityIdentifier is specified, look up the user by username. * If username/password are specified, look up the user and verify the password. * @param credentials */ async getByCredentials(credentials: AuthenticatableCredentials): Promise> { if ( !credentials.identifier && credentials.credential ) { return ORMUser.query() .where('username', '=', credentials.credential) .first() } if ( credentials.identifier && credentials.credential ) { const user = await ORMUser.query() .where('username', '=', credentials.identifier) .first() if ( user && await user.verifyPassword(credentials.credential) ) { return user } } } async createByCredentials(credentials: AuthenticatableCredentials): Promise { if ( await this.getByCredentials(credentials) ) { throw new AuthenticatableAlreadyExistsError(`Authenticatable already exists with credentials.`, { identifier: credentials.identifier, }) } const user = this.injector.make(ORMUser) user.username = credentials.identifier await user.setPassword(credentials.credential) await user.save() return user } }