From 8c054905c37983b38a8f22613f8505d3d69e57b4 Mon Sep 17 00:00:00 2001 From: lowcarbdev Date: Sat, 17 Jan 2026 21:14:15 -0700 Subject: [PATCH] list users --- README.md | 26 ++++++++++++++++++++++++++ internal/auth.go | 26 ++++++++++++++++++++++++++ main.go | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/README.md b/README.md index bd50a1d..49af03c 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,32 @@ MIT ## FAQ +Q: How do I list all users? + +Docker: +```bash +docker exec -it /app/sbv -list-users +``` + +Binary: +```bash +./sbv -list-users +``` + +Q: How do I reset a user's password? + +Docker: +```bash +docker exec -it /app/sbv -reset-password +``` + +Binary: +```bash +./sbv -reset-password +``` + +You will be prompted to enter and confirm the new password. + Q: What backups does this program support? XML backups from the [SMS Backup & Restore app](https://play.google.com/store/apps/details?id=com.riteshsahu.SMSBackupRestore&hl=en_US). Android devices are supported. iPhone (iOS) devices are not supported by SMS Backup & Restore. diff --git a/internal/auth.go b/internal/auth.go index da6f47f..58c090f 100644 --- a/internal/auth.go +++ b/internal/auth.go @@ -223,3 +223,29 @@ func UpdatePassword(userID string, newPassword string) error { return nil } + +// ListUsers returns all users in the database +func ListUsers() ([]User, error) { + rows, err := authDB.Query("SELECT id, username, password_hash, created_at FROM users ORDER BY username") + if err != nil { + return nil, fmt.Errorf("failed to query users: %w", err) + } + defer rows.Close() + + var users []User + for rows.Next() { + var user User + var createdAt int64 + if err := rows.Scan(&user.ID, &user.Username, &user.PasswordHash, &createdAt); err != nil { + return nil, fmt.Errorf("failed to scan user: %w", err) + } + user.CreatedAt = time.Unix(createdAt, 0) + users = append(users, user) + } + + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("error iterating users: %w", err) + } + + return users, nil +} diff --git a/main.go b/main.go index 8c7dd28..738c782 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,8 @@ import ( "net/http" _ "net/http/pprof" "os" + "path/filepath" + "text/tabwriter" "time" "github.com/labstack/echo/v4" @@ -20,6 +22,7 @@ var logger *slog.Logger func main() { // Parse CLI flags resetPassword := flag.String("reset-password", "", "Reset password for the specified username") + listUsers := flag.Bool("list-users", false, "List all users") flag.Parse() // Initialize slog logger @@ -51,6 +54,15 @@ func main() { os.Exit(0) } + // Handle list users if requested + if *listUsers { + if err := handleListUsers(dbPathPrefix); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } + os.Exit(0) + } + // Create Echo instance e := echo.New() @@ -209,3 +221,28 @@ func handleResetPassword(username string) error { fmt.Printf("Password reset successfully for user '%s'\n", username) return nil } + +// handleListUsers lists all users with their usernames, UUIDs, and ingest directories +func handleListUsers(dbPathPrefix string) error { + users, err := internal.ListUsers() + if err != nil { + return fmt.Errorf("failed to list users: %w", err) + } + + if len(users) == 0 { + fmt.Println("No users found.") + return nil + } + + w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + fmt.Fprintln(w, "USERNAME\tUUID\tINGEST DIRECTORY") + fmt.Fprintln(w, "--------\t----\t----------------") + + for _, user := range users { + ingestDir := filepath.Join(dbPathPrefix, "data", user.ID, "ingest") + fmt.Fprintf(w, "%s\t%s\t%s\n", user.Username, user.ID, ingestDir) + } + + w.Flush() + return nil +}