reset user password

This commit is contained in:
lowcarbdev
2026-01-17 20:52:03 -07:00
parent d674f03d66
commit d9cedb876b
4 changed files with 77 additions and 3 deletions
+2 -1
View File
@@ -9,6 +9,7 @@ require (
github.com/labstack/echo/v4 v4.13.4
github.com/strukturag/libheif-go v0.0.0-20250130134905-55b3482bea15
golang.org/x/crypto v0.44.0
golang.org/x/term v0.39.0
)
require (
@@ -18,7 +19,7 @@ require (
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/text v0.31.0 // indirect
golang.org/x/time v0.14.0 // indirect
)
+4 -2
View File
@@ -27,8 +27,10 @@ golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvm
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+13
View File
@@ -112,6 +112,19 @@ func VerifyPassword(user *User, password string) bool {
return err == nil
}
// GetUsernameByID retrieves username by user ID
func GetUsernameByID(userID string) (string, error) {
var username string
err := authDB.QueryRow("SELECT username FROM users WHERE id = ?", userID).Scan(&username)
if err != nil {
if err == sql.ErrNoRows {
return "", fmt.Errorf("user not found")
}
return "", err
}
return username, nil
}
// GenerateSessionID generates a random session ID
func GenerateSessionID() (string, error) {
bytes := make([]byte, 32)
+58
View File
@@ -1,6 +1,8 @@
package main
import (
"flag"
"fmt"
"log/slog"
"net/http"
_ "net/http/pprof"
@@ -10,11 +12,16 @@ import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/lowcarbdev/sbv/internal"
"golang.org/x/term"
)
var logger *slog.Logger
func main() {
// Parse CLI flags
resetPassword := flag.String("reset-password", "", "Reset password for the specified username")
flag.Parse()
// Initialize slog logger
logger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
@@ -35,6 +42,15 @@ func main() {
}
logger.Info("Authentication database initialized", "path", authDBPath)
// Handle password reset if requested
if *resetPassword != "" {
if err := handleResetPassword(*resetPassword); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
os.Exit(0)
}
// Create Echo instance
e := echo.New()
@@ -145,3 +161,45 @@ func main() {
os.Exit(1)
}
}
// handleResetPassword prompts for a new password and resets it for the given username
func handleResetPassword(username string) error {
// Look up the user
user, err := internal.GetUserByUsername(username)
if err != nil {
return fmt.Errorf("user '%s' not found", username)
}
// Prompt for new password
fmt.Print("Enter new password: ")
passwordBytes, err := term.ReadPassword(int(os.Stdin.Fd()))
fmt.Println()
if err != nil {
return fmt.Errorf("failed to read password: %w", err)
}
// Prompt for password confirmation
fmt.Print("Confirm new password: ")
confirmBytes, err := term.ReadPassword(int(os.Stdin.Fd()))
fmt.Println()
if err != nil {
return fmt.Errorf("failed to read password confirmation: %w", err)
}
password := string(passwordBytes)
if password != string(confirmBytes) {
return fmt.Errorf("passwords do not match")
}
if len(password) < 6 {
return fmt.Errorf("password must be at least 6 characters")
}
// Update the password
if err := internal.UpdatePassword(user.ID, password); err != nil {
return fmt.Errorf("failed to update password: %w", err)
}
fmt.Printf("Password reset successfully for user '%s'\n", username)
return nil
}