Add login rename and password reset flow
This commit is contained in:
parent
b625c95c29
commit
e7611b2d49
4 changed files with 362 additions and 28 deletions
|
|
@ -4,6 +4,7 @@ import (
|
|||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
|
|
@ -133,6 +134,13 @@ func ConnectDB() error {
|
|||
expires_at TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS app_password_resets(
|
||||
token_hash TEXT PRIMARY KEY,
|
||||
user_id INTEGER NOT NULL REFERENCES app_users(id) ON DELETE CASCADE,
|
||||
expires_at TEXT NOT NULL,
|
||||
used_at TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)`,
|
||||
}
|
||||
for _, stmt := range schema {
|
||||
if _, err := db.Exec(stmt); err != nil {
|
||||
|
|
@ -232,6 +240,44 @@ func SaveAppUser(username, displayName, passwordHash, role string, active bool)
|
|||
return err
|
||||
}
|
||||
|
||||
func UpdateAppUser(oldUsername, username, displayName, passwordHash, role string, active bool) error {
|
||||
oldUsername = strings.TrimSpace(oldUsername)
|
||||
username = strings.TrimSpace(username)
|
||||
displayName = strings.TrimSpace(displayName)
|
||||
role = normalizeRole(role)
|
||||
if oldUsername == "" || oldUsername == username {
|
||||
return SaveAppUser(username, displayName, passwordHash, role, active)
|
||||
}
|
||||
tx, err := DB.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
var existing int
|
||||
err = tx.QueryRow(`SELECT 1 FROM app_users WHERE username=?`, username).Scan(&existing)
|
||||
if err == nil {
|
||||
return fmt.Errorf("Login/E-Mail existiert bereits.")
|
||||
}
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
return err
|
||||
}
|
||||
if passwordHash == "" {
|
||||
_, err = tx.Exec(`UPDATE app_users SET username=?, display_name=?, role=?, active=?, updated_at=CURRENT_TIMESTAMP WHERE username=?`,
|
||||
username, displayName, role, boolInt(active), oldUsername)
|
||||
} else {
|
||||
_, err = tx.Exec(`UPDATE app_users SET username=?, display_name=?, password_hash=?, role=?, active=?, updated_at=CURRENT_TIMESTAMP WHERE username=?`,
|
||||
username, displayName, passwordHash, role, boolInt(active), oldUsername)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tx.Exec(`DELETE FROM app_sessions WHERE user_id IN (SELECT id FROM app_users WHERE username=?)`, username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func DeleteAppUser(username string) error {
|
||||
_, err := DB.Exec(`DELETE FROM app_users WHERE username=?`, username)
|
||||
return err
|
||||
|
|
@ -259,6 +305,46 @@ func CleanupSessions() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func CreatePasswordReset(tokenHash string, userID int64, expiresAt string) error {
|
||||
_, err := DB.Exec(`INSERT INTO app_password_resets(token_hash, user_id, expires_at) VALUES(?,?,?)`, tokenHash, userID, expiresAt)
|
||||
return err
|
||||
}
|
||||
|
||||
func PasswordResetUser(tokenHash string) (AppUser, error) {
|
||||
row := DB.QueryRow(`SELECT u.id, u.username, u.display_name, u.password_hash, u.role, u.active
|
||||
FROM app_password_resets r JOIN app_users u ON u.id=r.user_id
|
||||
WHERE r.token_hash=? AND r.used_at IS NULL AND r.expires_at > CURRENT_TIMESTAMP AND u.active=1`, tokenHash)
|
||||
return scanAppUser(row)
|
||||
}
|
||||
|
||||
func UsePasswordReset(tokenHash, passwordHash string) error {
|
||||
tx, err := DB.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
var userID int64
|
||||
err = tx.QueryRow(`SELECT user_id FROM app_password_resets WHERE token_hash=? AND used_at IS NULL AND expires_at > CURRENT_TIMESTAMP`, tokenHash).Scan(&userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tx.Exec(`UPDATE app_users SET password_hash=?, updated_at=CURRENT_TIMESTAMP WHERE id=?`, passwordHash, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tx.Exec(`UPDATE app_password_resets SET used_at=CURRENT_TIMESTAMP WHERE token_hash=?`, tokenHash); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tx.Exec(`DELETE FROM app_sessions WHERE user_id=?`, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func CleanupPasswordResets() error {
|
||||
_, err := DB.Exec(`DELETE FROM app_password_resets WHERE used_at IS NOT NULL OR expires_at <= CURRENT_TIMESTAMP`)
|
||||
return err
|
||||
}
|
||||
|
||||
func ListAccounts() ([]Account, error) {
|
||||
rows, err := DB.Query(`SELECT id,name,src_host,src_port,src_security,src_insecure,src_user,src_pass,src_proto,
|
||||
dst_host,dst_port,dst_security,dst_insecure,dst_user,dst_pass,mbox_dir,active
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue