fix: stabilize software updates

This commit is contained in:
admin committed 2026-08-29 18:38:38 +02:00
1 parent fc59092030
commit 26a960c6bd
25 files changed
+487 -146

No files matched your search

+39 -18
View File
@@ -30,6 +30,7 @@ type State struct {
LastCheckedAt time.Time
LastError string
CredentialConfigured bool
CredentialUsername string
UpdateAvailable bool
AgentAvailable bool
AgentCompatible bool
@@ -136,15 +137,15 @@ func (m *Manager) State() State {
return m.state
}
func (m *Manager) SaveCredential(ctx context.Context, username, token string) error {
username, token = strings.TrimSpace(username), strings.TrimSpace(token)
func (m *Manager) SaveCredential(ctx context.Context, username, credential string) error {
username = strings.TrimSpace(username)
if username == "" || len(username) > 128 {
return errors.New("Gitea-Benutzername fehlt oder ist zu lang")
}
if len(token) < 8 || len(token) > 1024 {
return errors.New("Gitea-Token fehlt oder hat eine ungültige Länge")
if len(credential) < 8 || len(credential) > 1024 {
return errors.New("Gitea-Passwort oder -Token fehlt oder hat eine ungültige Länge")
}
ciphertext, nonce, err := m.cipher.Encrypt(token)
ciphertext, nonce, err := m.cipher.Encrypt(credential)
if err != nil {
return fmt.Errorf("Update-Zugang verschlüsseln: %w", err)
}
@@ -169,11 +170,11 @@ func (m *Manager) CheckNow(ctx context.Context) error {
m.setStoredState(settings)
return ErrCredentialMissing
}
token, err := m.cipher.Decrypt(settings.TokenCiphertext, settings.TokenNonce)
credential, err := m.cipher.Decrypt(settings.TokenCiphertext, settings.TokenNonce)
if err != nil {
return m.recordFailure(ctx, errors.New("gespeicherter Update-Zugang konnte nicht entschlüsselt werden"))
}
release, err := m.fetchLatest(ctx, token)
release, err := m.fetchLatest(ctx, settings.RegistryUsername, credential)
if err != nil {
return m.recordFailure(ctx, err)
}
@@ -207,14 +208,14 @@ func (m *Manager) RequestUpdate(ctx context.Context, version string) error {
if err != nil {
return err
}
token, err := m.cipher.Decrypt(settings.TokenCiphertext, settings.TokenNonce)
credential, err := m.cipher.Decrypt(settings.TokenCiphertext, settings.TokenNonce)
if err != nil || settings.RegistryUsername == "" {
return ErrCredentialMissing
}
if err := m.store.SetDesiredSoftwareVersion(ctx, version); err != nil {
return err
}
request := updateprotocol.Request{Version: version, CurrentVersion: state.CurrentVersion, RegistryUsername: settings.RegistryUsername, RegistryToken: token}
request := updateprotocol.Request{Version: version, CurrentVersion: state.CurrentVersion, RegistryUsername: settings.RegistryUsername, RegistryToken: credential}
if err := m.agent.Start(ctx, request); err != nil {
cleanupCtx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
m.clearDesiredVersion(cleanupCtx, version)
@@ -254,17 +255,17 @@ func (m *Manager) UpdateStatus(ctx context.Context) (updateprotocol.Status, erro
return status, err
}
func (m *Manager) fetchLatest(ctx context.Context, token string) (releaseResponse, error) {
request, err := http.NewRequestWithContext(ctx, http.MethodGet, m.apiURL, nil)
func (m *Manager) fetchLatest(ctx context.Context, username, credential string) (releaseResponse, error) {
response, err := m.fetchLatestWithAuth(ctx, username, credential, true)
if err != nil {
return releaseResponse{}, errors.New("Update-Endpunkt ist ungültig")
return releaseResponse{}, err
}
request.Header.Set("Accept", "application/json")
request.Header.Set("Authorization", "token "+token)
request.Header.Set("User-Agent", "domain-control-update-checker/"+buildinfo.Version)
response, err := m.httpClient.Do(request)
if err != nil {
return releaseResponse{}, errors.New("Git-Server ist momentan nicht erreichbar")
if response.StatusCode == http.StatusUnauthorized || response.StatusCode == http.StatusForbidden {
response.Body.Close()
response, err = m.fetchLatestWithAuth(ctx, username, credential, false)
if err != nil {
return releaseResponse{}, err
}
}
defer response.Body.Close()
if response.StatusCode == http.StatusUnauthorized || response.StatusCode == http.StatusForbidden {
@@ -284,6 +285,25 @@ func (m *Manager) fetchLatest(ctx context.Context, token string) (releaseRespons
return release, nil
}
func (m *Manager) fetchLatestWithAuth(ctx context.Context, username, credential string, basic bool) (*http.Response, error) {
request, err := http.NewRequestWithContext(ctx, http.MethodGet, m.apiURL, nil)
if err != nil {
return nil, errors.New("Update-Endpunkt ist ungültig")
}
request.Header.Set("Accept", "application/json")
if basic {
request.SetBasicAuth(username, credential)
} else {
request.Header.Set("Authorization", "token "+credential)
}
request.Header.Set("User-Agent", "domain-control-update-checker/"+buildinfo.Version)
response, err := m.httpClient.Do(request)
if err != nil {
return nil, errors.New("Git-Server ist momentan nicht erreichbar")
}
return response, nil
}
func (m *Manager) safeReleaseURL(raw string) string {
apiURL, apiErr := url.Parse(m.apiURL)
releaseURL, releaseErr := url.Parse(raw)
@@ -313,6 +333,7 @@ func (m *Manager) setStoredState(settings model.SoftwareUpdateSettings) {
LastCheckedAt: settings.LastCheckedAt,
LastError: settings.LastError,
CredentialConfigured: settings.RegistryUsername != "" && len(settings.TokenCiphertext) > 0 && len(settings.TokenNonce) > 0,
CredentialUsername: settings.RegistryUsername,
}
if comparison, err := compareVersions(state.CurrentVersion, state.LatestVersion); err == nil {
state.UpdateAvailable = comparison < 0