Password: fail loudly when settings cannot be saved (#30767)

This commit is contained in:
andig 2026-06-12 23:51:03 +02:00 • committed by GitHub
parent cb09fccd34
commit c92fb3a4f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 34 additions and 3 deletions

View file

@ -1,6 +1,10 @@
package cmd
import (
"fmt"
"github.com/evcc-io/evcc/server/db"
"github.com/evcc-io/evcc/server/db/settings"
"github.com/spf13/cobra"
)
@ -12,3 +16,19 @@ var passwordCmd = &cobra.Command{
func init() {
rootCmd.AddCommand(passwordCmd)
}
// fatalDatabase logs a database error and exits, hinting at file permissions
// when the database is not writable by the current user.
func fatalDatabase(err error) {
if db.IsReadonly(err) {
log.FATAL.Println("database is not writable; run this command as the user owning the database file, e.g. sudo -u evcc")
}
log.FATAL.Fatal(err)
}
// persistPasswordSettings writes pending settings to the database
func persistPasswordSettings() {
if err := settings.Persist(); err != nil {
fatalDatabase(fmt.Errorf("cannot save settings: %w", err))
}
}

View file

@ -26,7 +26,7 @@ func runPasswordReset(cmd *cobra.Command, args []string) {
// setup persistence
if err := configureDatabase(conf.Database); err != nil {
log.FATAL.Fatal(err)
fatalDatabase(err)
}
confirm, _ := cmd.Flags().GetBool(flagForce)
@ -44,5 +44,6 @@ func runPasswordReset(cmd *cobra.Command, args []string) {
if confirm {
auth.New().RemoveAdminPassword()
persistPasswordSettings()
}
}

View file

@ -25,7 +25,7 @@ func runPasswordSet(cmd *cobra.Command, args []string) {
// setup persistence
if err := configureDatabase(conf.Database); err != nil {
log.FATAL.Fatal(err)
fatalDatabase(err)
}
prompt := &survey.Password{
@ -40,7 +40,9 @@ func runPasswordSet(cmd *cobra.Command, args []string) {
if password == "" {
log.FATAL.Fatal("password cannot be empty")
} else if err := auth.New().SetAdminPassword(password); err != nil {
log.FATAL.Fatal(err)
} else {
auth.New().SetAdminPassword(password)
persistPasswordSettings()
}
}

View file

@ -13,6 +13,7 @@ import (
"github.com/mitchellh/go-homedir"
"gorm.io/gorm"
sqlite3 "modernc.org/sqlite"
sqlite3lib "modernc.org/sqlite/lib"
)
var (
@ -112,6 +113,13 @@ func Close() error {
return db.Close()
}
// IsReadonly reports whether err indicates a database file that is not
// writable by the current user. The code mask covers extended result codes.
func IsReadonly(err error) bool {
var serr *sqlite3.Error
return errors.As(err, &serr) && serr.Code()&0xff == sqlite3lib.SQLITE_READONLY
}
type backuper interface {
NewBackup(string) (*sqlite3.Backup, error)
NewRestore(string) (*sqlite3.Backup, error)