Restore --reset-admin-password flag for CLI admin password reset
This commit is contained in:
parent
1ac8c2de5a
commit
88c870ab3c
2 changed files with 53 additions and 6 deletions
|
|
@ -3,15 +3,17 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag" // standard library for parsing command-line flags
|
||||
"fmt" // formatted I/O, used here for printing output
|
||||
"log" // logging package
|
||||
"net/http" // HTTP server and client
|
||||
"os" // OS-level operations like reading command-line args
|
||||
"strings" // string manipulation utilities
|
||||
"crypto/rand" // cryptographically secure random number generator
|
||||
"flag" // standard library for parsing command-line flags
|
||||
"fmt" // formatted I/O, used here for printing output
|
||||
"log" // logging package
|
||||
"net/http" // HTTP server and client
|
||||
"os" // OS-level operations like reading command-line args
|
||||
"strings" // string manipulation utilities
|
||||
|
||||
"github.com/gin-gonic/gin" // web framework
|
||||
"github.com/imc-vibe/backend/internal/api" // HTTP API routing and handlers
|
||||
"github.com/imc-vibe/backend/internal/auth" // password hashing
|
||||
"github.com/imc-vibe/backend/internal/config" // configuration loading
|
||||
"github.com/imc-vibe/backend/internal/db" // database connection and operations
|
||||
)
|
||||
|
|
@ -33,6 +35,10 @@ func main() {
|
|||
// Common ports: 80 (HTTP), 443 (HTTPS), 8080 (HTTP alternate).
|
||||
port := flag.String("port", "", "Port to listen on (default: 8080)")
|
||||
|
||||
// --reset-admin-password: Generate a random password for the admin user and exit.
|
||||
// Useful for initial setup or recovering from a lost password.
|
||||
resetAdminPassword := flag.Bool("reset-admin-password", false, "Reset admin password to a random value and exit")
|
||||
|
||||
// Customize the help output to show double-hyphen style (Unix convention).
|
||||
// By default, Go's flag package uses single hyphens.
|
||||
flag.Usage = func() {
|
||||
|
|
@ -75,6 +81,23 @@ func main() {
|
|||
log.Printf("Warning: Could not initialize schema: %v", err) // Non-fatal = continue
|
||||
}
|
||||
|
||||
// Handle --reset-admin-password flag.
|
||||
// When this flag is set, we generate a random password, update the database, and exit.
|
||||
if *resetAdminPassword {
|
||||
password := generateRandomPassword(16)
|
||||
hash, err := auth.HashPassword(password)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to hash password: %v", err)
|
||||
}
|
||||
if err := database.UpsertAdminUser("admin", hash); err != nil {
|
||||
log.Fatalf("Failed to reset admin password: %v", err)
|
||||
}
|
||||
fmt.Printf("Admin password reset successfully.\n")
|
||||
fmt.Printf("Username: admin\n")
|
||||
fmt.Printf("Password: %s\n", password)
|
||||
return
|
||||
}
|
||||
|
||||
// Start the web server.
|
||||
// From here on, we set up the HTTP router and handlers.
|
||||
|
||||
|
|
@ -162,6 +185,19 @@ func serveGinStaticFile(c *gin.Context, fs http.FileSystem, path string) {
|
|||
http.ServeContent(c.Writer, c.Request, fi.Name(), fi.ModTime(), file)
|
||||
}
|
||||
|
||||
// generateRandomPassword creates a cryptographically secure random password.
|
||||
func generateRandomPassword(length int) string {
|
||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"
|
||||
result := make([]byte, length)
|
||||
if _, err := rand.Read(result); err != nil {
|
||||
log.Fatalf("Failed to generate random password: %v", err)
|
||||
}
|
||||
for i := range result {
|
||||
result[i] = charset[int(result[i])%len(charset)]
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
|
||||
// mimeType returns the MIME type for a file based on its extension.
|
||||
// MIME types tell the browser what kind of file it is.
|
||||
// This is important for browsers to correctly interpret files.
|
||||
|
|
|
|||
|
|
@ -68,6 +68,17 @@ func (d *DB) DeleteImcUser(id uint) error {
|
|||
return d.Delete(&ImcUser{}, id).Error // Delete by primary key
|
||||
}
|
||||
|
||||
// UpsertAdminUser creates the admin user if it doesn't exist, or updates the password if it does.
|
||||
func (d *DB) UpsertAdminUser(username, passwordHash string) error {
|
||||
var user ImcUser
|
||||
err := d.Where("username = ? AND role = ?", username, "admin").First(&user).Error
|
||||
if err == nil {
|
||||
return d.Model(&ImcUser{}).Where("id = ?", user.ID).Update("password_hash", passwordHash).Error
|
||||
}
|
||||
_, err = d.CreateImcUser(username, passwordHash, "admin")
|
||||
return err
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Domain Access Control
|
||||
// These functions manage which domains users can access.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue