Skip to content

Commit 7ebc10e

Browse files
committed
feat: make withAuthFinder mixin accept hash manager and make options optional
1 parent cec6ee8 commit 7ebc10e

File tree

4 files changed

+34
-31
lines changed

4 files changed

+34
-31
lines changed

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@
5151
"quick:test": "cross-env NODE_DEBUG=\"adonisjs:auth:*\" node --enable-source-maps --import=@poppinss/ts-exec ./bin/test.js"
5252
},
5353
"devDependencies": {
54-
"@adonisjs/assembler": "^8.0.0-next.9",
55-
"@adonisjs/core": "^7.0.0-next.7",
54+
"@adonisjs/assembler": "^8.0.0-next.14",
55+
"@adonisjs/core": "^7.0.0-next.8",
5656
"@adonisjs/eslint-config": "^3.0.0-next.1",
5757
"@adonisjs/i18n": "^3.0.0-next.1",
5858
"@adonisjs/lucid": "^22.0.0-next.1",
@@ -71,7 +71,7 @@
7171
"@release-it/conventional-changelog": "^10.0.1",
7272
"@types/basic-auth": "^1.1.8",
7373
"@types/luxon": "^3.7.1",
74-
"@types/node": "^24.8.1",
74+
"@types/node": "^24.9.1",
7575
"@types/set-cookie-parser": "^2.4.10",
7676
"@types/sinon": "^17.0.4",
7777
"c8": "^10.1.3",
@@ -82,7 +82,7 @@
8282
"dotenv": "^17.2.3",
8383
"eslint": "^9.38.0",
8484
"luxon": "^3.7.2",
85-
"mysql2": "^3.15.2",
85+
"mysql2": "^3.15.3",
8686
"nock": "^14.0.10",
8787
"pg": "^8.16.3",
8888
"playwright": "^1.56.1",

src/mixins/lucid.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* file that was distributed with this source code.
88
*/
99

10-
import type { Hash } from '@adonisjs/core/hash'
10+
import type { Hash, HashManager } from '@adonisjs/core/hash'
1111
import { RuntimeException } from '@adonisjs/core/exceptions'
1212
import { beforeSave, type BaseModel } from '@adonisjs/lucid/orm'
1313
import type { NormalizeConstructor } from '@adonisjs/core/types/helpers'
@@ -59,12 +59,15 @@ type UserWithUserFinderClass<
5959
* }
6060
*/
6161
export function withAuthFinder(
62-
hash: () => Hash,
63-
options: {
64-
uids: string[]
65-
passwordColumnName: string
62+
hash: (() => Hash) | HashManager<any>,
63+
options?: {
64+
uids?: string[]
65+
passwordColumnName?: string
6666
}
6767
) {
68+
let normalizedOptions = { uids: ['email'], passwordColumnName: 'password', ...options }
69+
let hashFactory = typeof hash === 'function' ? hash : () => hash.use()
70+
6871
return function <Model extends NormalizeConstructor<typeof BaseModel>>(
6972
superclass: Model
7073
): UserWithUserFinderClass<Model> {
@@ -83,9 +86,9 @@ export function withAuthFinder(
8386
*/
8487
@beforeSave()
8588
static async hashPassword<T extends UserWithUserFinderClass>(this: T, user: InstanceType<T>) {
86-
if (user.$dirty[options.passwordColumnName]) {
87-
;(user as any)[options.passwordColumnName] = await hash().make(
88-
(user as any)[options.passwordColumnName]
89+
if (user.$dirty[normalizedOptions.passwordColumnName]) {
90+
;(user as any)[normalizedOptions.passwordColumnName] = await hashFactory().make(
91+
(user as any)[normalizedOptions.passwordColumnName]
8992
)
9093
}
9194
}
@@ -136,9 +139,9 @@ export function withAuthFinder(
136139
throw new E_INVALID_CREDENTIALS('Invalid user credentials')
137140
}
138141

139-
const user = await this.findForAuth(options.uids, uid)
142+
const user = await this.findForAuth(normalizedOptions.uids, uid)
140143
if (!user) {
141-
await hash().make(password)
144+
await hashFactory().make(password)
142145
throw new E_INVALID_CREDENTIALS('Invalid user credentials')
143146
}
144147

@@ -164,13 +167,13 @@ export function withAuthFinder(
164167
* }
165168
*/
166169
verifyPassword(plainPassword: string): Promise<boolean> {
167-
const passwordHash = (this as any)[options.passwordColumnName]
170+
const passwordHash = (this as any)[normalizedOptions.passwordColumnName]
168171
if (!passwordHash) {
169172
throw new RuntimeException(
170-
`Cannot verify password. The value for "${options.passwordColumnName}" column is undefined or null`
173+
`Cannot verify password. The value for "${normalizedOptions.passwordColumnName}" column is undefined or null`
171174
)
172175
}
173-
return hash().verify(passwordHash, plainPassword)
176+
return hashFactory().verify(passwordHash, plainPassword)
174177
}
175178
}
176179

tests/auth/mixins/with_auth_finder.spec.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import convertHrtime from 'convert-hrtime'
1212
import { compose } from '@adonisjs/core/helpers'
1313
import { BaseModel, column } from '@adonisjs/lucid/orm'
1414

15-
import { createDatabase, createTables, getHasher } from '../../helpers.ts'
1615
import { withAuthFinder } from '../../../src/mixins/lucid.ts'
16+
import { createDatabase, createTables, getHasher, getHasherManager } from '../../helpers.ts'
1717

1818
test.group('withAuthFinder | findForAuth', () => {
1919
test('find user for authentication using the mixin', async ({ assert, expectTypeOf }) => {
@@ -24,10 +24,7 @@ test.group('withAuthFinder | findForAuth', () => {
2424

2525
class User extends compose(
2626
BaseModel,
27-
withAuthFinder(() => hash, {
28-
uids: ['email', 'username'],
29-
passwordColumnName: 'password',
30-
})
27+
withAuthFinder(() => hash)
3128
) {
3229
@column({ isPrimary: true })
3330
declare id: number
@@ -62,15 +59,9 @@ test.group('withAuthFinder | findForAuth', () => {
6259
const db = await createDatabase()
6360
await createTables(db)
6461

65-
const hash = getHasher()
62+
const hash = getHasherManager()
6663

67-
class User extends compose(
68-
BaseModel,
69-
withAuthFinder(() => hash, {
70-
uids: ['email', 'username'],
71-
passwordColumnName: 'password',
72-
})
73-
) {
64+
class User extends compose(BaseModel, withAuthFinder(hash)) {
7465
@column({ isPrimary: true })
7566
declare id: number
7667

tests/helpers.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import { join } from 'node:path'
1111
import timekeeper from 'timekeeper'
1212
import { configDotenv } from 'dotenv'
13-
import { Hash } from '@adonisjs/core/hash'
13+
import { Hash, HashManager } from '@adonisjs/core/hash'
1414
import { mkdir, rm } from 'node:fs/promises'
1515
import { getActiveTest } from '@japa/runner'
1616
import { Emitter } from '@adonisjs/core/events'
@@ -35,6 +35,15 @@ export function getHasher() {
3535
return new Hash(new Scrypt({}))
3636
}
3737

38+
export function getHasherManager() {
39+
return new HashManager({
40+
default: 'scrypt',
41+
list: {
42+
scrypt: () => getHasher(),
43+
},
44+
})
45+
}
46+
3847
/**
3948
* Creates an instance of the database class for making queries
4049
*/

0 commit comments

Comments
 (0)