Skip to content

feat: Add permissions for links #1407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 13, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update types
  • Loading branch information
BrunoQuaresma committed May 13, 2022
commit 424a645d5207b07e5f40c66279abf2f53181cc69
4 changes: 2 additions & 2 deletions coderd/roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ func (api *api) checkPermissions(rw http.ResponseWriter, r *http.Request) {
return
}

var params codersdk.UserPermissionCheckRequest
var params codersdk.UserAuthorizationRequest
if !httpapi.Read(rw, r, &params) {
return
}

response := make(codersdk.UserPermissionCheckResponse)
response := make(codersdk.UserAuthorizationResponse)
for k, v := range params.Checks {
if v.Object.ResourceType == "" {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
Expand Down
16 changes: 8 additions & 8 deletions coderd/roles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/coder/coder/codersdk"
)

func TestPermissionCheck(t *testing.T) {
func TestAuthorization(t *testing.T) {
t.Parallel()

client := coderdtest.New(t, nil)
Expand All @@ -28,29 +28,29 @@ func TestPermissionCheck(t *testing.T) {
myself = "read-myself"
myWorkspace = "read-my-workspace"
)
params := map[string]codersdk.UserPermissionCheck{
params := map[string]codersdk.UserAuthorization{
allUsers: {
Object: codersdk.UserPermissionCheckObject{
Object: codersdk.UserAuthorizationObject{
ResourceType: "users",
},
Action: "read",
},
myself: {
Object: codersdk.UserPermissionCheckObject{
Object: codersdk.UserAuthorizationObject{
ResourceType: "users",
OwnerID: "me",
},
Action: "read",
},
myWorkspace: {
Object: codersdk.UserPermissionCheckObject{
Object: codersdk.UserAuthorizationObject{
ResourceType: "workspaces",
OwnerID: "me",
},
Action: "read",
},
readOrgWorkspaces: {
Object: codersdk.UserPermissionCheckObject{
Object: codersdk.UserAuthorizationObject{
ResourceType: "workspaces",
OrganizationID: admin.OrganizationID.String(),
},
Expand All @@ -61,7 +61,7 @@ func TestPermissionCheck(t *testing.T) {
testCases := []struct {
Name string
Client *codersdk.Client
Check codersdk.UserPermissionCheckResponse
Check codersdk.UserAuthorizationResponse
}{
{
Name: "Admin",
Expand Down Expand Up @@ -90,7 +90,7 @@ func TestPermissionCheck(t *testing.T) {
c := c
t.Run(c.Name, func(t *testing.T) {
t.Parallel()
resp, err := c.Client.CheckPermissions(context.Background(), codersdk.UserPermissionCheckRequest{Checks: params})
resp, err := c.Client.CheckPermissions(context.Background(), codersdk.UserAuthorizationRequest{Checks: params})
require.NoError(t, err, "check perms")
require.Equal(t, resp, c.Check)
})
Expand Down
4 changes: 2 additions & 2 deletions codersdk/roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (c *Client) ListOrganizationRoles(ctx context.Context, org uuid.UUID) ([]Ro
return roles, json.NewDecoder(res.Body).Decode(&roles)
}

func (c *Client) CheckPermissions(ctx context.Context, checks UserPermissionCheckRequest) (UserPermissionCheckResponse, error) {
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", uuidOrMe(Me)), checks)
if err != nil {
return nil, err
Expand All @@ -53,6 +53,6 @@ func (c *Client) CheckPermissions(ctx context.Context, checks UserPermissionChec
if res.StatusCode != http.StatusOK {
return nil, readBodyAsError(res)
}
var roles UserPermissionCheckResponse
var roles UserAuthorizationResponse
return roles, json.NewDecoder(res.Body).Decode(&roles)
}
16 changes: 8 additions & 8 deletions codersdk/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,23 @@ type UserRoles struct {
OrganizationRoles map[uuid.UUID][]string `json:"organization_roles"`
}

type UserPermissionCheckResponse map[string]bool
type UserAuthorizationResponse map[string]bool

// UserPermissionCheckRequest is a structure instead of a map because
// UserAuthorizationRequest is a structure instead of a map because
// go-playground/validate can only validate structs. If you attempt to pass
// a map into 'httpapi.Read', you will get an invalid type error.
type UserPermissionCheckRequest struct {
type UserAuthorizationRequest struct {
// Checks is a map keyed with an arbitrary string to a permission check.
// The key can be any string that is helpful to the caller, and allows
// multiple permission checks to be run in a single request.
// The key ensures that each permission check has the same key in the
// response.
Checks map[string]UserPermissionCheck `json:"checks"`
Checks map[string]UserAuthorization `json:"checks"`
}

// UserPermissionCheck is used to check if a user can do a given action
// UserAuthorization is used to check if a user can do a given action
// to a given set of objects.
type UserPermissionCheck struct {
type UserAuthorization struct {
// Object can represent a "set" of objects, such as:
// - All workspaces in an organization
// - All workspaces owned by me
Expand All @@ -103,12 +103,12 @@ type UserPermissionCheck struct {
// owned by 'me', try to also add an 'OrganizationID' to the settings.
// Omitting the 'OrganizationID' could produce the incorrect value, as
// workspaces have both `user` and `organization` owners.
Object UserPermissionCheckObject `json:"object"`
Object UserAuthorizationObject `json:"object"`
// Action can be 'create', 'read', 'update', or 'delete'
Action string `json:"action"`
}

type UserPermissionCheckObject struct {
type UserAuthorizationObject struct {
// ResourceType is the name of the resource.
// './coderd/rbac/object.go' has the list of valid resource types.
ResourceType string `json:"resource_type"`
Expand Down
9 changes: 3 additions & 6 deletions site/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,9 @@ export const getAuthMethods = async (): Promise<TypesGen.AuthMethods> => {

export const checkUserPermissions = async (
userId: string,
params: TypesGen.UserPermissionCheckRequest,
): Promise<TypesGen.UserPermissionCheckResponse> => {
const response = await axios.post<TypesGen.UserPermissionCheckResponse>(
`/api/v2/users/${userId}/authorization`,
params,
)
params: TypesGen.UserAuthorizationRequest,
): Promise<TypesGen.UserAuthorizationResponse> => {
const response = await axios.post<TypesGen.UserAuthorizationResponse>(`/api/v2/users/${userId}/authorization`, params)
return response.data
}

Expand Down
12 changes: 6 additions & 6 deletions site/src/api/typesGenerated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,26 +316,26 @@ export interface User {
}

// From codersdk/users.go:95:6
export interface UserPermissionCheck {
readonly object: UserPermissionCheckObject
export interface UserAuthorization {
readonly object: UserAuthorizationObject
readonly action: string
}

// From codersdk/users.go:111:6
export interface UserPermissionCheckObject {
export interface UserAuthorizationObject {
readonly resource_type: string
readonly owner_id?: string
readonly organization_id?: string
readonly resource_id?: string
}

// From codersdk/users.go:84:6
export interface UserPermissionCheckRequest {
readonly checks: Record<string, UserPermissionCheck>
export interface UserAuthorizationRequest {
readonly checks: Record<string, UserAuthorization>
}

// From codersdk/users.go:79:6
export type UserPermissionCheckResponse = Record<string, boolean>
export type UserAuthorizationResponse = Record<string, boolean>

// From codersdk/users.go:74:6
export interface UserRoles {
Expand Down
4 changes: 2 additions & 2 deletions site/src/components/Navbar/Navbar.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { screen, waitFor } from "@testing-library/react"
import React from "react"
import * as API from "../../api"
import { renderWithAuth } from "../../testHelpers"
import * as API from "../../api/api"
import { renderWithAuth } from "../../testHelpers/renderHelpers"
import { checks } from "../../xServices/auth/authXService"
import { Language as AdminDropdownLanguage } from "../AdminDropdown/AdminDropdown"
import { Navbar } from "./Navbar"
Expand Down
2 changes: 1 addition & 1 deletion site/src/xServices/auth/authXService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const authMachine =
data: TypesGen.User
}
checkPermissions: {
data: TypesGen.UserPermissionCheckResponse
data: TypesGen.UserAuthorizationResponse
}
},
},
Expand Down