feat: Rbac more coderd endpoints, unit test to confirm (#1437)

* feat: Enforce authorize call on all endpoints
- Make 'request()' exported for running custom requests
* Rbac users endpoints
* 401 -> 403
This commit is contained in:
Steven Masley
2022-05-17 13:43:19 -05:00
committed by GitHub
parent 495c87b6c3
commit 4ad5ac2d4a
40 changed files with 631 additions and 319 deletions

View File

@ -18,7 +18,7 @@ type BuildInfoResponse struct {
// BuildInfo returns build information for this instance of Coder.
func (c *Client) BuildInfo(ctx context.Context) (BuildInfoResponse, error) {
res, err := c.request(ctx, http.MethodGet, "/api/v2/buildinfo", nil)
res, err := c.Request(ctx, http.MethodGet, "/api/v2/buildinfo", nil)
if err != nil {
return BuildInfoResponse{}, err
}

View File

@ -35,9 +35,9 @@ type Client struct {
type requestOption func(*http.Request)
// request performs an HTTP request with the body provided.
// Request performs an HTTP request with the body provided.
// The caller is responsible for closing the response body.
func (c *Client) request(ctx context.Context, method, path string, body interface{}, opts ...requestOption) (*http.Response, error) {
func (c *Client) Request(ctx context.Context, method, path string, body interface{}, opts ...requestOption) (*http.Response, error) {
serverURL, err := c.URL.Parse(path)
if err != nil {
return nil, xerrors.Errorf("parse url: %w", err)

View File

@ -20,7 +20,7 @@ type UploadResponse struct {
// Upload uploads an arbitrary file with the content type provided.
// This is used to upload a source-code archive.
func (c *Client) Upload(ctx context.Context, contentType string, content []byte) (UploadResponse, error) {
res, err := c.request(ctx, http.MethodPost, "/api/v2/files", content, func(r *http.Request) {
res, err := c.Request(ctx, http.MethodPost, "/api/v2/files", content, func(r *http.Request) {
r.Header.Set("Content-Type", contentType)
})
if err != nil {
@ -36,7 +36,7 @@ func (c *Client) Upload(ctx context.Context, contentType string, content []byte)
// Download fetches a file by uploaded hash.
func (c *Client) Download(ctx context.Context, hash string) ([]byte, string, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/files/%s", hash), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/files/%s", hash), nil)
if err != nil {
return nil, "", err
}

View File

@ -25,7 +25,7 @@ type AgentGitSSHKey struct {
// GitSSHKey returns the user's git SSH public key.
func (c *Client) GitSSHKey(ctx context.Context, user string) (GitSSHKey, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/gitsshkey", user), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/gitsshkey", user), nil)
if err != nil {
return GitSSHKey{}, xerrors.Errorf("execute request: %w", err)
}
@ -41,7 +41,7 @@ func (c *Client) GitSSHKey(ctx context.Context, user string) (GitSSHKey, error)
// RegenerateGitSSHKey will create a new SSH key pair for the user and return it.
func (c *Client) RegenerateGitSSHKey(ctx context.Context, user string) (GitSSHKey, error) {
res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/gitsshkey", user), nil)
res, err := c.Request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/gitsshkey", user), nil)
if err != nil {
return GitSSHKey{}, xerrors.Errorf("execute request: %w", err)
}
@ -57,7 +57,7 @@ func (c *Client) RegenerateGitSSHKey(ctx context.Context, user string) (GitSSHKe
// AgentGitSSHKey will return the user's SSH key pair for the workspace.
func (c *Client) AgentGitSSHKey(ctx context.Context) (AgentGitSSHKey, error) {
res, err := c.request(ctx, http.MethodGet, "/api/v2/workspaceagents/me/gitsshkey", nil)
res, err := c.Request(ctx, http.MethodGet, "/api/v2/workspaceagents/me/gitsshkey", nil)
if err != nil {
return AgentGitSSHKey{}, xerrors.Errorf("execute request: %w", err)
}

View File

@ -62,7 +62,7 @@ type CreateWorkspaceRequest struct {
}
func (c *Client) Organization(ctx context.Context, id uuid.UUID) (Organization, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s", id.String()), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s", id.String()), nil)
if err != nil {
return Organization{}, xerrors.Errorf("execute request: %w", err)
}
@ -78,7 +78,7 @@ func (c *Client) Organization(ctx context.Context, id uuid.UUID) (Organization,
// ProvisionerDaemonsByOrganization returns provisioner daemons available for an organization.
func (c *Client) ProvisionerDaemonsByOrganization(ctx context.Context, organizationID uuid.UUID) ([]ProvisionerDaemon, error) {
res, err := c.request(ctx, http.MethodGet,
res, err := c.Request(ctx, http.MethodGet,
fmt.Sprintf("/api/v2/organizations/%s/provisionerdaemons", organizationID.String()),
nil,
)
@ -98,7 +98,7 @@ func (c *Client) ProvisionerDaemonsByOrganization(ctx context.Context, organizat
// CreateTemplateVersion processes source-code and optionally associates the version with a template.
// Executing without a template is useful for validating source-code.
func (c *Client) CreateTemplateVersion(ctx context.Context, organizationID uuid.UUID, req CreateTemplateVersionRequest) (TemplateVersion, error) {
res, err := c.request(ctx, http.MethodPost,
res, err := c.Request(ctx, http.MethodPost,
fmt.Sprintf("/api/v2/organizations/%s/templateversions", organizationID.String()),
req,
)
@ -117,7 +117,7 @@ func (c *Client) CreateTemplateVersion(ctx context.Context, organizationID uuid.
// CreateTemplate creates a new template inside an organization.
func (c *Client) CreateTemplate(ctx context.Context, organizationID uuid.UUID, request CreateTemplateRequest) (Template, error) {
res, err := c.request(ctx, http.MethodPost,
res, err := c.Request(ctx, http.MethodPost,
fmt.Sprintf("/api/v2/organizations/%s/templates", organizationID.String()),
request,
)
@ -136,7 +136,7 @@ func (c *Client) CreateTemplate(ctx context.Context, organizationID uuid.UUID, r
// TemplatesByOrganization lists all templates inside of an organization.
func (c *Client) TemplatesByOrganization(ctx context.Context, organizationID uuid.UUID) ([]Template, error) {
res, err := c.request(ctx, http.MethodGet,
res, err := c.Request(ctx, http.MethodGet,
fmt.Sprintf("/api/v2/organizations/%s/templates", organizationID.String()),
nil,
)
@ -155,7 +155,7 @@ func (c *Client) TemplatesByOrganization(ctx context.Context, organizationID uui
// TemplateByName finds a template inside the organization provided with a case-insensitive name.
func (c *Client) TemplateByName(ctx context.Context, organizationID uuid.UUID, name string) (Template, error) {
res, err := c.request(ctx, http.MethodGet,
res, err := c.Request(ctx, http.MethodGet,
fmt.Sprintf("/api/v2/organizations/%s/templates/%s", organizationID.String(), name),
nil,
)
@ -174,7 +174,7 @@ func (c *Client) TemplateByName(ctx context.Context, organizationID uuid.UUID, n
// CreateWorkspace creates a new workspace for the template specified.
func (c *Client) CreateWorkspace(ctx context.Context, organizationID uuid.UUID, request CreateWorkspaceRequest) (Workspace, error) {
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/organizations/%s/workspaces", organizationID), request)
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/organizations/%s/workspaces", organizationID), request)
if err != nil {
return Workspace{}, err
}
@ -190,7 +190,7 @@ func (c *Client) CreateWorkspace(ctx context.Context, organizationID uuid.UUID,
// WorkspacesByOrganization returns all workspaces in the specified organization.
func (c *Client) WorkspacesByOrganization(ctx context.Context, organizationID uuid.UUID) ([]Workspace, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/workspaces", organizationID), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/workspaces", organizationID), nil)
if err != nil {
return nil, err
}
@ -206,7 +206,7 @@ func (c *Client) WorkspacesByOrganization(ctx context.Context, organizationID uu
// WorkspacesByOwner returns all workspaces contained in the organization owned by the user.
func (c *Client) WorkspacesByOwner(ctx context.Context, organizationID uuid.UUID, user string) ([]Workspace, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/workspaces/%s", organizationID, user), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/workspaces/%s", organizationID, user), nil)
if err != nil {
return nil, err
}
@ -222,7 +222,7 @@ func (c *Client) WorkspacesByOwner(ctx context.Context, organizationID uuid.UUID
// WorkspaceByOwnerAndName returns a workspace by the owner's UUID and the workspace's name.
func (c *Client) WorkspaceByOwnerAndName(ctx context.Context, organization uuid.UUID, owner string, name string) (Workspace, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/workspaces/%s/%s", organization, owner, name), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/workspaces/%s/%s", organization, owner, name), nil)
if err != nil {
return Workspace{}, err
}

View File

@ -26,7 +26,7 @@ type Pagination struct {
Offset int `json:"offset,omitempty"`
}
// asRequestOption returns a function that can be used in (*Client).request.
// asRequestOption returns a function that can be used in (*Client).Request.
// It modifies the request query parameters.
func (p Pagination) asRequestOption() requestOption {
return func(r *http.Request) {

View File

@ -43,7 +43,7 @@ type CreateParameterRequest struct {
}
func (c *Client) CreateParameter(ctx context.Context, scope ParameterScope, id uuid.UUID, req CreateParameterRequest) (Parameter, error) {
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/parameters/%s/%s", scope, id.String()), req)
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/parameters/%s/%s", scope, id.String()), req)
if err != nil {
return Parameter{}, err
}
@ -58,7 +58,7 @@ func (c *Client) CreateParameter(ctx context.Context, scope ParameterScope, id u
}
func (c *Client) DeleteParameter(ctx context.Context, scope ParameterScope, id uuid.UUID, name string) error {
res, err := c.request(ctx, http.MethodDelete, fmt.Sprintf("/api/v2/parameters/%s/%s/%s", scope, id.String(), name), nil)
res, err := c.Request(ctx, http.MethodDelete, fmt.Sprintf("/api/v2/parameters/%s/%s/%s", scope, id.String(), name), nil)
if err != nil {
return err
}
@ -73,7 +73,7 @@ func (c *Client) DeleteParameter(ctx context.Context, scope ParameterScope, id u
}
func (c *Client) Parameters(ctx context.Context, scope ParameterScope, id uuid.UUID) ([]Parameter, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/parameters/%s/%s", scope, id.String()), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/parameters/%s/%s", scope, id.String()), nil)
if err != nil {
return nil, err
}

View File

@ -99,7 +99,7 @@ func (c *Client) provisionerJobLogsBefore(ctx context.Context, path string, befo
if !before.IsZero() {
values["before"] = []string{strconv.FormatInt(before.UTC().UnixMilli(), 10)}
}
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("%s?%s", path, values.Encode()), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("%s?%s", path, values.Encode()), nil)
if err != nil {
return nil, err
}
@ -118,7 +118,7 @@ func (c *Client) provisionerJobLogsAfter(ctx context.Context, path string, after
if !after.IsZero() {
afterQuery = fmt.Sprintf("&after=%d", after.UTC().UnixMilli())
}
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("%s?follow%s", path, afterQuery), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("%s?follow%s", path, afterQuery), nil)
if err != nil {
return nil, err
}

View File

@ -17,7 +17,7 @@ type Role struct {
// ListSiteRoles lists all available site wide roles.
// This is not user specific.
func (c *Client) ListSiteRoles(ctx context.Context) ([]Role, error) {
res, err := c.request(ctx, http.MethodGet, "/api/v2/users/roles", nil)
res, err := c.Request(ctx, http.MethodGet, "/api/v2/users/roles", nil)
if err != nil {
return nil, err
}
@ -32,7 +32,7 @@ func (c *Client) ListSiteRoles(ctx context.Context) ([]Role, error) {
// ListOrganizationRoles lists all available roles for a given organization.
// This is not user specific.
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)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/members/roles", org.String()), nil)
if err != nil {
return nil, err
}
@ -45,7 +45,7 @@ func (c *Client) ListOrganizationRoles(ctx context.Context, org uuid.UUID) ([]Ro
}
func (c *Client) CheckPermissions(ctx context.Context, checks UserAuthorizationRequest) (UserAuthorizationResponse, error) {
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/authorization", Me), checks)
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/authorization", Me), checks)
if err != nil {
return nil, err
}

View File

@ -32,7 +32,7 @@ type UpdateActiveTemplateVersion struct {
// Template returns a single template.
func (c *Client) Template(ctx context.Context, template uuid.UUID) (Template, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templates/%s", template), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templates/%s", template), nil)
if err != nil {
return Template{}, nil
}
@ -45,7 +45,7 @@ func (c *Client) Template(ctx context.Context, template uuid.UUID) (Template, er
}
func (c *Client) DeleteTemplate(ctx context.Context, template uuid.UUID) error {
res, err := c.request(ctx, http.MethodDelete, fmt.Sprintf("/api/v2/templates/%s", template), nil)
res, err := c.Request(ctx, http.MethodDelete, fmt.Sprintf("/api/v2/templates/%s", template), nil)
if err != nil {
return err
}
@ -59,7 +59,7 @@ func (c *Client) DeleteTemplate(ctx context.Context, template uuid.UUID) error {
// UpdateActiveTemplateVersion updates the active template version to the ID provided.
// The template version must be attached to the template.
func (c *Client) UpdateActiveTemplateVersion(ctx context.Context, template uuid.UUID, req UpdateActiveTemplateVersion) error {
res, err := c.request(ctx, http.MethodPatch, fmt.Sprintf("/api/v2/templates/%s/versions", template), req)
res, err := c.Request(ctx, http.MethodPatch, fmt.Sprintf("/api/v2/templates/%s/versions", template), req)
if err != nil {
return nil
}
@ -79,7 +79,7 @@ type TemplateVersionsByTemplateRequest struct {
// TemplateVersionsByTemplate lists versions associated with a template.
func (c *Client) TemplateVersionsByTemplate(ctx context.Context, req TemplateVersionsByTemplateRequest) ([]TemplateVersion, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templates/%s/versions", req.TemplateID), nil, req.Pagination.asRequestOption())
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templates/%s/versions", req.TemplateID), nil, req.Pagination.asRequestOption())
if err != nil {
return nil, err
}
@ -94,7 +94,7 @@ func (c *Client) TemplateVersionsByTemplate(ctx context.Context, req TemplateVer
// TemplateVersionByName returns a template version by it's friendly name.
// This is used for path-based routing. Like: /templates/example/versions/helloworld
func (c *Client) TemplateVersionByName(ctx context.Context, template uuid.UUID, name string) (TemplateVersion, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templates/%s/versions/%s", template, name), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templates/%s/versions/%s", template, name), nil)
if err != nil {
return TemplateVersion{}, err
}

View File

@ -31,7 +31,7 @@ type TemplateVersionParameter parameter.ComputedValue
// TemplateVersion returns a template version by ID.
func (c *Client) TemplateVersion(ctx context.Context, id uuid.UUID) (TemplateVersion, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s", id), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s", id), nil)
if err != nil {
return TemplateVersion{}, err
}
@ -45,7 +45,7 @@ func (c *Client) TemplateVersion(ctx context.Context, id uuid.UUID) (TemplateVer
// CancelTemplateVersion marks a template version job as canceled.
func (c *Client) CancelTemplateVersion(ctx context.Context, version uuid.UUID) error {
res, err := c.request(ctx, http.MethodPatch, fmt.Sprintf("/api/v2/templateversions/%s/cancel", version), nil)
res, err := c.Request(ctx, http.MethodPatch, fmt.Sprintf("/api/v2/templateversions/%s/cancel", version), nil)
if err != nil {
return err
}
@ -58,7 +58,7 @@ func (c *Client) CancelTemplateVersion(ctx context.Context, version uuid.UUID) e
// TemplateVersionSchema returns schemas for a template version by ID.
func (c *Client) TemplateVersionSchema(ctx context.Context, version uuid.UUID) ([]TemplateVersionParameterSchema, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/schema", version), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/schema", version), nil)
if err != nil {
return nil, err
}
@ -72,7 +72,7 @@ func (c *Client) TemplateVersionSchema(ctx context.Context, version uuid.UUID) (
// TemplateVersionParameters returns computed parameters for a template version.
func (c *Client) TemplateVersionParameters(ctx context.Context, version uuid.UUID) ([]TemplateVersionParameter, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/parameters", version), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/parameters", version), nil)
if err != nil {
return nil, err
}
@ -86,7 +86,7 @@ func (c *Client) TemplateVersionParameters(ctx context.Context, version uuid.UUI
// TemplateVersionResources returns resources a template version declares.
func (c *Client) TemplateVersionResources(ctx context.Context, version uuid.UUID) ([]WorkspaceResource, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/resources", version), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/resources", version), nil)
if err != nil {
return nil, err
}

View File

@ -155,7 +155,7 @@ type AuthMethods struct {
// HasFirstUser returns whether the first user has been created.
func (c *Client) HasFirstUser(ctx context.Context) (bool, error) {
res, err := c.request(ctx, http.MethodGet, "/api/v2/users/first", nil)
res, err := c.Request(ctx, http.MethodGet, "/api/v2/users/first", nil)
if err != nil {
return false, err
}
@ -172,7 +172,7 @@ func (c *Client) HasFirstUser(ctx context.Context) (bool, error) {
// CreateFirstUser attempts to create the first user on a Coder deployment.
// This initial user has superadmin privileges. If >0 users exist, this request will fail.
func (c *Client) CreateFirstUser(ctx context.Context, req CreateFirstUserRequest) (CreateFirstUserResponse, error) {
res, err := c.request(ctx, http.MethodPost, "/api/v2/users/first", req)
res, err := c.Request(ctx, http.MethodPost, "/api/v2/users/first", req)
if err != nil {
return CreateFirstUserResponse{}, err
}
@ -186,7 +186,7 @@ func (c *Client) CreateFirstUser(ctx context.Context, req CreateFirstUserRequest
// CreateUser creates a new user.
func (c *Client) CreateUser(ctx context.Context, req CreateUserRequest) (User, error) {
res, err := c.request(ctx, http.MethodPost, "/api/v2/users", req)
res, err := c.Request(ctx, http.MethodPost, "/api/v2/users", req)
if err != nil {
return User{}, err
}
@ -200,7 +200,7 @@ func (c *Client) CreateUser(ctx context.Context, req CreateUserRequest) (User, e
// UpdateUserProfile enables callers to update profile information
func (c *Client) UpdateUserProfile(ctx context.Context, user string, req UpdateUserProfileRequest) (User, error) {
res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/profile", user), req)
res, err := c.Request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/profile", user), req)
if err != nil {
return User{}, err
}
@ -224,7 +224,7 @@ func (c *Client) UpdateUserStatus(ctx context.Context, user string, status UserS
return User{}, xerrors.Errorf("status %q is not supported", status)
}
res, err := c.request(ctx, http.MethodPut, path, nil)
res, err := c.Request(ctx, http.MethodPut, path, nil)
if err != nil {
return User{}, err
}
@ -240,7 +240,7 @@ func (c *Client) UpdateUserStatus(ctx context.Context, user string, status UserS
// UpdateUserPassword updates a user password.
// It calls PUT /users/{user}/password
func (c *Client) UpdateUserPassword(ctx context.Context, user string, req UpdateUserPasswordRequest) error {
res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/password", user), req)
res, err := c.Request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/password", user), req)
if err != nil {
return err
}
@ -254,7 +254,7 @@ func (c *Client) UpdateUserPassword(ctx context.Context, user string, req Update
// UpdateUserRoles grants the userID the specified roles.
// Include ALL roles the user has.
func (c *Client) UpdateUserRoles(ctx context.Context, user string, req UpdateRoles) (User, error) {
res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/roles", user), req)
res, err := c.Request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/roles", user), req)
if err != nil {
return User{}, err
}
@ -269,7 +269,7 @@ func (c *Client) UpdateUserRoles(ctx context.Context, user string, req UpdateRol
// UpdateOrganizationMemberRoles grants the userID the specified roles in an org.
// Include ALL roles the user has.
func (c *Client) UpdateOrganizationMemberRoles(ctx context.Context, organizationID uuid.UUID, user string, req UpdateRoles) (OrganizationMember, error) {
res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/organizations/%s/members/%s/roles", organizationID, user), req)
res, err := c.Request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/organizations/%s/members/%s/roles", organizationID, user), req)
if err != nil {
return OrganizationMember{}, err
}
@ -283,7 +283,7 @@ func (c *Client) UpdateOrganizationMemberRoles(ctx context.Context, organization
// GetUserRoles returns all roles the user has
func (c *Client) GetUserRoles(ctx context.Context, user string) (UserRoles, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/roles", user), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/roles", user), nil)
if err != nil {
return UserRoles{}, err
}
@ -297,7 +297,7 @@ func (c *Client) GetUserRoles(ctx context.Context, user string) (UserRoles, erro
// CreateAPIKey generates an API key for the user ID provided.
func (c *Client) CreateAPIKey(ctx context.Context, user string) (*GenerateAPIKeyResponse, error) {
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/keys", user), nil)
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/keys", user), nil)
if err != nil {
return nil, err
}
@ -312,7 +312,7 @@ func (c *Client) CreateAPIKey(ctx context.Context, user string) (*GenerateAPIKey
// LoginWithPassword creates a session token authenticating with an email and password.
// Call `SetSessionToken()` to apply the newly acquired token to the client.
func (c *Client) LoginWithPassword(ctx context.Context, req LoginWithPasswordRequest) (LoginWithPasswordResponse, error) {
res, err := c.request(ctx, http.MethodPost, "/api/v2/users/login", req)
res, err := c.Request(ctx, http.MethodPost, "/api/v2/users/login", req)
if err != nil {
return LoginWithPasswordResponse{}, err
}
@ -333,7 +333,7 @@ func (c *Client) LoginWithPassword(ctx context.Context, req LoginWithPasswordReq
func (c *Client) Logout(ctx context.Context) error {
// Since `LoginWithPassword` doesn't actually set a SessionToken
// (it requires a call to SetSessionToken), this is essentially a no-op
res, err := c.request(ctx, http.MethodPost, "/api/v2/users/logout", nil)
res, err := c.Request(ctx, http.MethodPost, "/api/v2/users/logout", nil)
if err != nil {
return err
}
@ -343,7 +343,7 @@ func (c *Client) Logout(ctx context.Context) error {
// User returns a user for the ID/username provided.
func (c *Client) User(ctx context.Context, userIdent string) (User, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s", userIdent), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s", userIdent), nil)
if err != nil {
return User{}, err
}
@ -358,7 +358,7 @@ func (c *Client) User(ctx context.Context, userIdent string) (User, error) {
// Users returns all users according to the request parameters. If no parameters are set,
// the default behavior is to return all users in a single page.
func (c *Client) Users(ctx context.Context, req UsersRequest) ([]User, error) {
res, err := c.request(ctx, http.MethodGet, "/api/v2/users", nil,
res, err := c.Request(ctx, http.MethodGet, "/api/v2/users", nil,
req.Pagination.asRequestOption(),
func(r *http.Request) {
q := r.URL.Query()
@ -382,7 +382,7 @@ func (c *Client) Users(ctx context.Context, req UsersRequest) ([]User, error) {
// OrganizationsByUser returns all organizations the user is a member of.
func (c *Client) OrganizationsByUser(ctx context.Context, user string) ([]Organization, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations", user), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations", user), nil)
if err != nil {
return nil, err
}
@ -395,7 +395,7 @@ func (c *Client) OrganizationsByUser(ctx context.Context, user string) ([]Organi
}
func (c *Client) OrganizationByName(ctx context.Context, user string, name string) (Organization, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations/%s", user, name), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations/%s", user, name), nil)
if err != nil {
return Organization{}, err
}
@ -409,7 +409,7 @@ func (c *Client) OrganizationByName(ctx context.Context, user string, name strin
// CreateOrganization creates an organization and adds the provided user as an admin.
func (c *Client) CreateOrganization(ctx context.Context, user string, req CreateOrganizationRequest) (Organization, error) {
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/organizations", user), req)
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/organizations", user), req)
if err != nil {
return Organization{}, err
}
@ -425,7 +425,7 @@ func (c *Client) CreateOrganization(ctx context.Context, user string, req Create
// AuthMethods returns types of authentication available to the user.
func (c *Client) AuthMethods(ctx context.Context) (AuthMethods, error) {
res, err := c.request(ctx, http.MethodGet, "/api/v2/users/authmethods", nil)
res, err := c.Request(ctx, http.MethodGet, "/api/v2/users/authmethods", nil)
if err != nil {
return AuthMethods{}, err
}
@ -441,7 +441,7 @@ func (c *Client) AuthMethods(ctx context.Context) (AuthMethods, error) {
// WorkspacesByUser returns all workspaces a user has access to.
func (c *Client) WorkspacesByUser(ctx context.Context, user string) ([]Workspace, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/workspaces", user), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/workspaces", user), nil)
if err != nil {
return nil, err
}

View File

@ -65,7 +65,7 @@ func (c *Client) AuthWorkspaceGoogleInstanceIdentity(ctx context.Context, servic
if err != nil {
return WorkspaceAgentAuthenticateResponse{}, xerrors.Errorf("get metadata identity: %w", err)
}
res, err := c.request(ctx, http.MethodPost, "/api/v2/workspaceagents/google-instance-identity", GoogleInstanceIdentityToken{
res, err := c.Request(ctx, http.MethodPost, "/api/v2/workspaceagents/google-instance-identity", GoogleInstanceIdentityToken{
JSONWebToken: jwt,
})
if err != nil {
@ -129,7 +129,7 @@ func (c *Client) AuthWorkspaceAWSInstanceIdentity(ctx context.Context) (Workspac
return WorkspaceAgentAuthenticateResponse{}, xerrors.Errorf("read token: %w", err)
}
res, err = c.request(ctx, http.MethodPost, "/api/v2/workspaceagents/aws-instance-identity", AWSInstanceIdentityToken{
res, err = c.Request(ctx, http.MethodPost, "/api/v2/workspaceagents/aws-instance-identity", AWSInstanceIdentityToken{
Signature: string(signature),
Document: string(document),
})
@ -164,7 +164,7 @@ func (c *Client) AuthWorkspaceAzureInstanceIdentity(ctx context.Context) (Worksp
return WorkspaceAgentAuthenticateResponse{}, err
}
res, err = c.request(ctx, http.MethodPost, "/api/v2/workspaceagents/azure-instance-identity", token)
res, err = c.Request(ctx, http.MethodPost, "/api/v2/workspaceagents/azure-instance-identity", token)
if err != nil {
return WorkspaceAgentAuthenticateResponse{}, err
}
@ -213,7 +213,7 @@ func (c *Client) ListenWorkspaceAgent(ctx context.Context, logger slog.Logger) (
}
listener, err := peerbroker.Listen(session, func(ctx context.Context) ([]webrtc.ICEServer, *peer.ConnOptions, error) {
// This can be cached if it adds to latency too much.
res, err := c.request(ctx, http.MethodGet, "/api/v2/workspaceagents/me/iceservers", nil)
res, err := c.Request(ctx, http.MethodGet, "/api/v2/workspaceagents/me/iceservers", nil)
if err != nil {
return nil, nil, err
}
@ -240,7 +240,7 @@ func (c *Client) ListenWorkspaceAgent(ctx context.Context, logger slog.Logger) (
if err != nil {
return agent.Metadata{}, nil, xerrors.Errorf("listen peerbroker: %w", err)
}
res, err = c.request(ctx, http.MethodGet, "/api/v2/workspaceagents/me/metadata", nil)
res, err = c.Request(ctx, http.MethodGet, "/api/v2/workspaceagents/me/metadata", nil)
if err != nil {
return agent.Metadata{}, nil, err
}
@ -292,7 +292,7 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti
return nil, xerrors.Errorf("negotiate connection: %w", err)
}
res, err = c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaceagents/%s/iceservers", agentID.String()), nil)
res, err = c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaceagents/%s/iceservers", agentID.String()), nil)
if err != nil {
return nil, err
}
@ -326,7 +326,7 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti
// WorkspaceAgent returns an agent by ID.
func (c *Client) WorkspaceAgent(ctx context.Context, id uuid.UUID) (WorkspaceAgent, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaceagents/%s", id), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaceagents/%s", id), nil)
if err != nil {
return WorkspaceAgent{}, err
}

View File

@ -32,7 +32,7 @@ type WorkspaceBuild struct {
// WorkspaceBuild returns a single workspace build for a workspace.
// If history is "", the latest version is returned.
func (c *Client) WorkspaceBuild(ctx context.Context, id uuid.UUID) (WorkspaceBuild, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspacebuilds/%s", id), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspacebuilds/%s", id), nil)
if err != nil {
return WorkspaceBuild{}, err
}
@ -46,7 +46,7 @@ func (c *Client) WorkspaceBuild(ctx context.Context, id uuid.UUID) (WorkspaceBui
// CancelWorkspaceBuild marks a workspace build job as canceled.
func (c *Client) CancelWorkspaceBuild(ctx context.Context, id uuid.UUID) error {
res, err := c.request(ctx, http.MethodPatch, fmt.Sprintf("/api/v2/workspacebuilds/%s/cancel", id), nil)
res, err := c.Request(ctx, http.MethodPatch, fmt.Sprintf("/api/v2/workspacebuilds/%s/cancel", id), nil)
if err != nil {
return err
}
@ -59,7 +59,7 @@ func (c *Client) CancelWorkspaceBuild(ctx context.Context, id uuid.UUID) error {
// WorkspaceResourcesByBuild returns resources for a workspace build.
func (c *Client) WorkspaceResourcesByBuild(ctx context.Context, build uuid.UUID) ([]WorkspaceResource, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspacebuilds/%s/resources", build), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspacebuilds/%s/resources", build), nil)
if err != nil {
return nil, err
}
@ -83,7 +83,7 @@ func (c *Client) WorkspaceBuildLogsAfter(ctx context.Context, build uuid.UUID, a
// WorkspaceBuildState returns the provisioner state of the build.
func (c *Client) WorkspaceBuildState(ctx context.Context, build uuid.UUID) ([]byte, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspacebuilds/%s/state", build), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspacebuilds/%s/state", build), nil)
if err != nil {
return nil, err
}

View File

@ -69,7 +69,7 @@ type WorkspaceAgentInstanceMetadata struct {
}
func (c *Client) WorkspaceResource(ctx context.Context, id uuid.UUID) (WorkspaceResource, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaceresources/%s", id), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaceresources/%s", id), nil)
if err != nil {
return WorkspaceResource{}, err
}

View File

@ -40,7 +40,7 @@ type CreateWorkspaceBuildRequest struct {
// Workspace returns a single workspace.
func (c *Client) Workspace(ctx context.Context, id uuid.UUID) (Workspace, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaces/%s", id), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaces/%s", id), nil)
if err != nil {
return Workspace{}, err
}
@ -53,7 +53,7 @@ func (c *Client) Workspace(ctx context.Context, id uuid.UUID) (Workspace, error)
}
func (c *Client) WorkspaceBuilds(ctx context.Context, workspace uuid.UUID) ([]WorkspaceBuild, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaces/%s/builds", workspace), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaces/%s/builds", workspace), nil)
if err != nil {
return nil, err
}
@ -67,7 +67,7 @@ func (c *Client) WorkspaceBuilds(ctx context.Context, workspace uuid.UUID) ([]Wo
// CreateWorkspaceBuild queues a new build to occur for a workspace.
func (c *Client) CreateWorkspaceBuild(ctx context.Context, workspace uuid.UUID, request CreateWorkspaceBuildRequest) (WorkspaceBuild, error) {
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/workspaces/%s/builds", workspace), request)
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/workspaces/%s/builds", workspace), request)
if err != nil {
return WorkspaceBuild{}, err
}
@ -80,7 +80,7 @@ func (c *Client) CreateWorkspaceBuild(ctx context.Context, workspace uuid.UUID,
}
func (c *Client) WorkspaceBuildByName(ctx context.Context, workspace uuid.UUID, name string) (WorkspaceBuild, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaces/%s/builds/%s", workspace, name), nil)
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaces/%s/builds/%s", workspace, name), nil)
if err != nil {
return WorkspaceBuild{}, err
}
@ -101,7 +101,7 @@ type UpdateWorkspaceAutostartRequest struct {
// If the provided schedule is empty, autostart is disabled for the workspace.
func (c *Client) UpdateWorkspaceAutostart(ctx context.Context, id uuid.UUID, req UpdateWorkspaceAutostartRequest) error {
path := fmt.Sprintf("/api/v2/workspaces/%s/autostart", id.String())
res, err := c.request(ctx, http.MethodPut, path, req)
res, err := c.Request(ctx, http.MethodPut, path, req)
if err != nil {
return xerrors.Errorf("update workspace autostart: %w", err)
}
@ -121,7 +121,7 @@ type UpdateWorkspaceAutostopRequest struct {
// If the provided schedule is empty, autostop is disabled for the workspace.
func (c *Client) UpdateWorkspaceAutostop(ctx context.Context, id uuid.UUID, req UpdateWorkspaceAutostopRequest) error {
path := fmt.Sprintf("/api/v2/workspaces/%s/autostop", id.String())
res, err := c.request(ctx, http.MethodPut, path, req)
res, err := c.Request(ctx, http.MethodPut, path, req)
if err != nil {
return xerrors.Errorf("update workspace autostop: %w", err)
}