Add e2e tests

Signed-off-by: Bryan Frimin <bryan@probo.com>
This commit is contained in:
Bryan Frimin
2026-07-03 10:08:32 +02:00
parent d357d9ded9
commit b03dad70e0
21 changed files with 2638 additions and 0 deletions

View File

@@ -933,3 +933,209 @@ func TestMeasureDocumentMapping_CreateDelete(t *testing.T) {
require.NoError(t, err)
})
}
// The mapping mutations below link two independently-authored resources
// (e.g. controlId + measureId) together. Each is only safe because the
// underlying service loads BOTH ids in the caller's own scope before
// upserting the junction row (see e.g. ControlService.CreateMeasureMapping);
// an attacker supplying a valid GID from another organization on either
// side must be rejected. These tests pin that invariant for every mapping
// mutation.
func TestControlMeasureMapping_TenantIsolation(t *testing.T) {
t.Parallel()
org1Owner := testutil.NewClient(t, testutil.RoleOwner)
org2Owner := testutil.NewClient(t, testutil.RoleOwner)
frameworkID := factory.CreateFramework(org1Owner)
controlID := factory.CreateControl(org1Owner, frameworkID)
org2MeasureID := factory.NewMeasure(org2Owner).Create()
_, err := org1Owner.Do(`
mutation($input: CreateControlMeasureMappingInput!) {
createControlMeasureMapping(input: $input) {
controlEdge { node { id } }
}
}
`, map[string]any{
"input": map[string]any{
"controlId": controlID,
"measureId": org2MeasureID,
},
})
require.Error(t, err, "must not link a control to a measure from another organization")
}
func TestRiskMeasureMapping_TenantIsolation(t *testing.T) {
t.Parallel()
org1Owner := testutil.NewClient(t, testutil.RoleOwner)
org2Owner := testutil.NewClient(t, testutil.RoleOwner)
riskID := factory.CreateRisk(org1Owner)
org2MeasureID := factory.NewMeasure(org2Owner).Create()
_, err := org1Owner.Do(`
mutation($input: CreateRiskMeasureMappingInput!) {
createRiskMeasureMapping(input: $input) {
riskEdge { node { id } }
}
}
`, map[string]any{
"input": map[string]any{
"riskId": riskID,
"measureId": org2MeasureID,
},
})
require.Error(t, err, "must not link a risk to a measure from another organization")
}
func TestControlDocumentMapping_TenantIsolation(t *testing.T) {
t.Parallel()
org1Owner := testutil.NewClient(t, testutil.RoleOwner)
org2Owner := testutil.NewClient(t, testutil.RoleOwner)
frameworkID := factory.CreateFramework(org1Owner)
controlID := factory.CreateControl(org1Owner, frameworkID)
org2DocumentID := factory.NewDocument(org2Owner).Create()
_, err := org1Owner.Do(`
mutation($input: CreateControlDocumentMappingInput!) {
createControlDocumentMapping(input: $input) {
controlEdge { node { id } }
}
}
`, map[string]any{
"input": map[string]any{
"controlId": controlID,
"documentId": org2DocumentID,
},
})
require.Error(t, err, "must not link a control to a document from another organization")
}
func TestControlAuditMapping_TenantIsolation(t *testing.T) {
t.Parallel()
org1Owner := testutil.NewClient(t, testutil.RoleOwner)
org2Owner := testutil.NewClient(t, testutil.RoleOwner)
frameworkID := factory.CreateFramework(org1Owner)
controlID := factory.CreateControl(org1Owner, frameworkID)
org2FrameworkID := factory.CreateFramework(org2Owner)
org2AuditID := factory.CreateAudit(org2Owner, org2FrameworkID)
_, err := org1Owner.Do(`
mutation($input: CreateControlAuditMappingInput!) {
createControlAuditMapping(input: $input) {
controlEdge { node { id } }
}
}
`, map[string]any{
"input": map[string]any{
"controlId": controlID,
"auditId": org2AuditID,
},
})
require.Error(t, err, "must not link a control to an audit from another organization")
}
func TestRiskDocumentMapping_TenantIsolation(t *testing.T) {
t.Parallel()
org1Owner := testutil.NewClient(t, testutil.RoleOwner)
org2Owner := testutil.NewClient(t, testutil.RoleOwner)
riskID := factory.CreateRisk(org1Owner)
org2DocumentID := factory.NewDocument(org2Owner).Create()
_, err := org1Owner.Do(`
mutation($input: CreateRiskDocumentMappingInput!) {
createRiskDocumentMapping(input: $input) {
riskEdge { node { id } }
}
}
`, map[string]any{
"input": map[string]any{
"riskId": riskID,
"documentId": org2DocumentID,
},
})
require.Error(t, err, "must not link a risk to a document from another organization")
}
func TestRiskObligationMapping_TenantIsolation(t *testing.T) {
t.Parallel()
org1Owner := testutil.NewClient(t, testutil.RoleOwner)
org2Owner := testutil.NewClient(t, testutil.RoleOwner)
riskID := factory.CreateRisk(org1Owner)
org2ProfileID := factory.CreateUser(org2Owner)
var createObligationResult struct {
CreateObligation struct {
ObligationEdge struct {
Node struct {
ID string `json:"id"`
} `json:"node"`
} `json:"obligationEdge"`
} `json:"createObligation"`
}
err := org2Owner.Execute(`
mutation($input: CreateObligationInput!) {
createObligation(input: $input) {
obligationEdge {
node { id }
}
}
}
`, map[string]any{
"input": map[string]any{
"organizationId": org2Owner.GetOrganizationID().String(),
"area": "Risk Management",
"requirement": "Org2 Obligation for Mapping Isolation",
"ownerId": org2ProfileID,
"status": "NON_COMPLIANT",
"type": "LEGAL",
},
}, &createObligationResult)
require.NoError(t, err)
org2ObligationID := createObligationResult.CreateObligation.ObligationEdge.Node.ID
_, err = org1Owner.Do(`
mutation($input: CreateRiskObligationMappingInput!) {
createRiskObligationMapping(input: $input) {
riskEdge { node { id } }
}
}
`, map[string]any{
"input": map[string]any{
"riskId": riskID,
"obligationId": org2ObligationID,
},
})
require.Error(t, err, "must not link a risk to an obligation from another organization")
}
func TestMeasureDocumentMapping_TenantIsolation(t *testing.T) {
t.Parallel()
org1Owner := testutil.NewClient(t, testutil.RoleOwner)
org2Owner := testutil.NewClient(t, testutil.RoleOwner)
measureID := factory.NewMeasure(org1Owner).Create()
org2DocumentID := factory.NewDocument(org2Owner).Create()
_, err := org1Owner.Do(`
mutation($input: CreateMeasureDocumentMappingInput!) {
createMeasureDocumentMapping(input: $input) {
measureEdge { node { id } }
}
}
`, map[string]any{
"input": map[string]any{
"measureId": measureID,
"documentId": org2DocumentID,
},
})
require.Error(t, err, "must not link a measure to a document from another organization")
}