mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: Rename 'admin' to 'owner' (#3498)
Co-authored-by: Colin Adler <colin1adler@gmail.com>
This commit is contained in:
co-authored by
Colin Adler
parent
2306d2c709
commit
01dd35f1ba
@@ -0,0 +1,22 @@
|
|||||||
|
UPDATE
|
||||||
|
users
|
||||||
|
SET
|
||||||
|
-- Replace 'template-admin' and 'user-admin' role with 'admin'
|
||||||
|
rbac_roles = array_append(
|
||||||
|
array_remove(
|
||||||
|
array_remove(rbac_roles, 'template-admin'),
|
||||||
|
'user-admin'
|
||||||
|
), 'admin')
|
||||||
|
WHERE
|
||||||
|
-- Only on existing admins. If they have either role, make them an admin
|
||||||
|
ARRAY ['template-admin', 'user-admin'] && rbac_roles;
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE
|
||||||
|
users
|
||||||
|
SET
|
||||||
|
-- Replace 'owner' with 'admin'
|
||||||
|
rbac_roles = array_replace(rbac_roles, 'owner', 'admin')
|
||||||
|
WHERE
|
||||||
|
-- Only on the owner
|
||||||
|
'owner' = ANY(rbac_roles);
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
UPDATE
|
||||||
|
users
|
||||||
|
SET
|
||||||
|
-- Replace the role 'admin' with the role 'owner'
|
||||||
|
rbac_roles = array_replace(rbac_roles, 'admin', 'owner')
|
||||||
|
WHERE
|
||||||
|
-- Update the first user with the role 'admin'. This should be the first
|
||||||
|
-- user ever, but if that user was demoted from an admin, then choose
|
||||||
|
-- the next best user.
|
||||||
|
id = (SELECT id FROM users WHERE 'admin' = ANY(rbac_roles) ORDER BY created_at ASC LIMIT 1);
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE
|
||||||
|
users
|
||||||
|
SET
|
||||||
|
-- Replace 'admin' role with 'template-admin' and 'user-admin'
|
||||||
|
rbac_roles = array_cat(array_remove(rbac_roles, 'admin'), ARRAY ['template-admin', 'user-admin'])
|
||||||
|
WHERE
|
||||||
|
-- Only on existing admins
|
||||||
|
'admin' = ANY(rbac_roles);
|
||||||
@@ -40,7 +40,7 @@ func TestExtractUserRoles(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "Admin",
|
Name: "Admin",
|
||||||
AddUser: func(db database.Store) (database.User, []string, string) {
|
AddUser: func(db database.Store) (database.User, []string, string) {
|
||||||
roles := []string{rbac.RoleAdmin()}
|
roles := []string{rbac.RoleOwner()}
|
||||||
user, token := addUser(t, db, roles...)
|
user, token := addUser(t, db, roles...)
|
||||||
return user, append(roles, rbac.RoleMember()), token
|
return user, append(roles, rbac.RoleMember()), token
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ import (
|
|||||||
|
|
||||||
"cdr.dev/slog"
|
"cdr.dev/slog"
|
||||||
"cdr.dev/slog/sloggers/slogtest"
|
"cdr.dev/slog/sloggers/slogtest"
|
||||||
|
|
||||||
"github.com/coder/coder/coderd/database"
|
"github.com/coder/coder/coderd/database"
|
||||||
"github.com/coder/coder/coderd/database/databasefake"
|
"github.com/coder/coder/coderd/database/databasefake"
|
||||||
|
"github.com/coder/coder/coderd/rbac"
|
||||||
"github.com/coder/coder/codersdk"
|
"github.com/coder/coder/codersdk"
|
||||||
"github.com/coder/coder/testutil"
|
"github.com/coder/coder/testutil"
|
||||||
)
|
)
|
||||||
@@ -77,7 +77,7 @@ func TestProvisionerJobLogs_Unit(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, err = fDB.InsertUser(ctx, database.InsertUserParams{
|
_, err = fDB.InsertUser(ctx, database.InsertUserParams{
|
||||||
ID: userID,
|
ID: userID,
|
||||||
RBACRoles: []string{"admin"},
|
RBACRoles: []string{rbac.RoleOwner()},
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, err = fDB.InsertWorkspaceBuild(ctx, database.InsertWorkspaceBuildParams{
|
_, err = fDB.InsertWorkspaceBuild(ctx, database.InsertWorkspaceBuildParams{
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func TestFilter(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "Admin",
|
Name: "Admin",
|
||||||
SubjectID: userIDs[0].String(),
|
SubjectID: userIDs[0].String(),
|
||||||
Roles: []string{RoleOrgMember(orgIDs[0]), "auditor", RoleAdmin(), RoleMember()},
|
Roles: []string{RoleOrgMember(orgIDs[0]), "auditor", RoleOwner(), RoleMember()},
|
||||||
ObjectType: ResourceWorkspace.Type,
|
ObjectType: ResourceWorkspace.Type,
|
||||||
Action: ActionRead,
|
Action: ActionRead,
|
||||||
},
|
},
|
||||||
@@ -292,7 +292,7 @@ func TestAuthorizeDomain(t *testing.T) {
|
|||||||
user = subject{
|
user = subject{
|
||||||
UserID: "me",
|
UserID: "me",
|
||||||
Roles: []Role{
|
Roles: []Role{
|
||||||
must(RoleByName(RoleAdmin())),
|
must(RoleByName(RoleOwner())),
|
||||||
must(RoleByName(RoleMember())),
|
must(RoleByName(RoleMember())),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -499,7 +499,7 @@ func TestAuthorizeLevels(t *testing.T) {
|
|||||||
user := subject{
|
user := subject{
|
||||||
UserID: "me",
|
UserID: "me",
|
||||||
Roles: []Role{
|
Roles: []Role{
|
||||||
must(RoleByName(RoleAdmin())),
|
must(RoleByName(RoleOwner())),
|
||||||
{
|
{
|
||||||
Name: "org-deny:" + defOrg.String(),
|
Name: "org-deny:" + defOrg.String(),
|
||||||
Org: map[string][]Permission{
|
Org: map[string][]Permission{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
admin string = "admin"
|
owner string = "owner"
|
||||||
member string = "member"
|
member string = "member"
|
||||||
templateAdmin string = "template-admin"
|
templateAdmin string = "template-admin"
|
||||||
userAdmin string = "user-admin"
|
userAdmin string = "user-admin"
|
||||||
@@ -24,8 +24,8 @@ const (
|
|||||||
// Once we have a database implementation, the "default" roles can be defined on the
|
// Once we have a database implementation, the "default" roles can be defined on the
|
||||||
// site and orgs, and these functions can be removed.
|
// site and orgs, and these functions can be removed.
|
||||||
|
|
||||||
func RoleAdmin() string {
|
func RoleOwner() string {
|
||||||
return roleName(admin, "")
|
return roleName(owner, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func RoleTemplateAdmin() string {
|
func RoleTemplateAdmin() string {
|
||||||
@@ -59,10 +59,10 @@ var (
|
|||||||
// https://github.com/coder/coder/issues/1194
|
// https://github.com/coder/coder/issues/1194
|
||||||
builtInRoles = map[string]func(orgID string) Role{
|
builtInRoles = map[string]func(orgID string) Role{
|
||||||
// admin grants all actions to all resources.
|
// admin grants all actions to all resources.
|
||||||
admin: func(_ string) Role {
|
owner: func(_ string) Role {
|
||||||
return Role{
|
return Role{
|
||||||
Name: admin,
|
Name: owner,
|
||||||
DisplayName: "Admin",
|
DisplayName: "Owner",
|
||||||
Site: permissions(map[Object][]Action{
|
Site: permissions(map[Object][]Action{
|
||||||
ResourceWildcard: {WildcardSymbol},
|
ResourceWildcard: {WildcardSymbol},
|
||||||
}),
|
}),
|
||||||
@@ -187,8 +187,8 @@ var (
|
|||||||
// The first key is the actor role, the second is the roles they can assign.
|
// The first key is the actor role, the second is the roles they can assign.
|
||||||
// map[actor_role][assign_role]<can_assign>
|
// map[actor_role][assign_role]<can_assign>
|
||||||
assignRoles = map[string]map[string]bool{
|
assignRoles = map[string]map[string]bool{
|
||||||
admin: {
|
owner: {
|
||||||
admin: true,
|
owner: true,
|
||||||
auditor: true,
|
auditor: true,
|
||||||
member: true,
|
member: true,
|
||||||
orgAdmin: true,
|
orgAdmin: true,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func TestRoleByName(t *testing.T) {
|
|||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Role Role
|
Role Role
|
||||||
}{
|
}{
|
||||||
{Role: builtInRoles[admin]("")},
|
{Role: builtInRoles[owner]("")},
|
||||||
{Role: builtInRoles[member]("")},
|
{Role: builtInRoles[member]("")},
|
||||||
{Role: builtInRoles[templateAdmin]("")},
|
{Role: builtInRoles[templateAdmin]("")},
|
||||||
{Role: builtInRoles[userAdmin]("")},
|
{Role: builtInRoles[userAdmin]("")},
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func BenchmarkRBACFilter(b *testing.B) {
|
|||||||
{
|
{
|
||||||
Name: "Admin",
|
Name: "Admin",
|
||||||
// Give some extra roles that an admin might have
|
// Give some extra roles that an admin might have
|
||||||
Roles: []string{rbac.RoleOrgMember(orgs[0]), "auditor", rbac.RoleAdmin(), rbac.RoleMember()},
|
Roles: []string{rbac.RoleOrgMember(orgs[0]), "auditor", rbac.RoleOwner(), rbac.RoleMember()},
|
||||||
UserID: users[0],
|
UserID: users[0],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -119,7 +119,7 @@ func TestRolePermissions(t *testing.T) {
|
|||||||
memberMe := authSubject{Name: "member_me", UserID: currentUser.String(), Roles: []string{rbac.RoleMember()}}
|
memberMe := authSubject{Name: "member_me", UserID: currentUser.String(), Roles: []string{rbac.RoleMember()}}
|
||||||
orgMemberMe := authSubject{Name: "org_member_me", UserID: currentUser.String(), Roles: []string{rbac.RoleMember(), rbac.RoleOrgMember(orgID)}}
|
orgMemberMe := authSubject{Name: "org_member_me", UserID: currentUser.String(), Roles: []string{rbac.RoleMember(), rbac.RoleOrgMember(orgID)}}
|
||||||
|
|
||||||
admin := authSubject{Name: "admin", UserID: adminID.String(), Roles: []string{rbac.RoleMember(), rbac.RoleAdmin()}}
|
admin := authSubject{Name: "admin", UserID: adminID.String(), Roles: []string{rbac.RoleMember(), rbac.RoleOwner()}}
|
||||||
orgAdmin := authSubject{Name: "org_admin", UserID: adminID.String(), Roles: []string{rbac.RoleMember(), rbac.RoleOrgMember(orgID), rbac.RoleOrgAdmin(orgID)}}
|
orgAdmin := authSubject{Name: "org_admin", UserID: adminID.String(), Roles: []string{rbac.RoleMember(), rbac.RoleOrgMember(orgID), rbac.RoleOrgAdmin(orgID)}}
|
||||||
|
|
||||||
otherOrgMember := authSubject{Name: "org_member_other", UserID: uuid.NewString(), Roles: []string{rbac.RoleMember(), rbac.RoleOrgMember(otherOrg)}}
|
otherOrgMember := authSubject{Name: "org_member_other", UserID: uuid.NewString(), Roles: []string{rbac.RoleMember(), rbac.RoleOrgMember(otherOrg)}}
|
||||||
@@ -358,7 +358,7 @@ func TestIsOrgRole(t *testing.T) {
|
|||||||
OrgID string
|
OrgID string
|
||||||
}{
|
}{
|
||||||
// Not org roles
|
// Not org roles
|
||||||
{RoleName: rbac.RoleAdmin()},
|
{RoleName: rbac.RoleOwner()},
|
||||||
{RoleName: rbac.RoleMember()},
|
{RoleName: rbac.RoleMember()},
|
||||||
{RoleName: "auditor"},
|
{RoleName: "auditor"},
|
||||||
|
|
||||||
@@ -413,7 +413,7 @@ func TestListRoles(t *testing.T) {
|
|||||||
// Always use constant strings, as if the names change, we need to write
|
// Always use constant strings, as if the names change, we need to write
|
||||||
// a SQL migration to change the name on the backend.
|
// a SQL migration to change the name on the backend.
|
||||||
require.ElementsMatch(t, []string{
|
require.ElementsMatch(t, []string{
|
||||||
"admin",
|
"owner",
|
||||||
"member",
|
"member",
|
||||||
"auditor",
|
"auditor",
|
||||||
"template-admin",
|
"template-admin",
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ func TestListRoles(t *testing.T) {
|
|||||||
require.NoError(t, err, "create org")
|
require.NoError(t, err, "create org")
|
||||||
|
|
||||||
const forbidden = "Forbidden"
|
const forbidden = "Forbidden"
|
||||||
siteRoles := convertRoles(rbac.RoleAdmin(), "auditor", "template-admin", "user-admin")
|
siteRoles := convertRoles(rbac.RoleOwner(), "auditor", "template-admin", "user-admin")
|
||||||
orgRoles := convertRoles(rbac.RoleOrgAdmin(admin.OrganizationID))
|
orgRoles := convertRoles(rbac.RoleOrgAdmin(admin.OrganizationID))
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ func TestTemplate(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true})
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true})
|
||||||
user := coderdtest.CreateFirstUser(t, client)
|
user := coderdtest.CreateFirstUser(t, client)
|
||||||
member := coderdtest.CreateAnotherUser(t, client, user.OrganizationID, rbac.RoleAdmin())
|
member := coderdtest.CreateAnotherUser(t, client, user.OrganizationID, rbac.RoleOwner())
|
||||||
memberWithDeleted := coderdtest.CreateAnotherUser(t, client, user.OrganizationID, rbac.RoleAdmin())
|
memberWithDeleted := coderdtest.CreateAnotherUser(t, client, user.OrganizationID, rbac.RoleOwner())
|
||||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||||
|
|||||||
+1
-1
@@ -102,7 +102,7 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
|
|||||||
// and add some rbac bypass when calling api functions this way??
|
// and add some rbac bypass when calling api functions this way??
|
||||||
// Add the admin role to this first user.
|
// Add the admin role to this first user.
|
||||||
_, err = api.Database.UpdateUserRoles(r.Context(), database.UpdateUserRolesParams{
|
_, err = api.Database.UpdateUserRoles(r.Context(), database.UpdateUserRolesParams{
|
||||||
GrantedRoles: []string{rbac.RoleAdmin()},
|
GrantedRoles: []string{rbac.RoleOwner()},
|
||||||
ID: user.ID,
|
ID: user.ID,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -53,11 +53,11 @@ func TestSearchUsers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "OnlyParams",
|
Name: "OnlyParams",
|
||||||
Query: "status:acTIve sEArch:User-Name role:Admin",
|
Query: "status:acTIve sEArch:User-Name role:Owner",
|
||||||
Expected: database.GetUsersParams{
|
Expected: database.GetUsersParams{
|
||||||
Search: "user-name",
|
Search: "user-name",
|
||||||
Status: []database.UserStatus{database.UserStatusActive},
|
Status: []database.UserStatus{database.UserStatusActive},
|
||||||
RbacRole: []string{rbac.RoleAdmin()},
|
RbacRole: []string{rbac.RoleOwner()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -71,11 +71,11 @@ func TestSearchUsers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "QuotedKey",
|
Name: "QuotedKey",
|
||||||
Query: `"status":acTIve "sEArch":User-Name "role":Admin`,
|
Query: `"status":acTIve "sEArch":User-Name "role":Owner`,
|
||||||
Expected: database.GetUsersParams{
|
Expected: database.GetUsersParams{
|
||||||
Search: "user-name",
|
Search: "user-name",
|
||||||
Status: []database.UserStatus{database.UserStatusActive},
|
Status: []database.UserStatus{database.UserStatusActive},
|
||||||
RbacRole: []string{rbac.RoleAdmin()},
|
RbacRole: []string{rbac.RoleOwner()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+13
-13
@@ -279,7 +279,7 @@ func TestPostUsers(t *testing.T) {
|
|||||||
client := coderdtest.New(t, nil)
|
client := coderdtest.New(t, nil)
|
||||||
first := coderdtest.CreateFirstUser(t, client)
|
first := coderdtest.CreateFirstUser(t, client)
|
||||||
notInOrg := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
|
notInOrg := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
|
||||||
other := coderdtest.CreateAnotherUser(t, client, first.OrganizationID, rbac.RoleAdmin(), rbac.RoleMember())
|
other := coderdtest.CreateAnotherUser(t, client, first.OrganizationID, rbac.RoleOwner(), rbac.RoleMember())
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -513,7 +513,7 @@ func TestGrantSiteRoles(t *testing.T) {
|
|||||||
Name: "UserNotExists",
|
Name: "UserNotExists",
|
||||||
Client: admin,
|
Client: admin,
|
||||||
AssignToUser: uuid.NewString(),
|
AssignToUser: uuid.NewString(),
|
||||||
Roles: []string{rbac.RoleAdmin()},
|
Roles: []string{rbac.RoleOwner()},
|
||||||
Error: true,
|
Error: true,
|
||||||
StatusCode: http.StatusBadRequest,
|
StatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
@@ -539,7 +539,7 @@ func TestGrantSiteRoles(t *testing.T) {
|
|||||||
Client: admin,
|
Client: admin,
|
||||||
OrgID: first.OrganizationID,
|
OrgID: first.OrganizationID,
|
||||||
AssignToUser: codersdk.Me,
|
AssignToUser: codersdk.Me,
|
||||||
Roles: []string{rbac.RoleAdmin()},
|
Roles: []string{rbac.RoleOwner()},
|
||||||
Error: true,
|
Error: true,
|
||||||
StatusCode: http.StatusBadRequest,
|
StatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
@@ -629,7 +629,7 @@ func TestInitialRoles(t *testing.T) {
|
|||||||
roles, err := client.GetUserRoles(ctx, codersdk.Me)
|
roles, err := client.GetUserRoles(ctx, codersdk.Me)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.ElementsMatch(t, roles.Roles, []string{
|
require.ElementsMatch(t, roles.Roles, []string{
|
||||||
rbac.RoleAdmin(),
|
rbac.RoleOwner(),
|
||||||
}, "should be a member and admin")
|
}, "should be a member and admin")
|
||||||
|
|
||||||
require.ElementsMatch(t, roles.OrganizationRoles[first.OrganizationID], []string{
|
require.ElementsMatch(t, roles.OrganizationRoles[first.OrganizationID], []string{
|
||||||
@@ -744,7 +744,7 @@ func TestUsersFilter(t *testing.T) {
|
|||||||
for i := 0; i < 15; i++ {
|
for i := 0; i < 15; i++ {
|
||||||
roles := []string{}
|
roles := []string{}
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
roles = append(roles, rbac.RoleAdmin())
|
roles = append(roles, rbac.RoleOwner())
|
||||||
}
|
}
|
||||||
if i%3 == 0 {
|
if i%3 == 0 {
|
||||||
roles = append(roles, "auditor")
|
roles = append(roles, "auditor")
|
||||||
@@ -823,12 +823,12 @@ func TestUsersFilter(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "Admins",
|
Name: "Admins",
|
||||||
Filter: codersdk.UsersRequest{
|
Filter: codersdk.UsersRequest{
|
||||||
Role: rbac.RoleAdmin(),
|
Role: rbac.RoleOwner(),
|
||||||
Status: codersdk.UserStatusSuspended + "," + codersdk.UserStatusActive,
|
Status: codersdk.UserStatusSuspended + "," + codersdk.UserStatusActive,
|
||||||
},
|
},
|
||||||
FilterF: func(_ codersdk.UsersRequest, u codersdk.User) bool {
|
FilterF: func(_ codersdk.UsersRequest, u codersdk.User) bool {
|
||||||
for _, r := range u.Roles {
|
for _, r := range u.Roles {
|
||||||
if r.Name == rbac.RoleAdmin() {
|
if r.Name == rbac.RoleOwner() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -838,12 +838,12 @@ func TestUsersFilter(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "AdminsUppercase",
|
Name: "AdminsUppercase",
|
||||||
Filter: codersdk.UsersRequest{
|
Filter: codersdk.UsersRequest{
|
||||||
Role: "ADMIN",
|
Role: "OWNER",
|
||||||
Status: codersdk.UserStatusSuspended + "," + codersdk.UserStatusActive,
|
Status: codersdk.UserStatusSuspended + "," + codersdk.UserStatusActive,
|
||||||
},
|
},
|
||||||
FilterF: func(_ codersdk.UsersRequest, u codersdk.User) bool {
|
FilterF: func(_ codersdk.UsersRequest, u codersdk.User) bool {
|
||||||
for _, r := range u.Roles {
|
for _, r := range u.Roles {
|
||||||
if r.Name == rbac.RoleAdmin() {
|
if r.Name == rbac.RoleOwner() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -863,11 +863,11 @@ func TestUsersFilter(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "SearchQuery",
|
Name: "SearchQuery",
|
||||||
Filter: codersdk.UsersRequest{
|
Filter: codersdk.UsersRequest{
|
||||||
SearchQuery: "i role:admin status:active",
|
SearchQuery: "i role:owner status:active",
|
||||||
},
|
},
|
||||||
FilterF: func(_ codersdk.UsersRequest, u codersdk.User) bool {
|
FilterF: func(_ codersdk.UsersRequest, u codersdk.User) bool {
|
||||||
for _, r := range u.Roles {
|
for _, r := range u.Roles {
|
||||||
if r.Name == rbac.RoleAdmin() {
|
if r.Name == rbac.RoleOwner() {
|
||||||
return (strings.ContainsAny(u.Username, "iI") || strings.ContainsAny(u.Email, "iI")) &&
|
return (strings.ContainsAny(u.Username, "iI") || strings.ContainsAny(u.Email, "iI")) &&
|
||||||
u.Status == codersdk.UserStatusActive
|
u.Status == codersdk.UserStatusActive
|
||||||
}
|
}
|
||||||
@@ -878,11 +878,11 @@ func TestUsersFilter(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "SearchQueryInsensitive",
|
Name: "SearchQueryInsensitive",
|
||||||
Filter: codersdk.UsersRequest{
|
Filter: codersdk.UsersRequest{
|
||||||
SearchQuery: "i Role:Admin STATUS:Active",
|
SearchQuery: "i Role:Owner STATUS:Active",
|
||||||
},
|
},
|
||||||
FilterF: func(_ codersdk.UsersRequest, u codersdk.User) bool {
|
FilterF: func(_ codersdk.UsersRequest, u codersdk.User) bool {
|
||||||
for _, r := range u.Roles {
|
for _, r := range u.Roles {
|
||||||
if r.Name == rbac.RoleAdmin() {
|
if r.Name == rbac.RoleOwner() {
|
||||||
return (strings.ContainsAny(u.Username, "iI") || strings.ContainsAny(u.Email, "iI")) &&
|
return (strings.ContainsAny(u.Username, "iI") || strings.ContainsAny(u.Email, "iI")) &&
|
||||||
u.Status == codersdk.UserStatusActive
|
u.Status == codersdk.UserStatusActive
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ func TestAdminViewAllWorkspaces(t *testing.T) {
|
|||||||
|
|
||||||
// This other user is not in the first user's org. Since other is an admin, they can
|
// This other user is not in the first user's org. Since other is an admin, they can
|
||||||
// still see the "first" user's workspace.
|
// still see the "first" user's workspace.
|
||||||
other := coderdtest.CreateAnotherUser(t, client, otherOrg.ID, rbac.RoleAdmin())
|
other := coderdtest.CreateAnotherUser(t, client, otherOrg.ID, rbac.RoleOwner())
|
||||||
otherWorkspaces, err := other.Workspaces(ctx, codersdk.WorkspaceFilter{})
|
otherWorkspaces, err := other.Workspaces(ctx, codersdk.WorkspaceFilter{})
|
||||||
require.NoError(t, err, "(other) fetch workspaces")
|
require.NoError(t, err, "(other) fetch workspaces")
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ func TestPostWorkspacesByOrganization(t *testing.T) {
|
|||||||
client := coderdtest.New(t, nil)
|
client := coderdtest.New(t, nil)
|
||||||
first := coderdtest.CreateFirstUser(t, client)
|
first := coderdtest.CreateFirstUser(t, client)
|
||||||
|
|
||||||
other := coderdtest.CreateAnotherUser(t, client, first.OrganizationID, rbac.RoleMember(), rbac.RoleAdmin())
|
other := coderdtest.CreateAnotherUser(t, client, first.OrganizationID, rbac.RoleMember(), rbac.RoleOwner())
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -406,7 +406,7 @@ func TestWorkspaceFilter(t *testing.T) {
|
|||||||
|
|
||||||
users := make([]coderUser, 0)
|
users := make([]coderUser, 0)
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
userClient := coderdtest.CreateAnotherUser(t, client, first.OrganizationID, rbac.RoleAdmin())
|
userClient := coderdtest.CreateAnotherUser(t, client, first.OrganizationID, rbac.RoleOwner())
|
||||||
user, err := userClient.User(ctx, codersdk.Me)
|
user, err := userClient.User(ctx, codersdk.Me)
|
||||||
require.NoError(t, err, "fetch me")
|
require.NoError(t, err, "fetch me")
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -7,10 +7,10 @@ possible way to use Coder.
|
|||||||
|
|
||||||
Please [install Coder](../install.md) before proceeding with the steps below.
|
Please [install Coder](../install.md) before proceeding with the steps below.
|
||||||
|
|
||||||
## First time admin user setup
|
## First time owner user setup
|
||||||
|
|
||||||
1. Run `coder login <your Access URL>` in a new terminal and follow the
|
1. Run `coder login <your Access URL>` in a new terminal and follow the
|
||||||
interactive instructions to create your admin user and password.
|
interactive instructions to create your owner user and password.
|
||||||
|
|
||||||
> If using `coder server --tunnel`, the Access URL appears in the terminal logs.
|
> If using `coder server --tunnel`, the Access URL appears in the terminal logs.
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ coder ssh <workspaceName>
|
|||||||
```
|
```
|
||||||
|
|
||||||
To access your workspace in the Coder dashboard, navigate to the [configured access URL](../configure.md),
|
To access your workspace in the Coder dashboard, navigate to the [configured access URL](../configure.md),
|
||||||
and log in with the admin credentials provided to you by Coder.
|
and log in with the owner credentials provided to you by Coder.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -6,13 +6,13 @@ This article walks you through the user roles available in Coder and creating an
|
|||||||
|
|
||||||
Coder offers these user roles in the community edition:
|
Coder offers these user roles in the community edition:
|
||||||
|
|
||||||
| | User Admin | Template Admin | Admin |
|
| | User Admin | Template Admin | Owner |
|
||||||
| ------------------------------------------ | ---------- | -------------- | ----- |
|
| ------------------------------------------ | ---------- | -------------- |-------|
|
||||||
| Add and remove Users | ✅ | | ✅ |
|
| Add and remove Users | ✅ | | ✅ |
|
||||||
| Change User roles | | | ✅ |
|
| Change User roles | | | ✅ |
|
||||||
| Manage Templates | | ✅ | ✅ |
|
| Manage Templates | | ✅ | ✅ |
|
||||||
| View, update and delete **ALL** Workspaces | | ✅ | ✅ |
|
| View, update and delete **ALL** Workspaces | | ✅ | ✅ |
|
||||||
| Execute and use **ALL** Workspaces | | | ✅ |
|
| Execute and use **ALL** Workspaces | | | ✅ |
|
||||||
|
|
||||||
A user may have one or more roles. All users have an implicit Member role
|
A user may have one or more roles. All users have an implicit Member role
|
||||||
that may use personal workspaces.
|
that may use personal workspaces.
|
||||||
@@ -21,7 +21,7 @@ that may use personal workspaces.
|
|||||||
|
|
||||||
To create a user with the web UI:
|
To create a user with the web UI:
|
||||||
|
|
||||||
1. Log in as an admin.
|
1. Log in as a user admin.
|
||||||
2. Go to **Users** > **New user**.
|
2. Go to **Users** > **New user**.
|
||||||
3. In the window that opens, provide the **username**, **email**, and
|
3. In the window that opens, provide the **username**, **email**, and
|
||||||
**password** for the user (they can opt to change their password after their
|
**password** for the user (they can opt to change their password after their
|
||||||
@@ -56,7 +56,7 @@ Create a workspace coder create !
|
|||||||
|
|
||||||
## Suspend a user
|
## Suspend a user
|
||||||
|
|
||||||
Admins can suspend a user, removing the user's access to Coder.
|
User admins can suspend a user, removing the user's access to Coder.
|
||||||
|
|
||||||
To suspend a user via the web UI:
|
To suspend a user via the web UI:
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ Confirm the user suspension by typing **yes** and pressing **enter**.
|
|||||||
|
|
||||||
## Activate a suspended user
|
## Activate a suspended user
|
||||||
|
|
||||||
Admins can activate a suspended user, restoring their access to Coder.
|
User admins can activate a suspended user, restoring their access to Coder.
|
||||||
|
|
||||||
To activate a user via the web UI:
|
To activate a user via the web UI:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user