mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: set groupsync to use default org (#12146)
* fix: assign new oauth users to default org This is not a final solution, as we eventually want to be able to map to different orgs. This makes it so multi-org does not break oauth/oidc.
This commit is contained in:
@@ -793,16 +793,6 @@ func (q *querier) DeleteGroupMemberFromGroup(ctx context.Context, arg database.D
|
||||
return update(q.log, q.auth, fetch, q.db.DeleteGroupMemberFromGroup)(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) DeleteGroupMembersByOrgAndUser(ctx context.Context, arg database.DeleteGroupMembersByOrgAndUserParams) error {
|
||||
// This will remove the user from all groups in the org. This counts as updating a group.
|
||||
// NOTE: instead of fetching all groups in the org with arg.UserID as a member, we instead
|
||||
// check if the caller has permission to update any group in the org.
|
||||
fetch := func(ctx context.Context, arg database.DeleteGroupMembersByOrgAndUserParams) (rbac.Objecter, error) {
|
||||
return rbac.ResourceGroup.InOrg(arg.OrganizationID), nil
|
||||
}
|
||||
return update(q.log, q.auth, fetch, q.db.DeleteGroupMembersByOrgAndUser)(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) DeleteLicense(ctx context.Context, id int32) (int32, error) {
|
||||
err := deleteQ(q.log, q.auth, q.db.GetLicenseByID, func(ctx context.Context, id int32) error {
|
||||
_, err := q.db.DeleteLicense(ctx, id)
|
||||
@@ -2555,6 +2545,14 @@ func (q *querier) RegisterWorkspaceProxy(ctx context.Context, arg database.Regis
|
||||
return updateWithReturn(q.log, q.auth, fetch, q.db.RegisterWorkspaceProxy)(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) RemoveUserFromAllGroups(ctx context.Context, userID uuid.UUID) error {
|
||||
// This is a system function to clear user groups in group sync.
|
||||
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.RemoveUserFromAllGroups(ctx, userID)
|
||||
}
|
||||
|
||||
func (q *querier) RevokeDBCryptKey(ctx context.Context, activeKeyDigest string) error {
|
||||
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {
|
||||
return err
|
||||
|
||||
@@ -344,17 +344,14 @@ func (s *MethodTestSuite) TestGroup() {
|
||||
GroupNames: slice.New(g1.Name, g2.Name),
|
||||
}).Asserts(rbac.ResourceGroup.InOrg(o.ID), rbac.ActionUpdate).Returns()
|
||||
}))
|
||||
s.Run("DeleteGroupMembersByOrgAndUser", s.Subtest(func(db database.Store, check *expects) {
|
||||
s.Run("RemoveUserFromAllGroups", s.Subtest(func(db database.Store, check *expects) {
|
||||
o := dbgen.Organization(s.T(), db, database.Organization{})
|
||||
u1 := dbgen.User(s.T(), db, database.User{})
|
||||
g1 := dbgen.Group(s.T(), db, database.Group{OrganizationID: o.ID})
|
||||
g2 := dbgen.Group(s.T(), db, database.Group{OrganizationID: o.ID})
|
||||
_ = dbgen.GroupMember(s.T(), db, database.GroupMember{GroupID: g1.ID, UserID: u1.ID})
|
||||
_ = dbgen.GroupMember(s.T(), db, database.GroupMember{GroupID: g2.ID, UserID: u1.ID})
|
||||
check.Args(database.DeleteGroupMembersByOrgAndUserParams{
|
||||
OrganizationID: o.ID,
|
||||
UserID: u1.ID,
|
||||
}).Asserts(rbac.ResourceGroup.InOrg(o.ID), rbac.ActionUpdate).Returns()
|
||||
check.Args(u1.ID).Asserts(rbac.ResourceSystem, rbac.ActionUpdate).Returns()
|
||||
}))
|
||||
s.Run("UpdateGroupByID", s.Subtest(func(db database.Store, check *expects) {
|
||||
g := dbgen.Group(s.T(), db, database.Group{})
|
||||
|
||||
@@ -1135,36 +1135,6 @@ func (q *FakeQuerier) DeleteGroupMemberFromGroup(_ context.Context, arg database
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) DeleteGroupMembersByOrgAndUser(_ context.Context, arg database.DeleteGroupMembersByOrgAndUserParams) error {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
newMembers := q.groupMembers[:0]
|
||||
for _, member := range q.groupMembers {
|
||||
if member.UserID != arg.UserID {
|
||||
// Do not delete the other members
|
||||
newMembers = append(newMembers, member)
|
||||
} else if member.UserID == arg.UserID {
|
||||
// We only want to delete from groups in the organization in the args.
|
||||
for _, group := range q.groups {
|
||||
// Find the group that the member is apartof.
|
||||
if group.ID == member.GroupID {
|
||||
// Only add back the member if the organization ID does not match
|
||||
// the arg organization ID. Since the arg is saying which
|
||||
// org to delete.
|
||||
if group.OrganizationID != arg.OrganizationID {
|
||||
newMembers = append(newMembers, member)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
q.groupMembers = newMembers
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) DeleteLicense(_ context.Context, id int32) (int32, error) {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
@@ -6096,6 +6066,22 @@ func (q *FakeQuerier) RegisterWorkspaceProxy(_ context.Context, arg database.Reg
|
||||
return database.WorkspaceProxy{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) RemoveUserFromAllGroups(_ context.Context, userID uuid.UUID) error {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
newMembers := q.groupMembers[:0]
|
||||
for _, member := range q.groupMembers {
|
||||
if member.UserID == userID {
|
||||
continue
|
||||
}
|
||||
newMembers = append(newMembers, member)
|
||||
}
|
||||
q.groupMembers = newMembers
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) RevokeDBCryptKey(_ context.Context, activeKeyDigest string) error {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
@@ -211,13 +211,6 @@ func (m metricsStore) DeleteGroupMemberFromGroup(ctx context.Context, arg databa
|
||||
return err
|
||||
}
|
||||
|
||||
func (m metricsStore) DeleteGroupMembersByOrgAndUser(ctx context.Context, arg database.DeleteGroupMembersByOrgAndUserParams) error {
|
||||
start := time.Now()
|
||||
err := m.s.DeleteGroupMembersByOrgAndUser(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("DeleteGroupMembersByOrgAndUser").Observe(time.Since(start).Seconds())
|
||||
return err
|
||||
}
|
||||
|
||||
func (m metricsStore) DeleteLicense(ctx context.Context, id int32) (int32, error) {
|
||||
start := time.Now()
|
||||
licenseID, err := m.s.DeleteLicense(ctx, id)
|
||||
@@ -1642,6 +1635,13 @@ func (m metricsStore) RegisterWorkspaceProxy(ctx context.Context, arg database.R
|
||||
return proxy, err
|
||||
}
|
||||
|
||||
func (m metricsStore) RemoveUserFromAllGroups(ctx context.Context, userID uuid.UUID) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.RemoveUserFromAllGroups(ctx, userID)
|
||||
m.queryLatencies.WithLabelValues("RemoveUserFromAllGroups").Observe(time.Since(start).Seconds())
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m metricsStore) RevokeDBCryptKey(ctx context.Context, activeKeyDigest string) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.RevokeDBCryptKey(ctx, activeKeyDigest)
|
||||
|
||||
@@ -313,20 +313,6 @@ func (mr *MockStoreMockRecorder) DeleteGroupMemberFromGroup(arg0, arg1 any) *gom
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteGroupMemberFromGroup", reflect.TypeOf((*MockStore)(nil).DeleteGroupMemberFromGroup), arg0, arg1)
|
||||
}
|
||||
|
||||
// DeleteGroupMembersByOrgAndUser mocks base method.
|
||||
func (m *MockStore) DeleteGroupMembersByOrgAndUser(arg0 context.Context, arg1 database.DeleteGroupMembersByOrgAndUserParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DeleteGroupMembersByOrgAndUser", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DeleteGroupMembersByOrgAndUser indicates an expected call of DeleteGroupMembersByOrgAndUser.
|
||||
func (mr *MockStoreMockRecorder) DeleteGroupMembersByOrgAndUser(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteGroupMembersByOrgAndUser", reflect.TypeOf((*MockStore)(nil).DeleteGroupMembersByOrgAndUser), arg0, arg1)
|
||||
}
|
||||
|
||||
// DeleteLicense mocks base method.
|
||||
func (m *MockStore) DeleteLicense(arg0 context.Context, arg1 int32) (int32, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -3470,6 +3456,20 @@ func (mr *MockStoreMockRecorder) RegisterWorkspaceProxy(arg0, arg1 any) *gomock.
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterWorkspaceProxy", reflect.TypeOf((*MockStore)(nil).RegisterWorkspaceProxy), arg0, arg1)
|
||||
}
|
||||
|
||||
// RemoveUserFromAllGroups mocks base method.
|
||||
func (m *MockStore) RemoveUserFromAllGroups(arg0 context.Context, arg1 uuid.UUID) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RemoveUserFromAllGroups", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// RemoveUserFromAllGroups indicates an expected call of RemoveUserFromAllGroups.
|
||||
func (mr *MockStoreMockRecorder) RemoveUserFromAllGroups(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveUserFromAllGroups", reflect.TypeOf((*MockStore)(nil).RemoveUserFromAllGroups), arg0, arg1)
|
||||
}
|
||||
|
||||
// RevokeDBCryptKey mocks base method.
|
||||
func (m *MockStore) RevokeDBCryptKey(arg0 context.Context, arg1 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
@@ -58,7 +58,6 @@ type sqlcQuerier interface {
|
||||
DeleteGitSSHKey(ctx context.Context, userID uuid.UUID) error
|
||||
DeleteGroupByID(ctx context.Context, id uuid.UUID) error
|
||||
DeleteGroupMemberFromGroup(ctx context.Context, arg DeleteGroupMemberFromGroupParams) error
|
||||
DeleteGroupMembersByOrgAndUser(ctx context.Context, arg DeleteGroupMembersByOrgAndUserParams) error
|
||||
DeleteLicense(ctx context.Context, id int32) (int32, error)
|
||||
DeleteOAuth2ProviderAppByID(ctx context.Context, id uuid.UUID) error
|
||||
DeleteOAuth2ProviderAppSecretByID(ctx context.Context, id uuid.UUID) error
|
||||
@@ -322,6 +321,7 @@ type sqlcQuerier interface {
|
||||
InsertWorkspaceResourceMetadata(ctx context.Context, arg InsertWorkspaceResourceMetadataParams) ([]WorkspaceResourceMetadatum, error)
|
||||
ListWorkspaceAgentPortShares(ctx context.Context, workspaceID uuid.UUID) ([]WorkspaceAgentPortShare, error)
|
||||
RegisterWorkspaceProxy(ctx context.Context, arg RegisterWorkspaceProxyParams) (WorkspaceProxy, error)
|
||||
RemoveUserFromAllGroups(ctx context.Context, userID uuid.UUID) error
|
||||
RevokeDBCryptKey(ctx context.Context, activeKeyDigest string) error
|
||||
// Non blocking lock. Returns true if the lock was acquired, false otherwise.
|
||||
//
|
||||
|
||||
@@ -1288,24 +1288,6 @@ func (q *sqlQuerier) DeleteGroupMemberFromGroup(ctx context.Context, arg DeleteG
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteGroupMembersByOrgAndUser = `-- name: DeleteGroupMembersByOrgAndUser :exec
|
||||
DELETE FROM
|
||||
group_members
|
||||
WHERE
|
||||
group_members.user_id = $1
|
||||
AND group_id = ANY(SELECT id FROM groups WHERE organization_id = $2)
|
||||
`
|
||||
|
||||
type DeleteGroupMembersByOrgAndUserParams struct {
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) DeleteGroupMembersByOrgAndUser(ctx context.Context, arg DeleteGroupMembersByOrgAndUserParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteGroupMembersByOrgAndUser, arg.UserID, arg.OrganizationID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getGroupMembers = `-- name: GetGroupMembers :many
|
||||
SELECT
|
||||
users.id, users.email, users.username, users.hashed_password, users.created_at, users.updated_at, users.status, users.rbac_roles, users.login_type, users.avatar_url, users.deleted, users.last_seen_at, users.quiet_hours_schedule, users.theme_preference, users.name
|
||||
@@ -1419,6 +1401,18 @@ func (q *sqlQuerier) InsertUserGroupsByName(ctx context.Context, arg InsertUserG
|
||||
return err
|
||||
}
|
||||
|
||||
const removeUserFromAllGroups = `-- name: RemoveUserFromAllGroups :exec
|
||||
DELETE FROM
|
||||
group_members
|
||||
WHERE
|
||||
user_id = $1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) RemoveUserFromAllGroups(ctx context.Context, userID uuid.UUID) error {
|
||||
_, err := q.db.ExecContext(ctx, removeUserFromAllGroups, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteGroupByID = `-- name: DeleteGroupByID :exec
|
||||
DELETE FROM
|
||||
groups
|
||||
|
||||
@@ -42,12 +42,11 @@ SELECT
|
||||
FROM
|
||||
groups;
|
||||
|
||||
-- name: DeleteGroupMembersByOrgAndUser :exec
|
||||
-- name: RemoveUserFromAllGroups :exec
|
||||
DELETE FROM
|
||||
group_members
|
||||
WHERE
|
||||
group_members.user_id = @user_id
|
||||
AND group_id = ANY(SELECT id FROM groups WHERE organization_id = @organization_id);
|
||||
user_id = @user_id;
|
||||
|
||||
-- name: InsertGroupMember :exec
|
||||
INSERT INTO
|
||||
|
||||
Reference in New Issue
Block a user