diff --git a/packages/n8n-node/nodes/Probo/actions/accessReview/addSource.operation.ts b/packages/n8n-node/nodes/Probo/actions/accessReview/addSource.operation.ts new file mode 100644 index 000000000..1056921e5 --- /dev/null +++ b/packages/n8n-node/nodes/Probo/actions/accessReview/addSource.operation.ts @@ -0,0 +1,87 @@ +// Copyright (c) 2025-2026 Probo Inc . +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; +import { proboApiRequest } from '../../GenericFunctions'; + +export const description: INodeProperties[] = [ + { + displayName: 'Access Review Campaign ID', + name: 'accessReviewCampaignId', + type: 'string', + displayOptions: { + show: { + resource: ['accessReview'], + operation: ['addSource'], + }, + }, + default: '', + description: 'The ID of the access review campaign', + required: true, + }, + { + displayName: 'Access Review Source ID', + name: 'accessReviewSourceId', + type: 'string', + displayOptions: { + show: { + resource: ['accessReview'], + operation: ['addSource'], + }, + }, + default: '', + description: 'The ID of the access review source to add to the campaign', + required: true, + }, +]; + +export async function execute( + this: IExecuteFunctions, + itemIndex: number, +): Promise { + const accessReviewCampaignId = this.getNodeParameter('accessReviewCampaignId', itemIndex) as string; + const accessReviewSourceId = this.getNodeParameter('accessReviewSourceId', itemIndex) as string; + + const query = ` + mutation AddAccessReviewCampaignSource($input: AddAccessReviewCampaignSourceInput!) { + addAccessReviewCampaignSource(input: $input) { + accessReviewCampaign { + id + name + description + status + startedAt + completedAt + createdAt + updatedAt + } + } + } + `; + + const responseData = await proboApiRequest.call(this, query, { + input: { accessReviewCampaignId, accessReviewSourceId }, + }); + + return { + json: responseData, + pairedItem: { item: itemIndex }, + }; +} diff --git a/packages/n8n-node/nodes/Probo/actions/accessReview/index.ts b/packages/n8n-node/nodes/Probo/actions/accessReview/index.ts index 18eb48ba5..4a71bd6e5 100644 --- a/packages/n8n-node/nodes/Probo/actions/accessReview/index.ts +++ b/packages/n8n-node/nodes/Probo/actions/accessReview/index.ts @@ -19,6 +19,7 @@ // SOFTWARE. import type { INodeProperties } from 'n8n-workflow'; +import * as addSourceOp from './addSource.operation'; import * as createOp from './create.operation'; import * as deleteOp from './delete.operation'; import * as getOp from './get.operation'; @@ -40,6 +41,12 @@ export const description: INodeProperties[] = [ }, }, options: [ + { + name: 'Add Source', + value: 'addSource', + description: 'Add a scope source to an access review campaign', + action: 'Add a scope source to an access review campaign', + }, { name: 'Cancel', value: 'cancel', @@ -91,6 +98,7 @@ export const description: INodeProperties[] = [ ], default: 'create', }, + ...addSourceOp.description, ...createOp.description, ...deleteOp.description, ...getOp.description, @@ -102,6 +110,7 @@ export const description: INodeProperties[] = [ ]; export { + addSourceOp as addSource, createOp as create, deleteOp as delete, getOp as get, diff --git a/pkg/server/api/console/v1/access_review_campaign_resolvers.go b/pkg/server/api/console/v1/access_review_campaign_resolvers.go index 9f1411bce..3edce2568 100644 --- a/pkg/server/api/console/v1/access_review_campaign_resolvers.go +++ b/pkg/server/api/console/v1/access_review_campaign_resolvers.go @@ -9,6 +9,7 @@ import ( "context" "errors" "fmt" + "strings" "github.com/vikstrous/dataloadgen" "go.gearno.de/kit/log" @@ -796,6 +797,10 @@ func (r *mutationResolver) StartAccessReviewCampaign(ctx context.Context, input campaign, err := r.accessReview.StartCampaign(ctx, scope, input.AccessReviewCampaignID) if err != nil { + if strings.HasPrefix(err.Error(), "cannot start campaign:") { + return nil, gqlutils.Invalid(ctx, err) + } + r.logger.ErrorCtx(ctx, "cannot start access review campaign", log.Error(err)) return nil, gqlutils.Internal(ctx)