mirror of
https://github.com/navidrome/navidrome.git
synced 2025-03-31 11:07:36 +03:00
feat(ui): hide absolute paths from regular users
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
3394580413
commit
46a2ec0ba1
2 changed files with 97 additions and 13 deletions
|
@ -1,24 +1,22 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import React from 'react'
|
||||
import { useRecordContext } from 'react-admin'
|
||||
import { usePermissions, useRecordContext } from 'react-admin'
|
||||
import config from '../config'
|
||||
|
||||
export const PathField = (props) => {
|
||||
const record = useRecordContext(props)
|
||||
return (
|
||||
<span>
|
||||
{record.libraryPath}
|
||||
{config.separator}
|
||||
{record.path}
|
||||
</span>
|
||||
)
|
||||
const { permissions } = usePermissions()
|
||||
let path = permissions === 'admin' ? record.libraryPath : ''
|
||||
|
||||
if (path && path.endsWith(config.separator)) {
|
||||
path = `${path}${record.path}`
|
||||
} else {
|
||||
path = path ? `${path}${config.separator}${record.path}` : record.path
|
||||
}
|
||||
|
||||
return <span>{path}</span>
|
||||
}
|
||||
|
||||
PathField.propTypes = {
|
||||
label: PropTypes.string,
|
||||
record: PropTypes.object,
|
||||
}
|
||||
|
||||
PathField.defaultProps = {
|
||||
addLabel: true,
|
||||
}
|
||||
|
|
86
ui/src/common/PathField.test.jsx
Normal file
86
ui/src/common/PathField.test.jsx
Normal file
|
@ -0,0 +1,86 @@
|
|||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import { PathField } from './PathField'
|
||||
import { usePermissions, useRecordContext } from 'react-admin'
|
||||
import config from '../config'
|
||||
|
||||
// Mock react-admin hooks
|
||||
vi.mock('react-admin', () => ({
|
||||
usePermissions: vi.fn(),
|
||||
useRecordContext: vi.fn(),
|
||||
}))
|
||||
|
||||
// Mock config
|
||||
vi.mock('../config', () => ({
|
||||
default: {
|
||||
separator: '/',
|
||||
},
|
||||
}))
|
||||
|
||||
describe('PathField', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('renders path without libraryPath for non-admin users', () => {
|
||||
// Setup
|
||||
usePermissions.mockReturnValue({ permissions: 'user' })
|
||||
useRecordContext.mockReturnValue({
|
||||
path: 'music/song.mp3',
|
||||
libraryPath: '/data/media',
|
||||
})
|
||||
|
||||
// Act
|
||||
const { container } = render(<PathField />)
|
||||
|
||||
// Assert
|
||||
expect(container.textContent).toBe('music/song.mp3')
|
||||
expect(container.textContent).not.toContain('/data/media')
|
||||
})
|
||||
|
||||
it('renders combined path for admin users when libraryPath does not end with separator', () => {
|
||||
// Setup
|
||||
usePermissions.mockReturnValue({ permissions: 'admin' })
|
||||
useRecordContext.mockReturnValue({
|
||||
path: 'music/song.mp3',
|
||||
libraryPath: '/data/media',
|
||||
})
|
||||
|
||||
// Act
|
||||
const { container } = render(<PathField />)
|
||||
|
||||
// Assert
|
||||
expect(container.textContent).toBe('/data/media/music/song.mp3')
|
||||
})
|
||||
|
||||
it('renders combined path for admin users when libraryPath ends with separator', () => {
|
||||
// Setup
|
||||
usePermissions.mockReturnValue({ permissions: 'admin' })
|
||||
useRecordContext.mockReturnValue({
|
||||
path: 'music/song.mp3',
|
||||
libraryPath: '/data/media/',
|
||||
})
|
||||
|
||||
// Act
|
||||
const { container } = render(<PathField />)
|
||||
|
||||
// Assert
|
||||
expect(container.textContent).toBe('/data/media/music/song.mp3')
|
||||
})
|
||||
|
||||
it('works with a different separator from config', () => {
|
||||
// Setup
|
||||
config.separator = '\\'
|
||||
usePermissions.mockReturnValue({ permissions: 'admin' })
|
||||
useRecordContext.mockReturnValue({
|
||||
path: 'music\\song.mp3',
|
||||
libraryPath: 'C:\\data',
|
||||
})
|
||||
|
||||
// Act
|
||||
const { container } = render(<PathField />)
|
||||
|
||||
// Assert
|
||||
expect(container.textContent).toBe('C:\\data\\music\\song.mp3')
|
||||
})
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue