From fb61fd790bebccfb65545eb993cd21509acee096 Mon Sep 17 00:00:00 2001 From: Bruno Date: Fri, 6 May 2022 18:08:52 +0000 Subject: [PATCH 1/2] Return DisplayName and Name in the roles endpoint --- coderd/rbac/builtin.go | 15 ++++++++++----- coderd/rbac/role.go | 5 +++-- coderd/roles.go | 7 +++++-- coderd/roles_test.go | 26 +++++++++++++------------- coderd/users.go | 8 ++++---- codersdk/roles.go | 29 +++++++++++++++++++++++++---- 6 files changed, 60 insertions(+), 30 deletions(-) diff --git a/coderd/rbac/builtin.go b/coderd/rbac/builtin.go index 26ec0a1afa1cc..ade2f79f6f8d7 100644 --- a/coderd/rbac/builtin.go +++ b/coderd/rbac/builtin.go @@ -51,7 +51,8 @@ var ( // admin grants all actions to all resources. admin: func(_ string) Role { return Role{ - Name: admin, + Name: admin, + DisplayName: "Admin", Site: permissions(map[Object][]Action{ ResourceWildcard: {WildcardSymbol}, }), @@ -61,7 +62,8 @@ var ( // member grants all actions to all resources owned by the user member: func(_ string) Role { return Role{ - Name: member, + Name: member, + DisplayName: "Member", User: permissions(map[Object][]Action{ ResourceWildcard: {WildcardSymbol}, }), @@ -73,7 +75,8 @@ var ( // TODO: Finish the auditor as we add resources. auditor: func(_ string) Role { return Role{ - Name: "auditor", + Name: "auditor", + DisplayName: "Auditor", Site: permissions(map[Object][]Action{ // Should be able to read all template details, even in orgs they // are not in. @@ -86,7 +89,8 @@ var ( // organization scope. orgAdmin: func(organizationID string) Role { return Role{ - Name: roleName(orgAdmin, organizationID), + Name: roleName(orgAdmin, organizationID), + DisplayName: "Organization Admin", Org: map[string][]Permission{ organizationID: { { @@ -104,7 +108,8 @@ var ( // in an organization. orgMember: func(organizationID string) Role { return Role{ - Name: roleName(orgMember, organizationID), + Name: roleName(orgMember, organizationID), + DisplayName: "Organization Member", Org: map[string][]Permission{ organizationID: {}, }, diff --git a/coderd/rbac/role.go b/coderd/rbac/role.go index a083b2a11ac80..c236bf4a3cf59 100644 --- a/coderd/rbac/role.go +++ b/coderd/rbac/role.go @@ -17,8 +17,9 @@ type Permission struct { // Users of this package should instead **only** use the role names, and // this package will expand the role names into their json payloads. type Role struct { - Name string `json:"name"` - Site []Permission `json:"site"` + Name string `json:"name"` + DisplayName string `json:"display_name"` + Site []Permission `json:"site"` // Org is a map of orgid to permissions. We represent orgid as a string. // We scope the organizations in the role so we can easily combine all the // roles. diff --git a/coderd/roles.go b/coderd/roles.go index 64bd7353b4293..ccd7f0c85a39e 100644 --- a/coderd/roles.go +++ b/coderd/roles.go @@ -4,6 +4,7 @@ import ( "net/http" "github.com/coder/coder/coderd/httpmw" + "github.com/coder/coder/codersdk" "github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/rbac" @@ -13,7 +14,8 @@ import ( func (*api) assignableSiteRoles(rw http.ResponseWriter, _ *http.Request) { // TODO: @emyrk in the future, allow granular subsets of roles to be returned based on the // role of the user. - roles := rbac.SiteRoles() + roleNames := rbac.SiteRoles() + roles := codersdk.RolesFromName(roleNames) httpapi.Write(rw, http.StatusOK, roles) } @@ -22,6 +24,7 @@ func (*api) assignableOrgRoles(rw http.ResponseWriter, r *http.Request) { // TODO: @emyrk in the future, allow granular subsets of roles to be returned based on the // role of the user. organization := httpmw.OrganizationParam(r) - roles := rbac.OrganizationRoles(organization.ID) + roleNames := rbac.OrganizationRoles(organization.ID) + roles := codersdk.RolesFromName(roleNames) httpapi.Write(rw, http.StatusOK, roles) } diff --git a/coderd/roles_test.go b/coderd/roles_test.go index 523439883e33d..850785ea72c25 100644 --- a/coderd/roles_test.go +++ b/coderd/roles_test.go @@ -45,13 +45,13 @@ func TestListRoles(t *testing.T) { testCases := []struct { Name string Client *codersdk.Client - APICall func() ([]string, error) - ExpectedRoles []string + APICall func() ([]codersdk.Role, error) + ExpectedRoles []codersdk.Role AuthorizedError string }{ { Name: "MemberListSite", - APICall: func() ([]string, error) { + APICall: func() ([]codersdk.Role, error) { x, err := member.ListSiteRoles(ctx) return x, err }, @@ -59,14 +59,14 @@ func TestListRoles(t *testing.T) { }, { Name: "OrgMemberListOrg", - APICall: func() ([]string, error) { + APICall: func() ([]codersdk.Role, error) { return member.ListOrganizationRoles(ctx, admin.OrganizationID) }, AuthorizedError: unauth, }, { Name: "NonOrgMemberListOrg", - APICall: func() ([]string, error) { + APICall: func() ([]codersdk.Role, error) { return member.ListOrganizationRoles(ctx, otherOrg.ID) }, AuthorizedError: notMember, @@ -74,21 +74,21 @@ func TestListRoles(t *testing.T) { // Org admin { Name: "OrgAdminListSite", - APICall: func() ([]string, error) { + APICall: func() ([]codersdk.Role, error) { return orgAdmin.ListSiteRoles(ctx) }, AuthorizedError: unauth, }, { Name: "OrgAdminListOrg", - APICall: func() ([]string, error) { + APICall: func() ([]codersdk.Role, error) { return orgAdmin.ListOrganizationRoles(ctx, admin.OrganizationID) }, - ExpectedRoles: rbac.OrganizationRoles(admin.OrganizationID), + ExpectedRoles: codersdk.RolesFromName(rbac.OrganizationRoles(admin.OrganizationID)), }, { Name: "OrgAdminListOtherOrg", - APICall: func() ([]string, error) { + APICall: func() ([]codersdk.Role, error) { return orgAdmin.ListOrganizationRoles(ctx, otherOrg.ID) }, AuthorizedError: notMember, @@ -96,17 +96,17 @@ func TestListRoles(t *testing.T) { // Admin { Name: "AdminListSite", - APICall: func() ([]string, error) { + APICall: func() ([]codersdk.Role, error) { return client.ListSiteRoles(ctx) }, - ExpectedRoles: rbac.SiteRoles(), + ExpectedRoles: codersdk.RolesFromName(rbac.SiteRoles()), }, { Name: "AdminListOrg", - APICall: func() ([]string, error) { + APICall: func() ([]codersdk.Role, error) { return client.ListOrganizationRoles(ctx, admin.OrganizationID) }, - ExpectedRoles: rbac.OrganizationRoles(admin.OrganizationID), + ExpectedRoles: codersdk.RolesFromName(rbac.OrganizationRoles(admin.OrganizationID)), }, } diff --git a/coderd/users.go b/coderd/users.go index 108ad0813cb49..7841198558f5b 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -361,10 +361,10 @@ func (api *api) putUserSuspend(rw http.ResponseWriter, r *http.Request) { } func (api *api) putUserPassword(rw http.ResponseWriter, r *http.Request) { - var ( - user = httpmw.UserParam(r) - params codersdk.UpdateUserPasswordRequest - ) + var ( + user = httpmw.UserParam(r) + params codersdk.UpdateUserPasswordRequest + ) if !httpapi.Read(rw, r, ¶ms) { return } diff --git a/codersdk/roles.go b/codersdk/roles.go index d7d6d0fe2b8bc..f7877aba32baf 100644 --- a/codersdk/roles.go +++ b/codersdk/roles.go @@ -6,12 +6,18 @@ import ( "fmt" "net/http" + "github.com/coder/coder/coderd/rbac" "github.com/google/uuid" ) +type Role struct { + Name string `json:"name"` + DisplayName string `json:"display_name"` +} + // ListSiteRoles lists all available site wide roles. // This is not user specific. -func (c *Client) ListSiteRoles(ctx context.Context) ([]string, error) { +func (c *Client) ListSiteRoles(ctx context.Context) ([]Role, error) { res, err := c.request(ctx, http.MethodGet, "/api/v2/users/roles", nil) if err != nil { return nil, err @@ -20,13 +26,13 @@ func (c *Client) ListSiteRoles(ctx context.Context) ([]string, error) { if res.StatusCode != http.StatusOK { return nil, readBodyAsError(res) } - var roles []string + var roles []Role return roles, json.NewDecoder(res.Body).Decode(&roles) } // ListOrganizationRoles lists all available roles for a given organization. // This is not user specific. -func (c *Client) ListOrganizationRoles(ctx context.Context, org uuid.UUID) ([]string, error) { +func (c *Client) ListOrganizationRoles(ctx context.Context, org uuid.UUID) ([]Role, error) { res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/members/roles/", org.String()), nil) if err != nil { return nil, err @@ -35,6 +41,21 @@ func (c *Client) ListOrganizationRoles(ctx context.Context, org uuid.UUID) ([]st if res.StatusCode != http.StatusOK { return nil, readBodyAsError(res) } - var roles []string + var roles []Role return roles, json.NewDecoder(res.Body).Decode(&roles) } + +func RolesFromName(roleNames []string) []Role { + roles := make([]Role, 0, len(roleNames)) + for _, roleName := range roleNames { + role, err := rbac.RoleByName(roleName) + if err != nil { + continue + } + roles = append(roles, Role{ + Name: role.Name, + DisplayName: role.DisplayName, + }) + } + return roles +} From 85d6f69344ae923ace900caddc89de6ef266ea02 Mon Sep 17 00:00:00 2001 From: Bruno Date: Fri, 6 May 2022 19:09:27 +0000 Subject: [PATCH 2/2] Return the Role struct instead of only the name --- coderd/rbac/builtin.go | 14 +++++++------- coderd/rbac/builtin_test.go | 16 ++++++++++++++-- coderd/roles.go | 10 ++++------ coderd/roles_test.go | 6 +++--- codersdk/roles.go | 16 ++++++---------- 5 files changed, 34 insertions(+), 28 deletions(-) diff --git a/coderd/rbac/builtin.go b/coderd/rbac/builtin.go index ade2f79f6f8d7..6a85cfe3256a2 100644 --- a/coderd/rbac/builtin.go +++ b/coderd/rbac/builtin.go @@ -156,11 +156,11 @@ func IsOrgRole(roleName string) (string, bool) { // // This should be a list in a database, but until then we build // the list from the builtins. -func OrganizationRoles(organizationID uuid.UUID) []string { - var roles []string +func OrganizationRoles(organizationID uuid.UUID) []Role { + var roles []Role for _, roleF := range builtInRoles { - role := roleF(organizationID.String()).Name - _, scope, err := roleSplit(role) + role := roleF(organizationID.String()) + _, scope, err := roleSplit(role.Name) if err != nil { // This should never happen continue @@ -177,8 +177,8 @@ func OrganizationRoles(organizationID uuid.UUID) []string { // // This should be a list in a database, but until then we build // the list from the builtins. -func SiteRoles() []string { - var roles []string +func SiteRoles() []Role { + var roles []Role for _, roleF := range builtInRoles { role := roleF("random") _, scope, err := roleSplit(role.Name) @@ -187,7 +187,7 @@ func SiteRoles() []string { continue } if scope == "" { - roles = append(roles, role.Name) + roles = append(roles, role) } } return roles diff --git a/coderd/rbac/builtin_test.go b/coderd/rbac/builtin_test.go index d8b937f78ac53..72cde1eea40a6 100644 --- a/coderd/rbac/builtin_test.go +++ b/coderd/rbac/builtin_test.go @@ -65,6 +65,12 @@ func TestIsOrgRole(t *testing.T) { func TestListRoles(t *testing.T) { t.Parallel() + siteRoles := rbac.SiteRoles() + siteRoleNames := make([]string, 0, len(siteRoles)) + for _, role := range siteRoles { + siteRoleNames = append(siteRoleNames, role.Name) + } + // If this test is ever failing, just update the list to the roles // expected from the builtin set. require.ElementsMatch(t, []string{ @@ -72,12 +78,18 @@ func TestListRoles(t *testing.T) { "member", "auditor", }, - rbac.SiteRoles()) + siteRoleNames) orgID := uuid.New() + orgRoles := rbac.OrganizationRoles(orgID) + orgRoleNames := make([]string, 0, len(orgRoles)) + for _, role := range orgRoles { + orgRoleNames = append(orgRoleNames, role.Name) + } + require.ElementsMatch(t, []string{ fmt.Sprintf("organization-admin:%s", orgID.String()), fmt.Sprintf("organization-member:%s", orgID.String()), }, - rbac.OrganizationRoles(orgID)) + orgRoleNames) } diff --git a/coderd/roles.go b/coderd/roles.go index ccd7f0c85a39e..470d726252809 100644 --- a/coderd/roles.go +++ b/coderd/roles.go @@ -14,9 +14,8 @@ import ( func (*api) assignableSiteRoles(rw http.ResponseWriter, _ *http.Request) { // TODO: @emyrk in the future, allow granular subsets of roles to be returned based on the // role of the user. - roleNames := rbac.SiteRoles() - roles := codersdk.RolesFromName(roleNames) - httpapi.Write(rw, http.StatusOK, roles) + roles := rbac.SiteRoles() + httpapi.Write(rw, http.StatusOK, codersdk.ConvertRoles(roles)) } // assignableSiteRoles returns all site wide roles that can be assigned. @@ -24,7 +23,6 @@ func (*api) assignableOrgRoles(rw http.ResponseWriter, r *http.Request) { // TODO: @emyrk in the future, allow granular subsets of roles to be returned based on the // role of the user. organization := httpmw.OrganizationParam(r) - roleNames := rbac.OrganizationRoles(organization.ID) - roles := codersdk.RolesFromName(roleNames) - httpapi.Write(rw, http.StatusOK, roles) + roles := rbac.OrganizationRoles(organization.ID) + httpapi.Write(rw, http.StatusOK, codersdk.ConvertRoles(roles)) } diff --git a/coderd/roles_test.go b/coderd/roles_test.go index 850785ea72c25..6254ffa73d1d1 100644 --- a/coderd/roles_test.go +++ b/coderd/roles_test.go @@ -84,7 +84,7 @@ func TestListRoles(t *testing.T) { APICall: func() ([]codersdk.Role, error) { return orgAdmin.ListOrganizationRoles(ctx, admin.OrganizationID) }, - ExpectedRoles: codersdk.RolesFromName(rbac.OrganizationRoles(admin.OrganizationID)), + ExpectedRoles: codersdk.ConvertRoles(rbac.OrganizationRoles(admin.OrganizationID)), }, { Name: "OrgAdminListOtherOrg", @@ -99,14 +99,14 @@ func TestListRoles(t *testing.T) { APICall: func() ([]codersdk.Role, error) { return client.ListSiteRoles(ctx) }, - ExpectedRoles: codersdk.RolesFromName(rbac.SiteRoles()), + ExpectedRoles: codersdk.ConvertRoles(rbac.SiteRoles()), }, { Name: "AdminListOrg", APICall: func() ([]codersdk.Role, error) { return client.ListOrganizationRoles(ctx, admin.OrganizationID) }, - ExpectedRoles: codersdk.RolesFromName(rbac.OrganizationRoles(admin.OrganizationID)), + ExpectedRoles: codersdk.ConvertRoles(rbac.OrganizationRoles(admin.OrganizationID)), }, } diff --git a/codersdk/roles.go b/codersdk/roles.go index f7877aba32baf..cc2234505fa2d 100644 --- a/codersdk/roles.go +++ b/codersdk/roles.go @@ -45,17 +45,13 @@ func (c *Client) ListOrganizationRoles(ctx context.Context, org uuid.UUID) ([]Ro return roles, json.NewDecoder(res.Body).Decode(&roles) } -func RolesFromName(roleNames []string) []Role { - roles := make([]Role, 0, len(roleNames)) - for _, roleName := range roleNames { - role, err := rbac.RoleByName(roleName) - if err != nil { - continue - } - roles = append(roles, Role{ - Name: role.Name, +func ConvertRoles(roles []rbac.Role) []Role { + converted := make([]Role, 0, len(roles)) + for _, role := range roles { + converted = append(converted, Role{ DisplayName: role.DisplayName, + Name: role.Name, }) } - return roles + return converted } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy