Skip to content

Commit 205c36c

Browse files
committed
add support for private templates
1 parent 072b3e4 commit 205c36c

File tree

14 files changed

+160
-32
lines changed

14 files changed

+160
-32
lines changed

coderd/database/databasefake/databasefake.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,7 @@ func (q *fakeQuerier) UpdateTemplateMetaByID(_ context.Context, arg database.Upd
970970
tpl.Icon = arg.Icon
971971
tpl.MaxTtl = arg.MaxTtl
972972
tpl.MinAutostartInterval = arg.MinAutostartInterval
973+
tpl.IsPrivate = arg.IsPrivate
973974
q.templates[idx] = tpl
974975
return tpl, nil
975976
}
@@ -1670,6 +1671,7 @@ func (q *fakeQuerier) InsertTemplate(_ context.Context, arg database.InsertTempl
16701671
MaxTtl: arg.MaxTtl,
16711672
MinAutostartInterval: arg.MinAutostartInterval,
16721673
CreatedBy: arg.CreatedBy,
1674+
IsPrivate: arg.IsPrivate,
16731675
}
16741676
template = template.SetUserACL(database.UserACL{})
16751677
q.templates = append(q.templates, template)

coderd/database/dump.sql

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
BEGIN;
22

33
ALTER TABLE templates DROP COLUMN user_acl;
4+
ALTER TABLE templates DROP COLUMN is_private;
45
DROP TYPE template_role;
56

67
COMMIT;

coderd/database/migrations/000050_template_acl.up.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
BEGIN;
22

33
ALTER TABLE templates ADD COLUMN user_acl jsonb NOT NULL default '{}';
4+
ALTER TABLE templates ADD COLUMN is_private boolean NOT NULL default 'false';
45

56
CREATE TYPE template_role AS ENUM (
67
'read',

coderd/database/modelmethods.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,16 @@ func templateRoleToActions(t TemplateRole) []rbac.Action {
5757
}
5858

5959
func (t Template) RBACObject() rbac.Object {
60-
return rbac.ResourceTemplate.InOrg(t.OrganizationID).WithACLUserList(t.UserACL().Actions())
60+
obj := rbac.ResourceTemplate
61+
if t.IsPrivate {
62+
obj = rbac.ResourceTemplatePrivate
63+
}
64+
return obj.InOrg(t.OrganizationID).WithACLUserList(t.UserACL().Actions())
6165
}
6266

63-
func (t TemplateVersion) RBACObject(template Template) rbac.Object {
67+
func (TemplateVersion) RBACObject(template Template) rbac.Object {
6468
// Just use the parent template resource for controlling versions
65-
return rbac.ResourceTemplate.InOrg(t.OrganizationID).WithACLUserList(template.UserACL().Actions())
69+
return template.RBACObject()
6670
}
6771

6872
func (w Workspace) RBACObject() rbac.Object {

coderd/database/models.go

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

coderd/database/queries.sql.go

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

coderd/database/queries/templates.sql

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@ INSERT INTO
6868
max_ttl,
6969
min_autostart_interval,
7070
created_by,
71-
icon
71+
icon,
72+
is_private
7273
)
7374
VALUES
74-
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING *;
75+
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING *;
7576

7677
-- name: UpdateTemplateActiveVersionByID :exec
7778
UPDATE
@@ -100,7 +101,8 @@ SET
100101
max_ttl = $4,
101102
min_autostart_interval = $5,
102103
name = $6,
103-
icon = $7
104+
icon = $7,
105+
is_private = $8
104106
WHERE
105107
id = $1
106108
RETURNING

coderd/rbac/builtin.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ var (
108108
Name: templateAdmin,
109109
DisplayName: "Template Admin",
110110
Site: permissions(map[string][]Action{
111-
ResourceTemplate.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
111+
ResourceTemplate.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
112+
ResourceTemplatePrivate.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
112113
// CRUD all files, even those they did not upload.
113114
ResourceFile.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
114115
ResourceWorkspace.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
@@ -167,11 +168,21 @@ var (
167168
ResourceType: ResourceOrganization.Type,
168169
Action: ActionRead,
169170
},
171+
{
172+
// All org members can read templates in the org
173+
ResourceType: ResourceTemplate.Type,
174+
Action: ActionRead,
175+
},
170176
{
171177
// Can read available roles.
172178
ResourceType: ResourceOrgRoleAssignment.Type,
173179
Action: ActionRead,
174180
},
181+
{
182+
// Can read public templates.
183+
ResourceType: ResourceTemplate.Type,
184+
Action: ActionRead,
185+
},
175186
},
176187
},
177188
}

coderd/rbac/object.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ var (
4545
Type: "template",
4646
}
4747

48+
ResourceTemplatePrivate = Object{
49+
Type: "template_private",
50+
}
51+
4852
ResourceFile = Object{
4953
Type: "file",
5054
}

coderd/templates.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
257257
MaxTtl: int64(maxTTL),
258258
MinAutostartInterval: int64(minAutostartInterval),
259259
CreatedBy: apiKey.UserID,
260+
IsPrivate: createTemplate.IsPrivate,
260261
})
261262
if err != nil {
262263
return xerrors.Errorf("insert template: %s", err)
@@ -457,10 +458,8 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
457458

458459
// Only users who are able to create templates (aka template admins)
459460
// are able to control user permissions.
460-
// TODO: It might be cleaner to control template perms access
461-
// via a separate RBAC resource, and restrict all actions to the template
462-
// admin role.
463-
if len(req.UserPerms) > 0 && !api.Authorize(r, rbac.ActionCreate, template) {
461+
if (len(req.UserPerms) > 0 || req.IsPrivate != nil) &&
462+
!api.Authorize(r, rbac.ActionCreate, template) {
464463
httpapi.ResourceNotFound(rw)
465464
return
466465
}
@@ -525,7 +524,8 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
525524
req.Icon == template.Icon &&
526525
req.MaxTTLMillis == time.Duration(template.MaxTtl).Milliseconds() &&
527526
req.MinAutostartIntervalMillis == time.Duration(template.MinAutostartInterval).Milliseconds() &&
528-
len(req.UserPerms) == 0 {
527+
len(req.UserPerms) == 0 &&
528+
(req.IsPrivate == nil || req.IsPrivate != nil && *req.IsPrivate == template.IsPrivate) {
529529
return nil
530530
}
531531

@@ -535,6 +535,7 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
535535
icon := req.Icon
536536
maxTTL := time.Duration(req.MaxTTLMillis) * time.Millisecond
537537
minAutostartInterval := time.Duration(req.MinAutostartIntervalMillis) * time.Millisecond
538+
isPrivate := template.IsPrivate
538539

539540
if name == "" {
540541
name = template.Name
@@ -545,6 +546,9 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
545546
if minAutostartInterval == 0 {
546547
minAutostartInterval = time.Duration(template.MinAutostartInterval)
547548
}
549+
if req.IsPrivate != nil {
550+
isPrivate = *req.IsPrivate
551+
}
548552

549553
if len(req.UserPerms) > 0 {
550554
userACL := template.UserACL()
@@ -572,6 +576,7 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
572576
Icon: icon,
573577
MaxTtl: int64(maxTTL),
574578
MinAutostartInterval: int64(minAutostartInterval),
579+
IsPrivate: isPrivate,
575580
})
576581
if err != nil {
577582
return err
@@ -819,6 +824,7 @@ func (api *API) convertTemplate(
819824
CreatedByID: template.CreatedBy,
820825
CreatedByName: createdByName,
821826
UserRoles: convertTemplateACL(template.UserACL()),
827+
IsPrivate: template.IsPrivate,
822828
}
823829
}
824830

0 commit comments

Comments
 (0)