refactor: Add roles into the user response (#1347)

This commit is contained in:
Bruno Quaresma
2022-05-09 11:38:14 -05:00
committed by GitHub
parent ad8d9dd71a
commit e54324d880
10 changed files with 74 additions and 37 deletions

View File

@ -15,7 +15,7 @@ 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()
httpapi.Write(rw, http.StatusOK, codersdk.ConvertRoles(roles))
httpapi.Write(rw, http.StatusOK, convertRoles(roles))
}
// assignableSiteRoles returns all site wide roles that can be assigned.
@ -24,5 +24,20 @@ func (*api) assignableOrgRoles(rw http.ResponseWriter, r *http.Request) {
// role of the user.
organization := httpmw.OrganizationParam(r)
roles := rbac.OrganizationRoles(organization.ID)
httpapi.Write(rw, http.StatusOK, codersdk.ConvertRoles(roles))
httpapi.Write(rw, http.StatusOK, convertRoles(roles))
}
func convertRole(role rbac.Role) codersdk.Role {
return codersdk.Role{
DisplayName: role.DisplayName,
Name: role.Name,
}
}
func convertRoles(roles []rbac.Role) []codersdk.Role {
converted := make([]codersdk.Role, 0, len(roles))
for _, role := range roles {
converted = append(converted, convertRole(role))
}
return converted
}

View File

@ -84,7 +84,7 @@ func TestListRoles(t *testing.T) {
APICall: func() ([]codersdk.Role, error) {
return orgAdmin.ListOrganizationRoles(ctx, admin.OrganizationID)
},
ExpectedRoles: codersdk.ConvertRoles(rbac.OrganizationRoles(admin.OrganizationID)),
ExpectedRoles: 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.ConvertRoles(rbac.SiteRoles()),
ExpectedRoles: convertRoles(rbac.SiteRoles()),
},
{
Name: "AdminListOrg",
APICall: func() ([]codersdk.Role, error) {
return client.ListOrganizationRoles(ctx, admin.OrganizationID)
},
ExpectedRoles: codersdk.ConvertRoles(rbac.OrganizationRoles(admin.OrganizationID)),
ExpectedRoles: convertRoles(rbac.OrganizationRoles(admin.OrganizationID)),
},
}
@ -127,3 +127,18 @@ func TestListRoles(t *testing.T) {
})
}
}
func convertRole(role rbac.Role) codersdk.Role {
return codersdk.Role{
DisplayName: role.DisplayName,
Name: role.Name,
}
}
func convertRoles(roles []rbac.Role) []codersdk.Role {
converted := make([]codersdk.Role, 0, len(roles))
for _, role := range roles {
converted = append(converted, convertRole(role))
}
return converted
}

View File

@ -807,14 +807,22 @@ func (api *api) createUser(ctx context.Context, req codersdk.CreateUserRequest)
}
func convertUser(user database.User, organizationIDs []uuid.UUID) codersdk.User {
return codersdk.User{
convertedUser := codersdk.User{
ID: user.ID,
Email: user.Email,
CreatedAt: user.CreatedAt,
Username: user.Username,
Status: codersdk.UserStatus(user.Status),
OrganizationIDs: organizationIDs,
Roles: make([]codersdk.Role, 0),
}
for _, roleName := range user.RBACRoles {
rbacRole, _ := rbac.RoleByName(roleName)
convertedUser.Roles = append(convertedUser.Roles, convertRole(rbacRole))
}
return convertedUser
}
func convertUsers(users []database.User, organizationIDsByUserID map[uuid.UUID][]uuid.UUID) []codersdk.User {

View File

@ -6,7 +6,6 @@ import (
"fmt"
"net/http"
"github.com/coder/coder/coderd/rbac"
"github.com/google/uuid"
)
@ -44,14 +43,3 @@ func (c *Client) ListOrganizationRoles(ctx context.Context, org uuid.UUID) ([]Ro
var roles []Role
return roles, json.NewDecoder(res.Body).Decode(&roles)
}
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 converted
}

View File

@ -45,6 +45,7 @@ type User struct {
Username string `json:"username" validate:"required"`
Status UserStatus `json:"status"`
OrganizationIDs []uuid.UUID `json:"organization_ids"`
Roles []Role `json:"roles"`
}
type CreateFirstUserRequest struct {
@ -216,17 +217,17 @@ func (c *Client) UpdateUserRoles(ctx context.Context, userID uuid.UUID, req Upda
// UpdateOrganizationMemberRoles grants the userID the specified roles in an org.
// Include ALL roles the user has.
func (c *Client) UpdateOrganizationMemberRoles(ctx context.Context, organizationID, userID uuid.UUID, req UpdateRoles) (User, error) {
func (c *Client) UpdateOrganizationMemberRoles(ctx context.Context, organizationID, userID uuid.UUID, req UpdateRoles) (OrganizationMember, error) {
res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/organizations/%s/members/%s/roles", organizationID, uuidOrMe(userID)), req)
if err != nil {
return User{}, err
return OrganizationMember{}, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return User{}, readBodyAsError(res)
return OrganizationMember{}, readBodyAsError(res)
}
var user User
return user, json.NewDecoder(res.Body).Decode(&user)
var member OrganizationMember
return member, json.NewDecoder(res.Body).Decode(&member)
}
// GetUserRoles returns all roles the user has

View File

@ -24,6 +24,7 @@ export interface UserResponse {
readonly created_at: string
readonly status: "active" | "suspended"
readonly organization_ids: string[]
readonly roles: { name: string; display_name: string }[]
}
/**

View File

@ -12,7 +12,7 @@ export interface AgentGitSSHKey {
readonly private_key: string
}
// From codersdk/users.go:109:6
// From codersdk/users.go:110:6
export interface AuthMethods {
readonly password: boolean
readonly github: boolean
@ -30,7 +30,7 @@ export interface BuildInfoResponse {
readonly version: string
}
// From codersdk/users.go:50:6
// From codersdk/users.go:51:6
export interface CreateFirstUserRequest {
readonly email: string
readonly username: string
@ -38,13 +38,13 @@ export interface CreateFirstUserRequest {
readonly organization: string
}
// From codersdk/users.go:58:6
// From codersdk/users.go:59:6
export interface CreateFirstUserResponse {
readonly user_id: string
readonly organization_id: string
}
// From codersdk/users.go:104:6
// From codersdk/users.go:105:6
export interface CreateOrganizationRequest {
readonly name: string
}
@ -77,7 +77,7 @@ export interface CreateTemplateVersionRequest {
readonly parameter_values: CreateParameterRequest[]
}
// From codersdk/users.go:63:6
// From codersdk/users.go:64:6
export interface CreateUserRequest {
readonly email: string
readonly username: string
@ -101,7 +101,7 @@ export interface CreateWorkspaceRequest {
readonly parameter_values: CreateParameterRequest[]
}
// From codersdk/users.go:100:6
// From codersdk/users.go:101:6
export interface GenerateAPIKeyResponse {
readonly key: string
}
@ -119,13 +119,13 @@ export interface GoogleInstanceIdentityToken {
readonly json_web_token: string
}
// From codersdk/users.go:89:6
// From codersdk/users.go:90:6
export interface LoginWithPasswordRequest {
readonly email: string
readonly password: string
}
// From codersdk/users.go:95:6
// From codersdk/users.go:96:6
export interface LoginWithPasswordResponse {
readonly session_token: string
}
@ -195,6 +195,12 @@ export interface ProvisionerJobLog {
readonly output: string
}
// From codersdk/roles.go:13:6
export interface Role {
readonly name: string
readonly display_name: string
}
// From codersdk/templates.go:17:6
export interface Template {
readonly id: string
@ -255,17 +261,17 @@ export interface UpdateActiveTemplateVersion {
readonly id: string
}
// From codersdk/users.go:79:6
// From codersdk/users.go:80:6
export interface UpdateRoles {
readonly roles: string[]
}
// From codersdk/users.go:75:6
// From codersdk/users.go:76:6
export interface UpdateUserPasswordRequest {
readonly password: string
}
// From codersdk/users.go:70:6
// From codersdk/users.go:71:6
export interface UpdateUserProfileRequest {
readonly email: string
readonly username: string
@ -294,9 +300,10 @@ export interface User {
readonly username: string
readonly status: UserStatus
readonly organization_ids: string[]
readonly roles: Role[]
}
// From codersdk/users.go:83:6
// From codersdk/users.go:84:6
export interface UserRoles {
readonly roles: string[]
readonly organization_roles: Record<string, string[]>

View File

@ -1,7 +1,6 @@
import { Story } from "@storybook/react"
import React from "react"
import { MockUser } from "../../testHelpers"
import { generateRandomString } from "../../util/random"
import { ResetPasswordDialog, ResetPasswordDialogProps } from "./ResetPasswordDialog"
export default {
@ -19,5 +18,5 @@ export const Example = Template.bind({})
Example.args = {
open: true,
user: MockUser,
newPassword: generateRandomString(12),
newPassword: "somerandomstringhere",
}

View File

@ -37,6 +37,7 @@ describe("AccountPage", () => {
created_at: new Date().toString(),
status: "active",
organization_ids: ["123"],
roles: [],
...data,
}),
)

View File

@ -28,6 +28,7 @@ export const MockUser: UserResponse = {
created_at: "",
status: "active",
organization_ids: ["fc0774ce-cc9e-48d4-80ae-88f7a4d4a8b0"],
roles: [],
}
export const MockUser2: UserResponse = {
@ -37,6 +38,7 @@ export const MockUser2: UserResponse = {
created_at: "",
status: "active",
organization_ids: ["fc0774ce-cc9e-48d4-80ae-88f7a4d4a8b0"],
roles: [],
}
export const MockOrganization: Organization = {