package main import ( "database/sql" "fmt" "log" "os" "strings" "time" "git.wntrmute.dev/kyle/mcias/data" _ "github.com/mattn/go-sqlite3" "github.com/spf13/cobra" "github.com/spf13/viper" ) var ( username string password string ) var userCmd = &cobra.Command{ Use: "user", Short: "Manage users", Long: `Commands for managing users in the MCIAS system.`, } var addUserCmd = &cobra.Command{ Use: "add", Short: "Add a new user", Long: `Add a new user to the MCIAS system. This command requires a username and password.`, Run: func(cmd *cobra.Command, args []string) { addUser() }, } var listUsersCmd = &cobra.Command{ Use: "list", Short: "List all users", Long: `List all users in the MCIAS system.`, Run: func(cmd *cobra.Command, args []string) { listUsers() }, } func init() { rootCmd.AddCommand(userCmd) userCmd.AddCommand(addUserCmd) userCmd.AddCommand(listUsersCmd) addUserCmd.Flags().StringVarP(&username, "username", "u", "", "Username for the new user") addUserCmd.Flags().StringVarP(&password, "password", "p", "", "Password for the new user") if err := addUserCmd.MarkFlagRequired("username"); err != nil { fmt.Fprintf(os.Stderr, "Error marking username flag as required: %v\n", err) } if err := addUserCmd.MarkFlagRequired("password"); err != nil { fmt.Fprintf(os.Stderr, "Error marking password flag as required: %v\n", err) } } func addUser() { dbPath := viper.GetString("db") logger := log.New(os.Stdout, "MCIAS: ", log.LstdFlags) db, err := sql.Open("sqlite3", dbPath) if err != nil { logger.Fatalf("Failed to open database: %v", err) } defer db.Close() var count int err = db.QueryRow("SELECT COUNT(*) FROM users WHERE user = ?", username).Scan(&count) if err != nil { logger.Fatalf("Failed to check if user exists: %v", err) } if count > 0 { logger.Fatalf("User %s already exists", username) } user := &data.User{} login := &data.Login{ User: username, Password: password, } if err := user.Register(login); err != nil { logger.Fatalf("Failed to register user: %v", err) } query := `INSERT INTO users (id, created, user, password, salt) VALUES (?, ?, ?, ?, ?)` _, err = db.Exec(query, user.ID, user.Created, user.User, user.Password, user.Salt) if err != nil { logger.Fatalf("Failed to insert user into database: %v", err) } fmt.Printf("User %s added successfully with ID %s\n", user.User, user.ID) } func listUsers() { dbPath := viper.GetString("db") logger := log.New(os.Stdout, "MCIAS: ", log.LstdFlags) db, err := sql.Open("sqlite3", dbPath) if err != nil { logger.Fatalf("Failed to open database: %v", err) } defer db.Close() rows, err := db.Query("SELECT id, created, user FROM users ORDER BY user") if err != nil { logger.Fatalf("Failed to query users: %v", err) } defer rows.Close() fmt.Printf("%-24s %-30s %-20s\n", "ID", "USERNAME", "CREATED") fmt.Println(strings.Repeat("-", 76)) for rows.Next() { var id string var created int64 var username string if err := rows.Scan(&id, &created, &username); err != nil { logger.Fatalf("Failed to scan user row: %v", err) } createdTime := time.Unix(created, 0).Format(time.RFC3339) fmt.Printf("%-24s %-30s %-20s\n", id, username, createdTime) } if err := rows.Err(); err != nil { logger.Fatalf("Error iterating user rows: %v", err) } }