navidrome/persistence/plugin_cleanup.go
2026-01-12 08:16:08 -05:00

87 lines
3.1 KiB
Go

package persistence
import (
"github.com/pocketbase/dbx"
)
// cleanupPluginUserReferences removes a user ID from all plugins' users JSON arrays
// and auto-disables plugins that lose their only permitted user (when users permission is required).
// This is called from userRepository.Delete() to maintain referential integrity.
func cleanupPluginUserReferences(db dbx.Builder, userID string) error {
// SQLite JSON function: json_remove removes the element at the path where user matches.
// We use a subquery with json_each to find and remove the user ID from the array.
// This updates all plugins where the users array contains the given user ID.
_, err := db.NewQuery(`
UPDATE plugin
SET users = (
SELECT json_group_array(value)
FROM json_each(plugin.users)
WHERE value != {:userID}
),
updated_at = CURRENT_TIMESTAMP
WHERE users IS NOT NULL
AND users != ''
AND EXISTS (SELECT 1 FROM json_each(plugin.users) WHERE value = {:userID})
`).Bind(dbx.Params{"userID": userID}).Execute()
if err != nil {
return err
}
// Auto-disable plugins that:
// 1. Are currently enabled
// 2. Require users permission (manifest has permissions.users)
// 3. Don't have allUsers enabled
// 4. Now have an empty users array after cleanup
//
// The manifest check uses JSON path to see if permissions.users exists.
_, err = db.NewQuery(`
UPDATE plugin
SET enabled = false,
updated_at = CURRENT_TIMESTAMP
WHERE enabled = true
AND all_users = false
AND json_extract(manifest, '$.permissions.users') IS NOT NULL
AND (users IS NULL OR users = '' OR users = '[]' OR json_array_length(users) = 0)
`).Execute()
return err
}
// cleanupPluginLibraryReferences removes a library ID from all plugins' libraries JSON arrays
// and auto-disables plugins that lose their only permitted library (when library permission is required).
// This is called from libraryRepository.Delete() to maintain referential integrity.
func cleanupPluginLibraryReferences(db dbx.Builder, libraryID int) error {
// SQLite JSON function: we filter out the library ID from the array.
// Libraries are stored as integers in the JSON array.
_, err := db.NewQuery(`
UPDATE plugin
SET libraries = (
SELECT json_group_array(value)
FROM json_each(plugin.libraries)
WHERE CAST(value AS INTEGER) != {:libraryID}
),
updated_at = CURRENT_TIMESTAMP
WHERE libraries IS NOT NULL
AND libraries != ''
AND EXISTS (SELECT 1 FROM json_each(plugin.libraries) WHERE CAST(value AS INTEGER) = {:libraryID})
`).Bind(dbx.Params{"libraryID": libraryID}).Execute()
if err != nil {
return err
}
// Auto-disable plugins that:
// 1. Are currently enabled
// 2. Require library permission (manifest has permissions.library)
// 3. Don't have allLibraries enabled
// 4. Now have an empty libraries array after cleanup
_, err = db.NewQuery(`
UPDATE plugin
SET enabled = false,
updated_at = CURRENT_TIMESTAMP
WHERE enabled = true
AND all_libraries = false
AND json_extract(manifest, '$.permissions.library') IS NOT NULL
AND (libraries IS NULL OR libraries = '' OR libraries = '[]' OR json_array_length(libraries) = 0)
`).Execute()
return err
}