* fix(ui): use div for fragment, check lastfm url for artist page
* use span instead of div for better compat
* fix: implement isLastFmURL utility and add tests for URL validation
---------
Co-authored-by: Deluan <deluan@navidrome.org>
* Rework frontend code interacting directly with DOM
Rework frontend code that uses user-supplied data to render things like
comments and notes. In places where using React's built-in sanitization
is possible, the feature is used. In other places, where some markup
might be necessary, DOMPurify is used to sanitize the HTML before
rendering it.
Solves: GHSA-rh3r-8pxm-hg4w
* Remove test post DOM rework
* fixup! Rework frontend code interacting directly with DOM
* refactor: rename ArtistRadio to SimilarSongs for clarity and consistency
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: implement GetSimilarSongsByTrack and related functionality for song similarity retrieval
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance GetSimilarSongsByTrack to include artist and album details and update tests
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance song matching by implementing title and artist filtering in loadTracksByTitleAndArtist
Signed-off-by: Deluan <deluan@navidrome.org>
* test: add unit tests for song matching functionality in provider
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: extract song matching functionality into its own file
Signed-off-by: Deluan <deluan@navidrome.org>
* docs: clarify similarSongsFallback function description in provider.go
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: initialize result slice for songs with capacity based on response length
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: simplify agent method calls for retrieving images and similar songs
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: simplify agent method calls for retrieving images and similar songs
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: remove outdated comments in GetSimilarSongs methods
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: use composite key for song matches to handle duplicates by title and artist
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: consolidate expectations setup for similar songs tests
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add instant mix action to song context menu and update translations
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(provider): handle unknown entity types in GetSimilarSongs
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: move playSimilar action to playbackActions and streamline song processing
Signed-off-by: Deluan <deluan@navidrome.org>
* format
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance instant mix functionality with loading notification and shuffle option
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: implement fuzzy matching for similar songs based on configurable threshold
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: implement track matching with multiple specificity levels
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: enhance track matching by implementing unified scoring with specificity levels
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance deezer top tracks result with album
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance track matching with fuzzy album similarity for improved scoring
Signed-off-by: Deluan <deluan@navidrome.org>
* docs: document multi-phase song matching algorithm with detailed scoring and prioritization
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: enable library access for headless processes
Fixed multi-library filtering to allow headless processes (shares, external providers) to access data by skipping library restrictions when no user context is present.
Previously, the library filtering system returned empty results (WHERE 1=0) for processes without user authentication, breaking functionality like public shares and external service integrations.
Key changes:
- Modified applyLibraryFilter methods to skip filtering when user.ID == invalidUserId
- Refactored tag repository to use helper method for library filtering logic
- Fixed SQL aggregation bug in tag statistics calculation across multiple libraries
- Added comprehensive test coverage for headless process scenarios
- Updated genre repository to support proper column mappings for aggregated data
This preserves the secure "safe by default" approach for authenticated users while restoring backward compatibility for background processes that need unrestricted data access.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: resolve SQL ambiguity errors in share queries
Fixed SQL ambiguity errors that were breaking share links after the Multi-library PR.
The Multi-library changes introduced JOINs between album and library tables,
both of which have 'id' columns, causing 'ambiguous column name: id' errors
when unqualified column references were used in WHERE clauses.
Changes made:
- Updated core/share.go to use 'album.id' instead of 'id' in contentsLabelFromAlbums
- Updated persistence/share_repository.go to use 'album.id' in album share loading
- Updated persistence/sql_participations.go to use 'artist.id' for consistency
- Added regression tests to prevent future SQL ambiguity issues
This resolves HTTP 500 errors that users experienced when accessing existing
share URLs after the Multi-library feature was merged.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: improve headless library access handling
Added proper user context validation and reordered joins in applyLibraryFilterToArtistQuery to ensure library filtering works correctly for both authenticated and headless operations. The user_library join is now only applied when a valid user context exists, while the library_artist join is always applied to maintain proper data relationships. (+1 squashed commit)
Squashed commits:
[a28c6965b] fix: remove headless library access guard
Removed the invalidUserId guard condition in applyLibraryFilterToArtistQuery that was preventing proper library filtering for headless operations. This fix ensures that library filtering joins are always applied consistently, allowing headless library access to work correctly with the library_artist junction table filtering.
The previous guard was skipping all library filtering when no user context was present, which could cause issues with headless operations that still need to respect library boundaries through the library_artist relationship.
* fix: simplify genre selection query in genre repository
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: enhance tag library filtering tests for headless access
Signed-off-by: Deluan <deluan@navidrome.org>
* test: add comprehensive test coverage for headless library access
Added extensive test coverage for headless library access improvements including:
- Added 17 new tests across 4 test files covering headless access scenarios
- artist_repository_test.go: Added headless process tests for GetAll, Count,
Get operations and explicit library_id filtering functionality
- genre_repository_test.go: Added library filtering tests for headless processes
including GetAll, Count, ReadAll, and Read operations
- sql_base_repository_test.go: Added applyLibraryFilter method tests covering
admin users, regular users, and headless processes with/without custom table names
- share_repository_test.go: Added headless access tests and SQL ambiguity
verification for the album.id vs id fix in loadMedia function
- Cleaned up test setup by replacing log.NewContext usage with GinkgoT().Context()
and removing unnecessary configtest.SetupConfig() calls for better test isolation
These tests ensure that headless processes (background operations without user context)
can access all libraries while respecting explicit filters, and verify that the SQL
ambiguity fixes work correctly without breaking existing functionality.
* revert: remove user context handling from scrobble buffer getParticipants
Reverts commit 5b8ef74f05109ecf30ddfc936361b84314522869.
The artist repository no longer requires user context for proper library
filtering, so the workaround of temporarily injecting user context into
the scrobbleBufferRepository.Next method is no longer needed.
This simplifies the code and removes the dependency on fetching user
information during background scrobbling operations.
* fix: improve library access filtering for artists
Enhanced artist repository filtering to properly handle library access restrictions
and prevent artists with no accessible content from appearing in results.
Backend changes:
- Modified roleFilter to use direct JSON_EXTRACT instead of EXISTS subquery for better performance
- Enhanced applyLibraryFilterToArtistQuery to filter out artists with empty stats (no content)
- Changed from LEFT JOIN to INNER JOIN with library_artist table for stricter filtering
- Added condition to exclude artists where library_artist.stats = '{}' (empty content)
Frontend changes:
- Added null-checking in getCounter function to prevent TypeError when accessing undefined records
- Improved optional chaining for safer property access in role-based statistics display
These changes ensure that users only see artists that have actual accessible content
in their permitted libraries, fixing issues where artists appeared in the list
despite having no albums or songs available to the user.
* fix: update library access logic for non-admin users and enhance test coverage
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: refine library artist query and implement cleanup for empty entries
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: consolidate artist repository tests to eliminate duplication
Significantly refactored artist_repository_test.go to reduce code duplication and
improve maintainability by ~27% (930 to 680 lines). Key improvements include:
- Added test helper functions createTestArtistWithMBID() and createUserWithLibraries()
to eliminate repetitive test data creation
- Consolidated duplicate MBID search tests using DescribeTable for parameterized testing
- Removed entire 'Permission-Based Behavior Comparison' section (~150 lines) that
duplicated functionality already covered in other test contexts
- Reorganized search tests into cohesive 'MBID and Text Search' section with proper
setup/teardown and shared test infrastructure
- Streamlined missing artist tests and moved them to dedicated section
- Maintained 100% test coverage while eliminating redundant test patterns
All tests continue to pass with identical functionality and coverage.
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* attempt using artist | albumartist
* add primary stats, expose to ND and Subsonic
* response to feedback (1)
* address feedback part 1
* fix docs and artist show
* fix migration order
---------
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
* ui: add Play button to artist toolbar
* refactor
Signed-off-by: Deluan <deluan@navidrome.org>
* test(ui): add tests for Play button functionality in ArtistActions
Signed-off-by: Deluan <deluan@navidrome.org>
* ui: update Play button label to Top Songs in ArtistActions
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* Add Play Similar option
* Add pt-br translation for Play Similar
* Refactor playSimilar and add helper
* Improve Play Similar feedback
* Add artist actions bar with shuffle and radio
* Add Play Similar menu and align artist actions
* Refine artist actions and revert menu option
* fix(ui): enhance layout of ArtistActions and ArtistShow components
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(i18n): revert unused changes
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): improve layout for mobile
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): improve error handling for fetching similar songs
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): enhance error logging for fetching songs in shuffle
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(ui): shuffle handling to use async/await for better readability
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(ui): simplify button label handling in ArtistActions component
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(server): bring back legacy date mappings
Signed-off-by: Deluan <deluan@navidrome.org>
* reuse the mapDates logic in the legacyReleaseDate function
Signed-off-by: Deluan <deluan@navidrome.org>
* fix mappings
Signed-off-by: Deluan <deluan@navidrome.org>
* show original and release dates in album grid
Signed-off-by: Deluan <deluan@navidrome.org>
* fix tests based on new year mapping
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(subsonic): prefer returning original_year over (recording) year
when sorting albums
Signed-off-by: Deluan <deluan@navidrome.org>
* fix case when we don't have originalYear
Signed-off-by: Deluan <deluan@navidrome.org>
* show all dates in album's info, and remove the recording date from the album page
Signed-off-by: Deluan <deluan@navidrome.org>
* better?
Signed-off-by: Deluan <deluan@navidrome.org>
* add snapshot tests for Album Details
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(subsonic): sort order for getAlbumList?type=byYear
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(ui): Improve Artist Album pagination
- use maximum of albumartist/artist credits for determining pagination
- reduce default maxPerPage considerably. This gives values of 36/72/108 at largest size
* enable pagination when over 90
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* Allow ArtistExternalLink icons to be styled
* Allow AlbumExternalLink icons to be styled
* Standardize external links' classes to kebab-case
Co-authored-by: Deluan <deluan@navidrome.org>
* Seperate mobile desktop components
* Fix err
* Rename classes and fix some styles
* Add lastFM button and remove console log
* Add Mbiz Icon
* render bio as dangerouslySetInnerHTML and remove unused css classes
* Add Fav and Stars
* Remove unstandardised class selector
* Remove ext link from m view
* Fix naming and simplify rounded styling
* Refactor ArtistShow:
- Extracted DesktopArtistDetails to its own file
- Removed album count as it was incorrect, it is not considering compilations
- Show bio and image from Native API, if it is available, before calling `getArtistInfo`
Co-authored-by: Deluan <deluan@navidrome.org>