Merge pull request 'fix(auth): subsonic_password on bootstrap + dev compose defaults' (#10) from dev into main
This commit was merged in pull request #10.
This commit is contained in:
+19
-2
@@ -16,8 +16,10 @@ services:
|
|||||||
POSTGRES_USER: minstrel
|
POSTGRES_USER: minstrel
|
||||||
POSTGRES_PASSWORD: minstrel
|
POSTGRES_PASSWORD: minstrel
|
||||||
POSTGRES_DB: minstrel
|
POSTGRES_DB: minstrel
|
||||||
ports:
|
networks:
|
||||||
- "5432:5432"
|
- minstrel
|
||||||
|
# ports:
|
||||||
|
# - "5432:5432"
|
||||||
volumes:
|
volumes:
|
||||||
- minstrel-pgdata:/var/lib/postgresql/data
|
- minstrel-pgdata:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
@@ -34,8 +36,23 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
SMARTMUSIC_DATABASE_URL: postgres://minstrel:minstrel@postgres:5432/minstrel?sslmode=disable
|
SMARTMUSIC_DATABASE_URL: postgres://minstrel:minstrel@postgres:5432/minstrel?sslmode=disable
|
||||||
SMARTMUSIC_LOG_FORMAT: text
|
SMARTMUSIC_LOG_FORMAT: text
|
||||||
|
SMARTMUSIC_LIBRARY_SCAN_PATHS: /music
|
||||||
|
SMARTMUSIC_LIBRARY_SCAN_ON_STARTUP: "true"
|
||||||
|
SMARTMUSIC_AUTH_ADMIN_USERNAME: admin
|
||||||
|
# SMARTMUSIC_AUTH_ADMIN_PASSWORD left unset on purpose — bootstrap
|
||||||
|
# generates one and prints it to stderr on first boot. Watch the logs
|
||||||
|
# of the minstrel service the first time you bring the stack up.
|
||||||
|
networks:
|
||||||
|
- minstrel
|
||||||
ports:
|
ports:
|
||||||
- "4533:4533"
|
- "4533:4533"
|
||||||
|
volumes:
|
||||||
|
# Point ./music at your test library (symlink, bind-mount, whatever).
|
||||||
|
# Read-only so a buggy scanner can't rewrite your files.
|
||||||
|
- /mnt/Media/Music:/music:ro
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
minstrel-pgdata:
|
minstrel-pgdata:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
minstrel:
|
||||||
@@ -64,12 +64,26 @@ func Bootstrap(ctx context.Context, pool *pgxpool.Pool, cfg config.AdminBootstra
|
|||||||
return fmt.Errorf("auth: insert admin: %w", err)
|
return fmt.Errorf("auth: insert admin: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mirror the bootstrap password into subsonic_password so Subsonic clients
|
||||||
|
// (Feishin, Symfonium, …) can authenticate via t+s without the operator
|
||||||
|
// having to run a separate SQL update after first boot. This is plaintext
|
||||||
|
// at rest — the cost of Subsonic's legacy auth — and matches what servers
|
||||||
|
// like Navidrome do. Operators who don't want a plaintext copy can clear
|
||||||
|
// it later with SetSubsonicPassword(nil).
|
||||||
|
subPass := password
|
||||||
|
if err := q.SetSubsonicPassword(ctx, dbq.SetSubsonicPasswordParams{
|
||||||
|
ID: user.ID,
|
||||||
|
SubsonicPassword: &subPass,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("auth: set subsonic password: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
logger.Info("admin bootstrapped", "username", cfg.Username, "user_id", user.ID.String())
|
logger.Info("admin bootstrapped", "username", cfg.Username, "user_id", user.ID.String())
|
||||||
if passwordGenerated {
|
if passwordGenerated {
|
||||||
fmt.Fprintf(os.Stderr, "\n--- minstrel admin bootstrap (shown once) ---\nusername: %s\npassword: %s\napi_token: %s\n---\n\n",
|
fmt.Fprintf(os.Stderr, "\n--- minstrel admin bootstrap (shown once) ---\nusername: %s\npassword: %s\napi_token: %s\n(password works for both the native UI and Subsonic clients)\n---\n\n",
|
||||||
cfg.Username, password, apiToken)
|
cfg.Username, password, apiToken)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(os.Stderr, "\n--- minstrel admin api token (shown once) ---\nusername: %s\napi_token: %s\n---\n\n",
|
fmt.Fprintf(os.Stderr, "\n--- minstrel admin api token (shown once) ---\nusername: %s\napi_token: %s\n(your configured password now also works for Subsonic clients)\n---\n\n",
|
||||||
cfg.Username, apiToken)
|
cfg.Username, apiToken)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ func TestBootstrap_Integration(t *testing.T) {
|
|||||||
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte("hunter2")); err != nil {
|
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte("hunter2")); err != nil {
|
||||||
t.Errorf("bcrypt compare: %v", err)
|
t.Errorf("bcrypt compare: %v", err)
|
||||||
}
|
}
|
||||||
|
if user.SubsonicPassword == nil || *user.SubsonicPassword != "hunter2" {
|
||||||
|
t.Errorf("subsonic_password = %v, want \"hunter2\"", user.SubsonicPassword)
|
||||||
|
}
|
||||||
|
|
||||||
byToken, err := q.GetUserByAPIToken(ctx, user.ApiToken)
|
byToken, err := q.GetUserByAPIToken(ctx, user.ApiToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user