mirror of
https://github.com/coder/coder.git
synced 2025-07-13 21:36:50 +00:00
feat: Implied 'member' roles for site and organization (#1917)
* feat: Member roles are implied and never exlpicitly added * Rename "GetAllUserRoles" to "GetAuthorizationRoles" * feat: Add migration to remove implied roles * rename user auth role middleware
This commit is contained in:
@ -276,7 +276,7 @@ func (q *fakeQuerier) GetUsersByIDs(_ context.Context, ids []uuid.UUID) ([]datab
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetAllUserRoles(_ context.Context, userID uuid.UUID) (database.GetAllUserRolesRow, error) {
|
||||
func (q *fakeQuerier) GetAuthorizationUserRoles(_ context.Context, userID uuid.UUID) (database.GetAuthorizationUserRolesRow, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
@ -286,6 +286,7 @@ func (q *fakeQuerier) GetAllUserRoles(_ context.Context, userID uuid.UUID) (data
|
||||
if u.ID == userID {
|
||||
u := u
|
||||
roles = append(roles, u.RBACRoles...)
|
||||
roles = append(roles, "member")
|
||||
user = &u
|
||||
break
|
||||
}
|
||||
@ -294,14 +295,15 @@ func (q *fakeQuerier) GetAllUserRoles(_ context.Context, userID uuid.UUID) (data
|
||||
for _, mem := range q.organizationMembers {
|
||||
if mem.UserID == userID {
|
||||
roles = append(roles, mem.Roles...)
|
||||
roles = append(roles, "organization-member:"+mem.OrganizationID.String())
|
||||
}
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
return database.GetAllUserRolesRow{}, sql.ErrNoRows
|
||||
return database.GetAuthorizationUserRolesRow{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
return database.GetAllUserRolesRow{
|
||||
return database.GetAuthorizationUserRolesRow{
|
||||
ID: userID,
|
||||
Username: user.Username,
|
||||
Status: user.Status,
|
||||
|
11
coderd/database/migrations/000016_drop_member_roles.down.sql
Normal file
11
coderd/database/migrations/000016_drop_member_roles.down.sql
Normal file
@ -0,0 +1,11 @@
|
||||
--- Remove the now implied 'member' role.
|
||||
UPDATE
|
||||
users
|
||||
SET
|
||||
rbac_roles = array_append(rbac_roles, 'member');
|
||||
|
||||
--- Remove the now implied 'organization-member' role.
|
||||
UPDATE
|
||||
organization_members
|
||||
SET
|
||||
roles = array_append(roles, 'organization-member:'||organization_id::text);
|
11
coderd/database/migrations/000016_drop_member_roles.up.sql
Normal file
11
coderd/database/migrations/000016_drop_member_roles.up.sql
Normal file
@ -0,0 +1,11 @@
|
||||
--- Remove the now implied 'member' role.
|
||||
UPDATE
|
||||
users
|
||||
SET
|
||||
rbac_roles = array_remove(rbac_roles, 'member');
|
||||
|
||||
--- Remove the now implied 'organization-member' role.
|
||||
UPDATE
|
||||
organization_members
|
||||
SET
|
||||
roles = array_remove(roles, 'organization-member:'||organization_id::text);
|
@ -22,10 +22,12 @@ type querier interface {
|
||||
DeleteGitSSHKey(ctx context.Context, userID uuid.UUID) error
|
||||
DeleteParameterValueByID(ctx context.Context, id uuid.UUID) error
|
||||
GetAPIKeyByID(ctx context.Context, id string) (APIKey, error)
|
||||
GetAllUserRoles(ctx context.Context, userID uuid.UUID) (GetAllUserRolesRow, error)
|
||||
// GetAuditLogsBefore retrieves `limit` number of audit logs before the provided
|
||||
// ID.
|
||||
GetAuditLogsBefore(ctx context.Context, arg GetAuditLogsBeforeParams) ([]AuditLog, error)
|
||||
// This function returns roles for authorization purposes. Implied member roles
|
||||
// are included.
|
||||
GetAuthorizationUserRoles(ctx context.Context, userID uuid.UUID) (GetAuthorizationUserRolesRow, error)
|
||||
GetFileByHash(ctx context.Context, hash string) (File, error)
|
||||
GetGitSSHKey(ctx context.Context, userID uuid.UUID) (GitSSHKey, error)
|
||||
GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (WorkspaceBuild, error)
|
||||
|
@ -2088,12 +2088,18 @@ func (q *sqlQuerier) UpdateTemplateVersionDescriptionByJobID(ctx context.Context
|
||||
return err
|
||||
}
|
||||
|
||||
const getAllUserRoles = `-- name: GetAllUserRoles :one
|
||||
const getAuthorizationUserRoles = `-- name: GetAuthorizationUserRoles :one
|
||||
SELECT
|
||||
-- username is returned just to help for logging purposes
|
||||
-- status is used to enforce 'suspended' users, as all roles are ignored
|
||||
-- when suspended.
|
||||
id, username, status, array_cat(users.rbac_roles, organization_members.roles) :: text[] AS roles
|
||||
-- username is returned just to help for logging purposes
|
||||
-- status is used to enforce 'suspended' users, as all roles are ignored
|
||||
-- when suspended.
|
||||
id, username, status,
|
||||
array_cat(
|
||||
-- All users are members
|
||||
array_append(users.rbac_roles, 'member'),
|
||||
-- All org_members get the org-member role for their orgs
|
||||
array_append(organization_members.roles, 'organization-member:'||organization_members.organization_id::text)) :: text[]
|
||||
AS roles
|
||||
FROM
|
||||
users
|
||||
LEFT JOIN organization_members
|
||||
@ -2102,16 +2108,18 @@ WHERE
|
||||
id = $1
|
||||
`
|
||||
|
||||
type GetAllUserRolesRow struct {
|
||||
type GetAuthorizationUserRolesRow struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
Username string `db:"username" json:"username"`
|
||||
Status UserStatus `db:"status" json:"status"`
|
||||
Roles []string `db:"roles" json:"roles"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetAllUserRoles(ctx context.Context, userID uuid.UUID) (GetAllUserRolesRow, error) {
|
||||
row := q.db.QueryRowContext(ctx, getAllUserRoles, userID)
|
||||
var i GetAllUserRolesRow
|
||||
// This function returns roles for authorization purposes. Implied member roles
|
||||
// are included.
|
||||
func (q *sqlQuerier) GetAuthorizationUserRoles(ctx context.Context, userID uuid.UUID) (GetAuthorizationUserRolesRow, error) {
|
||||
row := q.db.QueryRowContext(ctx, getAuthorizationUserRoles, userID)
|
||||
var i GetAuthorizationUserRolesRow
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Username,
|
||||
|
@ -134,12 +134,20 @@ WHERE
|
||||
id = $1 RETURNING *;
|
||||
|
||||
|
||||
-- name: GetAllUserRoles :one
|
||||
-- name: GetAuthorizationUserRoles :one
|
||||
-- This function returns roles for authorization purposes. Implied member roles
|
||||
-- are included.
|
||||
SELECT
|
||||
-- username is returned just to help for logging purposes
|
||||
-- status is used to enforce 'suspended' users, as all roles are ignored
|
||||
-- when suspended.
|
||||
id, username, status, array_cat(users.rbac_roles, organization_members.roles) :: text[] AS roles
|
||||
-- username is returned just to help for logging purposes
|
||||
-- status is used to enforce 'suspended' users, as all roles are ignored
|
||||
-- when suspended.
|
||||
id, username, status,
|
||||
array_cat(
|
||||
-- All users are members
|
||||
array_append(users.rbac_roles, 'member'),
|
||||
-- All org_members get the org-member role for their orgs
|
||||
array_append(organization_members.roles, 'organization-member:'||organization_members.organization_id::text)) :: text[]
|
||||
AS roles
|
||||
FROM
|
||||
users
|
||||
LEFT JOIN organization_members
|
||||
|
Reference in New Issue
Block a user