chore(tfstated): refactor setting last login date time on successful HTTP basic auth

This commit is contained in:
Julien Dessaux 2024-12-28 23:16:09 +01:00
parent 6d00e12097
commit 1dbb1b9ee7
Signed by: adyxax
GPG key ID: F92E51B86E07177E
2 changed files with 39 additions and 32 deletions

View file

@ -4,7 +4,6 @@ import (
"context" "context"
"fmt" "fmt"
"net/http" "net/http"
"time"
"git.adyxax.org/adyxax/tfstated/pkg/database" "git.adyxax.org/adyxax/tfstated/pkg/database"
"git.adyxax.org/adyxax/tfstated/pkg/helpers" "git.adyxax.org/adyxax/tfstated/pkg/helpers"
@ -29,9 +28,7 @@ func Middleware(db *database.DB) func(http.Handler) http.Handler {
helpers.ErrorResponse(w, http.StatusForbidden, fmt.Errorf("Forbidden")) helpers.ErrorResponse(w, http.StatusForbidden, fmt.Errorf("Forbidden"))
return return
} }
now := time.Now().UTC() if err := db.TouchAccount(account); err != nil {
_, err = db.Exec(`UPDATE accounts SET last_login = ? WHERE id = ?`, now.Unix(), account.Id)
if err != nil {
helpers.ErrorResponse(w, http.StatusInternalServerError, err) helpers.ErrorResponse(w, http.StatusInternalServerError, err)
return return
} }

View file

@ -17,6 +17,36 @@ var AdvertiseAdminPassword = func(password string) {
slog.Info("Generated an initial admin password, please change it or delete the admin account after your first login", "password", password) slog.Info("Generated an initial admin password, please change it or delete the admin account after your first login", "password", password)
} }
func (db *DB) InitAdminAccount() error {
return db.WithTransaction(func(tx *sql.Tx) error {
var hasAdminAccount bool
if err := tx.QueryRowContext(db.ctx, `SELECT EXISTS (SELECT 1 FROM accounts WHERE is_admin);`).Scan(&hasAdminAccount); err != nil {
return fmt.Errorf("failed to select if there is an admin account in the database: %w", err)
}
if !hasAdminAccount {
var password uuid.UUID
if err := password.Generate(uuid.V4); err != nil {
return fmt.Errorf("failed to generate initial admin password: %w", err)
}
salt := helpers.GenerateSalt()
hash := helpers.HashPassword(password.String(), salt)
if _, err := tx.ExecContext(db.ctx,
`INSERT INTO accounts(username, salt, password_hash, is_admin)
VALUES ("admin", :salt, :hash, TRUE)
ON CONFLICT DO UPDATE SET password_hash = :hash
WHERE username = "admin";`,
sql.Named("salt", salt),
sql.Named("hash", hash),
); err == nil {
AdvertiseAdminPassword(password.String())
} else {
return fmt.Errorf("failed to set initial admin password: %w", err)
}
}
return nil
})
}
func (db *DB) LoadAccountByUsername(username string) (*model.Account, error) { func (db *DB) LoadAccountByUsername(username string) (*model.Account, error) {
account := model.Account{ account := model.Account{
Username: username, Username: username,
@ -49,32 +79,12 @@ func (db *DB) LoadAccountByUsername(username string) (*model.Account, error) {
return &account, nil return &account, nil
} }
func (db *DB) InitAdminAccount() error { func (db *DB) TouchAccount(account *model.Account) error {
return db.WithTransaction(func(tx *sql.Tx) error { now := time.Now().UTC()
var hasAdminAccount bool _, err := db.Exec(`UPDATE accounts SET last_login = ? WHERE id = ?`, now.Unix(), account.Id)
if err := tx.QueryRowContext(db.ctx, `SELECT EXISTS (SELECT 1 FROM accounts WHERE is_admin);`).Scan(&hasAdminAccount); err != nil { if err != nil {
return fmt.Errorf("failed to select if there is an admin account in the database: %w", err) return fmt.Errorf("failed to update last_login for user %s: %w", account.Username, err)
} }
if !hasAdminAccount { account.LastLogin = now
var password uuid.UUID return nil
if err := password.Generate(uuid.V4); err != nil {
return fmt.Errorf("failed to generate initial admin password: %w", err)
}
salt := helpers.GenerateSalt()
hash := helpers.HashPassword(password.String(), salt)
if _, err := tx.ExecContext(db.ctx,
`INSERT INTO accounts(username, salt, password_hash, is_admin)
VALUES ("admin", :salt, :hash, TRUE)
ON CONFLICT DO UPDATE SET password_hash = :hash
WHERE username = "admin";`,
sql.Named("salt", salt),
sql.Named("hash", hash),
); err == nil {
AdvertiseAdminPassword(password.String())
} else {
return fmt.Errorf("failed to set initial admin password: %w", err)
}
}
return nil
})
} }