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:
Steven Masley
2022-06-01 09:07:50 -05:00
committed by GitHub
parent 2878346f19
commit cc87a0cf6b
21 changed files with 131 additions and 115 deletions

View File

@ -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,

View 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);

View 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);

View File

@ -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)

View File

@ -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,

View File

@ -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