@@ -19,9 +19,9 @@ import (
19
19
func (r * RootCmd ) editRole () * serpent.Command {
20
20
formatter := cliui .NewOutputFormatter (
21
21
cliui .ChangeFormatterData (
22
- cliui .TableFormat ([]codersdk. Role {}, []string {"name" , "display_name" , "site_permissions" , "org_permissions" , "user_permissions" }),
22
+ cliui .TableFormat ([]roleTableView {}, []string {"name" , "display_name" , "site_permissions" , "org_permissions" , "user_permissions" }),
23
23
func (data any ) (any , error ) {
24
- return []codersdk. Role { data .(codersdk.Role )}, nil
24
+ return []roleTableView { roleToTableView ( data .(codersdk.Role ) )}, nil
25
25
},
26
26
),
27
27
cliui .JSONFormat (),
@@ -51,108 +51,126 @@ func (r *RootCmd) editRole() *serpent.Command {
51
51
},
52
52
},
53
53
Middleware : serpent .Chain (
54
- serpent .RequireNArgs ( 1 ),
54
+ serpent .RequireRangeArgs ( 0 , 1 ),
55
55
r .InitClient (client ),
56
56
),
57
57
Handler : func (inv * serpent.Invocation ) error {
58
58
ctx := inv .Context ()
59
- roles , err := client .ListSiteRoles (ctx )
60
- if err != nil {
61
- return xerrors .Errorf ("listing roles: %w" , err )
62
- }
63
-
64
- // Make sure the role actually exists first
65
- var originalRole codersdk.AssignableRoles
66
- for _ , r := range roles {
67
- if strings .EqualFold (inv .Args [0 ], r .Name ) {
68
- originalRole = r
69
- break
70
- }
71
- }
72
-
73
- if originalRole .Name == "" {
74
- _ , err = cliui .Prompt (inv , cliui.PromptOptions {
75
- Text : "No role exists with that name, do you want to create one?" ,
76
- Default : "yes" ,
77
- IsConfirm : true ,
78
- })
79
- if err != nil {
80
- return xerrors .Errorf ("abort: %w" , err )
81
- }
82
59
83
- originalRole .Role = codersdk.Role {
84
- Name : inv .Args [0 ],
85
- }
86
- }
87
-
88
- var customRole * codersdk.Role
89
- // Either interactive, or take input mode.
60
+ var customRole codersdk.Role
90
61
fi , _ := os .Stdin .Stat ()
91
62
if (fi .Mode () & os .ModeCharDevice ) == 0 {
63
+ // JSON Upload mode
92
64
bytes , err := io .ReadAll (os .Stdin )
93
65
if err != nil {
94
66
return xerrors .Errorf ("reading stdin: %w" , err )
95
67
}
96
68
97
- err = json .Unmarshal (bytes , customRole )
69
+ err = json .Unmarshal (bytes , & customRole )
98
70
if err != nil {
99
71
return xerrors .Errorf ("parsing stdin json: %w" , err )
100
72
}
101
- } else {
102
- // Interactive mode
103
- if len (originalRole .OrganizationPermissions ) > 0 {
104
- return xerrors .Errorf ("unable to edit role in interactive mode, it contains organization permissions" )
105
- }
106
73
107
- if len (originalRole .UserPermissions ) > 0 {
108
- return xerrors .Errorf ("unable to edit role in interactive mode, it contains user permissions" )
74
+ if customRole .Name == "" {
75
+ arr := make ([]json.RawMessage , 0 )
76
+ err = json .Unmarshal (bytes , & arr )
77
+ if err == nil && len (arr ) > 0 {
78
+ return xerrors .Errorf ("the input appears to be an array, only 1 role can be sent at a time" )
79
+ }
80
+ return xerrors .Errorf ("json input does not appear to be a valid role" )
109
81
}
110
-
111
- customRole , err = interactiveEdit (inv , & originalRole . Role )
82
+ } else {
83
+ interactiveRole , err : = interactiveEdit (inv , client )
112
84
if err != nil {
113
85
return xerrors .Errorf ("editing role: %w" , err )
114
86
}
115
- }
116
87
117
- totalOrg := 0
118
- for _ , o := range customRole .OrganizationPermissions {
119
- totalOrg += len (o )
120
- }
121
- preview := fmt .Sprintf ("perms: %d site, %d over %d orgs, %d user" ,
122
- len (customRole .SitePermissions ), totalOrg , len (customRole .OrganizationPermissions ), len (customRole .UserPermissions ))
123
- _ , err = cliui .Prompt (inv , cliui.PromptOptions {
124
- Text : "Are you sure you wish to update the role? " + preview ,
125
- Default : "yes" ,
126
- IsConfirm : true ,
127
- })
128
- if err != nil {
129
- return xerrors .Errorf ("abort: %w" , err )
88
+ customRole = * interactiveRole
89
+
90
+ // Only the interactive can answer prompts.
91
+ totalOrg := 0
92
+ for _ , o := range customRole .OrganizationPermissions {
93
+ totalOrg += len (o )
94
+ }
95
+ preview := fmt .Sprintf ("perms: %d site, %d over %d orgs, %d user" ,
96
+ len (customRole .SitePermissions ), totalOrg , len (customRole .OrganizationPermissions ), len (customRole .UserPermissions ))
97
+ _ , err = cliui .Prompt (inv , cliui.PromptOptions {
98
+ Text : "Are you sure you wish to update the role? " + preview ,
99
+ Default : "yes" ,
100
+ IsConfirm : true ,
101
+ })
102
+ if err != nil {
103
+ return xerrors .Errorf ("abort: %w" , err )
104
+ }
130
105
}
131
106
107
+ var err error
132
108
var updated codersdk.Role
133
109
if dryRun {
134
110
// Do not actually post
135
- updated = * customRole
111
+ updated = customRole
136
112
} else {
137
- updated , err = client .PatchRole (ctx , * customRole )
113
+ updated , err = client .PatchRole (ctx , customRole )
138
114
if err != nil {
139
115
return fmt .Errorf ("patch role: %w" , err )
140
116
}
141
117
}
142
118
143
- _ , err = formatter .Format (ctx , updated )
119
+ output , err : = formatter .Format (ctx , updated )
144
120
if err != nil {
145
121
return xerrors .Errorf ("formatting: %w" , err )
146
122
}
147
- return nil
123
+
124
+ _ , err = fmt .Fprintln (inv .Stdout , output )
125
+ return err
148
126
},
149
127
}
150
128
151
129
formatter .AttachOptions (& cmd .Options )
152
130
return cmd
153
131
}
154
132
155
- func interactiveEdit (inv * serpent.Invocation , role * codersdk.Role ) (* codersdk.Role , error ) {
133
+ func interactiveEdit (inv * serpent.Invocation , client * codersdk.Client ) (* codersdk.Role , error ) {
134
+ ctx := inv .Context ()
135
+ roles , err := client .ListSiteRoles (ctx )
136
+ if err != nil {
137
+ return nil , xerrors .Errorf ("listing roles: %w" , err )
138
+ }
139
+
140
+ // Make sure the role actually exists first
141
+ var originalRole codersdk.AssignableRoles
142
+ for _ , r := range roles {
143
+ if strings .EqualFold (inv .Args [0 ], r .Name ) {
144
+ originalRole = r
145
+ break
146
+ }
147
+ }
148
+
149
+ if originalRole .Name == "" {
150
+ _ , err = cliui .Prompt (inv , cliui.PromptOptions {
151
+ Text : "No role exists with that name, do you want to create one?" ,
152
+ Default : "yes" ,
153
+ IsConfirm : true ,
154
+ })
155
+ if err != nil {
156
+ return nil , xerrors .Errorf ("abort: %w" , err )
157
+ }
158
+
159
+ originalRole .Role = codersdk.Role {
160
+ Name : inv .Args [0 ],
161
+ }
162
+ }
163
+
164
+ // Some checks since interactive mode is limited in what it currently sees
165
+ if len (originalRole .OrganizationPermissions ) > 0 {
166
+ return nil , xerrors .Errorf ("unable to edit role in interactive mode, it contains organization permissions" )
167
+ }
168
+
169
+ if len (originalRole .UserPermissions ) > 0 {
170
+ return nil , xerrors .Errorf ("unable to edit role in interactive mode, it contains user permissions" )
171
+ }
172
+
173
+ role := & originalRole .Role
156
174
allowedResources := []codersdk.RBACResource {
157
175
codersdk .ResourceTemplate ,
158
176
codersdk .ResourceWorkspace ,
0 commit comments