Decouple each campaign from the live access-review sources it was started with by introducing a per-campaign source snapshot table (access_review_campaign_sources). The snapshot captures the source name, category, and connector at start time, so a review remains coherent even after the underlying source is edited or deleted. Fetch tracking becomes an append-only log (access_review_campaign_source_fetch_attempts) that preserves every attempt with its own status and error rather than overwriting a single row. Rename the shared access-review tables and enums to use a consistent access_review_ prefix throughout: access_entries → access_review_entries access_sources → access_review_sources access_source_category → access_review_source_category access_entry_* → access_review_entry_* The same rename propagates to every coredata type, service, GraphQL schema, MCP specification, CLI command, frontend component, and e2e test. The accessreview package gains dedicated actions.go and policies.go files for its own IAM policy set, mirroring the agentrun package pattern. Signed-off-by: Bryan Frimin <bryan@probo.com>
1819 lines
44 KiB
Go
1819 lines
44 KiB
Go
// Copyright (c) 2025-2026 Probo Inc <hello@probo.com>.
|
|
//
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
// copyright notice and this permission notice appear in all copies.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
// PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
// Package factory provides Rails-like test data factories using gofakeit.
|
|
package factory
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"maps"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/brianvoe/gofakeit/v7"
|
|
"github.com/stretchr/testify/require"
|
|
"go.probo.inc/probo/e2e/internal/testutil"
|
|
)
|
|
|
|
func SafeName(prefix string) string {
|
|
return fmt.Sprintf("%s %s", prefix, gofakeit.LetterN(8))
|
|
}
|
|
|
|
func SafeEmail() string {
|
|
return fmt.Sprintf("%s@example.com", strings.ToLower(gofakeit.LetterN(12)))
|
|
}
|
|
|
|
type Attrs map[string]any
|
|
|
|
func (a Attrs) get(key string, defaultVal any) any {
|
|
if a == nil {
|
|
return defaultVal
|
|
}
|
|
|
|
if v, ok := a[key]; ok {
|
|
return v
|
|
}
|
|
|
|
return defaultVal
|
|
}
|
|
|
|
func (a Attrs) getString(key string, defaultVal string) string {
|
|
if v, ok := a.get(key, defaultVal).(string); ok {
|
|
return v
|
|
}
|
|
|
|
return defaultVal
|
|
}
|
|
|
|
func (a Attrs) getStringPtr(key string) *string {
|
|
if a == nil {
|
|
return nil
|
|
}
|
|
|
|
if v, ok := a[key]; ok {
|
|
if s, ok := v.(string); ok {
|
|
return &s
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (a Attrs) getInt(key string, defaultVal int) int {
|
|
if a == nil {
|
|
return defaultVal
|
|
}
|
|
|
|
if v, ok := a[key]; ok {
|
|
switch val := v.(type) {
|
|
case int:
|
|
return val
|
|
case int64:
|
|
return int(val)
|
|
case float64:
|
|
return int(val)
|
|
}
|
|
}
|
|
|
|
return defaultVal
|
|
}
|
|
|
|
func (a Attrs) getBool(key string, defaultVal bool) bool {
|
|
if a == nil {
|
|
return defaultVal
|
|
}
|
|
|
|
if v, ok := a[key]; ok {
|
|
if b, ok := v.(bool); ok {
|
|
return b
|
|
}
|
|
}
|
|
|
|
return defaultVal
|
|
}
|
|
|
|
func CreateUser(c *testutil.Client, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateUserInput!) {
|
|
createUser(input: $input) {
|
|
profileEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": c.GetOrganizationID(),
|
|
"emailAddress": a.getString("emailAddress", SafeEmail()),
|
|
"fullName": a.getString("fullName", SafeName("User")),
|
|
"role": a.getString("role", "EMPLOYEE"),
|
|
"kind": "EMPLOYEE",
|
|
"additionalEmailAddresses": []string{},
|
|
}
|
|
if position := a.getStringPtr("position"); position != nil {
|
|
input["position"] = *position
|
|
}
|
|
|
|
var result struct {
|
|
CreateUser struct {
|
|
ProfileEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"profileEdge"`
|
|
} `json:"createUser"`
|
|
}
|
|
|
|
err := c.ExecuteConnect(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createUser mutation failed")
|
|
|
|
return result.CreateUser.ProfileEdge.Node.ID
|
|
}
|
|
|
|
func InviteUser(c *testutil.Client, profileID string) string {
|
|
c.T.Helper()
|
|
|
|
const query = `
|
|
mutation($input: InviteUserInput!) {
|
|
inviteUser(input: $input) {
|
|
invitationEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
var result struct {
|
|
InviteUser struct {
|
|
InvitationEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"invitationEdge"`
|
|
} `json:"inviteUser"`
|
|
}
|
|
|
|
err := c.ExecuteConnect(query, map[string]any{
|
|
"input": map[string]any{
|
|
"organizationId": c.GetOrganizationID().String(),
|
|
"profileId": profileID,
|
|
},
|
|
}, &result)
|
|
require.NoError(c.T, err, "inviteUser mutation failed")
|
|
|
|
return result.InviteUser.InvitationEdge.Node.ID
|
|
}
|
|
|
|
func CreateThirdParty(c *testutil.Client, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateThirdPartyInput!) {
|
|
createThirdParty(input: $input) {
|
|
thirdPartyEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": c.GetOrganizationID().String(),
|
|
"name": a.getString("name", SafeName("ThirdParty")),
|
|
}
|
|
if desc := a.getStringPtr("description"); desc != nil {
|
|
input["description"] = *desc
|
|
}
|
|
|
|
if url := a.getStringPtr("websiteUrl"); url != nil {
|
|
input["websiteUrl"] = *url
|
|
}
|
|
|
|
if cat := a.getStringPtr("category"); cat != nil {
|
|
input["category"] = *cat
|
|
}
|
|
|
|
var result struct {
|
|
CreateThirdParty struct {
|
|
ThirdPartyEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"thirdPartyEdge"`
|
|
} `json:"createThirdParty"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createThirdParty mutation failed")
|
|
|
|
return result.CreateThirdParty.ThirdPartyEdge.Node.ID
|
|
}
|
|
|
|
func CreateFramework(c *testutil.Client, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateFrameworkInput!) {
|
|
createFramework(input: $input) {
|
|
frameworkEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": c.GetOrganizationID().String(),
|
|
"name": a.getString("name", SafeName("Framework")),
|
|
}
|
|
if desc := a.getStringPtr("description"); desc != nil {
|
|
input["description"] = *desc
|
|
}
|
|
|
|
var result struct {
|
|
CreateFramework struct {
|
|
FrameworkEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"frameworkEdge"`
|
|
} `json:"createFramework"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createFramework mutation failed")
|
|
|
|
return result.CreateFramework.FrameworkEdge.Node.ID
|
|
}
|
|
|
|
func CreateControl(c *testutil.Client, frameworkID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateControlInput!) {
|
|
createControl(input: $input) {
|
|
controlEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"frameworkId": frameworkID,
|
|
"name": a.getString("name", SafeName("Control")),
|
|
"description": a.getString("description", "Test control description"),
|
|
"sectionTitle": a.getString("sectionTitle", fmt.Sprintf("Section %s", gofakeit.LetterN(3))),
|
|
"bestPractice": a.getBool("bestPractice", true),
|
|
"maturityLevel": a.getString("maturityLevel", "INITIAL"),
|
|
}
|
|
|
|
if justification := a.getStringPtr("notImplementedJustification"); justification != nil {
|
|
input["notImplementedJustification"] = *justification
|
|
}
|
|
|
|
var result struct {
|
|
CreateControl struct {
|
|
ControlEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"controlEdge"`
|
|
} `json:"createControl"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createControl mutation failed")
|
|
|
|
return result.CreateControl.ControlEdge.Node.ID
|
|
}
|
|
|
|
func CreateMeasure(c *testutil.Client, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateMeasureInput!) {
|
|
createMeasure(input: $input) {
|
|
measureEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": c.GetOrganizationID().String(),
|
|
"name": a.getString("name", SafeName("Measure")),
|
|
"category": a.getString("category", "POLICY"),
|
|
}
|
|
if desc := a.getStringPtr("description"); desc != nil {
|
|
input["description"] = *desc
|
|
}
|
|
|
|
var result struct {
|
|
CreateMeasure struct {
|
|
MeasureEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"measureEdge"`
|
|
} `json:"createMeasure"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createMeasure mutation failed")
|
|
|
|
return result.CreateMeasure.MeasureEdge.Node.ID
|
|
}
|
|
|
|
func CreateTask(c *testutil.Client, measureID *string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateTaskInput!) {
|
|
createTask(input: $input) {
|
|
taskEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": c.GetOrganizationID().String(),
|
|
"name": a.getString("name", SafeName("Task")),
|
|
"priority": a.getString("priority", "MEDIUM"),
|
|
}
|
|
if measureID != nil {
|
|
input["measureId"] = *measureID
|
|
}
|
|
|
|
if desc := a.getStringPtr("description"); desc != nil {
|
|
input["description"] = *desc
|
|
}
|
|
|
|
var result struct {
|
|
CreateTask struct {
|
|
TaskEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"taskEdge"`
|
|
} `json:"createTask"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createTask mutation failed")
|
|
|
|
return result.CreateTask.TaskEdge.Node.ID
|
|
}
|
|
|
|
func CreateRisk(c *testutil.Client, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateRiskInput!) {
|
|
createRisk(input: $input) {
|
|
riskEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": c.GetOrganizationID().String(),
|
|
"name": a.getString("name", SafeName("Risk")),
|
|
"category": a.getString("category", "SECURITY"),
|
|
"treatment": a.getString("treatment", "MITIGATED"),
|
|
"inherentLikelihood": a.getInt("inherentLikelihood", 2),
|
|
"inherentImpact": a.getInt("inherentImpact", 2),
|
|
}
|
|
if desc := a.getStringPtr("description"); desc != nil {
|
|
input["description"] = *desc
|
|
}
|
|
|
|
var result struct {
|
|
CreateRisk struct {
|
|
RiskEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"riskEdge"`
|
|
} `json:"createRisk"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createRisk mutation failed")
|
|
|
|
return result.CreateRisk.RiskEdge.Node.ID
|
|
}
|
|
|
|
type ThirdPartyBuilder struct {
|
|
client *testutil.Client
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewThirdParty(c *testutil.Client) *ThirdPartyBuilder {
|
|
return &ThirdPartyBuilder{client: c, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *ThirdPartyBuilder) WithName(name string) *ThirdPartyBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *ThirdPartyBuilder) WithDescription(desc string) *ThirdPartyBuilder {
|
|
b.attrs["description"] = desc
|
|
return b
|
|
}
|
|
|
|
func (b *ThirdPartyBuilder) WithWebsiteUrl(url string) *ThirdPartyBuilder {
|
|
b.attrs["websiteUrl"] = url
|
|
return b
|
|
}
|
|
|
|
func (b *ThirdPartyBuilder) WithCategory(category string) *ThirdPartyBuilder {
|
|
b.attrs["category"] = category
|
|
return b
|
|
}
|
|
|
|
func (b *ThirdPartyBuilder) Create() string {
|
|
return CreateThirdParty(b.client, b.attrs)
|
|
}
|
|
|
|
type FrameworkBuilder struct {
|
|
client *testutil.Client
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewFramework(c *testutil.Client) *FrameworkBuilder {
|
|
return &FrameworkBuilder{client: c, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *FrameworkBuilder) WithName(name string) *FrameworkBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *FrameworkBuilder) WithDescription(desc string) *FrameworkBuilder {
|
|
b.attrs["description"] = desc
|
|
return b
|
|
}
|
|
|
|
func (b *FrameworkBuilder) Create() string {
|
|
return CreateFramework(b.client, b.attrs)
|
|
}
|
|
|
|
type ControlBuilder struct {
|
|
client *testutil.Client
|
|
frameworkID string
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewControl(c *testutil.Client, frameworkID string) *ControlBuilder {
|
|
return &ControlBuilder{client: c, frameworkID: frameworkID, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *ControlBuilder) WithName(name string) *ControlBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *ControlBuilder) WithDescription(desc string) *ControlBuilder {
|
|
b.attrs["description"] = desc
|
|
return b
|
|
}
|
|
|
|
func (b *ControlBuilder) WithSectionTitle(title string) *ControlBuilder {
|
|
b.attrs["sectionTitle"] = title
|
|
return b
|
|
}
|
|
|
|
func (b *ControlBuilder) WithStatus(status string) *ControlBuilder {
|
|
b.attrs["status"] = status
|
|
return b
|
|
}
|
|
|
|
func (b *ControlBuilder) WithBestPractice(bestPractice bool) *ControlBuilder {
|
|
b.attrs["bestPractice"] = bestPractice
|
|
return b
|
|
}
|
|
|
|
func (b *ControlBuilder) WithMaturityLevel(maturityLevel string) *ControlBuilder {
|
|
b.attrs["maturityLevel"] = maturityLevel
|
|
return b
|
|
}
|
|
|
|
func (b *ControlBuilder) WithNotImplementedJustification(justification string) *ControlBuilder {
|
|
b.attrs["notImplementedJustification"] = justification
|
|
return b
|
|
}
|
|
|
|
func (b *ControlBuilder) Create() string {
|
|
return CreateControl(b.client, b.frameworkID, b.attrs)
|
|
}
|
|
|
|
type MeasureBuilder struct {
|
|
client *testutil.Client
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewMeasure(c *testutil.Client) *MeasureBuilder {
|
|
return &MeasureBuilder{client: c, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *MeasureBuilder) WithName(name string) *MeasureBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *MeasureBuilder) WithDescription(desc string) *MeasureBuilder {
|
|
b.attrs["description"] = desc
|
|
return b
|
|
}
|
|
|
|
func (b *MeasureBuilder) WithCategory(category string) *MeasureBuilder {
|
|
b.attrs["category"] = category
|
|
return b
|
|
}
|
|
|
|
func (b *MeasureBuilder) Create() string {
|
|
return CreateMeasure(b.client, b.attrs)
|
|
}
|
|
|
|
type TaskBuilder struct {
|
|
client *testutil.Client
|
|
measureID *string
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewTask(c *testutil.Client, measureID string) *TaskBuilder {
|
|
return &TaskBuilder{client: c, measureID: &measureID, attrs: Attrs{}}
|
|
}
|
|
|
|
func NewTaskWithoutMeasure(c *testutil.Client) *TaskBuilder {
|
|
return &TaskBuilder{client: c, measureID: nil, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *TaskBuilder) WithName(name string) *TaskBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *TaskBuilder) WithDescription(desc string) *TaskBuilder {
|
|
b.attrs["description"] = desc
|
|
return b
|
|
}
|
|
|
|
func (b *TaskBuilder) Create() string {
|
|
return CreateTask(b.client, b.measureID, b.attrs)
|
|
}
|
|
|
|
type RiskBuilder struct {
|
|
client *testutil.Client
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewRisk(c *testutil.Client) *RiskBuilder {
|
|
return &RiskBuilder{client: c, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *RiskBuilder) WithName(name string) *RiskBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *RiskBuilder) WithDescription(desc string) *RiskBuilder {
|
|
b.attrs["description"] = desc
|
|
return b
|
|
}
|
|
|
|
func (b *RiskBuilder) WithCategory(category string) *RiskBuilder {
|
|
b.attrs["category"] = category
|
|
return b
|
|
}
|
|
|
|
func (b *RiskBuilder) WithTreatment(treatment string) *RiskBuilder {
|
|
b.attrs["treatment"] = treatment
|
|
return b
|
|
}
|
|
|
|
func (b *RiskBuilder) WithLikelihood(likelihood int) *RiskBuilder {
|
|
b.attrs["inherentLikelihood"] = likelihood
|
|
return b
|
|
}
|
|
|
|
func (b *RiskBuilder) WithImpact(impact int) *RiskBuilder {
|
|
b.attrs["inherentImpact"] = impact
|
|
return b
|
|
}
|
|
|
|
func (b *RiskBuilder) Create() string {
|
|
return CreateRisk(b.client, b.attrs)
|
|
}
|
|
|
|
func CreateAudit(c *testutil.Client, frameworkID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateAuditInput!) {
|
|
createAudit(input: $input) {
|
|
auditEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": c.GetOrganizationID().String(),
|
|
"frameworkId": frameworkID,
|
|
"name": a.getString("name", SafeName("Audit")),
|
|
}
|
|
if state := a.getStringPtr("state"); state != nil {
|
|
input["state"] = *state
|
|
}
|
|
|
|
var result struct {
|
|
CreateAudit struct {
|
|
AuditEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"auditEdge"`
|
|
} `json:"createAudit"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createAudit mutation failed")
|
|
|
|
return result.CreateAudit.AuditEdge.Node.ID
|
|
}
|
|
|
|
type AuditBuilder struct {
|
|
client *testutil.Client
|
|
frameworkID string
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewAudit(c *testutil.Client, frameworkID string) *AuditBuilder {
|
|
return &AuditBuilder{client: c, frameworkID: frameworkID, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *AuditBuilder) WithName(name string) *AuditBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *AuditBuilder) WithState(state string) *AuditBuilder {
|
|
b.attrs["state"] = state
|
|
return b
|
|
}
|
|
|
|
func (b *AuditBuilder) Create() string {
|
|
return CreateAudit(b.client, b.frameworkID, b.attrs)
|
|
}
|
|
|
|
func CreateDatum(c *testutil.Client, ownerID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateDatumInput!) {
|
|
createDatum(input: $input) {
|
|
datumEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": c.GetOrganizationID().String(),
|
|
"ownerId": ownerID,
|
|
"name": a.getString("name", SafeName("Datum")),
|
|
"dataClassification": a.getString("dataClassification", "INTERNAL"),
|
|
}
|
|
if desc := a.getStringPtr("description"); desc != nil {
|
|
input["description"] = *desc
|
|
}
|
|
|
|
var result struct {
|
|
CreateDatum struct {
|
|
DatumEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"datumEdge"`
|
|
} `json:"createDatum"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createDatum mutation failed")
|
|
|
|
return result.CreateDatum.DatumEdge.Node.ID
|
|
}
|
|
|
|
type DatumBuilder struct {
|
|
client *testutil.Client
|
|
ownerID string
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewDatum(c *testutil.Client, ownerID string) *DatumBuilder {
|
|
return &DatumBuilder{client: c, ownerID: ownerID, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *DatumBuilder) WithName(name string) *DatumBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *DatumBuilder) WithDescription(desc string) *DatumBuilder {
|
|
b.attrs["description"] = desc
|
|
return b
|
|
}
|
|
|
|
func (b *DatumBuilder) WithDataClassification(classification string) *DatumBuilder {
|
|
b.attrs["dataClassification"] = classification
|
|
return b
|
|
}
|
|
|
|
func (b *DatumBuilder) Create() string {
|
|
return CreateDatum(b.client, b.ownerID, b.attrs)
|
|
}
|
|
|
|
type DocumentBuilder struct {
|
|
client *testutil.Client
|
|
attrs Attrs
|
|
versionID string
|
|
}
|
|
|
|
func NewDocument(c *testutil.Client) *DocumentBuilder {
|
|
return &DocumentBuilder{client: c, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *DocumentBuilder) WithTitle(title string) *DocumentBuilder {
|
|
b.attrs["title"] = title
|
|
return b
|
|
}
|
|
|
|
func (b *DocumentBuilder) WithContent(content string) *DocumentBuilder {
|
|
b.attrs["content"] = content
|
|
return b
|
|
}
|
|
|
|
func (b *DocumentBuilder) WithDocumentType(docType string) *DocumentBuilder {
|
|
b.attrs["documentType"] = docType
|
|
return b
|
|
}
|
|
|
|
func (b *DocumentBuilder) WithClassification(classification string) *DocumentBuilder {
|
|
b.attrs["classification"] = classification
|
|
return b
|
|
}
|
|
|
|
func (b *DocumentBuilder) VersionID() string {
|
|
return b.versionID
|
|
}
|
|
|
|
func (b *DocumentBuilder) Create() string {
|
|
b.client.T.Helper()
|
|
|
|
a := b.attrs
|
|
|
|
const query = `
|
|
mutation($input: CreateDocumentInput!) {
|
|
createDocument(input: $input) {
|
|
documentEdge {
|
|
node { id }
|
|
}
|
|
documentVersionEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": b.client.GetOrganizationID().String(),
|
|
"title": a.getString("title", SafeName("Document")),
|
|
"documentType": a.getString("documentType", "POLICY"),
|
|
"classification": a.getString("classification", "INTERNAL"),
|
|
}
|
|
|
|
var result struct {
|
|
CreateDocument struct {
|
|
DocumentEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"documentEdge"`
|
|
DocumentVersionEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"documentVersionEdge"`
|
|
} `json:"createDocument"`
|
|
}
|
|
|
|
err := b.client.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(b.client.T, err, "createDocument mutation failed")
|
|
|
|
b.versionID = result.CreateDocument.DocumentVersionEdge.Node.ID
|
|
|
|
return result.CreateDocument.DocumentEdge.Node.ID
|
|
}
|
|
|
|
func CreateProcessingActivity(c *testutil.Client, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateProcessingActivityInput!) {
|
|
createProcessingActivity(input: $input) {
|
|
processingActivityEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": c.GetOrganizationID().String(),
|
|
"name": a.getString("name", SafeName("ProcessingActivity")),
|
|
"specialOrCriminalData": a.getString("specialOrCriminalData", "NO"),
|
|
"lawfulBasis": a.getString("lawfulBasis", "CONSENT"),
|
|
"internationalTransfers": a.getBool("internationalTransfers", false),
|
|
"dataProtectionImpactAssessmentNeeded": a.getString("dataProtectionImpactAssessmentNeeded", "NOT_NEEDED"),
|
|
"transferImpactAssessmentNeeded": a.getString("transferImpactAssessmentNeeded", "NOT_NEEDED"),
|
|
"role": a.getString("role", "CONTROLLER"),
|
|
}
|
|
if purpose := a.getStringPtr("purpose"); purpose != nil {
|
|
input["purpose"] = *purpose
|
|
}
|
|
|
|
var result struct {
|
|
CreateProcessingActivity struct {
|
|
ProcessingActivityEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"processingActivityEdge"`
|
|
} `json:"createProcessingActivity"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createProcessingActivity mutation failed")
|
|
|
|
return result.CreateProcessingActivity.ProcessingActivityEdge.Node.ID
|
|
}
|
|
|
|
type ProcessingActivityBuilder struct {
|
|
client *testutil.Client
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewProcessingActivity(c *testutil.Client) *ProcessingActivityBuilder {
|
|
return &ProcessingActivityBuilder{client: c, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *ProcessingActivityBuilder) WithName(name string) *ProcessingActivityBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *ProcessingActivityBuilder) WithPurpose(purpose string) *ProcessingActivityBuilder {
|
|
b.attrs["purpose"] = purpose
|
|
return b
|
|
}
|
|
|
|
func (b *ProcessingActivityBuilder) WithLawfulBasis(basis string) *ProcessingActivityBuilder {
|
|
b.attrs["lawfulBasis"] = basis
|
|
return b
|
|
}
|
|
|
|
func (b *ProcessingActivityBuilder) WithInternationalTransfers(transfers bool) *ProcessingActivityBuilder {
|
|
b.attrs["internationalTransfers"] = transfers
|
|
return b
|
|
}
|
|
|
|
func (b *ProcessingActivityBuilder) WithSpecialOrCriminalData(value string) *ProcessingActivityBuilder {
|
|
b.attrs["specialOrCriminalData"] = value
|
|
return b
|
|
}
|
|
|
|
func (b *ProcessingActivityBuilder) Create() string {
|
|
return CreateProcessingActivity(b.client, b.attrs)
|
|
}
|
|
|
|
func CreateAccessReviewSource(c *testutil.Client, organizationID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateAccessReviewSourceInput!) {
|
|
createAccessReviewSource(input: $input) {
|
|
accessReviewSourceEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": organizationID,
|
|
"name": a.getString("name", SafeName("AccessReviewSource")),
|
|
}
|
|
if csvData := a.getStringPtr("csvData"); csvData != nil {
|
|
input["csvData"] = *csvData
|
|
}
|
|
|
|
if connectorID := a.getStringPtr("connectorId"); connectorID != nil {
|
|
input["connectorId"] = *connectorID
|
|
}
|
|
|
|
var result struct {
|
|
CreateAccessReviewSource struct {
|
|
AccessReviewSourceEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"accessReviewSourceEdge"`
|
|
} `json:"createAccessReviewSource"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createAccessReviewSource mutation failed")
|
|
|
|
return result.CreateAccessReviewSource.AccessReviewSourceEdge.Node.ID
|
|
}
|
|
|
|
type AccessReviewSourceBuilder struct {
|
|
client *testutil.Client
|
|
organizationID string
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewAccessReviewSource(c *testutil.Client, organizationID string) *AccessReviewSourceBuilder {
|
|
return &AccessReviewSourceBuilder{client: c, organizationID: organizationID, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *AccessReviewSourceBuilder) WithName(name string) *AccessReviewSourceBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *AccessReviewSourceBuilder) WithCsvData(csvData string) *AccessReviewSourceBuilder {
|
|
b.attrs["csvData"] = csvData
|
|
return b
|
|
}
|
|
|
|
func (b *AccessReviewSourceBuilder) Create() string {
|
|
return CreateAccessReviewSource(b.client, b.organizationID, b.attrs)
|
|
}
|
|
|
|
func CreateAccessReviewCampaign(c *testutil.Client, organizationID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateAccessReviewCampaignInput!) {
|
|
createAccessReviewCampaign(input: $input) {
|
|
accessReviewCampaignEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": organizationID,
|
|
"name": a.getString("name", SafeName("Campaign")),
|
|
}
|
|
|
|
if v, ok := a["accessReviewSourceIds"]; ok {
|
|
input["accessReviewSourceIds"] = v
|
|
}
|
|
|
|
var result struct {
|
|
CreateAccessReviewCampaign struct {
|
|
AccessReviewCampaignEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"accessReviewCampaignEdge"`
|
|
} `json:"createAccessReviewCampaign"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createAccessReviewCampaign mutation failed")
|
|
|
|
return result.CreateAccessReviewCampaign.AccessReviewCampaignEdge.Node.ID
|
|
}
|
|
|
|
type AccessReviewCampaignBuilder struct {
|
|
client *testutil.Client
|
|
organizationID string
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewAccessReviewCampaign(c *testutil.Client, organizationID string) *AccessReviewCampaignBuilder {
|
|
return &AccessReviewCampaignBuilder{client: c, organizationID: organizationID, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *AccessReviewCampaignBuilder) WithName(name string) *AccessReviewCampaignBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *AccessReviewCampaignBuilder) WithAccessReviewSourceIDs(ids []string) *AccessReviewCampaignBuilder {
|
|
b.attrs["accessReviewSourceIds"] = ids
|
|
return b
|
|
}
|
|
|
|
func (b *AccessReviewCampaignBuilder) Create() string {
|
|
return CreateAccessReviewCampaign(b.client, b.organizationID, b.attrs)
|
|
}
|
|
|
|
type StatementOfApplicabilityBuilder struct {
|
|
client *testutil.Client
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewStatementOfApplicability(c *testutil.Client) *StatementOfApplicabilityBuilder {
|
|
return &StatementOfApplicabilityBuilder{client: c, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *StatementOfApplicabilityBuilder) WithName(name string) *StatementOfApplicabilityBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *StatementOfApplicabilityBuilder) Create() string {
|
|
b.client.T.Helper()
|
|
|
|
a := b.attrs
|
|
|
|
const query = `
|
|
mutation($input: CreateStatementOfApplicabilityInput!) {
|
|
createStatementOfApplicability(input: $input) {
|
|
statementOfApplicabilityEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": b.client.GetOrganizationID().String(),
|
|
"name": a.getString("name", SafeName("SOA")),
|
|
}
|
|
|
|
var result struct {
|
|
CreateStatementOfApplicability struct {
|
|
StatementOfApplicabilityEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"statementOfApplicabilityEdge"`
|
|
} `json:"createStatementOfApplicability"`
|
|
}
|
|
|
|
err := b.client.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(b.client.T, err, "createStatementOfApplicability mutation failed")
|
|
|
|
return result.CreateStatementOfApplicability.StatementOfApplicabilityEdge.Node.ID
|
|
}
|
|
|
|
func CreateApplicabilityStatement(c *testutil.Client, soaID, controlID string, applicability bool, justification *string) string {
|
|
c.T.Helper()
|
|
|
|
const query = `
|
|
mutation($input: CreateApplicabilityStatementInput!) {
|
|
createApplicabilityStatement(input: $input) {
|
|
applicabilityStatementEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"statementOfApplicabilityId": soaID,
|
|
"controlId": controlID,
|
|
"applicability": applicability,
|
|
}
|
|
|
|
if justification != nil {
|
|
input["justification"] = *justification
|
|
}
|
|
|
|
var result struct {
|
|
CreateApplicabilityStatement struct {
|
|
ApplicabilityStatementEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"applicabilityStatementEdge"`
|
|
} `json:"createApplicabilityStatement"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createApplicabilityStatement mutation failed")
|
|
|
|
return result.CreateApplicabilityStatement.ApplicabilityStatementEdge.Node.ID
|
|
}
|
|
|
|
type OAuth2ClientResult struct {
|
|
ClientID string
|
|
ClientSecret string
|
|
}
|
|
|
|
func CreateOAuth2Client(c *testutil.Client, attrs Attrs) OAuth2ClientResult {
|
|
input := map[string]any{
|
|
"organization_id": c.GetOrganizationID().String(),
|
|
"client_name": SafeName("OAuth2 Client"),
|
|
"visibility": "private",
|
|
"redirect_uris": []string{"http://localhost:9999/callback"},
|
|
"grant_types": []string{
|
|
"authorization_code",
|
|
"refresh_token",
|
|
},
|
|
"response_types": []string{"code"},
|
|
"token_endpoint_auth_method": "client_secret_basic",
|
|
"scopes": "openid email profile offline_access",
|
|
}
|
|
|
|
maps.Copy(input, attrs)
|
|
|
|
resp, raw, err := testutil.OAuth2RegisterClient(c, input)
|
|
require.NoError(c.T, err, "OAuth2 client registration failed")
|
|
require.NotNil(c.T, resp, "OAuth2 client registration returned nil (status=%d body=%s)", raw.StatusCode, string(raw.Body))
|
|
|
|
return OAuth2ClientResult{
|
|
ClientID: resp.ClientID,
|
|
ClientSecret: resp.ClientSecret,
|
|
}
|
|
}
|
|
|
|
func CreatePublicOAuth2Client(c *testutil.Client, attrs Attrs) OAuth2ClientResult {
|
|
input := map[string]any{
|
|
"organization_id": c.GetOrganizationID().String(),
|
|
"client_name": SafeName("Public OAuth2 Client"),
|
|
"visibility": "private",
|
|
"redirect_uris": []string{"http://localhost:9999/callback"},
|
|
"grant_types": []string{
|
|
"authorization_code",
|
|
"refresh_token",
|
|
"urn:ietf:params:oauth:grant-type:device_code",
|
|
},
|
|
"response_types": []string{"code"},
|
|
"token_endpoint_auth_method": "none",
|
|
"scopes": "openid email profile offline_access",
|
|
}
|
|
|
|
maps.Copy(input, attrs)
|
|
|
|
resp, raw, err := testutil.OAuth2RegisterClient(c, input)
|
|
require.NoError(c.T, err, "public OAuth2 client registration failed")
|
|
require.NotNil(c.T, resp, "public OAuth2 client registration returned nil (status=%d body=%s)", raw.StatusCode, string(raw.Body))
|
|
|
|
return OAuth2ClientResult{
|
|
ClientID: resp.ClientID,
|
|
ClientSecret: resp.ClientSecret,
|
|
}
|
|
}
|
|
|
|
func SafeOrigin() string {
|
|
return fmt.Sprintf("https://%s.example.com", strings.ToLower(gofakeit.LetterN(10)))
|
|
}
|
|
|
|
func CreateCookieBanner(c *testutil.Client, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateCookieBannerInput!) {
|
|
createCookieBanner(input: $input) {
|
|
cookieBannerEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": c.GetOrganizationID().String(),
|
|
"name": a.getString("name", SafeName("CookieBanner")),
|
|
"origin": a.getString("origin", SafeOrigin()),
|
|
"cookiePolicyUrl": a.getString("cookiePolicyUrl", "https://example.com/cookies"),
|
|
"consentExpiryDays": a.getInt("consentExpiryDays", 365),
|
|
}
|
|
if ppURL := a.getStringPtr("privacyPolicyUrl"); ppURL != nil {
|
|
input["privacyPolicyUrl"] = *ppURL
|
|
}
|
|
|
|
var result struct {
|
|
CreateCookieBanner struct {
|
|
CookieBannerEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"cookieBannerEdge"`
|
|
} `json:"createCookieBanner"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createCookieBanner mutation failed")
|
|
|
|
return result.CreateCookieBanner.CookieBannerEdge.Node.ID
|
|
}
|
|
|
|
type CookieBannerBuilder struct {
|
|
client *testutil.Client
|
|
attrs Attrs
|
|
}
|
|
|
|
func NewCookieBanner(c *testutil.Client) *CookieBannerBuilder {
|
|
return &CookieBannerBuilder{client: c, attrs: Attrs{}}
|
|
}
|
|
|
|
func (b *CookieBannerBuilder) WithName(name string) *CookieBannerBuilder {
|
|
b.attrs["name"] = name
|
|
return b
|
|
}
|
|
|
|
func (b *CookieBannerBuilder) WithOrigin(origin string) *CookieBannerBuilder {
|
|
b.attrs["origin"] = origin
|
|
return b
|
|
}
|
|
|
|
func (b *CookieBannerBuilder) WithCookiePolicyUrl(url string) *CookieBannerBuilder {
|
|
b.attrs["cookiePolicyUrl"] = url
|
|
return b
|
|
}
|
|
|
|
func (b *CookieBannerBuilder) WithPrivacyPolicyUrl(url string) *CookieBannerBuilder {
|
|
b.attrs["privacyPolicyUrl"] = url
|
|
return b
|
|
}
|
|
|
|
func (b *CookieBannerBuilder) WithConsentExpiryDays(days int) *CookieBannerBuilder {
|
|
b.attrs["consentExpiryDays"] = days
|
|
return b
|
|
}
|
|
|
|
func (b *CookieBannerBuilder) Create() string {
|
|
return CreateCookieBanner(b.client, b.attrs)
|
|
}
|
|
|
|
func CreateCookieCategory(c *testutil.Client, bannerID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateCookieCategoryInput!) {
|
|
createCookieCategory(input: $input) {
|
|
cookieCategoryEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"cookieBannerId": bannerID,
|
|
"name": a.getString("name", SafeName("Category")),
|
|
"slug": a.getString("slug", strings.ToLower(gofakeit.LetterN(8))),
|
|
"description": a.getString("description", "Test cookie category"),
|
|
"rank": a.getInt("rank", 10),
|
|
}
|
|
|
|
var result struct {
|
|
CreateCookieCategory struct {
|
|
CookieCategoryEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"cookieCategoryEdge"`
|
|
} `json:"createCookieCategory"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createCookieCategory mutation failed")
|
|
|
|
return result.CreateCookieCategory.CookieCategoryEdge.Node.ID
|
|
}
|
|
|
|
func CreateTrackerPattern(c *testutil.Client, categoryID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateTrackerPatternInput!) {
|
|
createTrackerPattern(input: $input) {
|
|
trackerPatternEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"cookieCategoryId": categoryID,
|
|
"trackerType": a.getString("trackerType", "COOKIE"),
|
|
"pattern": a.getString("pattern", gofakeit.LetterN(8)+"_cookie"),
|
|
"matchType": a.getString("matchType", "EXACT"),
|
|
"displayName": a.getString("displayName", SafeName("Pattern")),
|
|
"description": a.getString("description", "Test tracker pattern"),
|
|
}
|
|
if _, ok := a["maxAgeSeconds"]; ok {
|
|
input["maxAgeSeconds"] = a.getInt("maxAgeSeconds", 0)
|
|
}
|
|
|
|
var result struct {
|
|
CreateTrackerPattern struct {
|
|
TrackerPatternEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"trackerPatternEdge"`
|
|
} `json:"createTrackerPattern"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createTrackerPattern mutation failed")
|
|
|
|
return result.CreateTrackerPattern.TrackerPatternEdge.Node.ID
|
|
}
|
|
|
|
func CreateTrackerResource(c *testutil.Client, categoryID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateTrackerResourceInput!) {
|
|
createTrackerResource(input: $input) {
|
|
trackerResourceEdge {
|
|
node { id }
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"cookieCategoryId": categoryID,
|
|
"type": a.getString("type", "SCRIPT"),
|
|
"origin": a.getString("origin", SafeOrigin()),
|
|
"path": a.getString("path", "/"+gofakeit.LetterN(8)+".js"),
|
|
"displayName": a.getString("displayName", SafeName("Resource")),
|
|
"description": a.getString("description", "Test tracker resource"),
|
|
}
|
|
|
|
var result struct {
|
|
CreateTrackerResource struct {
|
|
TrackerResourceEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"trackerResourceEdge"`
|
|
} `json:"createTrackerResource"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createTrackerResource mutation failed")
|
|
|
|
return result.CreateTrackerResource.TrackerResourceEdge.Node.ID
|
|
}
|
|
|
|
func ReportDetectedResources(c *testutil.Client, bannerID string, count int) {
|
|
c.T.Helper()
|
|
|
|
resources := make([]map[string]string, 0, count)
|
|
for range count {
|
|
resources = append(resources, map[string]string{
|
|
"url": fmt.Sprintf("https://%s.example.com/%s.js", strings.ToLower(gofakeit.LetterN(8)), gofakeit.LetterN(6)),
|
|
"resource_type": "script",
|
|
})
|
|
}
|
|
|
|
body, err := json.Marshal(map[string]any{"resources": resources})
|
|
require.NoError(c.T, err, "cannot marshal report body")
|
|
|
|
url := fmt.Sprintf("%s/api/cookie-banner/v1/%s/report", c.BaseURL(), bannerID)
|
|
resp, err := http.Post(url, "application/json", bytes.NewReader(body))
|
|
require.NoError(c.T, err, "report detected resources request failed")
|
|
|
|
defer func() { _ = resp.Body.Close() }()
|
|
|
|
require.Equal(c.T, http.StatusNoContent, resp.StatusCode, "report detected resources unexpected status")
|
|
}
|
|
|
|
func CreateRiskAssessment(c *testutil.Client, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateRiskAssessmentInput!) {
|
|
createRiskAssessment(input: $input) {
|
|
riskAssessmentEdge { node { id } }
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"organizationId": c.GetOrganizationID().String(),
|
|
"name": a.getString("name", SafeName("Risk Assessment")),
|
|
}
|
|
if desc := a.getStringPtr("description"); desc != nil {
|
|
input["description"] = *desc
|
|
}
|
|
|
|
var result struct {
|
|
CreateRiskAssessment struct {
|
|
RiskAssessmentEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"riskAssessmentEdge"`
|
|
} `json:"createRiskAssessment"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createRiskAssessment mutation failed")
|
|
|
|
return result.CreateRiskAssessment.RiskAssessmentEdge.Node.ID
|
|
}
|
|
|
|
func CreateRiskAssessmentScope(c *testutil.Client, riskAssessmentID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateRiskAssessmentScopeInput!) {
|
|
createRiskAssessmentScope(input: $input) {
|
|
riskAssessmentScopeEdge { node { id } }
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"riskAssessmentId": riskAssessmentID,
|
|
"name": a.getString("name", SafeName("Scope")),
|
|
}
|
|
|
|
var result struct {
|
|
CreateRiskAssessmentScope struct {
|
|
RiskAssessmentScopeEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"riskAssessmentScopeEdge"`
|
|
} `json:"createRiskAssessmentScope"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createRiskAssessmentScope mutation failed")
|
|
|
|
return result.CreateRiskAssessmentScope.RiskAssessmentScopeEdge.Node.ID
|
|
}
|
|
|
|
func CreateRiskAssessmentNode(c *testutil.Client, scopeID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateRiskAssessmentNodeInput!) {
|
|
createRiskAssessmentNode(input: $input) {
|
|
riskAssessmentNodeEdge { node { id } }
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"riskAssessmentScopeId": scopeID,
|
|
"nodeType": a.getString("nodeType", "ASSET"),
|
|
"name": a.getString("name", SafeName("Node")),
|
|
}
|
|
|
|
if boundaryID := a.getString("boundaryId", ""); boundaryID != "" {
|
|
input["boundaryId"] = boundaryID
|
|
}
|
|
|
|
var result struct {
|
|
CreateRiskAssessmentNode struct {
|
|
RiskAssessmentNodeEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"riskAssessmentNodeEdge"`
|
|
} `json:"createRiskAssessmentNode"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createRiskAssessmentNode mutation failed")
|
|
|
|
return result.CreateRiskAssessmentNode.RiskAssessmentNodeEdge.Node.ID
|
|
}
|
|
|
|
func CreateRiskAssessmentBoundary(c *testutil.Client, scopeID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateRiskAssessmentBoundaryInput!) {
|
|
createRiskAssessmentBoundary(input: $input) {
|
|
riskAssessmentBoundaryEdge { node { id } }
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"riskAssessmentScopeId": scopeID,
|
|
"name": a.getString("name", SafeName("Boundary")),
|
|
}
|
|
|
|
if parentID := a.getString("parentBoundaryId", ""); parentID != "" {
|
|
input["parentBoundaryId"] = parentID
|
|
}
|
|
|
|
var result struct {
|
|
CreateRiskAssessmentBoundary struct {
|
|
RiskAssessmentBoundaryEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"riskAssessmentBoundaryEdge"`
|
|
} `json:"createRiskAssessmentBoundary"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createRiskAssessmentBoundary mutation failed")
|
|
|
|
return result.CreateRiskAssessmentBoundary.RiskAssessmentBoundaryEdge.Node.ID
|
|
}
|
|
|
|
func CreateRiskAssessmentProcess(c *testutil.Client, scopeID, sourceNodeID, targetNodeID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateRiskAssessmentProcessInput!) {
|
|
createRiskAssessmentProcess(input: $input) {
|
|
riskAssessmentProcessEdge { node { id } }
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"riskAssessmentScopeId": scopeID,
|
|
"sourceNodeId": sourceNodeID,
|
|
"targetNodeId": targetNodeID,
|
|
"name": a.getString("name", SafeName("Process")),
|
|
}
|
|
|
|
var result struct {
|
|
CreateRiskAssessmentProcess struct {
|
|
RiskAssessmentProcessEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"riskAssessmentProcessEdge"`
|
|
} `json:"createRiskAssessmentProcess"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createRiskAssessmentProcess mutation failed")
|
|
|
|
return result.CreateRiskAssessmentProcess.RiskAssessmentProcessEdge.Node.ID
|
|
}
|
|
|
|
func CreateRiskAssessmentThreat(c *testutil.Client, scopeID, processID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateRiskAssessmentThreatInput!) {
|
|
createRiskAssessmentThreat(input: $input) {
|
|
riskAssessmentThreatEdge { node { id } }
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"riskAssessmentScopeId": scopeID,
|
|
"processId": processID,
|
|
"name": a.getString("name", SafeName("Threat")),
|
|
"category": a.getString("category", "Confidentiality"),
|
|
}
|
|
|
|
var result struct {
|
|
CreateRiskAssessmentThreat struct {
|
|
RiskAssessmentThreatEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"riskAssessmentThreatEdge"`
|
|
} `json:"createRiskAssessmentThreat"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createRiskAssessmentThreat mutation failed")
|
|
|
|
return result.CreateRiskAssessmentThreat.RiskAssessmentThreatEdge.Node.ID
|
|
}
|
|
|
|
func CreateRiskAssessmentScenario(c *testutil.Client, scopeID string, attrs ...Attrs) string {
|
|
c.T.Helper()
|
|
|
|
var a Attrs
|
|
if len(attrs) > 0 {
|
|
a = attrs[0]
|
|
}
|
|
|
|
const query = `
|
|
mutation($input: CreateRiskAssessmentScenarioInput!) {
|
|
createRiskAssessmentScenario(input: $input) {
|
|
riskAssessmentScenarioEdge { node { id } }
|
|
}
|
|
}
|
|
`
|
|
|
|
input := map[string]any{
|
|
"riskAssessmentScopeId": scopeID,
|
|
"name": a.getString("name", SafeName("Scenario")),
|
|
}
|
|
if desc := a.getStringPtr("description"); desc != nil {
|
|
input["description"] = *desc
|
|
}
|
|
|
|
var result struct {
|
|
CreateRiskAssessmentScenario struct {
|
|
RiskAssessmentScenarioEdge struct {
|
|
Node struct {
|
|
ID string `json:"id"`
|
|
} `json:"node"`
|
|
} `json:"riskAssessmentScenarioEdge"`
|
|
} `json:"createRiskAssessmentScenario"`
|
|
}
|
|
|
|
err := c.Execute(query, map[string]any{"input": input}, &result)
|
|
require.NoError(c.T, err, "createRiskAssessmentScenario mutation failed")
|
|
|
|
return result.CreateRiskAssessmentScenario.RiskAssessmentScenarioEdge.Node.ID
|
|
}
|
|
|
|
func LinkRiskAssessmentScenarioThreat(c *testutil.Client, scenarioID, threatID string) {
|
|
c.T.Helper()
|
|
|
|
const query = `
|
|
mutation($input: LinkRiskAssessmentScenarioThreatInput!) {
|
|
linkRiskAssessmentScenarioThreat(input: $input) {
|
|
riskAssessmentScenario { id }
|
|
}
|
|
}
|
|
`
|
|
|
|
_, err := c.Do(query, map[string]any{
|
|
"input": map[string]any{
|
|
"riskAssessmentScenarioId": scenarioID,
|
|
"threatId": threatID,
|
|
},
|
|
})
|
|
require.NoError(c.T, err, "linkRiskAssessmentScenarioThreat mutation failed")
|
|
}
|
|
|
|
func LinkRiskAssessmentScenarioRisk(c *testutil.Client, scenarioID, riskID string) {
|
|
c.T.Helper()
|
|
|
|
const query = `
|
|
mutation($input: LinkRiskAssessmentScenarioRiskInput!) {
|
|
linkRiskAssessmentScenarioRisk(input: $input) {
|
|
riskAssessmentScenario { id }
|
|
}
|
|
}
|
|
`
|
|
|
|
_, err := c.Do(query, map[string]any{
|
|
"input": map[string]any{
|
|
"riskAssessmentScenarioId": scenarioID,
|
|
"riskId": riskID,
|
|
},
|
|
})
|
|
require.NoError(c.T, err, "linkRiskAssessmentScenarioRisk mutation failed")
|
|
}
|