1
1
package coderd
2
2
3
3
import (
4
- "context"
5
4
"fmt"
6
5
"net/http"
7
6
@@ -11,125 +10,131 @@ import (
11
10
"github.com/coder/coder/v2/coderd/database"
12
11
"github.com/coder/coder/v2/coderd/database/db2sdk"
13
12
"github.com/coder/coder/v2/coderd/httpapi"
13
+ "github.com/coder/coder/v2/coderd/httpmw"
14
14
"github.com/coder/coder/v2/coderd/rbac"
15
15
"github.com/coder/coder/v2/coderd/rbac/policy"
16
16
"github.com/coder/coder/v2/codersdk"
17
17
)
18
18
19
- type enterpriseCustomRoleHandler struct {
20
- API * API
21
- Enabled bool
22
- }
23
-
24
- func (h enterpriseCustomRoleHandler ) PatchOrganizationRole (ctx context.Context , rw http.ResponseWriter , r * http.Request , orgID uuid.UUID , role codersdk.Role ) (codersdk.Role , bool ) {
25
- if ! h .Enabled {
26
- httpapi .Write (ctx , rw , http .StatusForbidden , codersdk.Response {
27
- Message : "Custom roles are not enabled" ,
28
- })
29
- return codersdk.Role {}, false
30
- }
31
-
19
+ // patchRole will allow creating a custom organization role
20
+ //
21
+ // @Summary Upsert a custom organization role
22
+ // @ID upsert-a-custom-organization-role
23
+ // @Security CoderSessionToken
24
+ // @Produce json
25
+ // @Param organization path string true "Organization ID" format(uuid)
26
+ // @Tags Members
27
+ // @Success 200 {array} codersdk.Role
28
+ // @Router /organizations/{organization}/members/roles [patch]
29
+ func (api * API ) patchOrgRoles (rw http.ResponseWriter , r * http.Request ) {
32
30
var (
33
- db = h .API .Database
34
- auditor = h .API .AGPL .Auditor .Load ()
31
+ ctx = r .Context ()
32
+ db = api .Database
33
+ auditor = api .AGPL .Auditor .Load ()
34
+ organization = httpmw .OrganizationParam (r )
35
35
aReq , commitAudit = audit .InitRequest [database.CustomRole ](rw , & audit.RequestParams {
36
36
Audit : * auditor ,
37
- Log : h . API .Logger ,
37
+ Log : api .Logger ,
38
38
Request : r ,
39
39
Action : database .AuditActionWrite ,
40
- OrganizationID : orgID ,
40
+ OrganizationID : organization . ID ,
41
41
})
42
42
)
43
43
defer commitAudit ()
44
44
45
+ var req codersdk.Role
46
+ if ! httpapi .Read (ctx , rw , r , & req ) {
47
+ return
48
+ }
49
+
45
50
// This check is not ideal, but we cannot enforce a unique role name in the db against
46
51
// the built-in role names.
47
- if rbac .ReservedRoleName (role .Name ) {
52
+ if rbac .ReservedRoleName (req .Name ) {
48
53
httpapi .Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
49
54
Message : "Reserved role name" ,
50
- Detail : fmt .Sprintf ("%q is a reserved role name, and not allowed to be used" , role .Name ),
55
+ Detail : fmt .Sprintf ("%q is a reserved role name, and not allowed to be used" , req .Name ),
51
56
})
52
- return codersdk. Role {}, false
57
+ return
53
58
}
54
59
55
- if err := httpapi .NameValid (role .Name ); err != nil {
60
+ if err := httpapi .NameValid (req .Name ); err != nil {
56
61
httpapi .Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
57
62
Message : "Invalid role name" ,
58
63
Detail : err .Error (),
59
64
})
60
- return codersdk. Role {}, false
65
+ return
61
66
}
62
67
63
68
// Only organization permissions are allowed to be granted
64
- if len (role .SitePermissions ) > 0 {
69
+ if len (req .SitePermissions ) > 0 {
65
70
httpapi .Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
66
71
Message : "Invalid request, not allowed to assign site wide permissions for an organization role." ,
67
72
Detail : "organization scoped roles may not contain site wide permissions" ,
68
73
})
69
- return codersdk. Role {}, false
74
+ return
70
75
}
71
76
72
- if len (role .UserPermissions ) > 0 {
77
+ if len (req .UserPermissions ) > 0 {
73
78
httpapi .Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
74
79
Message : "Invalid request, not allowed to assign user permissions for an organization role." ,
75
80
Detail : "organization scoped roles may not contain user permissions" ,
76
81
})
77
- return codersdk. Role {}, false
82
+ return
78
83
}
79
84
80
- if role .OrganizationID != orgID .String () {
85
+ if req .OrganizationID != organization . ID .String () {
81
86
httpapi .Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
82
87
Message : "Invalid request, organization in role and url must match" ,
83
- Detail : fmt .Sprintf ("role organization=%q does not match URL=%q" , role .OrganizationID , orgID .String ()),
88
+ Detail : fmt .Sprintf ("role organization=%q does not match URL=%q" , req .OrganizationID , organization . ID .String ()),
84
89
})
85
- return codersdk. Role {}, false
90
+ return
86
91
}
87
92
88
93
originalRoles , err := db .CustomRoles (ctx , database.CustomRolesParams {
89
94
LookupRoles : []database.NameOrganizationPair {
90
95
{
91
- Name : role .Name ,
92
- OrganizationID : orgID ,
96
+ Name : req .Name ,
97
+ OrganizationID : organization . ID ,
93
98
},
94
99
},
95
100
ExcludeOrgRoles : false ,
96
- OrganizationID : orgID ,
101
+ OrganizationID : organization . ID ,
97
102
})
98
103
// If it is a 404 (not found) error, ignore it.
99
104
if err != nil && ! httpapi .Is404Error (err ) {
100
105
httpapi .InternalServerError (rw , err )
101
- return codersdk. Role {}, false
106
+ return
102
107
}
103
108
if len (originalRoles ) == 1 {
104
109
// For auditing changes to a role.
105
110
aReq .Old = originalRoles [0 ]
106
111
}
107
112
108
113
inserted , err := db .UpsertCustomRole (ctx , database.UpsertCustomRoleParams {
109
- Name : role .Name ,
110
- DisplayName : role .DisplayName ,
114
+ Name : req .Name ,
115
+ DisplayName : req .DisplayName ,
111
116
OrganizationID : uuid.NullUUID {
112
- UUID : orgID ,
117
+ UUID : organization . ID ,
113
118
Valid : true ,
114
119
},
115
- SitePermissions : db2sdk .List (role .SitePermissions , sdkPermissionToDB ),
116
- OrgPermissions : db2sdk .List (role .OrganizationPermissions , sdkPermissionToDB ),
117
- UserPermissions : db2sdk .List (role .UserPermissions , sdkPermissionToDB ),
120
+ SitePermissions : db2sdk .List (req .SitePermissions , sdkPermissionToDB ),
121
+ OrgPermissions : db2sdk .List (req .OrganizationPermissions , sdkPermissionToDB ),
122
+ UserPermissions : db2sdk .List (req .UserPermissions , sdkPermissionToDB ),
118
123
})
119
124
if httpapi .Is404Error (err ) {
120
125
httpapi .ResourceNotFound (rw )
121
- return codersdk. Role {}, false
126
+ return
122
127
}
123
128
if err != nil {
124
129
httpapi .Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
125
130
Message : "Failed to update role permissions" ,
126
131
Detail : err .Error (),
127
132
})
128
- return codersdk. Role {}, false
133
+ return
129
134
}
130
135
aReq .New = inserted
131
136
132
- return db2sdk .Role (inserted ), true
137
+ httpapi . Write ( ctx , rw , http . StatusOK , db2sdk .Role (inserted ))
133
138
}
134
139
135
140
func sdkPermissionToDB (p codersdk.Permission ) database.CustomRolePermission {
0 commit comments