mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-29 06:37:17 +01:00
fix: resolve LibrarySelectionField validation error for non-admin users
Fixed validation error 'At least one library must be selected for non-admin users' that appeared even when libraries were selected. The issue was caused by a data format mismatch between backend and frontend. The backend sends user data with libraries as an array of objects, but the LibrarySelectionField component expects libraryIds as an array of IDs. Added data transformation in the data provider's getOne method to automatically convert libraries array to libraryIds format when fetching user records. Also extracted validation logic into a separate userValidation module for better code organization and added comprehensive test coverage to prevent similar issues.
This commit is contained in:
parent
cab5da7846
commit
b9386ab41a
4 changed files with 107 additions and 14 deletions
|
|
@ -139,7 +139,19 @@ const wrapperDataProvider = {
|
|||
},
|
||||
getOne: (resource, params) => {
|
||||
const [r, p] = mapResource(resource, params)
|
||||
return dataProvider.getOne(r, p)
|
||||
const response = dataProvider.getOne(r, p)
|
||||
|
||||
// Transform user data to ensure libraryIds is present for form compatibility
|
||||
if (resource === 'user') {
|
||||
return response.then((result) => {
|
||||
if (result.data.libraries && Array.isArray(result.data.libraries)) {
|
||||
result.data.libraryIds = result.data.libraries.map((lib) => lib.id)
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
return response
|
||||
},
|
||||
getMany: (resource, params) => {
|
||||
const [r, p] = mapResource(resource, params)
|
||||
|
|
|
|||
|
|
@ -18,11 +18,13 @@ import {
|
|||
useRefresh,
|
||||
FormDataConsumer,
|
||||
usePermissions,
|
||||
useRecordContext,
|
||||
} from 'react-admin'
|
||||
import { Typography } from '@material-ui/core'
|
||||
import { Title } from '../common'
|
||||
import DeleteUserButton from './DeleteUserButton'
|
||||
import { LibrarySelectionField } from './LibrarySelectionField.jsx'
|
||||
import { validateUserForm } from './userValidation'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
toolbar: {
|
||||
|
|
@ -103,18 +105,8 @@ const UserEdit = (props) => {
|
|||
)
|
||||
|
||||
// Custom validation function
|
||||
const validateUserForm = (values) => {
|
||||
const errors = {}
|
||||
// Only require library selection for non-admin users
|
||||
if (
|
||||
!values.isAdmin &&
|
||||
(!values.libraryIds || values.libraryIds.length === 0)
|
||||
) {
|
||||
errors.libraryIds = translate(
|
||||
'resources.user.validation.librariesRequired',
|
||||
)
|
||||
}
|
||||
return errors
|
||||
const validateForm = (values) => {
|
||||
return validateUserForm(values, translate)
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -123,7 +115,7 @@ const UserEdit = (props) => {
|
|||
variant={'outlined'}
|
||||
toolbar={<UserToolbar showDelete={canDelete} />}
|
||||
save={save}
|
||||
validate={validateUserForm}
|
||||
validate={validateForm}
|
||||
>
|
||||
{permissions === 'admin' && (
|
||||
<TextInput
|
||||
|
|
|
|||
19
ui/src/user/userValidation.js
Normal file
19
ui/src/user/userValidation.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// User form validation utilities
|
||||
export const validateUserForm = (values, translate) => {
|
||||
const errors = {}
|
||||
|
||||
// Only require library selection for non-admin users
|
||||
if (!values.isAdmin) {
|
||||
// Check both libraryIds (array of IDs) and libraries (array of objects)
|
||||
const hasLibraryIds = values.libraryIds && values.libraryIds.length > 0
|
||||
const hasLibraries = values.libraries && values.libraries.length > 0
|
||||
|
||||
if (!hasLibraryIds && !hasLibraries) {
|
||||
errors.libraryIds = translate(
|
||||
'resources.user.validation.librariesRequired',
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
70
ui/src/user/userValidation.test.js
Normal file
70
ui/src/user/userValidation.test.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { validateUserForm } from './userValidation'
|
||||
|
||||
describe('User Validation Utilities', () => {
|
||||
const mockTranslate = vi.fn((key) => key)
|
||||
|
||||
describe('validateUserForm', () => {
|
||||
it('should not return errors for admin users', () => {
|
||||
const values = {
|
||||
isAdmin: true,
|
||||
libraryIds: [],
|
||||
}
|
||||
const errors = validateUserForm(values, mockTranslate)
|
||||
expect(errors).toEqual({})
|
||||
})
|
||||
|
||||
it('should not return errors for non-admin users with libraries', () => {
|
||||
const values = {
|
||||
isAdmin: false,
|
||||
libraryIds: [1, 2, 3],
|
||||
}
|
||||
const errors = validateUserForm(values, mockTranslate)
|
||||
expect(errors).toEqual({})
|
||||
})
|
||||
|
||||
it('should return error for non-admin users without libraries', () => {
|
||||
const values = {
|
||||
isAdmin: false,
|
||||
libraryIds: [],
|
||||
}
|
||||
const errors = validateUserForm(values, mockTranslate)
|
||||
expect(errors.libraryIds).toBe(
|
||||
'resources.user.validation.librariesRequired',
|
||||
)
|
||||
})
|
||||
|
||||
it('should return error for non-admin users with undefined libraryIds', () => {
|
||||
const values = {
|
||||
isAdmin: false,
|
||||
}
|
||||
const errors = validateUserForm(values, mockTranslate)
|
||||
expect(errors.libraryIds).toBe(
|
||||
'resources.user.validation.librariesRequired',
|
||||
)
|
||||
})
|
||||
|
||||
it('should not return errors for non-admin users with libraries array', () => {
|
||||
const values = {
|
||||
isAdmin: false,
|
||||
libraries: [
|
||||
{ id: 1, name: 'Library 1' },
|
||||
{ id: 2, name: 'Library 2' },
|
||||
],
|
||||
}
|
||||
const errors = validateUserForm(values, mockTranslate)
|
||||
expect(errors).toEqual({})
|
||||
})
|
||||
|
||||
it('should return error for non-admin users with empty libraries array', () => {
|
||||
const values = {
|
||||
isAdmin: false,
|
||||
libraries: [],
|
||||
}
|
||||
const errors = validateUserForm(values, mockTranslate)
|
||||
expect(errors.libraryIds).toBe(
|
||||
'resources.user.validation.librariesRequired',
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue