mirror of
https://github.com/coder/coder.git
synced 2025-07-13 21:36:50 +00:00
refactor: Add roles into the user response (#1347)
This commit is contained in:
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 }[]
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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[]>
|
||||
|
@ -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",
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ describe("AccountPage", () => {
|
||||
created_at: new Date().toString(),
|
||||
status: "active",
|
||||
organization_ids: ["123"],
|
||||
roles: [],
|
||||
...data,
|
||||
}),
|
||||
)
|
||||
|
@ -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 = {
|
||||
|
Reference in New Issue
Block a user