Skip to content

feat(enterprise/coderd): allow system users to be added to groups #18341

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Aug 8, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
revert broken query changes
  • Loading branch information
SasSwart committed Aug 4, 2025
commit 8204ec2c30f581e57e665a368013207b7972ba11
18 changes: 15 additions & 3 deletions coderd/database/queries/groupmembers.sql
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
-- name: GetGroupMembers :many
SELECT * FROM group_members_expanded
WHERE (@include_system::bool OR NOT user_is_system);
WHERE CASE
WHEN @include_system::bool THEN TRUE
ELSE
user_is_system = false
END;

-- name: GetGroupMembersByGroupID :many
SELECT *
FROM group_members_expanded
WHERE group_id = @group_id
-- Filter by system type
AND (@include_system::bool OR NOT user_is_system);
AND CASE
WHEN @include_system::bool THEN TRUE
ELSE
user_is_system = false
END;

-- name: GetGroupMembersCountByGroupID :one
-- Returns the total count of members in a group. Shows the total
Expand All @@ -17,7 +25,11 @@ SELECT COUNT(*)
FROM group_members_expanded
WHERE group_id = @group_id
-- Filter by system type
AND (@include_system::bool OR NOT user_is_system);
AND CASE
WHEN @include_system::bool THEN TRUE
ELSE
user_is_system = false
END;

-- InsertUserGroupsByName adds a user to all provided groups, if they exist.
-- name: InsertUserGroupsByName :exec
Expand Down
8 changes: 6 additions & 2 deletions coderd/database/queries/organizationmembers.sql
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ WHERE
ELSE true
END
-- Filter by system type
AND (@include_system::bool OR NOT is_system);
AND CASE
WHEN @include_system::bool THEN TRUE
ELSE
is_system = false
END;

-- name: InsertOrganizationMember :one
INSERT INTO
Expand Down Expand Up @@ -86,7 +90,7 @@ WHERE
ELSE true
END
-- Filter by system type
AND (@include_system::bool OR NOT is_system)
AND CASE WHEN @include_system::bool THEN TRUE ELSE is_system = false END
ORDER BY
-- Deterministic and consistent ordering of all users. This is to ensure consistent pagination.
LOWER(username) ASC OFFSET @offset_opt
Expand Down
12 changes: 8 additions & 4 deletions coderd/database/queries/users.sql
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ FROM
users
WHERE
deleted = false
AND (@include_system::bool OR NOT is_system);
AND CASE WHEN @include_system::bool THEN TRUE ELSE is_system = false END;

-- name: GetActiveUserCount :one
SELECT
Expand All @@ -58,7 +58,7 @@ FROM
users
WHERE
status = 'active'::user_status AND deleted = false
AND (@include_system::bool OR NOT is_system);
AND CASE WHEN @include_system::bool THEN TRUE ELSE is_system = false END;

-- name: InsertUser :one
INSERT INTO
Expand Down Expand Up @@ -250,7 +250,11 @@ WHERE
created_at >= @created_after
ELSE true
END
AND (@include_system::bool OR NOT is_system)
AND CASE
WHEN @include_system::bool THEN TRUE
ELSE
is_system = false
END
AND CASE
WHEN @github_com_user_id :: bigint != 0 THEN
github_com_user_id = @github_com_user_id
Expand Down Expand Up @@ -360,7 +364,7 @@ RETURNING id, email, username, last_seen_at;
-- AllUserIDs returns all UserIDs regardless of user status or deletion.
-- name: AllUserIDs :many
SELECT DISTINCT id FROM USERS
WHERE (@include_system::bool OR NOT is_system);
WHERE CASE WHEN @include_system::bool THEN TRUE ELSE is_system = false END;

-- name: UpdateUserHashedOneTimePasscode :exec
UPDATE
Expand Down
10 changes: 5 additions & 5 deletions enterprise/coderd/prebuilds/membership.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,23 @@ func (s StoreMembershipReconciler) ReconcileAll(ctx context.Context, userID uuid
return xerrors.Errorf("determine prebuild organization membership: %w", err)
}

orgMemberShips := make(map[uuid.UUID]struct{}, 0)
orgMemberships := make(map[uuid.UUID]struct{}, 0)
defaultOrg, err := s.store.GetDefaultOrganization(ctx)
if err != nil {
return xerrors.Errorf("get default organization: %w", err)
}
orgMemberShips[defaultOrg.ID] = struct{}{}
orgMemberships[defaultOrg.ID] = struct{}{}
for _, o := range organizationMemberships {
orgMemberShips[o.ID] = struct{}{}
orgMemberships[o.ID] = struct{}{}
}

var membershipInsertionErrors error
for _, preset := range presets {
_, alreadyOrgMember := orgMemberShips[preset.OrganizationID]
_, alreadyOrgMember := orgMemberships[preset.OrganizationID]
if !alreadyOrgMember {
// Add the organization to our list of memberships regardless of potential failure below
// to avoid a retry that will probably be doomed anyway.
orgMemberShips[preset.OrganizationID] = struct{}{}
orgMemberships[preset.OrganizationID] = struct{}{}

// Insert the missing membership
_, err = s.store.InsertOrganizationMember(ctx, database.InsertOrganizationMemberParams{
Expand Down
3 changes: 1 addition & 2 deletions enterprise/coderd/workspacequota_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,11 +481,10 @@ func TestWorkspaceQuota(t *testing.T) {
coderdtest.AwaitTemplateVersionJobCompleted(t, client, versionZeroCost.ID)
templateZeroCost := coderdtest.CreateTemplate(t, client, user.OrganizationID, versionZeroCost.ID)

// Even with zero cost, should pass
// Workspace with zero cost should pass
workspaceZeroCost := coderdtest.CreateWorkspace(t, client, templateZeroCost.ID)
buildZeroCost := coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspaceZeroCost.LatestBuild.ID)

// Verify the build failed due to quota
require.Equal(t, codersdk.WorkspaceStatusRunning, buildZeroCost.Status)
require.Empty(t, buildZeroCost.Job.Error)

Expand Down
Loading