diff --git a/pkg/env/legacy_auth_test.go b/pkg/env/legacy_auth_test.go index 725f646..2f965b5 100644 --- a/pkg/env/legacy_auth_test.go +++ b/pkg/env/legacy_auth_test.go @@ -73,8 +73,8 @@ func TestLegacyAuthFieldsSurviveLoadAndSave(t *testing.T) { } configPath := filepath.Join(tempDir, consts.BossConfigFile) - if err := os.WriteFile(configPath, data, 0600); err != nil { - t.Fatalf("Failed to write config file: %v", err) + if writeErr := os.WriteFile(configPath, data, 0600); writeErr != nil { + t.Fatalf("Failed to write config file: %v", writeErr) } config, err := env.LoadConfiguration(tempDir) diff --git a/setup/migrations.go b/setup/migrations.go index 2137821..68748e1 100644 --- a/setup/migrations.go +++ b/setup/migrations.go @@ -61,43 +61,57 @@ func seven() { migrated := false for repo, auth := range configuration.Auth { - if auth == nil { - continue + if migrateLegacyAuth(repo, auth) { + migrated = true } + } - if auth.LegacyUser != "" { - if decrypted, err := oldDecrypt(auth.LegacyUser); err != nil { - msg.Warn("⚠️ Migration 7: could not migrate the user for %s: %v", repo, err) - } else { - auth.SetUser(decrypted) - } - } + if migrated { + configuration.SaveConfiguration() + } +} - if auth.LegacyPass != "" { - if decrypted, err := oldDecrypt(auth.LegacyPass); err != nil { - msg.Warn("⚠️ Migration 7: could not migrate the password for %s: %v", repo, err) - } else { - auth.SetPass(decrypted) - } - } +// migrateLegacyAuth converts one entry's legacy credentials and clears them, +// reporting whether anything was converted. +func migrateLegacyAuth(repo string, auth *env.Auth) bool { + if auth == nil { + return false + } + if auth.LegacyUser == "" && auth.LegacyPass == "" && auth.LegacyPassPhrase == "" { + return false + } - if auth.LegacyPassPhrase != "" { - if decrypted, err := oldDecrypt(auth.LegacyPassPhrase); err != nil { - msg.Warn("⚠️ Migration 7: could not migrate the passphrase for %s: %v", repo, err) - } else if decrypted != "" { - auth.SetPassPhrase(decrypted) - } - } + if decrypted, ok := decryptLegacy(repo, "user", auth.LegacyUser); ok { + auth.SetUser(decrypted) + } + if decrypted, ok := decryptLegacy(repo, "password", auth.LegacyPass); ok { + auth.SetPass(decrypted) + } + // An empty passphrase means the key has none, and storing it back would only + // re-create the value migration 7 exists to retire. + if decrypted, ok := decryptLegacy(repo, "passphrase", auth.LegacyPassPhrase); ok && decrypted != "" { + auth.SetPassPhrase(decrypted) + } - if auth.LegacyUser != "" || auth.LegacyPass != "" || auth.LegacyPassPhrase != "" { - auth.LegacyUser, auth.LegacyPass, auth.LegacyPassPhrase = "", "", "" - migrated = true - } + auth.LegacyUser, auth.LegacyPass, auth.LegacyPassPhrase = "", "", "" + + return true +} + +// decryptLegacy decrypts one legacy value, warning instead of aborting when it +// cannot be read. It reports false when there was nothing to convert. +func decryptLegacy(repo, field, value string) (string, bool) { + if value == "" { + return "", false } - if migrated { - configuration.SaveConfiguration() + decrypted, err := oldDecrypt(value) + if err != nil { + msg.Warn("⚠️ Migration 7: could not migrate the %s for %s: %v", field, repo, err) + return "", false } + + return decrypted, true } // cleanup cleans up the internal global directory.