Skip to content

Commit 8839537

Browse files
committed
move to org roles
1 parent 52c9813 commit 8839537

File tree

9 files changed

+336
-4
lines changed

9 files changed

+336
-4
lines changed

coderd/apidoc/docs.go

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

coderd/apidoc/swagger.json

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

coderd/coderd.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,8 @@ func New(options *Options) *API {
827827
})
828828
r.Route("/members", func(r chi.Router) {
829829
r.Get("/roles", api.assignableOrgRoles)
830+
r.With(httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentCustomRoles)).
831+
Patch("/roles", api.patchOrgRoles)
830832
r.Route("/{user}", func(r chi.Router) {
831833
r.Use(
832834
httpmw.ExtractOrganizationMemberParam(options.Database),
@@ -1247,6 +1249,8 @@ type API struct {
12471249
// passed to dbauthz.
12481250
AccessControlStore *atomic.Pointer[dbauthz.AccessControlStore]
12491251
PortSharer atomic.Pointer[portsharing.PortSharer]
1252+
// CustomRoleHandler is the AGPL/Enterprise implementation for custom roles.
1253+
CustomRoleHandler atomic.Pointer[CustomRoleHandler]
12501254

12511255
HTTPAuth *HTTPAuthorizer
12521256

coderd/database/queries.sql.go

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

coderd/database/queries/roles.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ INSERT INTO
2323
custom_roles (
2424
name,
2525
display_name,
26+
organization_id,
2627
site_permissions,
2728
org_permissions,
2829
user_permissions,
@@ -33,6 +34,7 @@ VALUES (
3334
-- Always force lowercase names
3435
lower(@name),
3536
@display_name,
37+
@organization_id,
3638
@site_permissions,
3739
@org_permissions,
3840
@user_permissions,

coderd/roles.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package coderd
22

33
import (
4+
"context"
45
"net/http"
56

7+
"github.com/google/uuid"
8+
69
"github.com/coder/coder/v2/coderd/database"
710
"github.com/coder/coder/v2/coderd/database/db2sdk"
811
"github.com/coder/coder/v2/coderd/httpmw"
@@ -14,6 +17,59 @@ import (
1417
"github.com/coder/coder/v2/coderd/rbac"
1518
)
1619

20+
// CustomRoleHandler handles AGPL/Enterprise interface for handling custom
21+
// roles. Ideally only included in the enterprise package, but the routes are
22+
// intermixed.
23+
type CustomRoleHandler interface {
24+
PatchOrganizationRole(ctx context.Context, db database.Store, rw http.ResponseWriter, orgID uuid.UUID, role codersdk.Role) (codersdk.Role, bool)
25+
}
26+
27+
type agplCustomRoleHandler struct{}
28+
29+
func (agplCustomRoleHandler) PatchOrganizationRole(ctx context.Context, db database.Store, rw http.ResponseWriter, orgID uuid.UUID, role codersdk.Role) (codersdk.Role, bool) {
30+
httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{
31+
Message: "Creating and updating custom roles is an Enterprise feature. Contact sales!",
32+
})
33+
return codersdk.Role{}, false
34+
}
35+
36+
// patchRole will allow creating a custom organization role
37+
//
38+
// @Summary Upsert a custom organization role
39+
// @ID upsert-a-custom-organization-role
40+
// @Security CoderSessionToken
41+
// @Produce json
42+
// @Tags Members
43+
// @Success 200 {array} codersdk.Role
44+
// @Router /organizations/{organization}/members/roles [patch]
45+
func (api *API) patchOrgRoles(rw http.ResponseWriter, r *http.Request) {
46+
var (
47+
ctx = r.Context()
48+
handler = *api.CustomRoleHandler.Load()
49+
organization = httpmw.OrganizationParam(r)
50+
)
51+
52+
var req codersdk.Role
53+
if !httpapi.Read(ctx, rw, r, &req) {
54+
return
55+
}
56+
57+
if err := httpapi.NameValid(req.Name); err != nil {
58+
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
59+
Message: "Invalid role name",
60+
Detail: err.Error(),
61+
})
62+
return
63+
}
64+
65+
updated, ok := handler.PatchOrganizationRole(ctx, api.Database, rw, organization.ID, req)
66+
if !ok {
67+
return
68+
}
69+
70+
httpapi.Write(ctx, rw, http.StatusOK, updated)
71+
}
72+
1773
// AssignableSiteRoles returns all site wide roles that can be assigned.
1874
//
1975
// @Summary Get site member roles

codersdk/roles.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type Permission struct {
3535

3636
// Role is a longer form of SlimRole used to edit custom roles.
3737
type Role struct {
38-
Name string `json:"name" table:"name,default_sort"`
38+
Name string `json:"name" table:"name,default_sort" validate:"username"`
3939
DisplayName string `json:"display_name" table:"display_name"`
4040
SitePermissions []Permission `json:"site_permissions" table:"site_permissions"`
4141
// map[<org_id>] -> Permissions

docs/api/members.md

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

0 commit comments

Comments
 (0)