Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2c13797

Browse files
authored
chore: implement deleting custom roles (#14101)
* chore: implement deleting custom roles* add trigger to delete role from organization members on delete* chore: add comments to explain populated field
1 parentd0feb70 commit2c13797

File tree

19 files changed

+627
-2
lines changed

19 files changed

+627
-2
lines changed

‎coderd/apidoc/docs.go

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apidoc/swagger.json

Lines changed: 41 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/dbauthz/dbauthz.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,20 @@ func (q *querier) DeleteCoordinator(ctx context.Context, id uuid.UUID) error {
958958
returnq.db.DeleteCoordinator(ctx,id)
959959
}
960960

961+
func (q*querier)DeleteCustomRole(ctx context.Context,arg database.DeleteCustomRoleParams)error {
962+
ifarg.OrganizationID.UUID!=uuid.Nil {
963+
iferr:=q.authorizeContext(ctx,policy.ActionDelete,rbac.ResourceAssignOrgRole.InOrg(arg.OrganizationID.UUID));err!=nil {
964+
returnerr
965+
}
966+
}else {
967+
iferr:=q.authorizeContext(ctx,policy.ActionDelete,rbac.ResourceAssignRole);err!=nil {
968+
returnerr
969+
}
970+
}
971+
972+
returnq.db.DeleteCustomRole(ctx,arg)
973+
}
974+
961975
func (q*querier)DeleteExternalAuthLink(ctx context.Context,arg database.DeleteExternalAuthLinkParams)error {
962976
returnfetchAndExec(q.log,q.auth,policy.ActionUpdatePersonal,func(ctx context.Context,arg database.DeleteExternalAuthLinkParams) (database.ExternalAuthLink,error) {
963977
//nolint:gosimple

‎coderd/database/dbauthz/dbauthz_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,31 @@ func (s *MethodTestSuite) TestUser() {
12471247
s.Run("CustomRoles",s.Subtest(func(db database.Store,check*expects) {
12481248
check.Args(database.CustomRolesParams{}).Asserts(rbac.ResourceAssignRole,policy.ActionRead).Returns([]database.CustomRole{})
12491249
}))
1250+
s.Run("Organization/DeleteCustomRole",s.Subtest(func(db database.Store,check*expects) {
1251+
customRole:=dbgen.CustomRole(s.T(),db, database.CustomRole{
1252+
OrganizationID: uuid.NullUUID{
1253+
UUID:uuid.New(),
1254+
Valid:true,
1255+
},
1256+
})
1257+
check.Args(database.DeleteCustomRoleParams{
1258+
Name:customRole.Name,
1259+
OrganizationID:customRole.OrganizationID,
1260+
}).Asserts(
1261+
rbac.ResourceAssignOrgRole.InOrg(customRole.OrganizationID.UUID),policy.ActionDelete)
1262+
}))
1263+
s.Run("Site/DeleteCustomRole",s.Subtest(func(db database.Store,check*expects) {
1264+
customRole:=dbgen.CustomRole(s.T(),db, database.CustomRole{
1265+
OrganizationID: uuid.NullUUID{
1266+
UUID:uuid.Nil,
1267+
Valid:false,
1268+
},
1269+
})
1270+
check.Args(database.DeleteCustomRoleParams{
1271+
Name:customRole.Name,
1272+
}).Asserts(
1273+
rbac.ResourceAssignRole,policy.ActionDelete)
1274+
}))
12501275
s.Run("Blank/UpsertCustomRole",s.Subtest(func(db database.Store,check*expects) {
12511276
// Blank is no perms in the role
12521277
check.Args(database.UpsertCustomRoleParams{

‎coderd/database/dbmem/dbmem.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,35 @@ func (*FakeQuerier) DeleteCoordinator(context.Context, uuid.UUID) error {
13811381
returnErrUnimplemented
13821382
}
13831383

1384+
func (q*FakeQuerier)DeleteCustomRole(_ context.Context,arg database.DeleteCustomRoleParams)error {
1385+
err:=validateDatabaseType(arg)
1386+
iferr!=nil {
1387+
returnerr
1388+
}
1389+
1390+
q.mutex.RLock()
1391+
deferq.mutex.RUnlock()
1392+
1393+
initial:=len(q.data.customRoles)
1394+
q.data.customRoles=slices.DeleteFunc(q.data.customRoles,func(role database.CustomRole)bool {
1395+
returnrole.OrganizationID.UUID==arg.OrganizationID.UUID&&role.Name==arg.Name
1396+
})
1397+
ifinitial==len(q.data.customRoles) {
1398+
returnsql.ErrNoRows
1399+
}
1400+
1401+
// Emulate the trigger 'remove_organization_member_custom_role'
1402+
fori,mem:=rangeq.organizationMembers {
1403+
ifmem.OrganizationID==arg.OrganizationID.UUID {
1404+
mem.Roles=slices.DeleteFunc(mem.Roles,func(rolestring)bool {
1405+
returnrole==arg.Name
1406+
})
1407+
q.organizationMembers[i]=mem
1408+
}
1409+
}
1410+
returnnil
1411+
}
1412+
13841413
func (q*FakeQuerier)DeleteExternalAuthLink(_ context.Context,arg database.DeleteExternalAuthLinkParams)error {
13851414
err:=validateDatabaseType(arg)
13861415
iferr!=nil {

‎coderd/database/dbmetrics/dbmetrics.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/dbmock/dbmock.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/dump.sql

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DROPTRIGGER IF EXISTS remove_organization_member_custom_roleON custom_roles;
2+
DROPFUNCTION IF EXISTS remove_organization_member_role;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
-- When a custom role is deleted, we need to remove the assigned role
2+
-- from all organization members that have it.
3+
-- This action cannot be reverted, so deleting a custom role should be
4+
-- done with caution.
5+
CREATE OR REPLACEFUNCTIONremove_organization_member_role()
6+
RETURNS TRIGGERAS
7+
$$
8+
BEGIN
9+
-- Delete the role from all organization members that have it.
10+
-- TODO: When site wide custom roles are supported, if the
11+
--organization_id is null, we should remove the role from the 'users'
12+
--table instead.
13+
IFOLD.organization_idIS NOT NULL THEN
14+
UPDATE organization_members
15+
-- this is a noop if the role is not assigned to the member
16+
SET roles= array_remove(roles,OLD.name)
17+
WHERE
18+
-- Scope to the correct organization
19+
organization_members.organization_id=OLD.organization_id;
20+
END IF;
21+
RETURN OLD;
22+
END;
23+
$$ LANGUAGE plpgsql;
24+
25+
26+
-- Attach the function to deleting the custom role
27+
CREATETRIGGERremove_organization_member_custom_role
28+
BEFOREDELETEON custom_roles FOR EACH ROW
29+
EXECUTE PROCEDURE remove_organization_member_role();
30+
31+
32+
COMMENTON TRIGGER
33+
remove_organization_member_custom_role
34+
ON custom_roles IS
35+
'When a custom_role is deleted, this trigger removes the role from all organization members.';

‎coderd/database/querier.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/queries.sql.go

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/queries/roles.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ WHERE
2525
END
2626
;
2727

28+
-- name: DeleteCustomRole :exec
29+
DELETEFROM
30+
custom_roles
31+
WHERE
32+
name=lower(@name)
33+
AND organization_id= @organization_id
34+
;
2835

2936
-- name: UpsertCustomRole :one
3037
INSERT INTO

‎coderd/httpapi/httpapi.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,24 @@ func Is404Error(err error) bool {
106106
returnfalse
107107
}
108108

109+
// This tests for dbauthz.IsNotAuthorizedError and rbac.IsUnauthorizedError.
110+
ifIsUnauthorizedError(err) {
111+
returntrue
112+
}
113+
returnxerrors.Is(err,sql.ErrNoRows)
114+
}
115+
116+
funcIsUnauthorizedError(errerror)bool {
117+
iferr==nil {
118+
returnfalse
119+
}
120+
109121
// This tests for dbauthz.IsNotAuthorizedError and rbac.IsUnauthorizedError.
110122
varunauthorized httpapiconstraints.IsUnauthorizedError
111123
iferrors.As(err,&unauthorized)&&unauthorized.IsUnauthorized() {
112124
returntrue
113125
}
114-
returnxerrors.Is(err,sql.ErrNoRows)
126+
returnfalse
115127
}
116128

117129
// Convenience error functions don't take contexts since their responses are

‎codersdk/roles.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,20 @@ func (c *Client) PatchOrganizationRole(ctx context.Context, role Role) (Role, er
105105
returnr,json.NewDecoder(res.Body).Decode(&r)
106106
}
107107

108+
// DeleteOrganizationRole will delete a custom organization role
109+
func (c*Client)DeleteOrganizationRole(ctx context.Context,organizationID uuid.UUID,roleNamestring)error {
110+
res,err:=c.Request(ctx,http.MethodDelete,
111+
fmt.Sprintf("/api/v2/organizations/%s/members/roles/%s",organizationID.String(),roleName),nil)
112+
iferr!=nil {
113+
returnerr
114+
}
115+
deferres.Body.Close()
116+
ifres.StatusCode!=http.StatusNoContent {
117+
returnReadBodyAsError(res)
118+
}
119+
returnnil
120+
}
121+
108122
// ListSiteRoles lists all assignable site wide roles.
109123
func (c*Client)ListSiteRoles(ctx context.Context) ([]AssignableRoles,error) {
110124
res,err:=c.Request(ctx,http.MethodGet,"/api/v2/users/roles",nil)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp