Skip to content

Commit 9aca231

Browse files
committed
Merge remote-tracking branch 'github/main' into asher/show-editable-orgs
2 parents 64631e1 + d6c4d47 commit 9aca231

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1912
-78
lines changed

agent/agent.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -588,10 +588,12 @@ func (a *agent) reportMetadata(ctx context.Context, conn drpc.Conn) error {
588588
updatedMetadata[mr.key] = mr.result
589589
continue
590590
case err := <-reportError:
591-
a.logger.Debug(ctx, "batch update metadata complete", slog.Error(err))
591+
logMsg := "batch update metadata complete"
592592
if err != nil {
593+
a.logger.Debug(ctx, logMsg, slog.Error(err))
593594
return xerrors.Errorf("failed to report metadata: %w", err)
594595
}
596+
a.logger.Debug(ctx, logMsg)
595597
reportInFlight = false
596598
case <-report:
597599
if len(updatedMetadata) == 0 {

cli/testdata/coder_server_--help.golden

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ OPTIONS:
2222
--cache-dir string, $CODER_CACHE_DIRECTORY (default: [cache dir])
2323
The directory to cache temporary files. If unspecified and
2424
$CACHE_DIRECTORY is set, it will be used for compatibility with
25-
systemd.
25+
systemd. This directory is NOT safe to be configured as a shared
26+
directory across coderd/provisionerd replicas.
2627

2728
--disable-owner-workspace-access bool, $CODER_DISABLE_OWNER_WORKSPACE_ACCESS
2829
Remove the permission for the 'owner' role to have workspace execution

cli/testdata/server-config.yaml.golden

+2-1
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,8 @@ updateCheck: false
414414
# (default: <unset>, type: bool)
415415
enableSwagger: false
416416
# The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is
417-
# set, it will be used for compatibility with systemd.
417+
# set, it will be used for compatibility with systemd. This directory is NOT safe
418+
# to be configured as a shared directory across coderd/provisionerd replicas.
418419
# (default: [cache dir], type: string)
419420
cacheDir: [cache dir]
420421
# Controls whether data will be stored in an in-memory database.

coderd/apidoc/docs.go

+45
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

+41
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/autobuild/lifecycle_executor.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"golang.org/x/xerrors"
1414

1515
"cdr.dev/slog"
16+
1617
"github.com/coder/coder/v2/coderd/audit"
1718
"github.com/coder/coder/v2/coderd/database"
1819
"github.com/coder/coder/v2/coderd/database/dbauthz"
@@ -296,10 +297,11 @@ func (e *Executor) runOnce(t time.Time) Stats {
296297

297298
if _, err := e.notificationsEnqueuer.Enqueue(e.ctx, ws.OwnerID, notifications.TemplateWorkspaceAutoUpdated,
298299
map[string]string{
299-
"name": ws.Name,
300-
"initiator": "autobuild",
301-
"reason": nextBuildReason,
302-
"template_version_name": activeTemplateVersion.Name,
300+
"name": ws.Name,
301+
"initiator": "autobuild",
302+
"reason": nextBuildReason,
303+
"template_version_name": activeTemplateVersion.Name,
304+
"template_version_message": activeTemplateVersion.Message,
303305
}, "autobuild",
304306
// Associate this notification with all the related entities.
305307
ws.ID, ws.OwnerID, ws.TemplateID, ws.OrganizationID,

coderd/database/dbauthz/dbauthz.go

+14
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,20 @@ func (q *querier) DeleteCoordinator(ctx context.Context, id uuid.UUID) error {
958958
return q.db.DeleteCoordinator(ctx, id)
959959
}
960960

961+
func (q *querier) DeleteCustomRole(ctx context.Context, arg database.DeleteCustomRoleParams) error {
962+
if arg.OrganizationID.UUID != uuid.Nil {
963+
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceAssignOrgRole.InOrg(arg.OrganizationID.UUID)); err != nil {
964+
return err
965+
}
966+
} else {
967+
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceAssignRole); err != nil {
968+
return err
969+
}
970+
}
971+
972+
return q.db.DeleteCustomRole(ctx, arg)
973+
}
974+
961975
func (q *querier) DeleteExternalAuthLink(ctx context.Context, arg database.DeleteExternalAuthLinkParams) error {
962976
return fetchAndExec(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

+25
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

+29
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,35 @@ func (*FakeQuerier) DeleteCoordinator(context.Context, uuid.UUID) error {
13811381
return ErrUnimplemented
13821382
}
13831383

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

coderd/database/dbmetrics/dbmetrics.go

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmock/dbmock.go

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dump.sql

+24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
UPDATE notification_templates
2+
SET body_template = E'Hi {{.UserName}}\n' ||
3+
E'Your workspace **{{.Labels.name}}** has been updated automatically to the latest template version ({{.Labels.template_version_name}}).'
4+
WHERE id = 'c34a0c09-0704-4cac-bd1c-0c0146811c2b';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
UPDATE notification_templates
2+
SET name = 'Workspace Updated Automatically', -- drive-by fix for capitalization to match other templates
3+
body_template = E'Hi {{.UserName}}\n' ||
4+
E'Your workspace **{{.Labels.name}}** has been updated automatically to the latest template version ({{.Labels.template_version_name}}).\n' ||
5+
E'Reason for update: **{{.Labels.template_version_message}}**' -- include template version message
6+
WHERE id = 'c34a0c09-0704-4cac-bd1c-0c0146811c2b';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DROP TRIGGER IF EXISTS remove_organization_member_custom_role ON custom_roles;
2+
DROP FUNCTION IF EXISTS remove_organization_member_role;
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 REPLACE FUNCTION remove_organization_member_role()
6+
RETURNS TRIGGER AS
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+
IF OLD.organization_id IS 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+
CREATE TRIGGER remove_organization_member_custom_role
28+
BEFORE DELETE ON custom_roles FOR EACH ROW
29+
EXECUTE PROCEDURE remove_organization_member_role();
30+
31+
32+
COMMENT ON 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

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)