The source headers, LICENSE files, and license metadata had drifted apart. Align the entire project to MIT: - Convert every source-file header to the MIT text across all comment styles (Go, TS, TSX, JS, MJS, SQL, CSS, GraphQL, shell), including SPDX-License-Identifier tags - Set the root and cookie-banner LICENSE files to the MIT text with a "MIT License" title line - Switch the package.json license fields, Docker image label, and cookie-banner README to MIT - Update docs and the genmodels header generator accordingly - Normalize copyright lines to a single format (Copyright (c) <year(s)> Probo Inc <hello@probo.com>.): unify the hello@getprobo.com and hello@probo.inc emails to hello@probo.com and the comma-separated years to a hyphenated range Genuine third-party references are intentionally left untouched: the Lucide icon attributions (Lucide is ISC) and the trivy dependency license allowlist. Signed-off-by: Sacha Al Himdani <sacha@probo.com>
1449 lines
43 KiB
Go
1449 lines
43 KiB
Go
// Copyright (c) 2025-2026 Probo Inc <hello@probo.com>.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
|
|
package console_test
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"go.probo.inc/probo/e2e/internal/factory"
|
|
"go.probo.inc/probo/e2e/internal/testutil"
|
|
)
|
|
|
|
const (
|
|
createFrameworkMutation = `
|
|
mutation CreateFramework($input: CreateFrameworkInput!) {
|
|
createFramework(input: $input) {
|
|
frameworkEdge { node { id } }
|
|
}
|
|
}`
|
|
|
|
updateFrameworkMutation = `
|
|
mutation UpdateFramework($input: UpdateFrameworkInput!) {
|
|
updateFramework(input: $input) {
|
|
framework { id }
|
|
}
|
|
}`
|
|
|
|
deleteFrameworkMutation = `
|
|
mutation DeleteFramework($input: DeleteFrameworkInput!) {
|
|
deleteFramework(input: $input) {
|
|
deletedFrameworkId
|
|
}
|
|
}`
|
|
|
|
listFrameworksQuery = `
|
|
query GetFrameworks($id: ID!) {
|
|
node(id: $id) {
|
|
... on Organization {
|
|
frameworks(first: 10) { totalCount }
|
|
}
|
|
}
|
|
}`
|
|
|
|
createControlMutation = `
|
|
mutation CreateControl($input: CreateControlInput!) {
|
|
createControl(input: $input) {
|
|
controlEdge { node { id } }
|
|
}
|
|
}`
|
|
|
|
updateControlMutation = `
|
|
mutation UpdateControl($input: UpdateControlInput!) {
|
|
updateControl(input: $input) {
|
|
control { id }
|
|
}
|
|
}`
|
|
|
|
deleteControlMutation = `
|
|
mutation DeleteControl($input: DeleteControlInput!) {
|
|
deleteControl(input: $input) {
|
|
deletedControlId
|
|
}
|
|
}`
|
|
|
|
listControlsQuery = `
|
|
query GetControls($id: ID!) {
|
|
node(id: $id) {
|
|
... on Framework {
|
|
controls(first: 10) { edges { node { id } } }
|
|
}
|
|
}
|
|
}`
|
|
|
|
createMeasureMutation = `
|
|
mutation CreateMeasure($input: CreateMeasureInput!) {
|
|
createMeasure(input: $input) {
|
|
measureEdge { node { id } }
|
|
}
|
|
}`
|
|
|
|
updateMeasureMutation = `
|
|
mutation UpdateMeasure($input: UpdateMeasureInput!) {
|
|
updateMeasure(input: $input) {
|
|
measure { id }
|
|
}
|
|
}`
|
|
|
|
deleteMeasureMutation = `
|
|
mutation DeleteMeasure($input: DeleteMeasureInput!) {
|
|
deleteMeasure(input: $input) {
|
|
deletedMeasureId
|
|
}
|
|
}`
|
|
|
|
listMeasuresQuery = `
|
|
query GetMeasures($id: ID!) {
|
|
node(id: $id) {
|
|
... on Organization {
|
|
measures(first: 10) { totalCount }
|
|
}
|
|
}
|
|
}`
|
|
|
|
createTaskMutation = `
|
|
mutation CreateTask($input: CreateTaskInput!) {
|
|
createTask(input: $input) {
|
|
taskEdge { node { id } }
|
|
}
|
|
}`
|
|
|
|
updateTaskMutation = `
|
|
mutation UpdateTask($input: UpdateTaskInput!) {
|
|
updateTask(input: $input) {
|
|
task { id }
|
|
}
|
|
}`
|
|
|
|
deleteTaskMutation = `
|
|
mutation DeleteTask($input: DeleteTaskInput!) {
|
|
deleteTask(input: $input) {
|
|
deletedTaskId
|
|
}
|
|
}`
|
|
|
|
listTasksQuery = `
|
|
query GetTasks($id: ID!) {
|
|
node(id: $id) {
|
|
... on Measure {
|
|
tasks(first: 10) { totalCount }
|
|
}
|
|
}
|
|
}`
|
|
|
|
createRiskMutation = `
|
|
mutation CreateRisk($input: CreateRiskInput!) {
|
|
createRisk(input: $input) {
|
|
riskEdge { node { id } }
|
|
}
|
|
}`
|
|
|
|
updateRiskMutation = `
|
|
mutation UpdateRisk($input: UpdateRiskInput!) {
|
|
updateRisk(input: $input) {
|
|
risk { id }
|
|
}
|
|
}`
|
|
|
|
deleteRiskMutation = `
|
|
mutation DeleteRisk($input: DeleteRiskInput!) {
|
|
deleteRisk(input: $input) {
|
|
deletedRiskId
|
|
}
|
|
}`
|
|
|
|
listRisksQuery = `
|
|
query GetRisks($id: ID!) {
|
|
node(id: $id) {
|
|
... on Organization {
|
|
risks(first: 10) { totalCount }
|
|
}
|
|
}
|
|
}`
|
|
|
|
createThirdPartyMutation = `
|
|
mutation CreateThirdParty($input: CreateThirdPartyInput!) {
|
|
createThirdParty(input: $input) {
|
|
thirdPartyEdge { node { id } }
|
|
}
|
|
}`
|
|
|
|
updateThirdPartyMutation = `
|
|
mutation UpdateThirdParty($input: UpdateThirdPartyInput!) {
|
|
updateThirdParty(input: $input) {
|
|
thirdParty { id }
|
|
}
|
|
}`
|
|
|
|
deleteThirdPartyMutation = `
|
|
mutation DeleteThirdParty($input: DeleteThirdPartyInput!) {
|
|
deleteThirdParty(input: $input) {
|
|
deletedThirdPartyId
|
|
}
|
|
}`
|
|
|
|
listThirdPartiesQuery = `
|
|
query GetThirdParties($id: ID!) {
|
|
node(id: $id) {
|
|
... on Organization {
|
|
thirdParties(first: 10) { totalCount }
|
|
}
|
|
}
|
|
}`
|
|
|
|
createAccessReviewSourceMutation = `
|
|
mutation CreateAccessReviewSource($input: CreateAccessReviewSourceInput!) {
|
|
createAccessReviewSource(input: $input) {
|
|
accessReviewSourceEdge { node { id } }
|
|
}
|
|
}`
|
|
|
|
updateAccessReviewSourceMutation = `
|
|
mutation UpdateAccessReviewSource($input: UpdateAccessReviewSourceInput!) {
|
|
updateAccessReviewSource(input: $input) {
|
|
accessReviewSource { id }
|
|
}
|
|
}`
|
|
|
|
deleteAccessReviewSourceMutation = `
|
|
mutation DeleteAccessReviewSource($input: DeleteAccessReviewSourceInput!) {
|
|
deleteAccessReviewSource(input: $input) {
|
|
deletedAccessReviewSourceId
|
|
}
|
|
}`
|
|
|
|
listAccessReviewSourcesQuery = `
|
|
query GetAccessReviewSources($id: ID!) {
|
|
node(id: $id) {
|
|
... on Organization {
|
|
accessReviewSources(first: 10) { totalCount }
|
|
}
|
|
}
|
|
}`
|
|
|
|
createAccessReviewCampaignMutation = `
|
|
mutation CreateCampaign($input: CreateAccessReviewCampaignInput!) {
|
|
createAccessReviewCampaign(input: $input) {
|
|
accessReviewCampaignEdge { node { id } }
|
|
}
|
|
}`
|
|
|
|
updateAccessReviewCampaignMutation = `
|
|
mutation UpdateCampaign($input: UpdateAccessReviewCampaignInput!) {
|
|
updateAccessReviewCampaign(input: $input) {
|
|
accessReviewCampaign { id }
|
|
}
|
|
}`
|
|
|
|
deleteAccessReviewCampaignMutation = `
|
|
mutation DeleteCampaign($input: DeleteAccessReviewCampaignInput!) {
|
|
deleteAccessReviewCampaign(input: $input) {
|
|
deletedAccessReviewCampaignId
|
|
}
|
|
}`
|
|
|
|
listAccessReviewCampaignsQuery = `
|
|
query GetCampaigns($id: ID!) {
|
|
node(id: $id) {
|
|
... on Organization {
|
|
accessReviewCampaigns(first: 10) { totalCount }
|
|
}
|
|
}
|
|
}`
|
|
|
|
updateOrganizationMutation = `
|
|
mutation UpdateOrganization($input: UpdateOrganizationInput!) {
|
|
updateOrganization(input: $input) {
|
|
organization { id }
|
|
}
|
|
}`
|
|
|
|
getOrganizationQuery = `
|
|
query GetOrganization($id: ID!) {
|
|
node(id: $id) {
|
|
... on Organization {
|
|
id
|
|
name
|
|
}
|
|
}
|
|
}`
|
|
|
|
listUsersQuery = `
|
|
query GetProfiles($id: ID!) {
|
|
node(id: $id) {
|
|
... on Organization {
|
|
profiles(first: 10) { totalCount }
|
|
}
|
|
}
|
|
}`
|
|
)
|
|
|
|
func TestRBAC(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
owner := testutil.NewClient(t, testutil.RoleOwner)
|
|
admin := testutil.NewClientInOrg(t, testutil.RoleAdmin, owner)
|
|
viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
|
|
|
|
// Pre-create resources for update/delete tests
|
|
frameworkID := factory.NewFramework(owner).WithName("RBAC Test Framework").Create()
|
|
controlID := factory.NewControl(owner, frameworkID).WithName("RBAC Test Control").Create()
|
|
measureID := factory.NewMeasure(owner).WithName("RBAC Test Measure").Create()
|
|
taskID := factory.NewTask(owner, measureID).WithName("RBAC Test Task").Create()
|
|
riskID := factory.NewRisk(owner).WithName("RBAC Test Risk").Create()
|
|
thirdPartyID := factory.NewThirdParty(owner).WithName("RBAC Test ThirdParty").Create()
|
|
accessReviewSourceID := factory.NewAccessReviewSource(owner, owner.GetOrganizationID().String()).WithName("RBAC Test Source").Create()
|
|
accessReviewCampaignID := factory.NewAccessReviewCampaign(owner, owner.GetOrganizationID().String()).WithName("RBAC Test Campaign").Create()
|
|
|
|
tests := []struct {
|
|
name string
|
|
role string
|
|
client *testutil.Client
|
|
query string
|
|
variables func() map[string]any
|
|
shouldAllow bool
|
|
useConnect bool // use connect API instead of console API
|
|
}{
|
|
{
|
|
name: "owner can create framework",
|
|
role: "owner",
|
|
client: owner,
|
|
query: createFrameworkMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Framework")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can create framework",
|
|
role: "admin",
|
|
client: admin,
|
|
query: createFrameworkMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Framework")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot create framework",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: createFrameworkMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Framework")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can update framework",
|
|
role: "owner",
|
|
client: owner,
|
|
query: updateFrameworkMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": frameworkID, "name": factory.SafeName("Updated Framework")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can update framework",
|
|
role: "admin",
|
|
client: admin,
|
|
query: updateFrameworkMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": frameworkID, "name": factory.SafeName("Updated Framework")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot update framework",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: updateFrameworkMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": frameworkID, "name": factory.SafeName("Updated Framework")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can delete framework",
|
|
role: "owner",
|
|
client: owner,
|
|
query: deleteFrameworkMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewFramework(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"frameworkId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can delete framework",
|
|
role: "admin",
|
|
client: admin,
|
|
query: deleteFrameworkMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewFramework(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"frameworkId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot delete framework",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: deleteFrameworkMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewFramework(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"frameworkId": id}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can list frameworks",
|
|
role: "owner",
|
|
client: owner,
|
|
query: listFrameworksQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can list frameworks",
|
|
role: "admin",
|
|
client: admin,
|
|
query: listFrameworksQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer can list frameworks",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: listFrameworksQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "owner can create control",
|
|
role: "owner",
|
|
client: owner,
|
|
query: createControlMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"frameworkId": frameworkID, "name": factory.SafeName("Control"), "description": "Test", "sectionTitle": factory.SafeName("Section Owner"), "bestPractice": true, "maturityLevel": "INITIAL"}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can create control",
|
|
role: "admin",
|
|
client: admin,
|
|
query: createControlMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"frameworkId": frameworkID, "name": factory.SafeName("Control"), "description": "Test", "sectionTitle": factory.SafeName("Section Admin"), "bestPractice": true, "maturityLevel": "INITIAL"}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot create control",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: createControlMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"frameworkId": frameworkID, "name": factory.SafeName("Control"), "description": "Test", "sectionTitle": factory.SafeName("Section Viewer"), "bestPractice": true, "maturityLevel": "INITIAL"}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can update control",
|
|
role: "owner",
|
|
client: owner,
|
|
query: updateControlMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": controlID, "name": factory.SafeName("Updated Control")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can update control",
|
|
role: "admin",
|
|
client: admin,
|
|
query: updateControlMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": controlID, "name": factory.SafeName("Updated Control")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot update control",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: updateControlMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": controlID, "name": factory.SafeName("Updated Control")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can delete control",
|
|
role: "owner",
|
|
client: owner,
|
|
query: deleteControlMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewControl(owner, frameworkID).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"controlId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can delete control",
|
|
role: "admin",
|
|
client: admin,
|
|
query: deleteControlMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewControl(owner, frameworkID).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"controlId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
// TODO: Fix permission bug - viewer should not be able to delete controls
|
|
// {
|
|
// name: "viewer cannot delete control",
|
|
// role: "viewer",
|
|
// client: viewer,
|
|
// query: deleteControlMutation,
|
|
// variables: func() map[string]any {
|
|
// id := factory.NewControl(owner, frameworkID).WithName(factory.SafeName("ToDelete")).Create()
|
|
// return map[string]any{"input": map[string]any{"controlId": id}}
|
|
// },
|
|
// shouldAllow: false,
|
|
// },
|
|
{
|
|
name: "owner can list controls",
|
|
role: "owner",
|
|
client: owner,
|
|
query: listControlsQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": frameworkID}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can list controls",
|
|
role: "admin",
|
|
client: admin,
|
|
query: listControlsQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": frameworkID}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer can list controls",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: listControlsQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": frameworkID}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "owner can create measure",
|
|
role: "owner",
|
|
client: owner,
|
|
query: createMeasureMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Measure"), "category": "POLICY"}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can create measure",
|
|
role: "admin",
|
|
client: admin,
|
|
query: createMeasureMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Measure"), "category": "POLICY"}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot create measure",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: createMeasureMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Measure"), "category": "POLICY"}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can update measure",
|
|
role: "owner",
|
|
client: owner,
|
|
query: updateMeasureMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": measureID, "name": factory.SafeName("Updated Measure")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can update measure",
|
|
role: "admin",
|
|
client: admin,
|
|
query: updateMeasureMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": measureID, "name": factory.SafeName("Updated Measure")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot update measure",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: updateMeasureMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": measureID, "name": factory.SafeName("Updated Measure")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can delete measure",
|
|
role: "owner",
|
|
client: owner,
|
|
query: deleteMeasureMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewMeasure(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"measureId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can delete measure",
|
|
role: "admin",
|
|
client: admin,
|
|
query: deleteMeasureMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewMeasure(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"measureId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot delete measure",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: deleteMeasureMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewMeasure(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"measureId": id}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can list measures",
|
|
role: "owner",
|
|
client: owner,
|
|
query: listMeasuresQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can list measures",
|
|
role: "admin",
|
|
client: admin,
|
|
query: listMeasuresQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer can list measures",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: listMeasuresQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "owner can create task",
|
|
role: "owner",
|
|
client: owner,
|
|
query: createTaskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "measureId": measureID, "name": factory.SafeName("Task"), "priority": "MEDIUM"}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can create task",
|
|
role: "admin",
|
|
client: admin,
|
|
query: createTaskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "measureId": measureID, "name": factory.SafeName("Task"), "priority": "MEDIUM"}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot create task",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: createTaskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "measureId": measureID, "name": factory.SafeName("Task"), "priority": "MEDIUM"}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can update task",
|
|
role: "owner",
|
|
client: owner,
|
|
query: updateTaskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"taskId": taskID, "name": factory.SafeName("Updated Task")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can update task",
|
|
role: "admin",
|
|
client: admin,
|
|
query: updateTaskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"taskId": taskID, "name": factory.SafeName("Updated Task")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot update task",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: updateTaskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"taskId": taskID, "name": factory.SafeName("Updated Task")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can delete task",
|
|
role: "owner",
|
|
client: owner,
|
|
query: deleteTaskMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewTask(owner, measureID).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"taskId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can delete task",
|
|
role: "admin",
|
|
client: admin,
|
|
query: deleteTaskMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewTask(owner, measureID).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"taskId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot delete task",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: deleteTaskMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewTask(owner, measureID).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"taskId": id}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
|
|
// Task - List
|
|
{
|
|
name: "owner can list tasks",
|
|
role: "owner",
|
|
client: owner,
|
|
query: listTasksQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": measureID}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can list tasks",
|
|
role: "admin",
|
|
client: admin,
|
|
query: listTasksQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": measureID}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer can list tasks",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: listTasksQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": measureID}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "owner can create risk",
|
|
role: "owner",
|
|
client: owner,
|
|
query: createRiskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Risk"), "category": "SECURITY", "treatment": "MITIGATED", "inherentLikelihood": 2, "inherentImpact": 2}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can create risk",
|
|
role: "admin",
|
|
client: admin,
|
|
query: createRiskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Risk"), "category": "SECURITY", "treatment": "MITIGATED", "inherentLikelihood": 2, "inherentImpact": 2}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot create risk",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: createRiskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Risk"), "category": "SECURITY", "treatment": "MITIGATED", "inherentLikelihood": 2, "inherentImpact": 2}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can update risk",
|
|
role: "owner",
|
|
client: owner,
|
|
query: updateRiskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": riskID, "name": factory.SafeName("Updated Risk")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can update risk",
|
|
role: "admin",
|
|
client: admin,
|
|
query: updateRiskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": riskID, "name": factory.SafeName("Updated Risk")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot update risk",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: updateRiskMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": riskID, "name": factory.SafeName("Updated Risk")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can delete risk",
|
|
role: "owner",
|
|
client: owner,
|
|
query: deleteRiskMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewRisk(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"riskId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can delete risk",
|
|
role: "admin",
|
|
client: admin,
|
|
query: deleteRiskMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewRisk(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"riskId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot delete risk",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: deleteRiskMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewRisk(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"riskId": id}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can list risks",
|
|
role: "owner",
|
|
client: owner,
|
|
query: listRisksQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can list risks",
|
|
role: "admin",
|
|
client: admin,
|
|
query: listRisksQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer can list risks",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: listRisksQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "owner can create thirdParty",
|
|
role: "owner",
|
|
client: owner,
|
|
query: createThirdPartyMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("ThirdParty")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can create thirdParty",
|
|
role: "admin",
|
|
client: admin,
|
|
query: createThirdPartyMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("ThirdParty")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot create thirdParty",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: createThirdPartyMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("ThirdParty")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can update thirdParty",
|
|
role: "owner",
|
|
client: owner,
|
|
query: updateThirdPartyMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": thirdPartyID, "name": factory.SafeName("Updated ThirdParty")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can update thirdParty",
|
|
role: "admin",
|
|
client: admin,
|
|
query: updateThirdPartyMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": thirdPartyID, "name": factory.SafeName("Updated ThirdParty")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot update thirdParty",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: updateThirdPartyMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"id": thirdPartyID, "name": factory.SafeName("Updated ThirdParty")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can delete thirdParty",
|
|
role: "owner",
|
|
client: owner,
|
|
query: deleteThirdPartyMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewThirdParty(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"thirdPartyId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can delete thirdParty",
|
|
role: "admin",
|
|
client: admin,
|
|
query: deleteThirdPartyMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewThirdParty(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"thirdPartyId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot delete thirdParty",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: deleteThirdPartyMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewThirdParty(owner).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"thirdPartyId": id}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
{
|
|
name: "owner can list third parties",
|
|
role: "owner",
|
|
client: owner,
|
|
query: listThirdPartiesQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can list third parties",
|
|
role: "admin",
|
|
client: admin,
|
|
query: listThirdPartiesQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer can list third parties",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: listThirdPartiesQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
// Access Source - Create
|
|
{
|
|
name: "owner can create access source",
|
|
role: "owner",
|
|
client: owner,
|
|
query: createAccessReviewSourceMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("AccessReviewSource")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can create access source",
|
|
role: "admin",
|
|
client: admin,
|
|
query: createAccessReviewSourceMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("AccessReviewSource")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot create access source",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: createAccessReviewSourceMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("AccessReviewSource")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
// Access Source - Update
|
|
{
|
|
name: "owner can update access source",
|
|
role: "owner",
|
|
client: owner,
|
|
query: updateAccessReviewSourceMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"accessReviewSourceId": accessReviewSourceID, "name": factory.SafeName("Updated Source")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can update access source",
|
|
role: "admin",
|
|
client: admin,
|
|
query: updateAccessReviewSourceMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"accessReviewSourceId": accessReviewSourceID, "name": factory.SafeName("Updated Source")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot update access source",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: updateAccessReviewSourceMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"accessReviewSourceId": accessReviewSourceID, "name": factory.SafeName("Updated Source")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
// Access Source - Delete
|
|
{
|
|
name: "owner can delete access source",
|
|
role: "owner",
|
|
client: owner,
|
|
query: deleteAccessReviewSourceMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewAccessReviewSource(owner, owner.GetOrganizationID().String()).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"accessReviewSourceId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can delete access source",
|
|
role: "admin",
|
|
client: admin,
|
|
query: deleteAccessReviewSourceMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewAccessReviewSource(owner, owner.GetOrganizationID().String()).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"accessReviewSourceId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot delete access source",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: deleteAccessReviewSourceMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewAccessReviewSource(owner, owner.GetOrganizationID().String()).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"accessReviewSourceId": id}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
// Access Source - List
|
|
{
|
|
name: "owner can list access sources",
|
|
role: "owner",
|
|
client: owner,
|
|
query: listAccessReviewSourcesQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can list access sources",
|
|
role: "admin",
|
|
client: admin,
|
|
query: listAccessReviewSourcesQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer can list access sources",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: listAccessReviewSourcesQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
// Access Review Campaign - Create
|
|
{
|
|
name: "owner can create access review campaign",
|
|
role: "owner",
|
|
client: owner,
|
|
query: createAccessReviewCampaignMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Campaign")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can create access review campaign",
|
|
role: "admin",
|
|
client: admin,
|
|
query: createAccessReviewCampaignMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Campaign")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot create access review campaign",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: createAccessReviewCampaignMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "name": factory.SafeName("Campaign")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
// Access Review Campaign - Update
|
|
{
|
|
name: "owner can update access review campaign",
|
|
role: "owner",
|
|
client: owner,
|
|
query: updateAccessReviewCampaignMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"accessReviewCampaignId": accessReviewCampaignID, "name": factory.SafeName("Updated Campaign")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can update access review campaign",
|
|
role: "admin",
|
|
client: admin,
|
|
query: updateAccessReviewCampaignMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"accessReviewCampaignId": accessReviewCampaignID, "name": factory.SafeName("Updated Campaign")}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot update access review campaign",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: updateAccessReviewCampaignMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"accessReviewCampaignId": accessReviewCampaignID, "name": factory.SafeName("Updated Campaign")}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
// Access Review Campaign - Delete
|
|
{
|
|
name: "owner can delete access review campaign",
|
|
role: "owner",
|
|
client: owner,
|
|
query: deleteAccessReviewCampaignMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewAccessReviewCampaign(owner, owner.GetOrganizationID().String()).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"accessReviewCampaignId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can delete access review campaign",
|
|
role: "admin",
|
|
client: admin,
|
|
query: deleteAccessReviewCampaignMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewAccessReviewCampaign(owner, owner.GetOrganizationID().String()).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"accessReviewCampaignId": id}}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer cannot delete access review campaign",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: deleteAccessReviewCampaignMutation,
|
|
variables: func() map[string]any {
|
|
id := factory.NewAccessReviewCampaign(owner, owner.GetOrganizationID().String()).WithName(factory.SafeName("ToDelete")).Create()
|
|
return map[string]any{"input": map[string]any{"accessReviewCampaignId": id}}
|
|
},
|
|
shouldAllow: false,
|
|
},
|
|
// Access Review Campaign - List
|
|
{
|
|
name: "owner can list access review campaigns",
|
|
role: "owner",
|
|
client: owner,
|
|
query: listAccessReviewCampaignsQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "admin can list access review campaigns",
|
|
role: "admin",
|
|
client: admin,
|
|
query: listAccessReviewCampaignsQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "viewer can list access review campaigns",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: listAccessReviewCampaignsQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
},
|
|
{
|
|
name: "owner can update organization",
|
|
role: "owner",
|
|
client: owner,
|
|
query: updateOrganizationMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "description": factory.SafeName("Updated Desc")}}
|
|
},
|
|
shouldAllow: true,
|
|
useConnect: true,
|
|
},
|
|
{
|
|
name: "admin can update organization",
|
|
role: "admin",
|
|
client: admin,
|
|
query: updateOrganizationMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "description": factory.SafeName("Updated Desc")}}
|
|
},
|
|
shouldAllow: true,
|
|
useConnect: true,
|
|
},
|
|
{
|
|
name: "viewer cannot update organization",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: updateOrganizationMutation,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "description": factory.SafeName("Updated Desc")}}
|
|
},
|
|
shouldAllow: false,
|
|
useConnect: true,
|
|
},
|
|
{
|
|
name: "owner can get organization",
|
|
role: "owner",
|
|
client: owner,
|
|
query: getOrganizationQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
useConnect: true,
|
|
},
|
|
{
|
|
name: "admin can get organization",
|
|
role: "admin",
|
|
client: admin,
|
|
query: getOrganizationQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
useConnect: true,
|
|
},
|
|
{
|
|
name: "viewer can get organization",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: getOrganizationQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
useConnect: true,
|
|
},
|
|
{
|
|
name: "owner can list users",
|
|
role: "owner",
|
|
client: owner,
|
|
query: listUsersQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
useConnect: true,
|
|
},
|
|
{
|
|
name: "admin can list users",
|
|
role: "admin",
|
|
client: admin,
|
|
query: listUsersQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
useConnect: true,
|
|
},
|
|
{
|
|
name: "viewer can list users",
|
|
role: "viewer",
|
|
client: viewer,
|
|
query: listUsersQuery,
|
|
variables: func() map[string]any {
|
|
return map[string]any{"id": owner.GetOrganizationID().String()}
|
|
},
|
|
shouldAllow: true,
|
|
useConnect: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(
|
|
tt.name,
|
|
func(t *testing.T) {
|
|
var err error
|
|
if tt.useConnect {
|
|
_, err = tt.client.DoConnect(tt.query, tt.variables())
|
|
} else {
|
|
_, err = tt.client.Do(tt.query, tt.variables())
|
|
}
|
|
|
|
if tt.shouldAllow {
|
|
require.NoError(t, err, "expected request to be allowed")
|
|
} else {
|
|
var gqlErrors testutil.GraphQLErrors
|
|
require.ErrorAs(t, err, &gqlErrors, "expected GraphQL error, got: %T", err)
|
|
require.Len(t, gqlErrors, 1, "expected exactly one GraphQL error, got %d errors: %v", len(gqlErrors), gqlErrors)
|
|
// Connect API uses a different error format - check either code or message
|
|
code := gqlErrors[0].Code()
|
|
msg := gqlErrors[0].Message
|
|
isForbidden := code == "FORBIDDEN" || (code == "" && (strings.Contains(msg, "does not have sufficient permissions") || strings.Contains(msg, "insufficient permissions")))
|
|
require.True(t, isForbidden, "expected FORBIDDEN error, got code=%q message=%q", code, msg)
|
|
}
|
|
},
|
|
)
|
|
}
|
|
}
|