fix: corrects local strategy user lookup when using loginWithUsername (#7587)

## Description

Fixes the local strategy user lookup.

- [x] I have read and understand the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## Checklist:

- [x] I have added tests that prove my fix is effective or that my
feature works
- [ ] Existing test suite passes locally with my changes
- [ ] I have made corresponding changes to the documentation
This commit is contained in:
Jarrod Flesch
2024-08-08 19:51:12 -04:00
committed by GitHub
parent ee62ed6ebb
commit 6227276d2c
2 changed files with 86 additions and 28 deletions

View File

@@ -1,6 +1,6 @@
import type { SanitizedCollectionConfig } from '../../../collections/config/types.js' import type { SanitizedCollectionConfig } from '../../../collections/config/types.js'
import type { JsonObject, Payload } from '../../../index.js' import type { JsonObject, Payload } from '../../../index.js'
import type { PayloadRequest } from '../../../types/index.js' import type { PayloadRequest, Where } from '../../../types/index.js'
import { ValidationError } from '../../../errors/index.js' import { ValidationError } from '../../../errors/index.js'
import { generatePasswordSaltHash } from './generatePasswordSaltHash.js' import { generatePasswordSaltHash } from './generatePasswordSaltHash.js'
@@ -22,23 +22,43 @@ export const registerLocalStrategy = async ({
}: Args): Promise<Record<string, unknown>> => { }: Args): Promise<Record<string, unknown>> => {
const loginWithUsername = collection?.auth?.loginWithUsername const loginWithUsername = collection?.auth?.loginWithUsername
let whereConstraint: Where
if (!loginWithUsername) {
whereConstraint = {
email: {
equals: doc.email,
},
}
} else {
whereConstraint = {
or: [],
}
if (doc.email) {
whereConstraint.or.push({
email: {
equals: doc.email,
},
})
}
if (doc.username) {
whereConstraint.or.push({
username: {
equals: doc.username,
},
})
}
}
const existingUser = await payload.find({ const existingUser = await payload.find({
collection: collection.slug, collection: collection.slug,
depth: 0, depth: 0,
limit: 1, limit: 1,
pagination: false, pagination: false,
req, req,
where: loginWithUsername where: whereConstraint,
? {
username: {
equals: doc.username,
},
}
: {
email: {
equals: doc.email,
},
},
}) })
if (existingUser.docs.length > 0) { if (existingUser.docs.length > 0) {

View File

@@ -17,22 +17,20 @@ describe('Login With Username Feature', () => {
} }
}) })
describe('hook execution', () => { it('should not allow creation with neither email nor username', async () => {
it('should not allow creation with neither email nor username', async () => { let errors = []
let errors = [] try {
try { await payload.create({
await payload.create({ collection: 'login-with-either',
collection: 'login-with-either', data: {
data: { email: null,
email: null, username: null,
username: null, },
}, })
}) } catch (error) {
} catch (error) { errors = error.data.errors
errors = error.data.errors }
} expect(errors).toHaveLength(2)
expect(errors).toHaveLength(2)
})
}) })
it('should not allow removing both username and email fields', async () => { it('should not allow removing both username and email fields', async () => {
@@ -115,4 +113,44 @@ describe('Login With Username Feature', () => {
}) })
expect(loginWithUsername).toHaveProperty('token') expect(loginWithUsername).toHaveProperty('token')
}) })
it('should allow mutliple creates with optional email and username', async () => {
// create a user with just email
await payload.create({
collection: 'login-with-either',
data: {
email: 'email1@mail.com',
password: 'test',
},
})
// create second user with just email
const emailUser2 = await payload.create({
collection: 'login-with-either',
data: {
email: 'email2@mail.com',
password: 'test',
},
})
expect(emailUser2).toHaveProperty('id')
// create user with just username
await payload.create({
collection: 'login-with-either',
data: {
username: 'username1',
password: 'test',
},
})
// create second user with just username
const usernameUser2 = await payload.create({
collection: 'login-with-either',
data: {
username: 'username2',
password: 'test',
},
})
expect(usernameUser2).toHaveProperty('id')
})
}) })