8000 chore: add prebuilds system user by dannykopping · Pull Request #16916 · coder/coder · GitHub
[go: up one dir, main page]

Skip to content

chore: add prebuilds system user #16916

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 28 commits into from
Mar 25, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
300e80f
add prebuilds system user database changes and associated changes
SasSwart Mar 12, 2025
b788237
optionally prevent system users from counting to user count
dannykopping Mar 13, 2025
8122595
appease the linter
dannykopping Mar 13, 2025
bfb7c28
add unit test for system user behaviour
dannykopping Mar 13, 2025
6639167
reverting RBAC changes; not relevant here
dannykopping Mar 13, 2025
769ae1d
removing unnecessary changes
dannykopping Mar 13, 2025
e7e9c27
exclude system user db tests from non-linux OSs
dannykopping Mar 13, 2025
3936047
Rename prebuild system user reference
SasSwart Mar 17, 2025
8bdcafb
ensure that users.IsSystem is not nullable
SasSwart Mar 17, 2025
324fde2
Fixes
dannykopping Mar 17, 2025
81d9dfa
Merge remote-tracking branch 'origin/main' into prebuilds-system-user
SasSwart Mar 18, 2025
896c881
renumber migrations
SasSwart Mar 18, 2025
de4fb8a
ensure that system users are filtered and 8000 returned consistently
SasSwart Mar 19, 2025
2751d5b
make -B lint
SasSwart Mar 19, 2025
1042c39
rewrite prebuilds system user tests in our usual style
SasSwart Mar 19, 2025
f9e9d11
add support for prebuilds user to dbmem
SasSwart Mar 19, 2025
7492965
appease the linter
SasSwart Mar 19, 2025
29e2020
add support for the prebuilds system user to dbmem
SasSwart Mar 19, 2025
8c51585
linter
SasSwart Mar 19, 2025
cdc5c71
fix dbmem tests
SasSwart Mar 19, 2025
0d4813a
remove restriction on modifying system users for now
SasSwart Mar 19, 2025
95d70a3
remove system user index
SasSwart Mar 20, 2025
8f1d71c
Merge remote-tracking branch 'origin/main' into prebuilds-system-user
SasSwart Mar 24, 2025
7e009e5
invert tests that check for system user update protection
SasSwart Mar 24, 2025
addd7c6
lint
SasSwart Mar 24, 2025
7a4ef24
Allow TestUpdateSystemUser to run against dbmem
SasSwart Mar 24, 2025
f30ce72
Merge remote-tracking branch 'origin/main' into prebuilds-system-user
SasSwart Mar 25, 2025
5f0ae5e
Renumber migrations
SasSwart Mar 25, 2025
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
ensure that system users are filtered and returned consistently
  • Loading branch information
SasSwart committed Mar 19, 2025
commit de4fb8ac80e3dc8d0815ecc28ce3dda453daaa7b
10 changes: 5 additions & 5 deletions coderd/database/dbauthz/dbauthz.go
Original file line number Diff line number Diff line change
Expand Up @@ -1747,15 +1747,15 @@ func (q *querier) GetGroupMembers(ctx context.Context) ([]database.GroupMember,
return q.db.GetGroupMembers(ctx)
}

func (q *querier) GetGroupMembersByGroupID(ctx context.Context, id uuid.UUID) ([]database.GroupMember, error) {
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.GetGroupMembersByGroupID)(ctx, id)
func (q *querier) GetGroupMembersByGroupID(ctx context.Context, arg database.GetGroupMembersByGroupIDParams) ([]database.GroupMember, error) {
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.GetGroupMembersByGroupID)(ctx, arg)
}

func (q *querier) GetGroupMembersCountByGroupID(ctx context.Context, groupID uuid.UUID) (int64, error) {
if _, err := q.GetGroupByID(ctx, groupID); err != nil { // AuthZ check
func (q *querier) GetGroupMembersCountByGroupID(ctx context.Context, arg database.GetGroupMembersCountByGroupIDParams) (int64, error) {
if _, err := q.GetGroupByID(ctx, arg.GroupID); err != nil { // AuthZ check
return 0, err
}
memberCount, err := q.db.GetGroupMembersCountByGroupID(ctx, groupID)
memberCount, err := q.db.GetGroupMembersCountByGroupID(ctx, arg)
if err != nil {
return 0, err
}
Expand Down
10 changes: 8 additions & 2 deletions coderd/database/dbauthz/dbauthz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,12 +387,18 @@ func (s *MethodTestSuite) TestGroup() {
g := dbgen.Group(s.T(), db, database.Group{})
u := dbgen.User(s.T(), db, database.User{})
gm := dbgen.GroupMember(s.T(), db, database.GroupMemberTable{GroupID: g.ID, UserID: u.ID})
check.Args(g.ID).Asserts(gm, policy.ActionRead)
check.Args(database.GetGroupMembersByGroupIDParams{
GroupID: g.ID,
IncludeSystem: false,
}).Asserts(gm, policy.ActionRead)
}))
s.Run("GetGroupMembersCountByGroupID", s.Subtest(func(db database.Store, check *expects) {
dbtestutil.DisableForeignKeysAndTriggers(s.T(), db)
g := dbgen.Group(s.T(), db, database.Group{})
check.Args(g.ID).Asserts(g, policy.ActionRead)
check.Args(database.GetGroupMembersCountByGroupIDParams{
GroupID: g.ID,
IncludeSystem: false,
}).Asserts(g, policy.ActionRead)
}))
s.Run("GetGroupMembers", s.Subtest(func(db database.Store, check *expects) {
dbtestutil.DisableForeignKeysAndTriggers(s.T(), db)
Expand Down
5 changes: 4 additions & 1 deletion coderd/database/dbauthz/groupsauth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,10 @@ func TestGroupsAuth(t *testing.T) {
require.Error(t, err, "group read")
}

members, err := db.GetGroupMembersByGroupID(actorCtx, group.ID)
members, err := db.GetGroupMembersByGroupID(actorCtx, database.GetGroupMembersByGroupIDParams{
GroupID: group.ID,
IncludeSystem: false,
})
if tc.ReadMembers {
require.NoError(t, err, "member read")
require.Len(t, members, tc.MembersExpected, "member count found does not match")
Expand Down
5 changes: 4 additions & 1 deletion coderd/database/dbgen/dbgen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ func TestGenerator(t *testing.T) {
gm := dbgen.GroupMember(t, db, database.GroupMemberTable{GroupID: g.ID, UserID: u.ID})
exp := []database.GroupMember{gm}

require.Equal(t, exp, must(db.GetGroupMembersByGroupID(context.Background(), g.ID)))
require.Equal(t, exp, must(db.GetGroupMembersByGroupID(context.Background(), database.GetGroupMembersByGroupIDParams{
GroupID: g.ID,
IncludeSystem: false,
})))
})

t.Run("Organization", func(t *testing.T) {
Expand Down
15 changes: 9 additions & 6 deletions coderd/database/dbmem/dbmem.go
Original file line number Diff line number Diff line change
Expand Up @@ -3427,17 +3427,17 @@
return groupMembers, nil
}

func (q *FakeQuerier) GetGroupMembersByGroupID(ctx context.Context, id uuid.UUID) ([]database.GroupMember, error) {
func (q *FakeQuerier) GetGroupMembersByGroupID(ctx context.Context, arg database.GetGroupMembersByGroupIDParams) ([]database.GroupMember, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

if q.isEveryoneGroup(id) {
return q.getEveryoneGroupMembersNoLock(ctx, id), nil
if q.isEveryoneGroup(arg.GroupID) {
return q.getEveryoneGroupMembersNoLock(ctx, arg.GroupID), nil
}

var groupMembers []database.GroupMember
for _, member := range q.groupMembers {
if member.GroupID == id {
if member.GroupID == arg.GroupID {
groupMember, err := q.getGroupMemberNoLock(ctx, member.UserID, member.GroupID)
if errors.Is(err, errUserDeleted) {
continue
Expand All @@ -3452,8 +3452,11 @@
return groupMembers, nil
}

func (q *FakeQuerier) GetGroupMembersCountByGroupID(ctx context.Context, groupID uuid.UUID) (int64, error) {
users, err := q.GetGroupMembersByGroupID(ctx, groupID)
func (q *FakeQuerier) GetGroupMembersCountByGroupID(ctx context.Context, arg database.GetGroupMembersCountByGroupIDParams) (int64, error) {
users, err := q.GetGroupMembersByGroupID(ctx, database.GetGroupMembersByGroupIDParams{

Check failure on line 3456 in coderd/database/dbmem/dbmem.go

View workflow job for this annotation

GitHub Actions / lint

S1016: should convert arg (type github.com/coder/coder/v2/coderd/database.GetGroupMembersCountByGroupIDParams) to github.com/coder/coder/v2/coderd/database.GetGroupMembersByGroupIDParams instead of using struct literal (gosimple)
GroupID: arg.GroupID,
IncludeSystem: arg.IncludeSystem,
})
if err != nil {
return 0, err
}
Expand Down
8 changes: 4 additions & 4 deletions coderd/database/dbmetrics/querymetrics.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions coderd/database/dbmock/dbmock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions coderd/database/dump.sql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions coderd/database/migrations/000302_system_user.down.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
DROP VIEW IF EXISTS group_members_expanded;
CREATE VIEW group_members_expanded AS
WITH all_members AS (
SELECT group_members.user_id,
group_members.group_id
FROM group_members
UNION
SELECT organization_members.user_id,
organization_members.organization_id AS group_id
FROM organization_members
)
SELECT users.id AS user_id,
users.email AS user_email,
users.username AS user_username,
users.hashed_password AS user_hashed_password,
users.created_at AS user_created_at,
users.updated_at AS user_updated_at,
users.status AS user_status,
users.rbac_roles AS user_rbac_roles,
users.login_type AS user_login_type,
users.avatar_url AS user_avatar_url,
users.deleted AS user_deleted,
users.last_seen_at AS user_last_seen_at,
users.quiet_hours_schedule AS user_quiet_hours_schedule,
users.name AS user_name,
users.github_com_user_id AS user_github_com_user_id,
groups.organization_id,
groups.name AS group_name,
all_members.group_id
FROM ((all_members
JOIN users ON ((users.id = all_members.user_id)))
JOIN groups ON ((groups.id = all_members.group_id)))
WHERE (users.deleted = false);

COMMENT ON VIEW group_members_expanded IS 'Joins group members with user information, organization ID, group name. Includes both regular group members and organization members (as part of the "Everyone" group).';

-- Remove system user from organizations
DELETE FROM organization_members
WHERE user_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0';
Expand Down
40 changes: 37 additions & 3 deletions coderd/database/migrations/000302_system_user.up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ CREATE INDEX user_is_system_idx ON users USING btree (is_system);

COMMENT ON COLUMN users.is_system IS 'Determines if a user is a system user, and therefore cannot login or perform normal actions';

-- TODO: tried using "none" for login type, but the migration produced this error: 'unsafe use of new value "none" of enum type login_type'
-- -> not sure why though? it exists on the login_type enum.
INSERT INTO users (id, email, username, name, created_at, updated_at, status, rbac_roles, hashed_password, is_system, login_type)
VALUES ('c42fdf75-3097-471c-8c33-fb52454d81c0', 'prebuilds@system', 'prebuilds', 'Prebuilds Owner', now(), now(),
'active', '{}', 'none', true, 'password'::login_type);
'active', '{}', 'none', true, 'none'::login_type);

-- Create function to check system user modifications
CREATE OR REPLACE FUNCTION prevent_system_user_changes()
Expand Down Expand Up @@ -37,6 +35,42 @@ CREATE TRIGGER prevent_system_user_deletions
WHEN (OLD.is_system = true)
EXECUTE FUNCTION prevent_system_user_changes();

DROP VIEW IF EXISTS group_members_expanded;
CREATE VIEW group_members_expanded AS
WITH all_members AS (
SELECT group_members.user_id,
group_members.group_id
FROM group_members
UNION
SELECT organization_members.user_id,
organization_members.organization_id AS group_id
FROM organization_members
)
SELECT users.id AS user_id,
users.email AS user_email,
users.username AS user_username,
users.hashed_password AS user_hashed_password,
users.created_at AS user_created_at,
users.updated_at AS user_updated_at,
users.status AS user_status,
users.rbac_roles AS user_rbac_roles,
users.login_type AS user_login_type,
users.avatar_url AS user_avatar_url,
users.deleted AS user_deleted,
users.last_seen_at AS user_last_seen_at,
users.quiet_hours_schedule AS user_quiet_hours_schedule,
users.name AS user_name,
users.github_com_user_id AS user_github_com_user_id,
users.is_system AS user_is_system,
groups.organization_id,
groups.name AS group_name,
all_members.group_id
FROM ((all_members
JOIN users ON ((users.id = all_members.user_id)))
JOIN groups ON ((groups.id = all_members.group_id)))
WHERE (users.deleted = false);

COMMENT ON VIEW group_members_expanded IS 'Joins group members with user information, organization ID, group name. Includes both regular group members and organization members (as part of the "Everyone" group).';
-- TODO: do we *want* to use the default org here? how do we handle multi-org?
WITH default_org AS (SELECT id
FROM organizations
Expand Down
1 change: 1 addition & 0 deletions coderd/database/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions coderd/database/querier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion coderd/database/querier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,10 @@ func TestWorkspaceQuotas(t *testing.T) {
})

// Fetch the 'Everyone' group members
everyoneMembers, err := db.GetGroupMembersByGroupID(ctx, org.ID)
everyoneMembers, err := db.GetGroupMembersByGroupID(ctx, database.GetGroupMembersByGroupIDParams{
GroupID: everyoneGroup.ID,
IncludeSystem: false,
})
require.NoError(t, err)

require.ElementsMatch(t, db2sdk.List(everyoneMembers, groupMemberIDs),
Expand Down
Loading
Loading
0