Fix e2e tests

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-02-06 14:38:14 +04:00
parent 9243681f1b
commit 8d20220c86
25 changed files with 323 additions and 1142 deletions

View File

@@ -20,7 +20,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.probo.inc/probo/e2e/internal/factory"
"go.probo.inc/probo/e2e/internal/testutil"
)
@@ -28,9 +27,8 @@ func TestAsset_Create(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).
WithFullName("Asset Owner").
Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
const query = `
mutation($input: CreateAssetInput!) {
@@ -73,7 +71,7 @@ func TestAsset_Create(t *testing.T) {
"organizationId": owner.GetOrganizationID().String(),
"name": "Production Database Server",
"amount": 5,
"ownerId": peopleID,
"ownerId": profileID.String(),
"assetType": "VIRTUAL",
"dataTypesStored": "Customer PII, Financial Records",
},
@@ -86,16 +84,15 @@ func TestAsset_Create(t *testing.T) {
assert.Equal(t, 5, asset.Amount)
assert.Equal(t, "VIRTUAL", asset.AssetType)
assert.Equal(t, "Customer PII, Financial Records", asset.DataTypesStored)
assert.Equal(t, peopleID, asset.Owner.ID)
assert.Equal(t, profileID.String(), asset.Owner.ID)
}
func TestAsset_Update(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).
WithFullName("Asset Owner for Update").
Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
const createQuery = `
mutation($input: CreateAssetInput!) {
@@ -124,7 +121,7 @@ func TestAsset_Update(t *testing.T) {
"organizationId": owner.GetOrganizationID().String(),
"name": "Test Asset",
"amount": 10,
"ownerId": peopleID,
"ownerId": profileID.String(),
"assetType": "VIRTUAL",
"dataTypesStored": "Test data",
},
@@ -175,9 +172,8 @@ func TestAsset_Delete(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).
WithFullName("Asset Owner for Delete").
Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
const createQuery = `
mutation($input: CreateAssetInput!) {
@@ -206,7 +202,7 @@ func TestAsset_Delete(t *testing.T) {
"organizationId": owner.GetOrganizationID().String(),
"name": "Asset to delete",
"amount": 1,
"ownerId": peopleID,
"ownerId": profileID.String(),
"assetType": "VIRTUAL",
"dataTypesStored": "None",
},
@@ -241,9 +237,8 @@ func TestAsset_List(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).
WithFullName("Asset Owner for List").
Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
// Create multiple assets
for i := 0; i < 3; i++ {
@@ -274,7 +269,7 @@ func TestAsset_List(t *testing.T) {
"organizationId": owner.GetOrganizationID().String(),
"name": fmt.Sprintf("Asset %c", 'A'+i),
"amount": i + 1,
"ownerId": peopleID,
"ownerId": profileID.String(),
"assetType": "VIRTUAL",
"dataTypesStored": "Test data",
},
@@ -329,9 +324,8 @@ func TestAsset_Types(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).
WithFullName("Asset Owner for Types").
Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
assetTypes := []string{"PHYSICAL", "VIRTUAL"}
@@ -366,7 +360,7 @@ func TestAsset_Types(t *testing.T) {
"organizationId": owner.GetOrganizationID().String(),
"name": "Asset " + assetType,
"amount": 1,
"ownerId": peopleID,
"ownerId": profileID.String(),
"assetType": assetType,
"dataTypesStored": "Test data",
},

View File

@@ -21,14 +21,14 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.probo.inc/probo/e2e/internal/factory"
"go.probo.inc/probo/e2e/internal/testutil"
)
func TestContinualImprovement_Create(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("CI Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
query := `
mutation CreateContinualImprovement($input: CreateContinualImprovementInput!) {
@@ -68,7 +68,7 @@ func TestContinualImprovement_Create(t *testing.T) {
"referenceId": fmt.Sprintf("CI-%d", time.Now().UnixNano()),
"description": "Improve security training program",
"source": "Internal Audit",
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "OPEN",
"priority": "HIGH",
},
@@ -86,7 +86,8 @@ func TestContinualImprovement_Create(t *testing.T) {
func TestContinualImprovement_Update(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("CI Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
createQuery := `
mutation CreateContinualImprovement($input: CreateContinualImprovementInput!) {
@@ -115,7 +116,7 @@ func TestContinualImprovement_Update(t *testing.T) {
"organizationId": owner.GetOrganizationID().String(),
"referenceId": fmt.Sprintf("CI-UPDATE-%d", time.Now().UnixNano()),
"description": "Original description",
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "OPEN",
"priority": "LOW",
},
@@ -166,7 +167,8 @@ func TestContinualImprovement_Update(t *testing.T) {
func TestContinualImprovement_Delete(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("CI Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
createQuery := `
mutation CreateContinualImprovement($input: CreateContinualImprovementInput!) {
@@ -194,7 +196,7 @@ func TestContinualImprovement_Delete(t *testing.T) {
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"referenceId": fmt.Sprintf("CI-DELETE-%d", time.Now().UnixNano()),
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "OPEN",
"priority": "LOW",
},
@@ -228,7 +230,8 @@ func TestContinualImprovement_Delete(t *testing.T) {
func TestContinualImprovement_List(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("CI Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
createQuery := `
mutation CreateContinualImprovement($input: CreateContinualImprovementInput!) {
@@ -248,7 +251,7 @@ func TestContinualImprovement_List(t *testing.T) {
"organizationId": owner.GetOrganizationID().String(),
"referenceId": fmt.Sprintf("CI-LIST-%d-%d", i, time.Now().UnixNano()),
"description": fmt.Sprintf("Improvement %d", i),
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "OPEN",
"priority": "MEDIUM",
},
@@ -302,7 +305,8 @@ func TestContinualImprovement_List(t *testing.T) {
func TestContinualImprovement_StatusAndPriorityValues(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("CI Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
t.Run("status values", func(t *testing.T) {
statuses := []string{"OPEN", "IN_PROGRESS", "CLOSED"}
@@ -337,7 +341,7 @@ func TestContinualImprovement_StatusAndPriorityValues(t *testing.T) {
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"referenceId": fmt.Sprintf("CI-STATUS-%s-%d", status, time.Now().UnixNano()),
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": status,
"priority": "LOW",
},
@@ -381,7 +385,7 @@ func TestContinualImprovement_StatusAndPriorityValues(t *testing.T) {
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"referenceId": fmt.Sprintf("CI-PRIORITY-%s-%d", priority, time.Now().UnixNano()),
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "OPEN",
"priority": priority,
},

View File

@@ -29,7 +29,8 @@ import (
func TestDatum_Create(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Datum Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
tests := []struct {
name string
@@ -102,7 +103,7 @@ func TestDatum_Create(t *testing.T) {
input := map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"ownerId": peopleID,
"ownerId": profileID.String(),
}
for k, v := range tt.input {
input[k] = v
@@ -139,7 +140,8 @@ func TestDatum_Create(t *testing.T) {
func TestDatum_Create_Validation(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Datum Validation Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
tests := []struct {
name string
@@ -259,7 +261,7 @@ func TestDatum_Create_Validation(t *testing.T) {
input["organizationId"] = owner.GetOrganizationID().String()
}
if !tt.skipOwner {
input["ownerId"] = peopleID
input["ownerId"] = profileID
}
for k, v := range tt.input {
input[k] = v
@@ -275,7 +277,8 @@ func TestDatum_Create_Validation(t *testing.T) {
func TestDatum_Update(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Datum Update Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
tests := []struct {
name string
@@ -287,7 +290,7 @@ func TestDatum_Update(t *testing.T) {
{
name: "update name",
setup: func() string {
return factory.NewDatum(owner, peopleID).
return factory.NewDatum(owner, profileID.String()).
WithName("Datum to Update").
Create()
},
@@ -303,7 +306,7 @@ func TestDatum_Update(t *testing.T) {
{
name: "update to PUBLIC classification",
setup: func() string {
return factory.NewDatum(owner, peopleID).
return factory.NewDatum(owner, profileID.String()).
WithName("Classification Test").
WithDataClassification("INTERNAL").
Create()
@@ -317,7 +320,7 @@ func TestDatum_Update(t *testing.T) {
{
name: "update to SECRET classification",
setup: func() string {
return factory.NewDatum(owner, peopleID).
return factory.NewDatum(owner, profileID.String()).
WithName("Classification Test").
Create()
},
@@ -372,8 +375,9 @@ func TestDatum_Update(t *testing.T) {
func TestDatum_Update_Validation(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Datum Update Validation Owner").Create()
baseDatumID := factory.NewDatum(owner, peopleID).WithName("Validation Test Datum").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
baseDatumID := factory.NewDatum(owner, profileID.String()).WithName("Validation Test Datum").Create()
tests := []struct {
name string
@@ -487,10 +491,11 @@ func TestDatum_Update_Validation(t *testing.T) {
func TestDatum_Delete(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Datum Delete Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
t.Run("delete existing datum", func(t *testing.T) {
datumID := factory.NewDatum(owner, peopleID).WithName("Datum to Delete").Create()
datumID := factory.NewDatum(owner, profileID.String()).WithName("Datum to Delete").Create()
query := `
mutation DeleteDatum($input: DeleteDatumInput!) {
@@ -552,11 +557,12 @@ func TestDatum_Delete_Validation(t *testing.T) {
func TestDatum_List(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Datum List Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
datumNames := []string{"Datum A", "Datum B", "Datum C"}
for _, name := range datumNames {
factory.NewDatum(owner, peopleID).WithName(name).Create()
factory.NewDatum(owner, profileID.String()).WithName(name).Create()
}
query := `
@@ -624,7 +630,8 @@ func TestDatum_Query(t *testing.T) {
func TestDatum_Timestamps(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Datum Timestamps Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
t.Run("createdAt and updatedAt are set on create", func(t *testing.T) {
beforeCreate := time.Now().Add(-time.Second)
@@ -658,7 +665,7 @@ func TestDatum_Timestamps(t *testing.T) {
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"ownerId": peopleID,
"ownerId": profileID.String(),
"name": "Timestamp Test Datum",
"dataClassification": "INTERNAL",
},
@@ -670,7 +677,7 @@ func TestDatum_Timestamps(t *testing.T) {
})
t.Run("updatedAt changes on update", func(t *testing.T) {
datumID := factory.NewDatum(owner, peopleID).WithName("Timestamp Update Test").Create()
datumID := factory.NewDatum(owner, profileID.String()).WithName("Timestamp Update Test").Create()
getQuery := `
query($id: ID!) {
@@ -734,8 +741,9 @@ func TestDatum_Timestamps(t *testing.T) {
func TestDatum_SubResolvers(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Datum SubResolver Owner").Create()
datumID := factory.NewDatum(owner, peopleID).WithName("SubResolver Test Datum").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
datumID := factory.NewDatum(owner, profileID.String()).WithName("SubResolver Test Datum").Create()
t.Run("owner sub-resolver", func(t *testing.T) {
query := `
@@ -764,7 +772,7 @@ func TestDatum_SubResolvers(t *testing.T) {
err := owner.Execute(query, map[string]any{"id": datumID}, &result)
require.NoError(t, err)
assert.Equal(t, peopleID, result.Node.Owner.ID)
assert.Equal(t, profileID.String(), result.Node.Owner.ID)
})
t.Run("organization sub-resolver", func(t *testing.T) {
@@ -805,7 +813,8 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("create", func(t *testing.T) {
t.Run("owner can create", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
_, err := owner.Do(`
mutation CreateDatum($input: CreateDatumInput!) {
@@ -816,7 +825,7 @@ func TestDatum_RBAC(t *testing.T) {
`, map[string]any{
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"ownerId": peopleID,
"ownerId": profileID.String(),
"name": "RBAC Test Datum",
"dataClassification": "INTERNAL",
},
@@ -827,7 +836,8 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("admin can create", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
admin := testutil.NewClientInOrg(t, testutil.RoleAdmin, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Admin Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
_, err := admin.Do(`
mutation CreateDatum($input: CreateDatumInput!) {
@@ -838,7 +848,7 @@ func TestDatum_RBAC(t *testing.T) {
`, map[string]any{
"input": map[string]any{
"organizationId": admin.GetOrganizationID().String(),
"ownerId": peopleID,
"ownerId": profileID.String(),
"name": "RBAC Test Datum",
"dataClassification": "INTERNAL",
},
@@ -849,7 +859,8 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("viewer cannot create", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Viewer Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
_, err := viewer.Do(`
mutation CreateDatum($input: CreateDatumInput!) {
@@ -860,7 +871,7 @@ func TestDatum_RBAC(t *testing.T) {
`, map[string]any{
"input": map[string]any{
"organizationId": viewer.GetOrganizationID().String(),
"ownerId": peopleID,
"ownerId": profileID.String(),
"name": "RBAC Test Datum",
"dataClassification": "INTERNAL",
},
@@ -872,8 +883,9 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("update", func(t *testing.T) {
t.Run("owner can update", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Update Owner").Create()
datumID := factory.NewDatum(owner, peopleID).WithName("RBAC Update Test").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
datumID := factory.NewDatum(owner, profileID.String()).WithName("RBAC Update Test").Create()
_, err := owner.Do(`
mutation UpdateDatum($input: UpdateDatumInput!) {
@@ -893,8 +905,9 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("admin can update", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
admin := testutil.NewClientInOrg(t, testutil.RoleAdmin, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Admin Update Owner").Create()
datumID := factory.NewDatum(owner, peopleID).WithName("RBAC Update Test").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
datumID := factory.NewDatum(owner, profileID.String()).WithName("RBAC Update Test").Create()
_, err := admin.Do(`
mutation UpdateDatum($input: UpdateDatumInput!) {
@@ -914,8 +927,9 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("viewer cannot update", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Viewer Update Owner").Create()
datumID := factory.NewDatum(owner, peopleID).WithName("RBAC Update Test").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
datumID := factory.NewDatum(owner, profileID.String()).WithName("RBAC Update Test").Create()
_, err := viewer.Do(`
mutation UpdateDatum($input: UpdateDatumInput!) {
@@ -936,8 +950,9 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("delete", func(t *testing.T) {
t.Run("owner can delete", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Delete Owner").Create()
datumID := factory.NewDatum(owner, peopleID).WithName("RBAC Delete Test").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
datumID := factory.NewDatum(owner, profileID.String()).WithName("RBAC Delete Test").Create()
_, err := owner.Do(`
mutation DeleteDatum($input: DeleteDatumInput!) {
@@ -954,8 +969,9 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("admin can delete", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
admin := testutil.NewClientInOrg(t, testutil.RoleAdmin, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Admin Delete Owner").Create()
datumID := factory.NewDatum(owner, peopleID).WithName("RBAC Delete Test").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
datumID := factory.NewDatum(owner, profileID.String()).WithName("RBAC Delete Test").Create()
_, err := admin.Do(`
mutation DeleteDatum($input: DeleteDatumInput!) {
@@ -972,8 +988,9 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("viewer cannot delete", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Viewer Delete Owner").Create()
datumID := factory.NewDatum(owner, peopleID).WithName("RBAC Delete Test").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
datumID := factory.NewDatum(owner, profileID.String()).WithName("RBAC Delete Test").Create()
_, err := viewer.Do(`
mutation DeleteDatum($input: DeleteDatumInput!) {
@@ -991,8 +1008,9 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("read", func(t *testing.T) {
t.Run("owner can read", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Read Owner").Create()
datumID := factory.NewDatum(owner, peopleID).WithName("RBAC Read Test").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
datumID := factory.NewDatum(owner, profileID.String()).WithName("RBAC Read Test").Create()
var result struct {
Node *struct {
@@ -1015,8 +1033,9 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("admin can read", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
admin := testutil.NewClientInOrg(t, testutil.RoleAdmin, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Admin Read Owner").Create()
datumID := factory.NewDatum(owner, peopleID).WithName("RBAC Read Test").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
datumID := factory.NewDatum(owner, profileID.String()).WithName("RBAC Read Test").Create()
var result struct {
Node *struct {
@@ -1039,8 +1058,9 @@ func TestDatum_RBAC(t *testing.T) {
t.Run("viewer can read", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Viewer Read Owner").Create()
datumID := factory.NewDatum(owner, peopleID).WithName("RBAC Read Test").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
datumID := factory.NewDatum(owner, profileID.String()).WithName("RBAC Read Test").Create()
var result struct {
Node *struct {
@@ -1065,7 +1085,8 @@ func TestDatum_RBAC(t *testing.T) {
func TestDatum_MaxLength_Validation(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Datum Max Length Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
longName := strings.Repeat("a", 1001)
@@ -1083,7 +1104,7 @@ func TestDatum_MaxLength_Validation(t *testing.T) {
_, err := owner.Do(query, map[string]any{
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"ownerId": peopleID,
"ownerId": profileID.String(),
"name": longName,
"dataClassification": "INTERNAL",
},
@@ -1093,7 +1114,7 @@ func TestDatum_MaxLength_Validation(t *testing.T) {
})
t.Run("update", func(t *testing.T) {
datumID := factory.NewDatum(owner, peopleID).WithName("Max Length Test").Create()
datumID := factory.NewDatum(owner, profileID.String()).WithName("Max Length Test").Create()
query := `
mutation UpdateDatum($input: UpdateDatumInput!) {
@@ -1117,10 +1138,11 @@ func TestDatum_MaxLength_Validation(t *testing.T) {
func TestDatum_Pagination(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Datum Pagination Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
for i := 0; i < 5; i++ {
factory.NewDatum(owner, peopleID).
factory.NewDatum(owner, profileID.String()).
WithName(fmt.Sprintf("Pagination Datum %d", i)).
Create()
}
@@ -1266,8 +1288,9 @@ func TestDatum_TenantIsolation(t *testing.T) {
org1Owner := testutil.NewClient(t, testutil.RoleOwner)
org2Owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(org1Owner).WithFullName("Org1 Datum Owner").Create()
datumID := factory.NewDatum(org1Owner, peopleID).WithName("Org1 Datum").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, org1Owner).GetProfileID()
datumID := factory.NewDatum(org1Owner, profileID.String()).WithName("Org1 Datum").Create()
t.Run("cannot read datum from another organization", func(t *testing.T) {
query := `
@@ -1373,10 +1396,11 @@ func TestDatum_TenantIsolation(t *testing.T) {
func TestDatum_Ordering(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Datum Ordering Owner").Create()
// TODO: right now we need to invite and accept invite to get new profile.
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
factory.NewDatum(owner, peopleID).WithName("AAA Order Test").Create()
factory.NewDatum(owner, peopleID).WithName("ZZZ Order Test").Create()
factory.NewDatum(owner, profileID.String()).WithName("AAA Order Test").Create()
factory.NewDatum(owner, profileID.String()).WithName("ZZZ Order Test").Create()
t.Run("order by created_at descending", func(t *testing.T) {
query := `

View File

@@ -29,7 +29,7 @@ import (
func TestDocument_Create(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
ownerPeopleID := factory.NewPeople(owner).WithFullName("Document Owner").Create()
ownerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
tests := []struct {
name string
@@ -113,7 +113,7 @@ func TestDocument_Create(t *testing.T) {
input := map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"ownerId": ownerPeopleID,
"ownerId": ownerProfileID.String(),
}
for k, v := range tt.input {
input[k] = v
@@ -151,7 +151,7 @@ func TestDocument_Create(t *testing.T) {
func TestDocument_Create_Validation(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
ownerPeopleID := factory.NewPeople(owner).WithFullName("Document Validation Owner").Create()
ownerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
tests := []struct {
name string
@@ -293,7 +293,7 @@ func TestDocument_Create_Validation(t *testing.T) {
input["organizationId"] = owner.GetOrganizationID().String()
}
if !tt.skipOwner {
input["ownerId"] = ownerPeopleID
input["ownerId"] = ownerProfileID.String()
}
for k, v := range tt.input {
input[k] = v
@@ -309,7 +309,7 @@ func TestDocument_Create_Validation(t *testing.T) {
func TestDocument_Update(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
ownerPeopleID := factory.NewPeople(owner).WithFullName("Document Update Owner").Create()
ownerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
tests := []struct {
name string
@@ -321,7 +321,7 @@ func TestDocument_Update(t *testing.T) {
{
name: "update title",
setup: func() string {
return factory.NewDocument(owner, ownerPeopleID).
return factory.NewDocument(owner, ownerProfileID.String()).
WithTitle("Document to Update").
Create()
},
@@ -337,7 +337,7 @@ func TestDocument_Update(t *testing.T) {
{
name: "update document type",
setup: func() string {
return factory.NewDocument(owner, ownerPeopleID).
return factory.NewDocument(owner, ownerProfileID.String()).
WithTitle("Type Test").
WithDocumentType("POLICY").
Create()
@@ -393,8 +393,8 @@ func TestDocument_Update(t *testing.T) {
func TestDocument_Update_Validation(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
ownerPeopleID := factory.NewPeople(owner).WithFullName("Document Update Validation Owner").Create()
baseDocumentID := factory.NewDocument(owner, ownerPeopleID).WithTitle("Validation Test Document").Create()
ownerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
baseDocumentID := factory.NewDocument(owner, ownerProfileID.String()).WithTitle("Validation Test Document").Create()
tests := []struct {
name string
@@ -484,10 +484,10 @@ func TestDocument_Update_Validation(t *testing.T) {
func TestDocument_Delete(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
ownerPeopleID := factory.NewPeople(owner).WithFullName("Document Delete Owner").Create()
ownerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
t.Run("delete existing document", func(t *testing.T) {
documentID := factory.NewDocument(owner, ownerPeopleID).WithTitle("Document to Delete").Create()
documentID := factory.NewDocument(owner, ownerProfileID.String()).WithTitle("Document to Delete").Create()
query := `
mutation DeleteDocument($input: DeleteDocumentInput!) {
@@ -549,11 +549,11 @@ func TestDocument_Delete_Validation(t *testing.T) {
func TestDocument_List(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
ownerPeopleID := factory.NewPeople(owner).WithFullName("Document List Owner").Create()
ownerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
documentTitles := []string{"Document A", "Document B", "Document C"}
for _, title := range documentTitles {
factory.NewDocument(owner, ownerPeopleID).WithTitle(title).Create()
factory.NewDocument(owner, ownerProfileID.String()).WithTitle(title).Create()
}
query := `
@@ -621,7 +621,7 @@ func TestDocument_Query(t *testing.T) {
func TestDocument_Timestamps(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
ownerPeopleID := factory.NewPeople(owner).WithFullName("Document Timestamps Owner").Create()
ownerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
t.Run("createdAt and updatedAt are set on create", func(t *testing.T) {
beforeCreate := time.Now().Add(-time.Second)
@@ -655,7 +655,7 @@ func TestDocument_Timestamps(t *testing.T) {
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"ownerId": ownerPeopleID,
"ownerId": ownerProfileID.String(),
"title": "Timestamp Test Document",
"content": "Test content",
"documentType": "POLICY",
@@ -669,7 +669,7 @@ func TestDocument_Timestamps(t *testing.T) {
})
t.Run("updatedAt changes on update", func(t *testing.T) {
documentID := factory.NewDocument(owner, ownerPeopleID).WithTitle("Timestamp Update Test").Create()
documentID := factory.NewDocument(owner, ownerProfileID.String()).WithTitle("Timestamp Update Test").Create()
getQuery := `
query($id: ID!) {
@@ -733,8 +733,8 @@ func TestDocument_Timestamps(t *testing.T) {
func TestDocument_SubResolvers(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
ownerPeopleID := factory.NewPeople(owner).WithFullName("Document SubResolver Owner").Create()
documentID := factory.NewDocument(owner, ownerPeopleID).WithTitle("SubResolver Test Document").Create()
ownerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
documentID := factory.NewDocument(owner, ownerProfileID.String()).WithTitle("SubResolver Test Document").Create()
t.Run("owner sub-resolver", func(t *testing.T) {
query := `
@@ -763,7 +763,7 @@ func TestDocument_SubResolvers(t *testing.T) {
err := owner.Execute(query, map[string]any{"id": documentID}, &result)
require.NoError(t, err)
assert.Equal(t, ownerPeopleID, result.Node.Owner.ID)
assert.Equal(t, ownerProfileID.String(), result.Node.Owner.ID)
})
t.Run("organization sub-resolver", func(t *testing.T) {
@@ -804,7 +804,7 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("create", func(t *testing.T) {
t.Run("owner can create", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
_, err := owner.Do(`
mutation CreateDocument($input: CreateDocumentInput!) {
@@ -815,7 +815,7 @@ func TestDocument_RBAC(t *testing.T) {
`, map[string]any{
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"ownerId": peopleID,
"ownerId": profileID.String(),
"title": "RBAC Test Document",
"content": "Test content",
"documentType": "POLICY",
@@ -828,7 +828,7 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("admin can create", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
admin := testutil.NewClientInOrg(t, testutil.RoleAdmin, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Admin Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
_, err := admin.Do(`
mutation CreateDocument($input: CreateDocumentInput!) {
@@ -839,7 +839,7 @@ func TestDocument_RBAC(t *testing.T) {
`, map[string]any{
"input": map[string]any{
"organizationId": admin.GetOrganizationID().String(),
"ownerId": peopleID,
"ownerId": profileID.String(),
"title": "RBAC Test Document",
"content": "Test content",
"documentType": "POLICY",
@@ -852,7 +852,7 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("viewer cannot create", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Viewer Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
_, err := viewer.Do(`
mutation CreateDocument($input: CreateDocumentInput!) {
@@ -863,7 +863,7 @@ func TestDocument_RBAC(t *testing.T) {
`, map[string]any{
"input": map[string]any{
"organizationId": viewer.GetOrganizationID().String(),
"ownerId": peopleID,
"ownerId": profileID.String(),
"title": "RBAC Test Document",
"content": "Test content",
"documentType": "POLICY",
@@ -877,8 +877,8 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("update", func(t *testing.T) {
t.Run("owner can update", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Update Owner").Create()
documentID := factory.NewDocument(owner, peopleID).WithTitle("RBAC Update Test").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
documentID := factory.NewDocument(owner, profileID.String()).WithTitle("RBAC Update Test").Create()
_, err := owner.Do(`
mutation UpdateDocument($input: UpdateDocumentInput!) {
@@ -898,8 +898,8 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("admin can update", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
admin := testutil.NewClientInOrg(t, testutil.RoleAdmin, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Admin Update Owner").Create()
documentID := factory.NewDocument(owner, peopleID).WithTitle("RBAC Update Test").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
documentID := factory.NewDocument(owner, profileID.String()).WithTitle("RBAC Update Test").Create()
_, err := admin.Do(`
mutation UpdateDocument($input: UpdateDocumentInput!) {
@@ -919,8 +919,8 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("viewer cannot update", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Viewer Update Owner").Create()
documentID := factory.NewDocument(owner, peopleID).WithTitle("RBAC Update Test").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
documentID := factory.NewDocument(owner, profileID.String()).WithTitle("RBAC Update Test").Create()
_, err := viewer.Do(`
mutation UpdateDocument($input: UpdateDocumentInput!) {
@@ -941,8 +941,8 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("delete", func(t *testing.T) {
t.Run("owner can delete", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Delete Owner").Create()
documentID := factory.NewDocument(owner, peopleID).WithTitle("RBAC Delete Test").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
documentID := factory.NewDocument(owner, profileID.String()).WithTitle("RBAC Delete Test").Create()
_, err := owner.Do(`
mutation DeleteDocument($input: DeleteDocumentInput!) {
@@ -959,8 +959,8 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("admin can delete", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
admin := testutil.NewClientInOrg(t, testutil.RoleAdmin, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Admin Delete Owner").Create()
documentID := factory.NewDocument(owner, peopleID).WithTitle("RBAC Delete Test").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
documentID := factory.NewDocument(owner, profileID.String()).WithTitle("RBAC Delete Test").Create()
_, err := admin.Do(`
mutation DeleteDocument($input: DeleteDocumentInput!) {
@@ -977,8 +977,8 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("viewer cannot delete", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Viewer Delete Owner").Create()
documentID := factory.NewDocument(owner, peopleID).WithTitle("RBAC Delete Test").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
documentID := factory.NewDocument(owner, profileID.String()).WithTitle("RBAC Delete Test").Create()
_, err := viewer.Do(`
mutation DeleteDocument($input: DeleteDocumentInput!) {
@@ -996,8 +996,8 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("read", func(t *testing.T) {
t.Run("owner can read", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Read Owner").Create()
documentID := factory.NewDocument(owner, peopleID).WithTitle("RBAC Read Test").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
documentID := factory.NewDocument(owner, profileID.String()).WithTitle("RBAC Read Test").Create()
var result struct {
Node *struct {
@@ -1020,8 +1020,8 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("admin can read", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
admin := testutil.NewClientInOrg(t, testutil.RoleAdmin, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Admin Read Owner").Create()
documentID := factory.NewDocument(owner, peopleID).WithTitle("RBAC Read Test").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
documentID := factory.NewDocument(owner, profileID.String()).WithTitle("RBAC Read Test").Create()
var result struct {
Node *struct {
@@ -1044,8 +1044,8 @@ func TestDocument_RBAC(t *testing.T) {
t.Run("viewer can read", func(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
peopleID := factory.NewPeople(owner).WithFullName("RBAC Viewer Read Owner").Create()
documentID := factory.NewDocument(owner, peopleID).WithTitle("RBAC Read Test").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
documentID := factory.NewDocument(owner, profileID.String()).WithTitle("RBAC Read Test").Create()
var result struct {
Node *struct {
@@ -1070,7 +1070,7 @@ func TestDocument_RBAC(t *testing.T) {
func TestDocument_MaxLength_Validation(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
ownerPeopleID := factory.NewPeople(owner).WithFullName("Document Max Length Owner").Create()
ownerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
longTitle := strings.Repeat("a", 1001)
@@ -1088,7 +1088,7 @@ func TestDocument_MaxLength_Validation(t *testing.T) {
_, err := owner.Do(query, map[string]any{
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"ownerId": ownerPeopleID,
"ownerId": ownerProfileID.String(),
"title": longTitle,
"content": "Test content",
"documentType": "POLICY",
@@ -1100,7 +1100,7 @@ func TestDocument_MaxLength_Validation(t *testing.T) {
})
t.Run("update", func(t *testing.T) {
documentID := factory.NewDocument(owner, ownerPeopleID).WithTitle("Max Length Test").Create()
documentID := factory.NewDocument(owner, ownerProfileID.String()).WithTitle("Max Length Test").Create()
query := `
mutation UpdateDocument($input: UpdateDocumentInput!) {
@@ -1124,10 +1124,10 @@ func TestDocument_MaxLength_Validation(t *testing.T) {
func TestDocument_Pagination(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
ownerPeopleID := factory.NewPeople(owner).WithFullName("Document Pagination Owner").Create()
ownerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
for i := 0; i < 5; i++ {
factory.NewDocument(owner, ownerPeopleID).
factory.NewDocument(owner, ownerProfileID.String()).
WithTitle(fmt.Sprintf("Pagination Document %d", i)).
Create()
}
@@ -1273,8 +1273,8 @@ func TestDocument_TenantIsolation(t *testing.T) {
org1Owner := testutil.NewClient(t, testutil.RoleOwner)
org2Owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(org1Owner).WithFullName("Org1 Document Owner").Create()
documentID := factory.NewDocument(org1Owner, peopleID).WithTitle("Org1 Document").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, org1Owner).GetProfileID()
documentID := factory.NewDocument(org1Owner, profileID.String()).WithTitle("Org1 Document").Create()
t.Run("cannot read document from another organization", func(t *testing.T) {
query := `
@@ -1380,10 +1380,10 @@ func TestDocument_TenantIsolation(t *testing.T) {
func TestDocument_Ordering(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
ownerPeopleID := factory.NewPeople(owner).WithFullName("Document Ordering Owner").Create()
ownerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
factory.NewDocument(owner, ownerPeopleID).WithTitle("AAA Order Test").Create()
factory.NewDocument(owner, ownerPeopleID).WithTitle("ZZZ Order Test").Create()
factory.NewDocument(owner, ownerProfileID.String()).WithTitle("AAA Order Test").Create()
factory.NewDocument(owner, ownerProfileID.String()).WithTitle("ZZZ Order Test").Create()
t.Run("order by created_at descending", func(t *testing.T) {
query := `

View File

@@ -19,14 +19,13 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.probo.inc/probo/e2e/internal/factory"
"go.probo.inc/probo/e2e/internal/testutil"
)
// createTestDocument creates a document and returns its ID and the document version ID
func createTestDocument(t *testing.T, owner *testutil.Client) (docID string, docVersionID string) {
t.Helper()
peopleID := factory.NewPeople(owner).WithFullName("Doc Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
query := `
mutation CreateDocument($input: CreateDocumentInput!) {
@@ -69,7 +68,7 @@ func createTestDocument(t *testing.T, owner *testutil.Client) (docID string, doc
"organizationId": owner.GetOrganizationID().String(),
"title": "Test Document",
"content": "Initial content",
"ownerId": peopleID,
"ownerId": profileID.String(),
"documentType": "POLICY",
"classification": "INTERNAL",
},
@@ -264,7 +263,7 @@ func TestDocumentVersion_RequestSignature(t *testing.T) {
publishedVersionID := publishResult.PublishDocumentVersion.DocumentVersion.ID
// Create a person to sign
signerID := factory.NewPeople(owner).WithFullName("Document Signer").Create()
signerProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
query := `
mutation RequestSignature($input: RequestSignatureInput!) {
@@ -301,14 +300,14 @@ func TestDocumentVersion_RequestSignature(t *testing.T) {
err = owner.Execute(query, map[string]any{
"input": map[string]any{
"documentVersionId": publishedVersionID,
"signatoryId": signerID,
"signatoryId": signerProfileID.String(),
},
}, &result)
require.NoError(t, err)
assert.NotEmpty(t, result.RequestSignature.DocumentVersionSignatureEdge.Node.ID)
assert.Equal(t, "REQUESTED", result.RequestSignature.DocumentVersionSignatureEdge.Node.State)
assert.Equal(t, signerID, result.RequestSignature.DocumentVersionSignatureEdge.Node.SignedBy.ID)
assert.Equal(t, signerProfileID.String(), result.RequestSignature.DocumentVersionSignatureEdge.Node.SignedBy.ID)
}
func TestDocumentVersion_BulkPublish(t *testing.T) {
@@ -383,8 +382,8 @@ func TestDocumentVersion_BulkRequestSignatures(t *testing.T) {
require.NoError(t, err)
// Create multiple signers
signer1ID := factory.NewPeople(owner).WithFullName("Bulk Signer 1").Create()
signer2ID := factory.NewPeople(owner).WithFullName("Bulk Signer 2").Create()
signer1ProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
signer2ProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
query := `
mutation BulkRequestSignatures($input: BulkRequestSignaturesInput!) {
@@ -413,7 +412,7 @@ func TestDocumentVersion_BulkRequestSignatures(t *testing.T) {
err = owner.Execute(query, map[string]any{
"input": map[string]any{
"documentIds": []string{docID},
"signatoryIds": []string{signer1ID, signer2ID},
"signatoryIds": []string{signer1ProfileID.String(), signer2ProfileID.String()},
},
}, &result)
require.NoError(t, err)

View File

@@ -19,7 +19,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.probo.inc/probo/e2e/internal/factory"
"go.probo.inc/probo/e2e/internal/testutil"
)
@@ -370,7 +369,7 @@ func TestControlDocumentMapping_CreateDelete(t *testing.T) {
controlID := createControlResult.CreateControl.ControlEdge.Node.ID
// Create a document
peopleID := factory.NewPeople(owner).WithFullName("Doc Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
var createDocumentResult struct {
CreateDocument struct {
DocumentEdge struct {
@@ -395,7 +394,7 @@ func TestControlDocumentMapping_CreateDelete(t *testing.T) {
"organizationId": owner.GetOrganizationID().String(),
"title": "Document for Control Mapping",
"content": "Document content",
"ownerId": peopleID,
"ownerId": profileID.String(),
"documentType": "POLICY",
"classification": "INTERNAL",
},
@@ -760,7 +759,7 @@ func TestRiskDocumentMapping_CreateDelete(t *testing.T) {
riskID := createRiskResult.CreateRisk.RiskEdge.Node.ID
// Create a document
peopleID := factory.NewPeople(owner).WithFullName("Doc Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
var createDocumentResult struct {
CreateDocument struct {
DocumentEdge struct {
@@ -785,7 +784,7 @@ func TestRiskDocumentMapping_CreateDelete(t *testing.T) {
"organizationId": owner.GetOrganizationID().String(),
"title": "Document for Risk Mapping",
"content": "Document content",
"ownerId": peopleID,
"ownerId": profileID.String(),
"documentType": "POLICY",
"classification": "INTERNAL",
},
@@ -874,7 +873,7 @@ func TestRiskObligationMapping_CreateDelete(t *testing.T) {
riskID := createRiskResult.CreateRisk.RiskEdge.Node.ID
// Create an obligation
peopleID := factory.NewPeople(owner).WithFullName("Obligation Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
var createObligationResult struct {
CreateObligation struct {
ObligationEdge struct {
@@ -899,7 +898,7 @@ func TestRiskObligationMapping_CreateDelete(t *testing.T) {
"organizationId": owner.GetOrganizationID().String(),
"area": "Risk Management",
"requirement": "Obligation for Risk Mapping",
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "NON_COMPLIANT",
"type": "LEGAL",
},

View File

@@ -690,8 +690,8 @@ func TestMeeting_SubResolvers_WithData(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
attendee1 := factory.NewPeople(owner).WithFullName("Attendee One").Create()
attendee2 := factory.NewPeople(owner).WithFullName("Attendee Two").Create()
attendee1ProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
attendee2ProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
var result struct {
CreateMeeting struct {
@@ -730,7 +730,7 @@ func TestMeeting_SubResolvers_WithData(t *testing.T) {
"organizationId": owner.GetOrganizationID().String(),
"name": "Meeting With Attendees",
"date": time.Now().Format(time.RFC3339Nano),
"attendeeIds": []string{attendee1, attendee2},
"attendeeIds": []string{attendee1ProfileID.String(), attendee2ProfileID.String()},
},
}, &result)
require.NoError(t, err)

View File

@@ -21,7 +21,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.probo.inc/probo/e2e/internal/factory"
"go.probo.inc/probo/e2e/internal/testutil"
)
@@ -100,7 +99,7 @@ func createAuditForNC(t *testing.T, owner *testutil.Client, name string) string
func TestNonconformity_Create(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("NC Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
auditID := createAuditForNC(t, owner, "NC Test Audit")
query := `
@@ -143,7 +142,7 @@ func TestNonconformity_Create(t *testing.T) {
"auditId": auditID,
"rootCause": "Insufficient access controls",
"correctiveAction": "Implement MFA",
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "OPEN",
},
}, &result)
@@ -159,7 +158,7 @@ func TestNonconformity_Create(t *testing.T) {
func TestNonconformity_Update(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("NC Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
auditID := createAuditForNC(t, owner, "NC Update Test Audit")
// Create a nonconformity to update
@@ -191,7 +190,7 @@ func TestNonconformity_Update(t *testing.T) {
"referenceId": fmt.Sprintf("NC-UPDATE-%d", time.Now().UnixNano()),
"auditId": auditID,
"rootCause": "Original root cause",
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "OPEN",
},
}, &createResult)
@@ -242,7 +241,7 @@ func TestNonconformity_Update(t *testing.T) {
func TestNonconformity_Delete(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("NC Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
auditID := createAuditForNC(t, owner, "NC Delete Test Audit")
// Create a nonconformity to delete
@@ -274,7 +273,7 @@ func TestNonconformity_Delete(t *testing.T) {
"referenceId": fmt.Sprintf("NC-DELETE-%d", time.Now().UnixNano()),
"auditId": auditID,
"rootCause": "Test root cause",
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "OPEN",
},
}, &createResult)
@@ -307,7 +306,7 @@ func TestNonconformity_Delete(t *testing.T) {
func TestNonconformity_List(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("NC Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
auditID := createAuditForNC(t, owner, "NC List Test Audit")
// Create multiple nonconformities
@@ -340,7 +339,7 @@ func TestNonconformity_List(t *testing.T) {
"referenceId": fmt.Sprintf("NC-LIST-%d-%d", i, time.Now().UnixNano()),
"auditId": auditID,
"rootCause": fmt.Sprintf("Root cause %d", i),
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "OPEN",
},
}, &createResult)
@@ -391,7 +390,7 @@ func TestNonconformity_List(t *testing.T) {
func TestNonconformity_StatusValues(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("NC Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
auditID := createAuditForNC(t, owner, "NC Status Test Audit")
statuses := []string{"OPEN", "IN_PROGRESS", "CLOSED"}
@@ -428,7 +427,7 @@ func TestNonconformity_StatusValues(t *testing.T) {
"referenceId": fmt.Sprintf("NC-STATUS-%s-%d", status, time.Now().UnixNano()),
"auditId": auditID,
"rootCause": "Test root cause",
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": status,
},
}, &result)

View File

@@ -19,14 +19,13 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.probo.inc/probo/e2e/internal/factory"
"go.probo.inc/probo/e2e/internal/testutil"
)
func TestObligation_Create(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Obligation Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
query := `
mutation CreateObligation($input: CreateObligationInput!) {
@@ -67,7 +66,7 @@ func TestObligation_Create(t *testing.T) {
"source": "GDPR Article 5",
"requirement": "Data must be processed lawfully",
"regulator": "ICO",
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "NON_COMPLIANT",
"type": "LEGAL",
},
@@ -85,7 +84,7 @@ func TestObligation_Create(t *testing.T) {
func TestObligation_Update(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Obligation Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
// Create an obligation to update
createQuery := `
@@ -114,7 +113,7 @@ func TestObligation_Update(t *testing.T) {
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"area": "Original Area",
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "NON_COMPLIANT",
"type": "LEGAL",
},
@@ -162,7 +161,7 @@ func TestObligation_Update(t *testing.T) {
func TestObligation_Delete(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Obligation Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
// Create an obligation to delete
createQuery := `
@@ -191,7 +190,7 @@ func TestObligation_Delete(t *testing.T) {
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"area": "Obligation to Delete",
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "NON_COMPLIANT",
"type": "LEGAL",
},
@@ -226,7 +225,7 @@ func TestObligation_Delete(t *testing.T) {
func TestObligation_List(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Obligation Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
// Create multiple obligations
areas := []string{"Area A", "Area B", "Area C"}
@@ -257,7 +256,7 @@ func TestObligation_List(t *testing.T) {
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"area": area,
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": "NON_COMPLIANT",
"type": "LEGAL",
},
@@ -310,7 +309,7 @@ func TestObligation_List(t *testing.T) {
func TestObligation_StatusValues(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).WithFullName("Obligation Owner").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
statuses := []string{"NON_COMPLIANT", "PARTIALLY_COMPLIANT", "COMPLIANT"}
@@ -344,7 +343,7 @@ func TestObligation_StatusValues(t *testing.T) {
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"area": "Status Test " + status,
"ownerId": peopleID,
"ownerId": profileID.String(),
"status": status,
"type": "LEGAL",
},

View File

@@ -1,677 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.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 console_test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.probo.inc/probo/e2e/internal/factory"
"go.probo.inc/probo/e2e/internal/testutil"
)
func TestPeople_Create(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
t.Run("with full details", func(t *testing.T) {
query := `
mutation CreatePeople($input: CreatePeopleInput!) {
createPeople(input: $input) {
peopleEdge {
node {
id
fullName
kind
position
}
}
}
}
`
var result struct {
CreatePeople struct {
PeopleEdge struct {
Node struct {
ID string `json:"id"`
FullName string `json:"fullName"`
Kind string `json:"kind"`
Position *string `json:"position"`
} `json:"node"`
} `json:"peopleEdge"`
} `json:"createPeople"`
}
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"fullName": "John Doe",
"primaryEmailAddress": "john.doe@example.com",
"additionalEmailAddresses": []string{},
"kind": "EMPLOYEE",
"position": "Software Engineer",
},
}, &result)
require.NoError(t, err)
people := result.CreatePeople.PeopleEdge.Node
assert.NotEmpty(t, people.ID)
assert.Equal(t, "John Doe", people.FullName)
assert.Equal(t, "EMPLOYEE", people.Kind)
assert.Equal(t, "Software Engineer", *people.Position)
})
t.Run("with different kinds", func(t *testing.T) {
kinds := []struct {
name string
kind string
}{
{"Employee", "EMPLOYEE"},
{"Contractor", "CONTRACTOR"},
{"Service Account", "SERVICE_ACCOUNT"},
}
for _, tt := range kinds {
t.Run(tt.name, func(t *testing.T) {
peopleID := factory.CreatePeople(owner, factory.Attrs{
"fullName": "Person " + tt.kind,
"kind": tt.kind,
})
query := `
query GetPeople($id: ID!) {
node(id: $id) {
... on People {
id
kind
}
}
}
`
var result struct {
Node struct {
ID string `json:"id"`
Kind string `json:"kind"`
} `json:"node"`
}
err := owner.Execute(query, map[string]any{"id": peopleID}, &result)
require.NoError(t, err)
assert.Equal(t, tt.kind, result.Node.Kind)
})
}
})
t.Run("with additional emails", func(t *testing.T) {
t.Skip("additionalEmailAddresses feature not fully implemented")
})
}
func TestPeople_Update(t *testing.T) {
t.Skip("updatePeople has server bug with additional_email_addresses null constraint")
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.CreatePeople(owner, factory.Attrs{
"fullName": "Person to Update",
})
query := `
mutation UpdatePeople($input: UpdatePeopleInput!) {
updatePeople(input: $input) {
people {
id
fullName
}
}
}
`
var result struct {
UpdatePeople struct {
People struct {
ID string `json:"id"`
FullName string `json:"fullName"`
} `json:"people"`
} `json:"updatePeople"`
}
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"id": peopleID,
"fullName": "Updated Name",
},
}, &result)
require.NoError(t, err)
assert.Equal(t, peopleID, result.UpdatePeople.People.ID)
assert.Equal(t, "Updated Name", result.UpdatePeople.People.FullName)
}
func TestPeople_Delete(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.CreatePeople(owner, factory.Attrs{
"fullName": "Person to Delete",
})
query := `
mutation DeletePeople($input: DeletePeopleInput!) {
deletePeople(input: $input) {
deletedPeopleId
}
}
`
var result struct {
DeletePeople struct {
DeletedPeopleID string `json:"deletedPeopleId"`
} `json:"deletePeople"`
}
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"peopleId": peopleID,
},
}, &result)
require.NoError(t, err)
assert.Equal(t, peopleID, result.DeletePeople.DeletedPeopleID)
}
func TestPeople_List(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
// Create multiple people
peopleNames := []string{"Person A", "Person B", "Person C"}
for _, name := range peopleNames {
factory.CreatePeople(owner, factory.Attrs{"fullName": name})
}
query := `
query ListPeoples($orgId: ID!) {
node(id: $orgId) {
... on Organization {
peoples(first: 10) {
edges {
node {
id
fullName
}
}
totalCount
}
}
}
}
`
var result struct {
Node struct {
Peoples struct {
Edges []struct {
Node struct {
ID string `json:"id"`
FullName string `json:"fullName"`
} `json:"node"`
} `json:"edges"`
TotalCount int `json:"totalCount"`
} `json:"peoples"`
} `json:"node"`
}
err := owner.Execute(query, map[string]any{
"orgId": owner.GetOrganizationID().String(),
}, &result)
require.NoError(t, err)
assert.GreaterOrEqual(t, result.Node.Peoples.TotalCount, 3)
}
func TestPeople_RequiredFields(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
tests := []struct {
name string
input map[string]any
skipOrganization bool
wantErrorContains string
}{
{
name: "missing organizationId",
input: map[string]any{
"fullName": "Test Person",
"primaryEmailAddress": "test@example.com",
"additionalEmailAddresses": []string{},
"kind": "EMPLOYEE",
},
skipOrganization: true,
wantErrorContains: "organizationId",
},
{
name: "missing fullName",
input: map[string]any{
"primaryEmailAddress": "test@example.com",
"additionalEmailAddresses": []string{},
"kind": "EMPLOYEE",
},
wantErrorContains: "fullName",
},
{
name: "missing primaryEmailAddress",
input: map[string]any{
"fullName": "Test Person",
"additionalEmailAddresses": []string{},
"kind": "EMPLOYEE",
},
wantErrorContains: "primaryEmailAddress",
},
{
name: "missing kind",
input: map[string]any{
"fullName": "Test Person",
"primaryEmailAddress": "test@example.com",
"additionalEmailAddresses": []string{},
},
wantErrorContains: "kind",
},
{
name: "empty fullName",
input: map[string]any{
"fullName": "",
"primaryEmailAddress": "test@example.com",
"additionalEmailAddresses": []string{},
"kind": "EMPLOYEE",
},
wantErrorContains: "full_name",
},
{
name: "invalid kind enum",
input: map[string]any{
"fullName": "Test Person",
"primaryEmailAddress": "test@example.com",
"additionalEmailAddresses": []string{},
"kind": "INVALID_KIND",
},
wantErrorContains: "kind",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
query := `
mutation CreatePeople($input: CreatePeopleInput!) {
createPeople(input: $input) {
peopleEdge {
node {
id
}
}
}
}
`
input := make(map[string]any)
if !tt.skipOrganization {
input["organizationId"] = owner.GetOrganizationID().String()
}
for k, v := range tt.input {
input[k] = v
}
_, err := owner.Do(query, map[string]any{"input": input})
require.Error(t, err)
assert.Contains(t, err.Error(), tt.wantErrorContains)
})
}
}
func TestPeople_KindEnum(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
kinds := []string{
"EMPLOYEE",
"CONTRACTOR",
}
for _, kind := range kinds {
t.Run("create with kind "+kind, func(t *testing.T) {
peopleID := factory.NewPeople(owner).
WithFullName("Kind Test " + kind).
WithKind(kind).
Create()
query := `
query($id: ID!) {
node(id: $id) {
... on People {
id
kind
}
}
}
`
var result struct {
Node struct {
ID string `json:"id"`
Kind string `json:"kind"`
} `json:"node"`
}
err := owner.Execute(query, map[string]any{"id": peopleID}, &result)
require.NoError(t, err)
assert.Equal(t, kind, result.Node.Kind)
})
}
}
func TestPeople_SubResolvers(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).
WithFullName("SubResolver Test Person").
Create()
t.Run("people node query", func(t *testing.T) {
query := `
query GetPeople($id: ID!) {
node(id: $id) {
... on People {
id
fullName
primaryEmailAddress
kind
}
}
}
`
var result struct {
Node struct {
ID string `json:"id"`
FullName string `json:"fullName"`
PrimaryEmailAddress string `json:"primaryEmailAddress"`
Kind string `json:"kind"`
} `json:"node"`
}
err := owner.Execute(query, map[string]any{"id": peopleID}, &result)
require.NoError(t, err)
assert.Equal(t, peopleID, result.Node.ID)
assert.Equal(t, "SubResolver Test Person", result.Node.FullName)
})
}
func TestPeople_InvalidID(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
t.Run("update with invalid ID", func(t *testing.T) {
query := `
mutation UpdatePeople($input: UpdatePeopleInput!) {
updatePeople(input: $input) {
people {
id
}
}
}
`
_, err := owner.Do(query, map[string]any{
"input": map[string]any{
"id": "invalid-id-format",
"fullName": "Test",
},
})
require.Error(t, err)
assert.Contains(t, err.Error(), "base64")
})
t.Run("delete with invalid ID", func(t *testing.T) {
query := `
mutation DeletePeople($input: DeletePeopleInput!) {
deletePeople(input: $input) {
deletedPeopleId
}
}
`
_, err := owner.Do(query, map[string]any{
"input": map[string]any{
"peopleId": "invalid-id-format",
},
})
require.Error(t, err)
assert.Contains(t, err.Error(), "base64")
})
t.Run("query with non-existent ID", func(t *testing.T) {
query := `
query GetPeople($id: ID!) {
node(id: $id) {
... on People {
id
fullName
}
}
}
`
err := owner.ExecuteShouldFail(query, map[string]any{
"id": "V0wtM0tMNmJBQ1lBQUFBQUFackhLSTJfbXJJRUFZVXo",
})
require.Error(t, err, "Non-existent ID should return error")
})
}
func TestPeople_OmittablePosition(t *testing.T) {
t.Skip("Skipped: server returns internal error when updating position field")
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(owner).
WithFullName("Position Test Person").
Create()
t.Run("set position", func(t *testing.T) {
query := `
mutation UpdatePeople($input: UpdatePeopleInput!) {
updatePeople(input: $input) {
people {
id
position
}
}
}
`
var result struct {
UpdatePeople struct {
People struct {
ID string `json:"id"`
Position *string `json:"position"`
} `json:"people"`
} `json:"updatePeople"`
}
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"id": peopleID,
"position": "Software Engineer",
},
}, &result)
require.NoError(t, err)
require.NotNil(t, result.UpdatePeople.People.Position)
assert.Equal(t, "Software Engineer", *result.UpdatePeople.People.Position)
})
t.Run("clear position with null", func(t *testing.T) {
query := `
mutation UpdatePeople($input: UpdatePeopleInput!) {
updatePeople(input: $input) {
people {
id
position
}
}
}
`
var result struct {
UpdatePeople struct {
People struct {
ID string `json:"id"`
Position *string `json:"position"`
} `json:"people"`
} `json:"updatePeople"`
}
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"id": peopleID,
"position": nil,
},
}, &result)
require.NoError(t, err)
assert.Nil(t, result.UpdatePeople.People.Position)
})
t.Run("update without position preserves value", func(t *testing.T) {
// First set a position
setQuery := `
mutation UpdatePeople($input: UpdatePeopleInput!) {
updatePeople(input: $input) {
people {
id
}
}
}
`
err := owner.Execute(setQuery, map[string]any{
"input": map[string]any{
"id": peopleID,
"position": "Senior Engineer",
},
}, nil)
require.NoError(t, err)
// Update only fullName
query := `
mutation UpdatePeople($input: UpdatePeopleInput!) {
updatePeople(input: $input) {
people {
id
fullName
position
}
}
}
`
var result struct {
UpdatePeople struct {
People struct {
ID string `json:"id"`
FullName string `json:"fullName"`
Position *string `json:"position"`
} `json:"people"`
} `json:"updatePeople"`
}
err = owner.Execute(query, map[string]any{
"input": map[string]any{
"id": peopleID,
"fullName": "Updated Name",
},
}, &result)
require.NoError(t, err)
require.NotNil(t, result.UpdatePeople.People.Position)
assert.Equal(t, "Senior Engineer", *result.UpdatePeople.People.Position)
})
}
func TestPeople_TenantIsolation(t *testing.T) {
t.Parallel()
org1Owner := testutil.NewClient(t, testutil.RoleOwner)
org2Owner := testutil.NewClient(t, testutil.RoleOwner)
peopleID := factory.NewPeople(org1Owner).WithFullName("Org1 Person").Create()
t.Run("cannot read people from another organization", func(t *testing.T) {
query := `
query($id: ID!) {
node(id: $id) {
... on People {
id
fullName
}
}
}
`
var result struct {
Node *struct {
ID string `json:"id"`
FullName string `json:"fullName"`
} `json:"node"`
}
err := org2Owner.Execute(query, map[string]any{"id": peopleID}, &result)
testutil.AssertNodeNotAccessible(t, err, result.Node == nil, "people")
})
t.Run("cannot update people from another organization", func(t *testing.T) {
query := `
mutation UpdatePeople($input: UpdatePeopleInput!) {
updatePeople(input: $input) {
people { id }
}
}
`
_, err := org2Owner.Do(query, map[string]any{
"input": map[string]any{
"id": peopleID,
"fullName": "Hijacked Person",
},
})
require.Error(t, err, "Should not be able to update people from another org")
})
t.Run("cannot delete people from another organization", func(t *testing.T) {
query := `
mutation DeletePeople($input: DeletePeopleInput!) {
deletePeople(input: $input) {
deletedPeopleId
}
}
`
_, err := org2Owner.Do(query, map[string]any{
"input": map[string]any{
"peopleId": peopleID,
},
})
require.Error(t, err, "Should not be able to delete people from another org")
})
}

View File

@@ -174,36 +174,6 @@ const (
}
}`
createPeopleMutation = `
mutation CreatePeople($input: CreatePeopleInput!) {
createPeople(input: $input) {
peopleEdge { node { id } }
}
}`
updatePeopleMutation = `
mutation UpdatePeople($input: UpdatePeopleInput!) {
updatePeople(input: $input) {
people { id }
}
}`
deletePeopleMutation = `
mutation DeletePeople($input: DeletePeopleInput!) {
deletePeople(input: $input) {
deletedPeopleId
}
}`
listPeoplesQuery = `
query GetPeoples($id: ID!) {
node(id: $id) {
... on Organization {
peoples(first: 10) { totalCount }
}
}
}`
createVendorMutation = `
mutation CreateVendor($input: CreateVendorInput!) {
createVendor(input: $input) {
@@ -274,7 +244,6 @@ func TestRBAC(t *testing.T) {
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()
peopleID := factory.NewPeople(owner).WithFullName("RBAC Test Person").Create()
vendorID := factory.NewVendor(owner).WithName("RBAC Test Vendor").Create()
tests := []struct {
@@ -904,130 +873,6 @@ func TestRBAC(t *testing.T) {
},
shouldAllow: true,
},
{
name: "owner can create people",
role: "owner",
client: owner,
query: createPeopleMutation,
variables: func() map[string]any {
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "fullName": factory.SafeName("Person"), "primaryEmailAddress": factory.SafeEmail(), "additionalEmailAddresses": []string{}, "kind": "EMPLOYEE"}}
},
shouldAllow: true,
},
{
name: "admin can create people",
role: "admin",
client: admin,
query: createPeopleMutation,
variables: func() map[string]any {
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "fullName": factory.SafeName("Person"), "primaryEmailAddress": factory.SafeEmail(), "additionalEmailAddresses": []string{}, "kind": "EMPLOYEE"}}
},
shouldAllow: true,
},
{
name: "viewer cannot create people",
role: "viewer",
client: viewer,
query: createPeopleMutation,
variables: func() map[string]any {
return map[string]any{"input": map[string]any{"organizationId": owner.GetOrganizationID().String(), "fullName": factory.SafeName("Person"), "primaryEmailAddress": factory.SafeEmail(), "additionalEmailAddresses": []string{}, "kind": "EMPLOYEE"}}
},
shouldAllow: false,
},
// TODO: Fix server-side issue - updatePeople mutation returns internal server error
// {
// name: "owner can update people",
// role: "owner",
// client: owner,
// query: updatePeopleMutation,
// variables: func() map[string]any {
// return map[string]any{"input": map[string]any{"id": peopleID, "fullName": factory.SafeName("Updated Person")}}
// },
// shouldAllow: true,
// },
// {
// name: "admin can update people",
// role: "admin",
// client: admin,
// query: updatePeopleMutation,
// variables: func() map[string]any {
// return map[string]any{"input": map[string]any{"id": peopleID, "fullName": factory.SafeName("Updated Person")}}
// },
// shouldAllow: true,
// },
{
name: "viewer cannot update people",
role: "viewer",
client: viewer,
query: updatePeopleMutation,
variables: func() map[string]any {
return map[string]any{"input": map[string]any{"id": peopleID, "fullName": factory.SafeName("Updated Person")}}
},
shouldAllow: false,
},
{
name: "owner can delete people",
role: "owner",
client: owner,
query: deletePeopleMutation,
variables: func() map[string]any {
id := factory.NewPeople(owner).WithFullName(factory.SafeName("ToDelete")).Create()
return map[string]any{"input": map[string]any{"peopleId": id}}
},
shouldAllow: true,
},
{
name: "admin can delete people",
role: "admin",
client: admin,
query: deletePeopleMutation,
variables: func() map[string]any {
id := factory.NewPeople(owner).WithFullName(factory.SafeName("ToDelete")).Create()
return map[string]any{"input": map[string]any{"peopleId": id}}
},
shouldAllow: true,
},
{
name: "viewer cannot delete people",
role: "viewer",
client: viewer,
query: deletePeopleMutation,
variables: func() map[string]any {
id := factory.NewPeople(owner).WithFullName(factory.SafeName("ToDelete")).Create()
return map[string]any{"input": map[string]any{"peopleId": id}}
},
shouldAllow: false,
},
{
name: "owner can list peoples",
role: "owner",
client: owner,
query: listPeoplesQuery,
variables: func() map[string]any {
return map[string]any{"id": owner.GetOrganizationID().String()}
},
shouldAllow: true,
},
{
name: "admin can list peoples",
role: "admin",
client: admin,
query: listPeoplesQuery,
variables: func() map[string]any {
return map[string]any{"id": owner.GetOrganizationID().String()}
},
shouldAllow: true,
},
{
name: "viewer can list peoples",
role: "viewer",
client: viewer,
query: listPeoplesQuery,
variables: func() map[string]any {
return map[string]any{"id": owner.GetOrganizationID().String()}
},
shouldAllow: true,
},
{
name: "owner can create vendor",
role: "owner",

View File

@@ -881,13 +881,8 @@ func TestRisk_OmittableOwner(t *testing.T) {
owner := testutil.NewClient(t, testutil.RoleOwner)
// Create a people for owner assignment
peopleID := factory.NewPeople(owner).
WithFullName("Risk Owner Person").
Create()
riskID := factory.NewRisk(owner).
WithName("Owner Test Risk").
Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
riskID := factory.NewRisk(owner).WithName("Owner Test Risk").Create()
t.Run("set owner", func(t *testing.T) {
query := `
@@ -919,11 +914,11 @@ func TestRisk_OmittableOwner(t *testing.T) {
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"id": riskID,
"ownerId": peopleID,
"ownerId": profileID.String(),
},
}, &result)
require.NoError(t, err)
assert.Equal(t, peopleID, result.UpdateRisk.Risk.Owner.ID)
assert.Equal(t, profileID.String(), result.UpdateRisk.Risk.Owner.ID)
})
t.Run("clear owner with null", func(t *testing.T) {

View File

@@ -30,7 +30,7 @@ func TestTask_Assign(t *testing.T) {
// Create measure and task
measureID := factory.NewMeasure(owner).Create()
taskID := factory.NewTask(owner, measureID).Create()
peopleID := factory.NewPeople(owner).WithFullName("Task Assignee").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
query := `
mutation UpdateTask($input: UpdateTaskInput!) {
@@ -61,14 +61,13 @@ func TestTask_Assign(t *testing.T) {
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"taskId": taskID,
"assignedToId": peopleID,
"assignedToId": profileID.String(),
},
}, &result)
require.NoError(t, err)
assert.Equal(t, taskID, result.UpdateTask.Task.ID)
assert.Equal(t, peopleID, result.UpdateTask.Task.AssignedTo.ID)
assert.Equal(t, "Task Assignee", result.UpdateTask.Task.AssignedTo.FullName)
assert.Equal(t, profileID.String(), result.UpdateTask.Task.AssignedTo.ID)
}
func TestTask_Unassign(t *testing.T) {
@@ -78,7 +77,7 @@ func TestTask_Unassign(t *testing.T) {
// Create measure, task, people and assign
measureID := factory.NewMeasure(owner).Create()
taskID := factory.NewTask(owner, measureID).Create()
peopleID := factory.NewPeople(owner).WithFullName("Person to Unassign").Create()
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
// First assign the task
assignQuery := `
@@ -94,7 +93,7 @@ func TestTask_Unassign(t *testing.T) {
_, err := owner.Do(assignQuery, map[string]any{
"input": map[string]any{
"taskId": taskID,
"assignedToId": peopleID,
"assignedToId": profileID.String(),
},
})
require.NoError(t, err)

View File

@@ -649,11 +649,8 @@ func TestTask_OmittableAssignee(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
// Create a people for assignee
peopleID := factory.NewPeople(owner).
WithFullName("Task Assignee Person").
Create()
// Create a profile for assignee
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
measureID := factory.NewMeasure(owner).
WithName("Task Assignee Test").
Create()
@@ -692,11 +689,11 @@ func TestTask_OmittableAssignee(t *testing.T) {
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"taskId": taskID,
"assignedToId": peopleID,
"assignedToId": profileID.String(),
},
}, &result)
require.NoError(t, err)
assert.Equal(t, peopleID, result.UpdateTask.Task.AssignedTo.ID)
assert.Equal(t, profileID.String(), result.UpdateTask.Task.AssignedTo.ID)
})
t.Run("clear assignee", func(t *testing.T) {

View File

@@ -754,11 +754,8 @@ func TestVendor_OmittableBusinessOwner(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
// Create a people for owner assignment
peopleID := factory.NewPeople(owner).
WithFullName("Business Owner Person").
Create()
// Create a profile for owner assignment
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
vendorID := factory.NewVendor(owner).
WithName("BusinessOwner Test Vendor").
Create()
@@ -793,11 +790,11 @@ func TestVendor_OmittableBusinessOwner(t *testing.T) {
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"id": vendorID,
"businessOwnerId": peopleID,
"businessOwnerId": profileID.String(),
},
}, &result)
require.NoError(t, err)
assert.Equal(t, peopleID, result.UpdateVendor.Vendor.BusinessOwner.ID)
assert.Equal(t, profileID.String(), result.UpdateVendor.Vendor.BusinessOwner.ID)
})
t.Run("clear business owner with null", func(t *testing.T) {
@@ -840,14 +837,9 @@ func TestVendor_OmittableSecurityOwner(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
// Create a people for owner assignment
peopleID := factory.NewPeople(owner).
WithFullName("Security Owner Person").
Create()
vendorID := factory.NewVendor(owner).
WithName("SecurityOwner Test Vendor").
Create()
// Create a profile for owner assignment
profileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
vendorID := factory.NewVendor(owner).WithName("SecurityOwner Test Vendor").Create()
t.Run("set security owner", func(t *testing.T) {
query := `
@@ -879,11 +871,11 @@ func TestVendor_OmittableSecurityOwner(t *testing.T) {
err := owner.Execute(query, map[string]any{
"input": map[string]any{
"id": vendorID,
"securityOwnerId": peopleID,
"securityOwnerId": profileID.String(),
},
}, &result)
require.NoError(t, err)
assert.Equal(t, peopleID, result.UpdateVendor.Vendor.SecurityOwner.ID)
assert.Equal(t, profileID.String(), result.UpdateVendor.Vendor.SecurityOwner.ID)
})
t.Run("clear security owner with null", func(t *testing.T) {

View File

@@ -371,48 +371,6 @@ func CreateRisk(c *testutil.Client, attrs ...Attrs) string {
return result.CreateRisk.RiskEdge.Node.ID
}
func CreatePeople(c *testutil.Client, attrs ...Attrs) string {
c.T.Helper()
var a Attrs
if len(attrs) > 0 {
a = attrs[0]
}
const query = `
mutation($input: CreatePeopleInput!) {
createPeople(input: $input) {
peopleEdge {
node { id }
}
}
}
`
input := map[string]any{
"organizationId": c.GetOrganizationID().String(),
"fullName": a.getString("fullName", SafeName("Person")),
"primaryEmailAddress": a.getString("primaryEmailAddress", SafeEmail()),
"additionalEmailAddresses": a.getSlice("additionalEmailAddresses", []string{}),
"kind": a.getString("kind", "EMPLOYEE"),
}
var result struct {
CreatePeople struct {
PeopleEdge struct {
Node struct {
ID string `json:"id"`
} `json:"node"`
} `json:"peopleEdge"`
} `json:"createPeople"`
}
err := c.Execute(query, map[string]any{"input": input}, &result)
require.NoError(c.T, err, "createPeople mutation failed")
return result.CreatePeople.PeopleEdge.Node.ID
}
type VendorBuilder struct {
client *testutil.Client
attrs Attrs
@@ -607,29 +565,6 @@ func (b *RiskBuilder) Create() string {
return CreateRisk(b.client, b.attrs)
}
type PeopleBuilder struct {
client *testutil.Client
attrs Attrs
}
func NewPeople(c *testutil.Client) *PeopleBuilder {
return &PeopleBuilder{client: c, attrs: Attrs{}}
}
func (b *PeopleBuilder) WithFullName(name string) *PeopleBuilder {
b.attrs["fullName"] = name
return b
}
func (b *PeopleBuilder) WithKind(kind string) *PeopleBuilder {
b.attrs["kind"] = kind
return b
}
func (b *PeopleBuilder) Create() string {
return CreatePeople(b.client, b.attrs)
}
func CreateAudit(c *testutil.Client, frameworkID string, attrs ...Attrs) string {
c.T.Helper()

View File

@@ -48,6 +48,7 @@ type Client struct {
baseURL string
role TestRole
userID gid.GID
profileID gid.GID
organizationID gid.GID
}
@@ -89,7 +90,7 @@ func NewClientInOrg(t testing.TB, role TestRole, ownerClient *Client) *Client {
},
}
client.setupTestUserInOrg(ownerClient)
client.SetupTestUserInOrg(ownerClient)
return client
}
@@ -105,7 +106,7 @@ func (c *Client) setupTestUser() {
// Create organization (this makes the user an OWNER)
orgName := fmt.Sprintf("Test Org %s", uniqueID)
c.organizationID = c.createOrganization(orgName)
c.organizationID, c.profileID = c.createOrganization(orgName)
// Assume organization session to use console API
c.assumeOrganizationSession()
@@ -116,7 +117,7 @@ func (c *Client) setupTestUser() {
}
}
func (c *Client) setupTestUserInOrg(ownerClient *Client) {
func (c *Client) SetupTestUserInOrg(ownerClient *Client) {
uniqueID := generateUniqueID()
email := fmt.Sprintf("test-%s@e2e.probo.test", uniqueID)
password := "TestPassword123!"
@@ -129,7 +130,7 @@ func (c *Client) setupTestUserInOrg(ownerClient *Client) {
invitationID := ownerClient.inviteMember(email, fullName, coredata.MembershipRole(c.role))
// New user accepts invitation
c.acceptInvitation(invitationID)
c.profileID = c.acceptInvitation(invitationID)
// Assume organization session to use console API
c.assumeOrganizationSession()
@@ -167,11 +168,16 @@ func (c *Client) signUp(email, password, fullName string) gid.GID {
return userID
}
func (c *Client) createOrganization(name string) gid.GID {
func (c *Client) createOrganization(name string) (gid.GID, gid.GID) {
const query = `
mutation($input: CreateOrganizationInput!) {
createOrganization(input: $input) {
organization { id }
membershipEdge {
node {
profile { id }
}
}
}
}
`
@@ -181,6 +187,14 @@ func (c *Client) createOrganization(name string) gid.GID {
Organization struct {
ID string `json:"id"`
} `json:"organization"`
MembershipEdge struct {
Node struct {
ID string `json:"id"`
Profile struct {
ID string `json:"id"`
} `json:"profile"`
} `json:"node"`
} `json:"membershipEdge"`
} `json:"createOrganization"`
}
@@ -192,7 +206,10 @@ func (c *Client) createOrganization(name string) gid.GID {
orgID, err := gid.ParseGID(result.CreateOrganization.Organization.ID)
require.NoError(c.T, err, "cannot parse organization ID")
return orgID
profileID, err := gid.ParseGID(result.CreateOrganization.MembershipEdge.Node.Profile.ID)
require.NoError(c.T, err, "cannot parse profile ID")
return orgID, profileID
}
func (c *Client) updateOwnMembershipRole(role coredata.MembershipRole) {
@@ -304,23 +321,42 @@ func (c *Client) inviteMember(email, fullName string, role coredata.MembershipRo
return invitationID
}
func (c *Client) acceptInvitation(invitationID gid.GID) {
func (c *Client) acceptInvitation(invitationID gid.GID) gid.GID {
const query = `
mutation($input: AcceptInvitationInput!) {
acceptInvitation(input: $input) {
membershipEdge {
node { id }
node {
profile { id }
}
}
}
}
`
var result struct {
AcceptInvitation struct {
MembershipEdge struct {
Node struct {
Profile struct {
ID string `json:"id"`
} `json:"profile"`
} `json:"node"`
} `json:"membershipEdge"`
} `json:"acceptInvitation"`
}
err := c.ExecuteConnect(query, map[string]any{
"input": map[string]any{
"invitationId": invitationID.String(),
},
}, nil)
}, &result)
require.NoError(c.T, err, "acceptInvitation mutation failed")
profileID, err := gid.ParseGID(result.AcceptInvitation.MembershipEdge.Node.Profile.ID)
require.NoError(c.T, err, "cannot parse profile ID")
return profileID
}
func (c *Client) assumeOrganizationSession() {
@@ -349,6 +385,10 @@ func (c *Client) GetUserID() gid.GID {
return c.userID
}
func (c *Client) GetProfileID() gid.GID {
return c.profileID
}
func (c *Client) GetOrganizationID() gid.GID {
return c.organizationID
}

View File

@@ -24,6 +24,8 @@ import (
"sync"
"syscall"
"time"
"go.gearno.de/kit/log"
)
var (
@@ -65,7 +67,7 @@ func Setup() {
done: make(chan error, 1),
}
cmd := exec.Command(binaryPath, "-cfg-file", configPath)
cmd := exec.Command(binaryPath, "-cfg-file", configPath, "-format", log.FormatPretty)
if coverDir != "" {
cmd.Env = append(os.Environ(), "GOCOVERDIR="+coverDir)
} else {

View File

@@ -61,7 +61,7 @@ func (p MembershipProfile) CursorKey(orderBy MembershipProfileOrderField) page.C
}
func (p *MembershipProfile) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT m.organization_id FROM iam_membership_profiles mp JOIN iam_memberships m ON mp.membership_id = m.id WHERE mp.id = $1 LIMIT 1;`
q := `SELECT m.organization_id, mp.identity_id FROM iam_membership_profiles mp JOIN iam_memberships m ON mp.membership_id = m.id WHERE mp.id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, p.ID).Scan(&organizationID); err != nil {
@@ -241,6 +241,7 @@ func (p *MembershipProfiles) LoadByMeetingID(
WITH attendees AS (
SELECT
p.id,
p.tenant_id,
p.identity_id,
p.membership_id,
i.email_address,

View File

@@ -445,6 +445,8 @@ WHERE
-- 8. Now that references are filled, add the NOT NULL constraints to those who need it
ALTER TABLE
assets
ALTER COLUMN
owner_id DROP NOT NULL,
ALTER COLUMN
owner_profile_id
SET
@@ -452,6 +454,8 @@ SET
ALTER TABLE
continual_improvements
ALTER COLUMN
owner_id DROP NOT NULL,
ALTER COLUMN
owner_profile_id
SET
@@ -459,6 +463,8 @@ SET
ALTER TABLE
data
ALTER COLUMN
owner_id DROP NOT NULL,
ALTER COLUMN
owner_profile_id
SET
@@ -466,20 +472,28 @@ SET
ALTER TABLE
document_versions
ALTER COLUMN
owner_id DROP NOT NULL,
ALTER COLUMN
owner_profile_id
SET
NOT NULL;
ALTER TABLE
meeting_attendees
meeting_attendees DROP CONSTRAINT meeting_attendees_pkey,
ALTER COLUMN
attendee_id DROP NOT NULL,
ALTER COLUMN
attendee_profile_id
SET
NOT NULL;
NOT NULL,
ADD
PRIMARY KEY (attendee_profile_id);
ALTER TABLE
nonconformities
ALTER COLUMN
owner_id DROP NOT NULL,
ALTER COLUMN
owner_profile_id
SET
@@ -487,6 +501,8 @@ SET
ALTER TABLE
obligations
ALTER COLUMN
owner_id DROP NOT NULL,
ALTER COLUMN
owner_profile_id
SET
@@ -494,6 +510,8 @@ SET
ALTER TABLE
document_version_signatures
ALTER COLUMN
signed_by DROP NOT NULL,
ALTER COLUMN
signed_by_profile_id
SET
@@ -501,6 +519,8 @@ SET
ALTER TABLE
states_of_applicability
ALTER COLUMN
owner_id DROP NOT NULL,
ALTER COLUMN
owner_profile_id
SET

View File

@@ -84,6 +84,18 @@ var IAMSelfManageInvitationPolicy = policy.NewPolicy(
).
WithDescription("Allows users to view and accept invitations sent to them")
// IAMSelfManageProfilePolicy allows users to view their own profiles.
var IAMSelfManageProfilePolicy = policy.NewPolicy(
"iam:self-manage-profile",
"Self-Manage Profiles",
// Users can view their own profiles
policy.Allow(ActionMembershipProfileGet).
WithSID("view-own-profiles").
When(policy.Equals("principal.id", "resource.identity_id")),
).
WithDescription("Allows users to view their organization profiles")
// IAMSelfManageMembershipPolicy allows users to view their own memberships.
var IAMSelfManageMembershipPolicy = policy.NewPolicy(
"iam:self-manage-membership",

View File

@@ -504,9 +504,9 @@ func (s *OrganizationService) CreateOrganization(
ctx context.Context,
identityID gid.GID,
req *CreateOrganizationRequest,
) (*coredata.Organization, error) {
) (*coredata.Organization, *coredata.Membership, error) {
if err := req.Validate(); err != nil {
return nil, fmt.Errorf("invalid request: %w", err)
return nil, nil, fmt.Errorf("invalid request: %w", err)
}
var (
@@ -584,7 +584,7 @@ func (s *OrganizationService) CreateOrganization(
)
if err != nil {
return nil, fmt.Errorf("cannot upload logo file: %w", err)
return nil, nil, fmt.Errorf("cannot upload logo file: %w", err)
}
logoFile.FileSize = fileSize
@@ -621,7 +621,7 @@ func (s *OrganizationService) CreateOrganization(
)
if err != nil {
return nil, fmt.Errorf("cannot upload logo file: %w", err)
return nil, nil, fmt.Errorf("cannot upload logo file: %w", err)
}
horizontalLogoFile.FileSize = fileSize
@@ -713,10 +713,10 @@ func (s *OrganizationService) CreateOrganization(
},
)
if err != nil {
return nil, fmt.Errorf("cannot insert organization: %w", err)
return nil, nil, fmt.Errorf("cannot insert organization: %w", err)
}
return organization, nil
return organization, membership, nil
}
func (s *OrganizationService) UpdateOrganization(ctx context.Context, organizationID gid.GID, req *UpdateOrganizationRequest) (*coredata.Organization, error) {

View File

@@ -66,6 +66,7 @@ func IAMPolicySet() *PolicySet {
IAMSelfManageIdentityPolicy,
IAMSelfManageSessionPolicy,
IAMSelfManageInvitationPolicy,
IAMSelfManageProfilePolicy,
IAMSelfManageMembershipPolicy,
IAMSelfManagePersonalAPIKeyPolicy,
)

View File

@@ -196,8 +196,8 @@ func (s MeetingService) Create(
}
if len(req.AttendeeIDs) > 0 {
var attendeePeople coredata.MembershipProfiles
if err := attendeePeople.LoadByIDs(ctx, conn, s.svc.scope, req.AttendeeIDs); err != nil {
var attendeeProfiles coredata.MembershipProfiles
if err := attendeeProfiles.LoadByIDs(ctx, conn, s.svc.scope, req.AttendeeIDs); err != nil {
return fmt.Errorf("cannot load attendee profiles: %w", err)
}

View File

@@ -251,7 +251,7 @@ func (r *membershipResolver) Identity(ctx context.Context, obj *types.Membership
// Profile is the resolver for the profile field.
func (r *membershipResolver) Profile(ctx context.Context, obj *types.Membership) (*types.MembershipProfile, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileGet); err != nil {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileGet, authz.WithSkipAssumptionCheck()); err != nil {
return nil, err
}
@@ -833,7 +833,7 @@ func (r *mutationResolver) CreateOrganization(ctx context.Context, input types.C
Size: input.HorizontalLogoFile.Size,
}
}
organization, err := r.iam.OrganizationService.CreateOrganization(
organization, membership, err := r.iam.OrganizationService.CreateOrganization(
ctx,
identity.ID,
&iam.CreateOrganizationRequest{
@@ -848,7 +848,8 @@ func (r *mutationResolver) CreateOrganization(ctx context.Context, input types.C
}
return &types.CreateOrganizationPayload{
Organization: types.NewOrganization(organization),
Organization: types.NewOrganization(organization),
MembershipEdge: types.NewMembershipEdge(membership, coredata.MembershipOrderFieldCreatedAt),
}, nil
}