package main import ( "database/sql" "fmt" "log" "os" "strings" "github.com/oklog/ulid/v2" "github.com/spf13/cobra" "github.com/spf13/viper" ) var ( roleName string roleUser string ) var roleCmd = &cobra.Command{ Use: "role", Short: "Manage roles", Long: `Commands for managing roles in the MCIAS system.`, } var addRoleCmd = &cobra.Command{ Use: "add", Short: "Add a new role", Long: `Add a new role to the MCIAS system.`, Run: func(cmd *cobra.Command, args []string) { addRole() }, } var listRolesCmd = &cobra.Command{ Use: "list", Short: "List all roles", Long: `List all roles in the MCIAS system.`, Run: func(cmd *cobra.Command, args []string) { listRoles() }, } var assignRoleCmd = &cobra.Command{ Use: "assign", Short: "Assign a role to a user", Long: `Assign a role to a user in the MCIAS system.`, Run: func(cmd *cobra.Command, args []string) { assignRole() }, } var revokeRoleCmd = &cobra.Command{ Use: "revoke", Short: "Revoke a role from a user", Long: `Revoke a role from a user in the MCIAS system.`, Run: func(cmd *cobra.Command, args []string) { revokeRole() }, } func init() { rootCmd.AddCommand(roleCmd) roleCmd.AddCommand(addRoleCmd) roleCmd.AddCommand(listRolesCmd) roleCmd.AddCommand(assignRoleCmd) roleCmd.AddCommand(revokeRoleCmd) addRoleCmd.Flags().StringVar(&roleName, "name", "", "Name of the role") if err := addRoleCmd.MarkFlagRequired("name"); err != nil { fmt.Fprintf(os.Stderr, "Error marking name flag as required: %v\n", err) } assignRoleCmd.Flags().StringVar(&roleUser, "user", "", "Username to assign the role to") assignRoleCmd.Flags().StringVar(&roleName, "role", "", "Name of the role to assign") if err := assignRoleCmd.MarkFlagRequired("user"); err != nil { fmt.Fprintf(os.Stderr, "Error marking user flag as required: %v\n", err) } if err := assignRoleCmd.MarkFlagRequired("role"); err != nil { fmt.Fprintf(os.Stderr, "Error marking role flag as required: %v\n", err) } revokeRoleCmd.Flags().StringVar(&roleUser, "user", "", "Username to revoke the role from") revokeRoleCmd.Flags().StringVar(&roleName, "role", "", "Name of the role to revoke") if err := revokeRoleCmd.MarkFlagRequired("user"); err != nil { fmt.Fprintf(os.Stderr, "Error marking user flag as required: %v\n", err) } if err := revokeRoleCmd.MarkFlagRequired("role"); err != nil { fmt.Fprintf(os.Stderr, "Error marking role flag as required: %v\n", err) } } func addRole() { 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() // Check if role already exists var count int err = db.QueryRow("SELECT COUNT(*) FROM roles WHERE role = ?", roleName).Scan(&count) if err != nil { logger.Fatalf("Failed to check if role exists: %v", err) } if count > 0 { logger.Fatalf("Role %s already exists", roleName) } // Generate a new ID for the role id := ulid.Make().String() // Insert the new role _, err = db.Exec("INSERT INTO roles (id, role) VALUES (?, ?)", id, roleName) if err != nil { logger.Fatalf("Failed to insert role: %v", err) } fmt.Printf("Role %s added successfully with ID %s\n", roleName, id) } func listRoles() { 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, role FROM roles ORDER BY role") if err != nil { logger.Fatalf("Failed to query roles: %v", err) } defer rows.Close() fmt.Printf("%-24s %-30s\n", "ID", "ROLE") fmt.Println(strings.Repeat("-", 55)) for rows.Next() { var id, role string if err := rows.Scan(&id, &role); err != nil { logger.Fatalf("Failed to scan role row: %v", err) } fmt.Printf("%-24s %-30s\n", id, role) } if err := rows.Err(); err != nil { logger.Fatalf("Error iterating role rows: %v", err) } } func assignRole() { 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() // Get user ID var userID string err = db.QueryRow("SELECT id FROM users WHERE user = ?", roleUser).Scan(&userID) if err != nil { if err == sql.ErrNoRows { logger.Fatalf("User %s not found", roleUser) } logger.Fatalf("Failed to get user ID: %v", err) } // Get role ID var roleID string err = db.QueryRow("SELECT id FROM roles WHERE role = ?", roleName).Scan(&roleID) if err != nil { if err == sql.ErrNoRows { logger.Fatalf("Role %s not found", roleName) } logger.Fatalf("Failed to get role ID: %v", err) } // Check if user already has this role var count int err = db.QueryRow("SELECT COUNT(*) FROM user_roles WHERE uid = ? AND rid = ?", userID, roleID).Scan(&count) if err != nil { logger.Fatalf("Failed to check if user has role: %v", err) } if count > 0 { logger.Fatalf("User %s already has role %s", roleUser, roleName) } // Generate a new ID for the user-role relationship id := ulid.Make().String() // Assign role to user _, err = db.Exec("INSERT INTO user_roles (id, uid, rid) VALUES (?, ?, ?)", id, userID, roleID) if err != nil { logger.Fatalf("Failed to assign role: %v", err) } fmt.Printf("Role %s assigned to user %s successfully\n", roleName, roleUser) } func revokeRole() { 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() // Get user ID var userID string err = db.QueryRow("SELECT id FROM users WHERE user = ?", roleUser).Scan(&userID) if err != nil { if err == sql.ErrNoRows { logger.Fatalf("User %s not found", roleUser) } logger.Fatalf("Failed to get user ID: %v", err) } // Get role ID var roleID string err = db.QueryRow("SELECT id FROM roles WHERE role = ?", roleName).Scan(&roleID) if err != nil { if err == sql.ErrNoRows { logger.Fatalf("Role %s not found", roleName) } logger.Fatalf("Failed to get role ID: %v", err) } // Check if user has this role var count int err = db.QueryRow("SELECT COUNT(*) FROM user_roles WHERE uid = ? AND rid = ?", userID, roleID).Scan(&count) if err != nil { logger.Fatalf("Failed to check if user has role: %v", err) } if count == 0 { logger.Fatalf("User %s does not have role %s", roleUser, roleName) } // Revoke role from user _, err = db.Exec("DELETE FROM user_roles WHERE uid = ? AND rid = ?", userID, roleID) if err != nil { logger.Fatalf("Failed to revoke role: %v", err) } fmt.Printf("Role %s revoked from user %s successfully\n", roleName, roleUser) }