mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
- Update locales (ru, tt, en) to use 'Turash' and 'Turash AI' - Update metadata, index.html, and pixel-art README - Replace example credentials/emails from @tuganyak.dev -> @turash.dev - Update admin defaults and migration seed to use new admin@turash.dev - Update docs mentioning the old name
279 lines
7.3 KiB
Go
279 lines
7.3 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"bugulma/backend/cmd/cli/internal"
|
|
"bugulma/backend/internal/domain"
|
|
"bugulma/backend/internal/repository"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/spf13/cobra"
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
var (
|
|
userEmail string
|
|
userPassword string
|
|
userName string
|
|
userRole string
|
|
resetMode bool
|
|
setupMode bool
|
|
)
|
|
|
|
var userCmd = &cobra.Command{
|
|
Use: "user",
|
|
Short: "User management operations",
|
|
Long: `Manage user accounts including password resets and bulk user setup.
|
|
Supports creating users, resetting passwords, and setting up default users.`,
|
|
}
|
|
|
|
var userCreateCmd = &cobra.Command{
|
|
Use: "create",
|
|
Short: "Create a new user account",
|
|
Long: `Create a new user account with the specified email, password, and role.
|
|
If no password is provided, it will be generated randomly.`,
|
|
RunE: runUserCreate,
|
|
}
|
|
|
|
var userResetPasswordCmd = &cobra.Command{
|
|
Use: "reset-password",
|
|
Short: "Reset a user's password",
|
|
Long: `Reset a user's password. Generates a bcrypt hash that can be used
|
|
to update the user's password in the database.`,
|
|
RunE: runUserResetPassword,
|
|
}
|
|
|
|
var userSetupCmd = &cobra.Command{
|
|
Use: "setup",
|
|
Short: "Set up default users",
|
|
Long: `Create default users for each role if they don't exist.
|
|
Creates admin, regular user, content manager, and viewer accounts.
|
|
Existing users are updated if their roles differ.`,
|
|
RunE: runUserSetup,
|
|
}
|
|
|
|
func init() {
|
|
// Create command flags
|
|
userCreateCmd.Flags().StringVarP(&userEmail, "email", "e", "", "User email (required)")
|
|
userCreateCmd.Flags().StringVarP(&userPassword, "password", "p", "", "User password (if not provided, will be prompted)")
|
|
userCreateCmd.Flags().StringVarP(&userName, "name", "n", "", "User name (required)")
|
|
userCreateCmd.Flags().StringVarP(&userRole, "role", "r", "user", "User role (admin, user, content_manager, viewer)")
|
|
userCreateCmd.MarkFlagRequired("email")
|
|
userCreateCmd.MarkFlagRequired("name")
|
|
|
|
// Reset password command flags
|
|
userResetPasswordCmd.Flags().StringVarP(&userPassword, "password", "p", "", "New password (required)")
|
|
userResetPasswordCmd.MarkFlagRequired("password")
|
|
|
|
// Add subcommands
|
|
userCmd.AddCommand(userCreateCmd)
|
|
userCmd.AddCommand(userResetPasswordCmd)
|
|
userCmd.AddCommand(userSetupCmd)
|
|
}
|
|
|
|
func runUserCreate(cmd *cobra.Command, args []string) error {
|
|
cfg, err := getConfig()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load config: %w", err)
|
|
}
|
|
|
|
// Connect to database
|
|
db, err := internal.ConnectPostgres(cfg)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to connect to database: %w", err)
|
|
}
|
|
|
|
userRepo := repository.NewUserRepository(db)
|
|
ctx := context.Background()
|
|
|
|
// Validate role
|
|
var role domain.UserRole
|
|
switch userRole {
|
|
case "admin":
|
|
role = domain.UserRoleAdmin
|
|
case "user":
|
|
role = domain.UserRoleUser
|
|
case "content_manager":
|
|
role = domain.UserRoleContentManager
|
|
case "viewer":
|
|
role = domain.UserRoleViewer
|
|
default:
|
|
return fmt.Errorf("invalid role: %s. Must be one of: admin, user, content_manager, viewer", userRole)
|
|
}
|
|
|
|
// Check if user exists
|
|
existing, err := userRepo.GetByEmail(ctx, userEmail)
|
|
if err == nil && existing != nil {
|
|
return fmt.Errorf("user with email %s already exists", userEmail)
|
|
}
|
|
|
|
// Hash password
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(userPassword), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to hash password: %w", err)
|
|
}
|
|
|
|
// Create user
|
|
user := &domain.User{
|
|
ID: uuid.New().String(),
|
|
Email: userEmail,
|
|
Name: userName,
|
|
Password: string(hashedPassword),
|
|
Role: role,
|
|
IsActive: true,
|
|
Permissions: "[]",
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
if err := userRepo.Create(ctx, user); err != nil {
|
|
return fmt.Errorf("failed to create user: %w", err)
|
|
}
|
|
|
|
if isVerbose() {
|
|
fmt.Printf("✓ Created user %s (%s) with role %s\n", userEmail, userName, role)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func runUserResetPassword(cmd *cobra.Command, args []string) error {
|
|
if len(args) != 1 {
|
|
return fmt.Errorf("email argument is required")
|
|
}
|
|
|
|
email := args[0]
|
|
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(userPassword), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to hash password: %w", err)
|
|
}
|
|
|
|
fmt.Println("-- Run this SQL to update the user password:")
|
|
fmt.Printf("UPDATE users SET password = '%s' WHERE email = '%s';\n", string(hashedPassword), email)
|
|
|
|
if isVerbose() {
|
|
fmt.Printf("✓ Generated password hash for user: %s\n", email)
|
|
fmt.Printf("Password: %s\n", userPassword)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func runUserSetup(cmd *cobra.Command, args []string) error {
|
|
cfg, err := getConfig()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load config: %w", err)
|
|
}
|
|
|
|
// Connect to database
|
|
db, err := internal.ConnectPostgres(cfg)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to connect to database: %w", err)
|
|
}
|
|
|
|
userRepo := repository.NewUserRepository(db)
|
|
ctx := context.Background()
|
|
|
|
// Define users for each role
|
|
users := []struct {
|
|
email string
|
|
name string
|
|
password string
|
|
role domain.UserRole
|
|
}{
|
|
{
|
|
email: "admin@turash.dev",
|
|
name: "Admin User",
|
|
password: "admin123",
|
|
role: domain.UserRoleAdmin,
|
|
},
|
|
{
|
|
email: "user@turash.dev",
|
|
name: "Regular User",
|
|
password: "user123",
|
|
role: domain.UserRoleUser,
|
|
},
|
|
{
|
|
email: "content@turash.dev",
|
|
name: "Content Manager",
|
|
password: "content123",
|
|
role: domain.UserRoleContentManager,
|
|
},
|
|
{
|
|
email: "viewer@turash.dev",
|
|
name: "Viewer User",
|
|
password: "viewer123",
|
|
role: domain.UserRoleViewer,
|
|
},
|
|
}
|
|
|
|
for _, u := range users {
|
|
// Check if user exists
|
|
existing, err := userRepo.GetByEmail(ctx, u.email)
|
|
if err == nil && existing != nil {
|
|
// Update role if different
|
|
if existing.Role != u.role {
|
|
if isVerbose() {
|
|
fmt.Printf("Updating user %s: role %s -> %s\n", u.email, existing.Role, u.role)
|
|
}
|
|
if err := userRepo.UpdateRole(ctx, existing.ID, u.role); err != nil {
|
|
log.Printf("Failed to update role for %s: %v", u.email, err)
|
|
continue
|
|
}
|
|
if !isQuiet() {
|
|
fmt.Printf("✓ Updated role for %s to %s\n", u.email, u.role)
|
|
}
|
|
} else {
|
|
if !isQuiet() {
|
|
fmt.Printf("✓ User %s already exists with role %s\n", u.email, u.role)
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
|
|
// Create new user
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
log.Printf("Failed to hash password for %s: %v", u.email, err)
|
|
continue
|
|
}
|
|
|
|
user := &domain.User{
|
|
ID: uuid.New().String(),
|
|
Email: u.email,
|
|
Name: u.name,
|
|
Password: string(hashedPassword),
|
|
Role: u.role,
|
|
IsActive: true,
|
|
Permissions: "[]",
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
if err := userRepo.Create(ctx, user); err != nil {
|
|
log.Printf("Failed to create user %s: %v", u.email, err)
|
|
continue
|
|
}
|
|
|
|
if !isQuiet() {
|
|
fmt.Printf("✓ Created user %s with role %s (password: %s)\n", u.email, u.role, u.password)
|
|
}
|
|
}
|
|
|
|
if !isQuiet() {
|
|
fmt.Println("\nAll users setup complete!")
|
|
fmt.Println("\nLogin credentials:")
|
|
fmt.Println(" Admin: admin@turash.dev / admin123")
|
|
fmt.Println(" User: user@turash.dev / user123")
|
|
fmt.Println(" Content Mgr: content@turash.dev / content123")
|
|
fmt.Println(" Viewer: viewer@turash.dev / viewer123")
|
|
}
|
|
|
|
return nil
|
|
}
|