UNPKG

4.46 kBSource Map (JSON)View Raw
1{"version":3,"sources":["../../../src/mixins/lucid.ts"],"sourcesContent":["/*\n * @adonisjs/auth\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport type { Hash } from '@adonisjs/core/hash'\nimport { RuntimeException } from '@adonisjs/core/exceptions'\nimport { beforeSave, type BaseModel } from '@adonisjs/lucid/orm'\nimport type { NormalizeConstructor } from '@adonisjs/core/types/helpers'\nimport { E_INVALID_CREDENTIALS } from '../errors.js'\n\n/**\n * Mixing to add user lookup and password verification methods\n * on a model.\n *\n * Under the hood, this mixin defines following methods and hooks\n *\n * - beforeSave hook to hash user password\n * - findForAuth method to find a user during authentication\n * - verifyCredentials method to verify user credentials and prevent\n * timing attacks.\n */\nexport function withAuthFinder(\n hash: () => Hash,\n options: {\n uids: string[]\n passwordColumnName: string\n }\n) {\n return <Model extends NormalizeConstructor<typeof BaseModel>>(superclass: Model) => {\n class UserWithUserFinder extends superclass {\n /**\n * Hook to verify user password when creating or updating\n * the user model.\n */\n @beforeSave()\n static async hashPassword<T extends typeof UserWithUserFinder>(\n this: T,\n user: InstanceType<T>\n ) {\n if (user.$dirty[options.passwordColumnName]) {\n ;(user as any)[options.passwordColumnName] = await hash().make(\n (user as any)[options.passwordColumnName]\n )\n }\n }\n\n /**\n * Finds the user for authentication via \"verifyCredentials\".\n * Feel free to override this method customize the user\n * lookup behavior.\n */\n static findForAuth<T extends typeof UserWithUserFinder>(\n this: T,\n uids: string[],\n value: string\n ): Promise<InstanceType<T> | null> {\n const query = this.query()\n uids.forEach((uid) => query.orWhere(uid, value))\n return query.limit(1).first()\n }\n\n /**\n * Find a user by uid and verify their password. This method is\n * safe from timing attacks.\n */\n static async verifyCredentials<T extends typeof UserWithUserFinder>(\n this: T,\n uid: string,\n password: string\n ) {\n /**\n * Fail when uid or the password are missing\n */\n if (!uid || !password) {\n throw new E_INVALID_CREDENTIALS('Invalid user credentials')\n }\n\n const user = await this.findForAuth(options.uids, uid)\n if (!user) {\n await hash().make(password)\n throw new E_INVALID_CREDENTIALS('Invalid user credentials')\n }\n\n const passwordHash = (user as any)[options.passwordColumnName]\n if (!passwordHash) {\n throw new RuntimeException(\n `Cannot verify password during login. The value of column \"${options.passwordColumnName}\" is undefined or null`\n )\n }\n\n if (await hash().verify(passwordHash, password)) {\n return user\n }\n\n throw new E_INVALID_CREDENTIALS('Invalid user credentials')\n }\n }\n\n return UserWithUserFinder\n }\n}\n"],"mappings":";;;;;;;;AAUA,SAAS,wBAAwB;AACjC,SAAS,kBAAkC;AAepC,SAAS,eACd,MACA,SAIA;AACA,SAAO,CAAuD,eAAsB;AAAA,IAClF,MAAM,2BAA2B,WAAW;AAAA,MAM1C,aAAa,aAEX,MACA;AACA,YAAI,KAAK,OAAO,QAAQ,kBAAkB,GAAG;AAC3C;AAAC,UAAC,KAAa,QAAQ,kBAAkB,IAAI,MAAM,KAAK,EAAE;AAAA,YACvD,KAAa,QAAQ,kBAAkB;AAAA,UAC1C;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,OAAO,YAEL,MACA,OACiC;AACjC,cAAM,QAAQ,KAAK,MAAM;AACzB,aAAK,QAAQ,CAAC,QAAQ,MAAM,QAAQ,KAAK,KAAK,CAAC;AAC/C,eAAO,MAAM,MAAM,CAAC,EAAE,MAAM;AAAA,MAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,aAAa,kBAEX,KACA,UACA;AAIA,YAAI,CAAC,OAAO,CAAC,UAAU;AACrB,gBAAM,IAAI,sBAAsB,0BAA0B;AAAA,QAC5D;AAEA,cAAM,OAAO,MAAM,KAAK,YAAY,QAAQ,MAAM,GAAG;AACrD,YAAI,CAAC,MAAM;AACT,gBAAM,KAAK,EAAE,KAAK,QAAQ;AAC1B,gBAAM,IAAI,sBAAsB,0BAA0B;AAAA,QAC5D;AAEA,cAAM,eAAgB,KAAa,QAAQ,kBAAkB;AAC7D,YAAI,CAAC,cAAc;AACjB,gBAAM,IAAI;AAAA,YACR,6DAA6D,QAAQ,kBAAkB;AAAA,UACzF;AAAA,QACF;AAEA,YAAI,MAAM,KAAK,EAAE,OAAO,cAAc,QAAQ,GAAG;AAC/C,iBAAO;AAAA,QACT;AAEA,cAAM,IAAI,sBAAsB,0BAA0B;AAAA,MAC5D;AAAA,IACF;AA7De;AAAA,MADZ,WAAW;AAAA,OALR,oBAMS;AA+Df,WAAO;AAAA,EACT;AACF;","names":[]}
\No newline at end of file