@@ -23,6 +23,7 @@ import (
2323 "golang.org/x/xerrors"
2424
2525 "github.com/coder/coder/v2/coderd/notifications/types"
26+ "github.com/coder/coder/v2/coderd/prebuilds"
2627
2728 "github.com/coder/coder/v2/coderd/database"
2829 "github.com/coder/coder/v2/coderd/database/dbtime"
@@ -154,6 +155,22 @@ func New() database.Store {
154155 panic (xerrors .Errorf ("failed to create psk provisioner key: %w" , err ))
155156 }
156157
158+ q .mutex .Lock ()
159+ // We can't insert this user using the interface, because it's a system user.
160+ q .data .users = append (q .data .users , database.User {
161+ ID : prebuilds .SystemUserID ,
162+ Email : "prebuilds@coder.com" ,
163+ Username : "prebuilds" ,
164+ CreatedAt : dbtime .Now (),
165+ UpdatedAt : dbtime .Now (),
166+ Status : "active" ,
167+ LoginType : "none" ,
168+ HashedPassword : []byte {},
169+ IsSystem : true ,
170+ Deleted : false ,
171+ })
172+ q .mutex .Unlock ()
173+
157174 return q
158175}
159176
@@ -442,6 +459,7 @@ func convertUsers(users []database.User, count int64) []database.GetUsersRow {
442459 Deleted : u .Deleted ,
443460 LastSeenAt : u .LastSeenAt ,
444461 Count : count ,
462+ IsSystem : u .IsSystem ,
445463 }
446464 }
447465
@@ -1554,11 +1572,16 @@ func (q *FakeQuerier) ActivityBumpWorkspace(ctx context.Context, arg database.Ac
15541572 return sql .ErrNoRows
15551573}
15561574
1557- func (q * FakeQuerier ) AllUserIDs (_ context.Context ) ([]uuid.UUID , error ) {
1575+ // nolint:revive // It's not a control flag, it's a filter.
1576+ func (q * FakeQuerier ) AllUserIDs (_ context.Context , includeSystem bool ) ([]uuid.UUID , error ) {
15581577 q .mutex .RLock ()
15591578 defer q .mutex .RUnlock ()
15601579 userIDs := make ([]uuid.UUID , 0 , len (q .users ))
15611580 for idx := range q .users {
1581+ if ! includeSystem && q .users [idx ].IsSystem {
1582+ continue
1583+ }
1584+
15621585 userIDs = append (userIDs , q .users [idx ].ID )
15631586 }
15641587 return userIDs , nil
@@ -2649,12 +2672,17 @@ func (q *FakeQuerier) GetAPIKeysLastUsedAfter(_ context.Context, after time.Time
26492672 return apiKeys , nil
26502673}
26512674
2652- func (q * FakeQuerier ) GetActiveUserCount (_ context.Context ) (int64 , error ) {
2675+ // nolint:revive // It's not a control flag, it's a filter.
2676+ func (q * FakeQuerier ) GetActiveUserCount (_ context.Context , includeSystem bool ) (int64 , error ) {
26532677 q .mutex .RLock ()
26542678 defer q .mutex .RUnlock ()
26552679
26562680 active := int64 (0 )
26572681 for _ , u := range q .users {
2682+ if ! includeSystem && u .IsSystem {
2683+ continue
2684+ }
2685+
26582686 if u .Status == database .UserStatusActive && ! u .Deleted {
26592687 active ++
26602688 }
@@ -3390,14 +3418,18 @@ func (q *FakeQuerier) GetGroupByOrgAndName(_ context.Context, arg database.GetGr
33903418 return database.Group {}, sql .ErrNoRows
33913419}
33923420
3393- func (q * FakeQuerier ) GetGroupMembers (ctx context.Context ) ([]database.GroupMember , error ) {
3421+ //nolint:revive // It's not a control flag, its a filter
3422+ func (q * FakeQuerier ) GetGroupMembers (ctx context.Context , includeSystem bool ) ([]database.GroupMember , error ) {
33943423 q .mutex .RLock ()
33953424 defer q .mutex .RUnlock ()
33963425
33973426 members := make ([]database.GroupMemberTable , 0 , len (q .groupMembers ))
33983427 members = append (members , q .groupMembers ... )
33993428 for _ , org := range q .organizations {
34003429 for _ , user := range q .users {
3430+ if ! includeSystem && user .IsSystem {
3431+ continue
3432+ }
34013433 members = append (members , database.GroupMemberTable {
34023434 UserID : user .ID ,
34033435 GroupID : org .ID ,
@@ -3420,17 +3452,17 @@ func (q *FakeQuerier) GetGroupMembers(ctx context.Context) ([]database.GroupMemb
34203452 return groupMembers , nil
34213453}
34223454
3423- func (q * FakeQuerier ) GetGroupMembersByGroupID (ctx context.Context , id uuid. UUID ) ([]database.GroupMember , error ) {
3455+ func (q * FakeQuerier ) GetGroupMembersByGroupID (ctx context.Context , arg database. GetGroupMembersByGroupIDParams ) ([]database.GroupMember , error ) {
34243456 q .mutex .RLock ()
34253457 defer q .mutex .RUnlock ()
34263458
3427- if q .isEveryoneGroup (id ) {
3428- return q .getEveryoneGroupMembersNoLock (ctx , id ), nil
3459+ if q .isEveryoneGroup (arg . GroupID ) {
3460+ return q .getEveryoneGroupMembersNoLock (ctx , arg . GroupID ), nil
34293461 }
34303462
34313463 var groupMembers []database.GroupMember
34323464 for _ , member := range q .groupMembers {
3433- if member .GroupID == id {
3465+ if member .GroupID == arg . GroupID {
34343466 groupMember , err := q .getGroupMemberNoLock (ctx , member .UserID , member .GroupID )
34353467 if errors .Is (err , errUserDeleted ) {
34363468 continue
@@ -3445,8 +3477,8 @@ func (q *FakeQuerier) GetGroupMembersByGroupID(ctx context.Context, id uuid.UUID
34453477 return groupMembers , nil
34463478}
34473479
3448- func (q * FakeQuerier ) GetGroupMembersCountByGroupID (ctx context.Context , groupID uuid. UUID ) (int64 , error ) {
3449- users , err := q .GetGroupMembersByGroupID (ctx , groupID )
3480+ func (q * FakeQuerier ) GetGroupMembersCountByGroupID (ctx context.Context , arg database. GetGroupMembersCountByGroupIDParams ) (int64 , error ) {
3481+ users , err := q .GetGroupMembersByGroupID (ctx , database . GetGroupMembersByGroupIDParams ( arg ) )
34503482 if err != nil {
34513483 return 0 , err
34523484 }
@@ -6223,12 +6255,16 @@ func (q *FakeQuerier) GetUserByID(_ context.Context, id uuid.UUID) (database.Use
62236255 return q .getUserByIDNoLock (id )
62246256}
62256257
6226- func (q * FakeQuerier ) GetUserCount (_ context.Context ) (int64 , error ) {
6258+ // nolint:revive // It's not a control flag, it's a filter.
6259+ func (q * FakeQuerier ) GetUserCount (_ context.Context , includeSystem bool ) (int64 , error ) {
62276260 q .mutex .RLock ()
62286261 defer q .mutex .RUnlock ()
62296262
62306263 existing := int64 (0 )
62316264 for _ , u := range q .users {
6265+ if ! includeSystem && u .IsSystem {
6266+ continue
6267+ }
62326268 if ! u .Deleted {
62336269 existing ++
62346270 }
@@ -6580,6 +6616,12 @@ func (q *FakeQuerier) GetUsers(_ context.Context, params database.GetUsersParams
65806616 users = usersFilteredByLastSeen
65816617 }
65826618
6619+ if ! params .IncludeSystem {
6620+ users = slices .DeleteFunc (users , func (u database.User ) bool {
6621+ return u .IsSystem
6622+ })
6623+ }
6624+
65836625 if params .GithubComUserID != 0 {
65846626 usersFilteredByGithubComUserID := make ([]database.User , 0 , len (users ))
65856627 for i , user := range users {
@@ -8933,6 +8975,7 @@ func (q *FakeQuerier) InsertUser(_ context.Context, arg database.InsertUserParam
89338975 Status : status ,
89348976 RBACRoles : arg .RBACRoles ,
89358977 LoginType : arg .LoginType ,
8978+ IsSystem : false ,
89368979 }
89378980 q .users = append (q .users , user )
89388981 sort .Slice (q .users , func (i , j int ) bool {
@@ -10091,7 +10134,7 @@ func (q *FakeQuerier) UpdateInactiveUsersToDormant(_ context.Context, params dat
1009110134
1009210135 var updated []database.UpdateInactiveUsersToDormantRow
1009310136 for index , user := range q .users {
10094- if user .Status == database .UserStatusActive && user .LastSeenAt .Before (params .LastSeenAfter ) {
10137+ if user .Status == database .UserStatusActive && user .LastSeenAt .Before (params .LastSeenAfter ) && ! user . IsSystem {
1009510138 q .users [index ].Status = database .UserStatusDormant
1009610139 q .users [index ].UpdatedAt = params .UpdatedAt
1009710140 updated = append (updated , database.UpdateInactiveUsersToDormantRow {
0 commit comments