| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- package cmd
- import (
- "context"
- "encoding/json"
- "fmt"
- "os"
- "strings"
- "gogs.dmsc.dev/arp/arp_cli/client"
- "gogs.dmsc.dev/arp/arp_cli/config"
- "github.com/AlecAivazis/survey/v2"
- "github.com/olekukonko/tablewriter"
- "github.com/urfave/cli/v3"
- )
- // RoleCommand returns the role command
- func RoleCommand() *cli.Command {
- return &cli.Command{
- Name: "role",
- Usage: "Manage roles",
- Description: `Manage ARP roles. Roles group permissions for access control.
- Use this command to create, list, update, and delete roles.`,
- Commands: []*cli.Command{
- {
- Name: "list",
- Aliases: []string{"ls"},
- Usage: "List all roles",
- Flags: []cli.Flag{
- &cli.BoolFlag{
- Name: "json",
- Aliases: []string{"j"},
- Usage: "Output as JSON",
- },
- },
- Action: roleList,
- },
- {
- Name: "get",
- Usage: "Get a role by ID",
- Flags: []cli.Flag{
- &cli.StringFlag{
- Name: "id",
- Aliases: []string{"i"},
- Usage: "Role ID",
- Required: true,
- },
- &cli.BoolFlag{
- Name: "json",
- Aliases: []string{"j"},
- Usage: "Output as JSON",
- },
- },
- Action: roleGet,
- },
- {
- Name: "create",
- Usage: "Create a new role",
- Action: roleCreate,
- Flags: []cli.Flag{
- &cli.StringFlag{
- Name: "name",
- Aliases: []string{"n"},
- Usage: "Role name",
- },
- &cli.StringFlag{
- Name: "description",
- Aliases: []string{"d"},
- Usage: "Role description",
- },
- &cli.StringSliceFlag{
- Name: "permissions",
- Aliases: []string{"p"},
- Usage: "Permission IDs",
- },
- },
- },
- {
- Name: "update",
- Usage: "Update a role",
- Action: roleUpdate,
- Flags: []cli.Flag{
- &cli.StringFlag{
- Name: "id",
- Aliases: []string{"i"},
- Usage: "Role ID",
- Required: true,
- },
- &cli.StringFlag{
- Name: "name",
- Aliases: []string{"n"},
- Usage: "Role name",
- },
- &cli.StringFlag{
- Name: "description",
- Aliases: []string{"d"},
- Usage: "Role description",
- },
- &cli.StringSliceFlag{
- Name: "permissions",
- Aliases: []string{"p"},
- Usage: "Permission IDs",
- },
- },
- },
- {
- Name: "delete",
- Usage: "Delete a role",
- Action: roleDelete,
- Flags: []cli.Flag{
- &cli.StringFlag{
- Name: "id",
- Aliases: []string{"i"},
- Usage: "Role ID",
- Required: true,
- },
- &cli.BoolFlag{
- Name: "yes",
- Aliases: []string{"y"},
- Usage: "Skip confirmation",
- },
- },
- },
- },
- }
- }
- type RoleDetail struct {
- ID string `json:"id"`
- Name string `json:"name"`
- Description string `json:"description"`
- Permissions []Permission `json:"permissions"`
- }
- type Permission struct {
- ID string `json:"id"`
- Code string `json:"code"`
- Description string `json:"description"`
- }
- func roleList(ctx context.Context, cmd *cli.Command) error {
- cfg, err := config.Load()
- if err != nil {
- return err
- }
- if err := RequireAuth(cfg); err != nil {
- return err
- }
- c := client.New(cfg.ServerURL)
- c.SetToken(cfg.Token)
- query := "query Roles { roles { id name description permissions { id code } } }"
- resp, err := c.Query(query, nil)
- if err != nil {
- return err
- }
- var result struct {
- Roles []RoleDetail `json:"roles"`
- }
- if err := json.Unmarshal(resp.Data, &result); err != nil {
- return err
- }
- if cmd.Bool("json") {
- enc := json.NewEncoder(os.Stdout)
- enc.SetIndent("", " ")
- return enc.Encode(result.Roles)
- }
- if len(result.Roles) == 0 {
- fmt.Println("No roles found.")
- return nil
- }
- table := tablewriter.NewWriter(os.Stdout)
- table.Header([]string{"ID", "Name", "Description", "Permissions"})
-
- for _, r := range result.Roles {
- perms := make([]string, len(r.Permissions))
- for i, p := range r.Permissions {
- perms[i] = p.Code
- }
- table.Append([]string{r.ID, r.Name, r.Description, strings.Join(perms, ", ")})
- }
- table.Render()
- return nil
- }
- func roleGet(ctx context.Context, cmd *cli.Command) error {
- cfg, err := config.Load()
- if err != nil {
- return err
- }
- if err := RequireAuth(cfg); err != nil {
- return err
- }
- c := client.New(cfg.ServerURL)
- c.SetToken(cfg.Token)
- id := cmd.String("id")
- query := "query Role($id: ID!) { role(id: $id) { id name description permissions { id code description } } }"
- resp, err := c.Query(query, map[string]interface{}{"id": id})
- if err != nil {
- return err
- }
- var result struct {
- Role *RoleDetail `json:"role"`
- }
- if err := json.Unmarshal(resp.Data, &result); err != nil {
- return err
- }
- if result.Role == nil {
- return fmt.Errorf("role not found")
- }
- if cmd.Bool("json") {
- enc := json.NewEncoder(os.Stdout)
- enc.SetIndent("", " ")
- return enc.Encode(result.Role)
- }
- r := result.Role
- fmt.Printf("ID: %s\n", r.ID)
- fmt.Printf("Name: %s\n", r.Name)
- fmt.Printf("Description: %s\n", r.Description)
- fmt.Printf("Permissions:\n")
- for _, p := range r.Permissions {
- fmt.Printf(" - %s (%s): %s\n", p.Code, p.ID, p.Description)
- }
- return nil
- }
- func roleCreate(ctx context.Context, cmd *cli.Command) error {
- cfg, err := config.Load()
- if err != nil {
- return err
- }
- if err := RequireAuth(cfg); err != nil {
- return err
- }
- name := cmd.String("name")
- description := cmd.String("description")
- permissions := cmd.StringSlice("permissions")
- if name == "" {
- prompt := &survey.Input{Message: "Role name:"}
- if err := survey.AskOne(prompt, &name, survey.WithValidator(survey.Required)); err != nil {
- return err
- }
- }
- if description == "" {
- prompt := &survey.Input{Message: "Description:"}
- if err := survey.AskOne(prompt, &description, survey.WithValidator(survey.Required)); err != nil {
- return err
- }
- }
- if len(permissions) == 0 {
- var permissionsStr string
- prompt := &survey.Input{Message: "Permission IDs (comma-separated):"}
- if err := survey.AskOne(prompt, &permissionsStr, survey.WithValidator(survey.Required)); err != nil {
- return err
- }
- for _, p := range strings.Split(permissionsStr, ",") {
- permissions = append(permissions, strings.TrimSpace(p))
- }
- }
- c := client.New(cfg.ServerURL)
- c.SetToken(cfg.Token)
- mutation := `mutation CreateRole($input: NewRole!) { createRole(input: $input) { id name description permissions { id code } } }`
- input := map[string]interface{}{
- "name": name,
- "description": description,
- "permissions": permissions,
- }
- resp, err := c.Mutation(mutation, map[string]interface{}{"input": input})
- if err != nil {
- return err
- }
- var result struct {
- CreateRole *RoleDetail `json:"createRole"`
- }
- if err := json.Unmarshal(resp.Data, &result); err != nil {
- return err
- }
- if result.CreateRole == nil {
- return fmt.Errorf("failed to create role")
- }
- fmt.Printf("Role created successfully!\n")
- fmt.Printf("ID: %s\n", result.CreateRole.ID)
- fmt.Printf("Name: %s\n", result.CreateRole.Name)
- return nil
- }
- func roleUpdate(ctx context.Context, cmd *cli.Command) error {
- cfg, err := config.Load()
- if err != nil {
- return err
- }
- if err := RequireAuth(cfg); err != nil {
- return err
- }
- id := cmd.String("id")
- name := cmd.String("name")
- description := cmd.String("description")
- permissions := cmd.StringSlice("permissions")
- if name == "" && description == "" && len(permissions) == 0 {
- fmt.Println("No updates provided. Use flags to specify what to update.")
- return nil
- }
- c := client.New(cfg.ServerURL)
- c.SetToken(cfg.Token)
- input := make(map[string]interface{})
- if name != "" {
- input["name"] = name
- }
- if description != "" {
- input["description"] = description
- }
- if len(permissions) > 0 {
- input["permissions"] = permissions
- }
- mutation := `mutation UpdateRole($id: ID!, $input: UpdateRoleInput!) { updateRole(id: $id, input: $input) { id name description permissions { id code } } }`
- resp, err := c.Mutation(mutation, map[string]interface{}{"id": id, "input": input})
- if err != nil {
- return err
- }
- var result struct {
- UpdateRole *RoleDetail `json:"updateRole"`
- }
- if err := json.Unmarshal(resp.Data, &result); err != nil {
- return err
- }
- if result.UpdateRole == nil {
- return fmt.Errorf("role not found")
- }
- fmt.Printf("Role updated successfully!\n")
- fmt.Printf("ID: %s\n", result.UpdateRole.ID)
- fmt.Printf("Name: %s\n", result.UpdateRole.Name)
- return nil
- }
- func roleDelete(ctx context.Context, cmd *cli.Command) error {
- cfg, err := config.Load()
- if err != nil {
- return err
- }
- if err := RequireAuth(cfg); err != nil {
- return err
- }
- id := cmd.String("id")
- skipConfirm := cmd.Bool("yes")
- if !skipConfirm {
- confirm := false
- prompt := &survey.Confirm{
- Message: fmt.Sprintf("Are you sure you want to delete role %s?", id),
- Default: false,
- }
- if err := survey.AskOne(prompt, &confirm); err != nil {
- return err
- }
- if !confirm {
- fmt.Println("Deletion cancelled.")
- return nil
- }
- }
- c := client.New(cfg.ServerURL)
- c.SetToken(cfg.Token)
- mutation := `mutation DeleteRole($id: ID!) { deleteRole(id: $id) }`
- resp, err := c.Mutation(mutation, map[string]interface{}{"id": id})
- if err != nil {
- return err
- }
- var result struct {
- DeleteRole bool `json:"deleteRole"`
- }
- if err := json.Unmarshal(resp.Data, &result); err != nil {
- return err
- }
- if result.DeleteRole {
- fmt.Printf("Role %s deleted successfully.\n", id)
- } else {
- fmt.Printf("Failed to delete role %s.\n", id)
- }
- return nil
- }
|