feat: complete API token export/import with version handling

Complete the API token export/import feature with proper version
handling and backward compatibility:

- Bump export format to version 4.1 to indicate API token support
- Import API tokens when loading v4.1 exports
- Handle version compatibility gracefully:
  - v4.1: Full support including API tokens
  - v4.0: Notice that tokens weren't included (backward compatible)
  - Other: Warning but best-effort import
- Initialize empty array instead of nil for cleaner JSON

This ensures API tokens are properly preserved when migrating or
restoring Pulse instances while maintaining backward compatibility
with older exports.
This commit is contained in:
rcourtman
2025-10-21 11:38:23 +00:00
parent 5c0d760d54
commit af48b510dc

View File

@@ -84,8 +84,8 @@ func (c *ConfigPersistence) ExportConfig(passphrase string) (string, error) {
if err != nil {
return "", fmt.Errorf("failed to load api tokens: %w", err)
}
if len(apiTokens) == 0 {
apiTokens = nil
if apiTokens == nil {
apiTokens = []APITokenRecord{}
}
// Load guest metadata (stored in data directory)
@@ -99,7 +99,7 @@ func (c *ConfigPersistence) ExportConfig(passphrase string) (string, error) {
// Create export data
exportData := ExportData{
Version: "4.0",
Version: "4.1",
ExportedAt: time.Now(),
Nodes: *nodes,
Alerts: *alertConfig,
@@ -153,9 +153,13 @@ func (c *ConfigPersistence) ImportConfig(encryptedData string, passphrase string
}
// Check version compatibility (warn but don't fail)
if exportData.Version != "4.0" {
// Log warning but continue - future versions might be compatible
fmt.Printf("Warning: Config was exported from version %s, current version is 4.0\n", exportData.Version)
switch exportData.Version {
case "4.1", "":
// current version, nothing to do
case "4.0":
fmt.Printf("Notice: Config was exported from version 4.0. API tokens were not included in that format.\n")
default:
fmt.Printf("Warning: Config was exported from unsupported version %s. Proceeding with best effort.\n", exportData.Version)
}
// Import all configurations
if err := c.SaveNodesConfig(exportData.Nodes.PVEInstances, exportData.Nodes.PBSInstances, exportData.Nodes.PMGInstances); err != nil {
@@ -182,6 +186,16 @@ func (c *ConfigPersistence) ImportConfig(encryptedData string, passphrase string
return fmt.Errorf("failed to import system settings: %w", err)
}
// Import API tokens for newer export formats
if exportData.Version == "4.1" {
if exportData.APITokens == nil {
exportData.APITokens = []APITokenRecord{}
}
if err := c.SaveAPITokens(exportData.APITokens); err != nil {
return fmt.Errorf("failed to import api tokens: %w", err)
}
}
// Import OIDC configuration
if exportData.OIDC != nil {
if err := c.SaveOIDCConfig(*exportData.OIDC); err != nil {