diff --git a/packages/n8n-node/nodes/Probo/Probo.node.ts b/packages/n8n-node/nodes/Probo/Probo.node.ts index efd7028ea..c8ab7535b 100644 --- a/packages/n8n-node/nodes/Probo/Probo.node.ts +++ b/packages/n8n-node/nodes/Probo/Probo.node.ts @@ -102,26 +102,21 @@ export class Probo implements INodeType { value: 'meeting', description: 'Manage meetings', }, - { - name: 'Member', - value: 'member', - description: 'Manage organization members', - }, { name: 'Organization', value: 'organization', description: 'Manage organizations', }, - { - name: 'People', - value: 'people', - description: 'Manage people', - }, { name: 'Risk', value: 'risk', description: 'Manage risks', }, + { + name: 'User', + value: 'user', + description: 'Manage organization users (profiles)', + }, { name: 'Vendor', value: 'vendor', diff --git a/packages/n8n-node/nodes/Probo/actions/index.ts b/packages/n8n-node/nodes/Probo/actions/index.ts index 00cb27b45..877870427 100644 --- a/packages/n8n-node/nodes/Probo/actions/index.ts +++ b/packages/n8n-node/nodes/Probo/actions/index.ts @@ -6,9 +6,9 @@ import * as datum from './datum'; import * as execute from './execute'; import * as framework from './framework'; import * as measure from './measure'; -import * as member from './member'; import * as meeting from './meeting'; import * as organization from './organization'; +import * as user from './user'; import * as risk from './risk'; import * as vendor from './vendor'; @@ -30,9 +30,9 @@ export const resources: Record = { execute: execute as ResourceModule, framework: framework as ResourceModule, measure: measure as ResourceModule, - member: member as ResourceModule, meeting: meeting as ResourceModule, organization: organization as ResourceModule, + user: user as ResourceModule, risk: risk as ResourceModule, vendor: vendor as ResourceModule, }; diff --git a/packages/n8n-node/nodes/Probo/actions/member/get.operation.ts b/packages/n8n-node/nodes/Probo/actions/member/get.operation.ts deleted file mode 100644 index 9b306d6c4..000000000 --- a/packages/n8n-node/nodes/Probo/actions/member/get.operation.ts +++ /dev/null @@ -1,124 +0,0 @@ -import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; -import { proboConnectApiRequest } from '../../GenericFunctions'; - -export const description: INodeProperties[] = [ - { - displayName: 'Membership ID', - name: 'membershipId', - type: 'string', - displayOptions: { - show: { - resource: ['member'], - operation: ['get'], - }, - }, - default: '', - description: 'The ID of the membership', - required: true, - }, - { - displayName: 'Options', - name: 'options', - type: 'collection', - placeholder: 'Add Option', - default: {}, - displayOptions: { - show: { - resource: ['member'], - operation: ['get'], - }, - }, - options: [ - { - displayName: 'Include Identity', - name: 'includeIdentity', - type: 'boolean', - default: true, - description: 'Whether to include identity (email, fullName) in the response', - }, - { - displayName: 'Include Profile', - name: 'includeProfile', - type: 'boolean', - default: true, - description: 'Whether to include profile in the response', - }, - { - displayName: 'Include Organization', - name: 'includeOrganization', - type: 'boolean', - default: true, - description: 'Whether to include organization in the response', - }, - ], - }, -]; - -export async function execute( - this: IExecuteFunctions, - itemIndex: number, -): Promise { - const membershipId = this.getNodeParameter('membershipId', itemIndex) as string; - const options = this.getNodeParameter('options', itemIndex, {}) as { - includeIdentity?: boolean; - includeProfile?: boolean; - includeOrganization?: boolean; - }; - - const identityFragment = - options.includeIdentity !== false - ? `identity { - id - email - fullName - emailVerified - }` - : ''; - - const profileFragment = - options.includeProfile !== false - ? `profile { - id - fullName - createdAt - updatedAt - }` - : ''; - - const organizationFragment = - options.includeOrganization !== false - ? `organization { - id - name - email - }` - : ''; - - const query = ` - query GetMember($membershipId: ID!) { - node(id: $membershipId) { - ... on Membership { - id - createdAt - role - source - state - ${identityFragment} - ${profileFragment} - ${organizationFragment} - } - } - } - `; - - const variables = { - membershipId, - }; - - const responseData = await proboConnectApiRequest.call(this, query, variables); - - return { - json: responseData, - pairedItem: { item: itemIndex }, - }; -} diff --git a/packages/n8n-node/nodes/Probo/actions/member/index.ts b/packages/n8n-node/nodes/Probo/actions/member/index.ts deleted file mode 100644 index c94baf837..000000000 --- a/packages/n8n-node/nodes/Probo/actions/member/index.ts +++ /dev/null @@ -1,60 +0,0 @@ -import type { INodeProperties } from 'n8n-workflow'; -import * as inviteOp from './invite.operation'; -import * as updateOp from './update.operation'; -import * as deleteOp from './delete.operation'; -import * as getOp from './get.operation'; -import * as getAllOp from './getAll.operation'; - -export const description: INodeProperties[] = [ - { - displayName: 'Operation', - name: 'operation', - type: 'options', - noDataExpression: true, - displayOptions: { - show: { - resource: ['member'], - }, - }, - options: [ - { - name: 'Delete', - value: 'delete', - description: 'Remove a member from an organization', - action: 'Delete a member', - }, - { - name: 'Get', - value: 'get', - description: 'Get a member (membership) by ID', - action: 'Get a member', - }, - { - name: 'Get Many', - value: 'getAll', - description: 'Get many members of an organization', - action: 'Get many members', - }, - { - name: 'Invite', - value: 'invite', - description: 'Invite a new member to an organization', - action: 'Invite a member', - }, - { - name: 'Update', - value: 'update', - description: 'Update a member\'s role', - action: 'Update a member', - }, - ], - default: 'invite', - }, - ...inviteOp.description, - ...updateOp.description, - ...deleteOp.description, - ...getOp.description, - ...getAllOp.description, -]; - -export { inviteOp as invite, updateOp as update, deleteOp as delete, getOp as get, getAllOp as getAll }; diff --git a/packages/n8n-node/nodes/Probo/actions/member/update.operation.ts b/packages/n8n-node/nodes/Probo/actions/member/update.operation.ts deleted file mode 100644 index cc17c910e..000000000 --- a/packages/n8n-node/nodes/Probo/actions/member/update.operation.ts +++ /dev/null @@ -1,161 +0,0 @@ -import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; -import { proboConnectApiRequest } from '../../GenericFunctions'; - -const roleOptions = [ - { name: 'Owner', value: 'OWNER' }, - { name: 'Admin', value: 'ADMIN' }, - { name: 'Employee', value: 'EMPLOYEE' }, - { name: 'Viewer', value: 'VIEWER' }, - { name: 'Auditor', value: 'AUDITOR' }, -]; - -export const description: INodeProperties[] = [ - { - displayName: 'Organization ID', - name: 'organizationId', - type: 'string', - displayOptions: { - show: { - resource: ['member'], - operation: ['update'], - }, - }, - default: '', - description: 'The ID of the organization', - required: true, - }, - { - displayName: 'Membership ID', - name: 'membershipId', - type: 'string', - displayOptions: { - show: { - resource: ['member'], - operation: ['update'], - }, - }, - default: '', - description: 'The ID of the membership to update', - required: true, - }, - { - displayName: 'Role', - name: 'role', - type: 'options', - displayOptions: { - show: { - resource: ['member'], - operation: ['update'], - }, - }, - options: roleOptions, - default: 'EMPLOYEE', - description: 'New role for the member', - required: true, - }, - { - displayName: 'Options', - name: 'options', - type: 'collection', - placeholder: 'Add Option', - default: {}, - displayOptions: { - show: { - resource: ['member'], - operation: ['update'], - }, - }, - options: [ - { - displayName: 'Include Identity', - name: 'includeIdentity', - type: 'boolean', - default: true, - description: 'Whether to include identity (email, fullName) in the response', - }, - { - displayName: 'Include Profile', - name: 'includeProfile', - type: 'boolean', - default: true, - description: 'Whether to include profile in the response', - }, - { - displayName: 'Include Organization', - name: 'includeOrganization', - type: 'boolean', - default: true, - description: 'Whether to include organization in the response', - }, - ], - }, -]; - -export async function execute( - this: IExecuteFunctions, - itemIndex: number, -): Promise { - const organizationId = this.getNodeParameter('organizationId', itemIndex) as string; - const membershipId = this.getNodeParameter('membershipId', itemIndex) as string; - const role = this.getNodeParameter('role', itemIndex) as string; - const options = this.getNodeParameter('options', itemIndex, {}) as { - includeIdentity?: boolean; - includeProfile?: boolean; - includeOrganization?: boolean; - }; - - const identityFragment = - options.includeIdentity !== false - ? `identity { - id - email - fullName - }` - : ''; - - const profileFragment = - options.includeProfile !== false - ? `profile { - id - fullName - }` - : ''; - - const organizationFragment = - options.includeOrganization !== false - ? `organization { - id - name - }` - : ''; - - const query = ` - mutation UpdateMembership($input: UpdateMembershipInput!) { - updateMembership(input: $input) { - membership { - id - createdAt - role - source - state - ${identityFragment} - ${profileFragment} - ${organizationFragment} - } - } - } - `; - - const input = { - organizationId, - membershipId, - role, - }; - - const responseData = await proboConnectApiRequest.call(this, query, { input }); - - return { - json: responseData, - pairedItem: { item: itemIndex }, - }; -} diff --git a/packages/n8n-node/nodes/Probo/actions/user/createUser.operation.ts b/packages/n8n-node/nodes/Probo/actions/user/createUser.operation.ts new file mode 100644 index 000000000..5a789b8d8 --- /dev/null +++ b/packages/n8n-node/nodes/Probo/actions/user/createUser.operation.ts @@ -0,0 +1,209 @@ +import type { + INodeProperties, + IExecuteFunctions, + INodeExecutionData, + IDataObject, +} from 'n8n-workflow'; +import { proboConnectApiRequest } from '../../GenericFunctions'; + +const roleOptions = [ + { name: 'Owner', value: 'OWNER' }, + { name: 'Admin', value: 'ADMIN' }, + { name: 'Employee', value: 'EMPLOYEE' }, + { name: 'Viewer', value: 'VIEWER' }, + { name: 'Auditor', value: 'AUDITOR' }, +]; + +const kindOptions = [ + { name: 'Employee', value: 'EMPLOYEE' }, + { name: 'Contractor', value: 'CONTRACTOR' }, + { name: 'Service Account', value: 'SERVICE_ACCOUNT' }, +]; + +export const description: INodeProperties[] = [ + { + displayName: 'Organization ID', + name: 'organizationId', + type: 'string', + displayOptions: { + show: { + resource: ['user'], + operation: ['createUser'], + }, + }, + default: '', + description: 'The ID of the organization', + required: true, + }, + { + displayName: 'Full Name', + name: 'fullName', + type: 'string', + displayOptions: { + show: { + resource: ['user'], + operation: ['createUser'], + }, + }, + default: '', + description: 'Full name of the user', + required: true, + }, + { + displayName: 'Email Address', + name: 'emailAddress', + type: 'string', + displayOptions: { + show: { + resource: ['user'], + operation: ['createUser'], + }, + }, + default: '', + placeholder: 'name@example.com', + description: 'Email address of the user', + required: true, + }, + { + displayName: 'Role', + name: 'role', + type: 'options', + displayOptions: { + show: { + resource: ['user'], + operation: ['createUser'], + }, + }, + options: roleOptions, + default: 'EMPLOYEE', + description: 'Membership role to assign', + required: true, + }, + { + displayName: 'Kind', + name: 'kind', + type: 'options', + displayOptions: { + show: { + resource: ['user'], + operation: ['createUser'], + }, + }, + options: kindOptions, + default: 'EMPLOYEE', + description: 'User kind (employee, contractor, or service account)', + required: true, + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: ['user'], + operation: ['createUser'], + }, + }, + options: [ + { + displayName: 'Additional Email Addresses', + name: 'additionalEmailAddresses', + type: 'string', + default: '', + description: 'Comma-separated additional email addresses', + }, + { + displayName: 'Position', + name: 'position', + type: 'string', + default: '', + description: 'Job or role position', + }, + { + displayName: 'Contract Start Date', + name: 'contractStartDate', + type: 'string', + default: '', + description: 'Contract start date (ISO 8601)', + }, + { + displayName: 'Contract End Date', + name: 'contractEndDate', + type: 'string', + default: '', + description: 'Contract end date (ISO 8601)', + }, + ], + }, +]; + +export async function execute( + this: IExecuteFunctions, + itemIndex: number, +): Promise { + const organizationId = this.getNodeParameter('organizationId', itemIndex) as string; + const fullName = this.getNodeParameter('fullName', itemIndex) as string; + const emailAddress = this.getNodeParameter('emailAddress', itemIndex) as string; + const role = this.getNodeParameter('role', itemIndex) as string; + const kind = this.getNodeParameter('kind', itemIndex) as string; + const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as { + additionalEmailAddresses?: string; + position?: string; + contractStartDate?: string; + contractEndDate?: string; + }; + + const input: IDataObject = { + organizationId, + fullName, + emailAddress, + role, + kind, + }; + if (additionalFields.additionalEmailAddresses) { + input.additionalEmailAddresses = additionalFields.additionalEmailAddresses + .split(',') + .map((e: string) => e.trim()) + .filter(Boolean); + } + if (additionalFields.position) { + input.position = additionalFields.position; + } + if (additionalFields.contractStartDate) { + input.contractStartDate = additionalFields.contractStartDate; + } + if (additionalFields.contractEndDate) { + input.contractEndDate = additionalFields.contractEndDate; + } + + const query = ` + mutation CreateUser($input: CreateUserInput!) { + createUser(input: $input) { + profileEdge { + node { + id + fullName + emailAddress + kind + position + contractStartDate + contractEndDate + createdAt + updatedAt + organization { id name } + membership { id role createdAt } + } + } + } + } + `; + + const responseData = await proboConnectApiRequest.call(this, query, { input }); + + return { + json: responseData, + pairedItem: { item: itemIndex }, + }; +} diff --git a/packages/n8n-node/nodes/Probo/actions/user/getUser.operation.ts b/packages/n8n-node/nodes/Probo/actions/user/getUser.operation.ts new file mode 100644 index 000000000..54a78ef96 --- /dev/null +++ b/packages/n8n-node/nodes/Probo/actions/user/getUser.operation.ts @@ -0,0 +1,57 @@ +import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; +import { proboConnectApiRequest } from '../../GenericFunctions'; + +export const description: INodeProperties[] = [ + { + displayName: 'User ID', + name: 'userId', + type: 'string', + displayOptions: { + show: { + resource: ['user'], + operation: ['getUser'], + }, + }, + default: '', + description: 'The ID of the user (profile)', + required: true, + }, +]; + +export async function execute( + this: IExecuteFunctions, + itemIndex: number, +): Promise { + const userId = this.getNodeParameter('userId', itemIndex) as string; + + const query = ` + query GetUser($userId: ID!) { + node(id: $userId) { + ... on Profile { + id + fullName + emailAddress + source + state + additionalEmailAddresses + kind + position + contractStartDate + contractEndDate + createdAt + updatedAt + identity { id email fullName emailVerified } + organization { id name email } + membership { id role createdAt } + } + } + } + `; + + const responseData = await proboConnectApiRequest.call(this, query, { userId }); + + return { + json: responseData, + pairedItem: { item: itemIndex }, + }; +} diff --git a/packages/n8n-node/nodes/Probo/actions/user/index.ts b/packages/n8n-node/nodes/Probo/actions/user/index.ts new file mode 100644 index 000000000..f437a11e7 --- /dev/null +++ b/packages/n8n-node/nodes/Probo/actions/user/index.ts @@ -0,0 +1,84 @@ +import type { INodeProperties } from 'n8n-workflow'; +import * as listUsersOp from './listUsers.operation'; +import * as getUserOp from './getUser.operation'; +import * as createUserOp from './createUser.operation'; +import * as inviteUserOp from './inviteUser.operation'; +import * as updateUserOp from './updateUser.operation'; +import * as updateMembershipOp from './updateMembership.operation'; +import * as removeUserOp from './removeUser.operation'; + +export const description: INodeProperties[] = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + resource: ['user'], + }, + }, + options: [ + { + name: 'Create', + value: 'createUser', + description: 'Create a new user in the organization', + action: 'Create a user', + }, + { + name: 'Get', + value: 'getUser', + description: 'Get a user (profile) by ID', + action: 'Get a user', + }, + { + name: 'Invite', + value: 'inviteUser', + description: 'Invite a user to the organization', + action: 'Invite a user', + }, + { + name: 'List', + value: 'listUsers', + description: 'List all users in the organization', + action: 'List users', + }, + { + name: 'Remove', + value: 'removeUser', + description: 'Remove a user from the organization', + action: 'Remove a user', + }, + { + name: 'Update', + value: 'updateUser', + description: 'Update a user (profile)', + action: 'Update a user', + }, + { + name: 'Update Membership', + value: 'updateMembership', + description: 'Update a user\'s membership role', + action: 'Update membership role', + }, + ], + default: 'listUsers', + }, + ...listUsersOp.description, + ...getUserOp.description, + ...createUserOp.description, + ...inviteUserOp.description, + ...updateUserOp.description, + ...updateMembershipOp.description, + ...removeUserOp.description, +]; + +export { + listUsersOp as listUsers, + getUserOp as getUser, + createUserOp as createUser, + inviteUserOp as inviteUser, + updateUserOp as updateUser, + updateMembershipOp as updateMembership, + removeUserOp as removeUser, +}; diff --git a/packages/n8n-node/nodes/Probo/actions/user/inviteUser.operation.ts b/packages/n8n-node/nodes/Probo/actions/user/inviteUser.operation.ts new file mode 100644 index 000000000..70ea0af3b --- /dev/null +++ b/packages/n8n-node/nodes/Probo/actions/user/inviteUser.operation.ts @@ -0,0 +1,66 @@ +import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; +import { proboConnectApiRequest } from '../../GenericFunctions'; + +export const description: INodeProperties[] = [ + { + displayName: 'Organization ID', + name: 'organizationId', + type: 'string', + displayOptions: { + show: { + resource: ['user'], + operation: ['inviteUser'], + }, + }, + default: '', + description: 'The ID of the organization', + required: true, + }, + { + displayName: 'Profile ID', + name: 'profileId', + type: 'string', + displayOptions: { + show: { + resource: ['user'], + operation: ['inviteUser'], + }, + }, + default: '', + description: 'The ID of the user (profile) to invite to the organization', + required: true, + }, +]; + +export async function execute( + this: IExecuteFunctions, + itemIndex: number, +): Promise { + const organizationId = this.getNodeParameter('organizationId', itemIndex) as string; + const profileId = this.getNodeParameter('profileId', itemIndex) as string; + + const query = ` + mutation InviteUser($input: InviteUserInput!) { + inviteUser(input: $input) { + invitationEdge { + node { + id + expiresAt + status + createdAt + user { id fullName emailAddress } + organization { id name } + } + } + } + } + `; + + const input = { organizationId, profileId }; + const responseData = await proboConnectApiRequest.call(this, query, { input }); + + return { + json: responseData, + pairedItem: { item: itemIndex }, + }; +} diff --git a/packages/n8n-node/nodes/Probo/actions/member/getAll.operation.ts b/packages/n8n-node/nodes/Probo/actions/user/listUsers.operation.ts similarity index 64% rename from packages/n8n-node/nodes/Probo/actions/member/getAll.operation.ts rename to packages/n8n-node/nodes/Probo/actions/user/listUsers.operation.ts index 1efaee73e..bb53efa7f 100644 --- a/packages/n8n-node/nodes/Probo/actions/member/getAll.operation.ts +++ b/packages/n8n-node/nodes/Probo/actions/user/listUsers.operation.ts @@ -1,4 +1,9 @@ -import type { INodeProperties, IExecuteFunctions, INodeExecutionData, IDataObject } from 'n8n-workflow'; +import type { + INodeProperties, + IExecuteFunctions, + INodeExecutionData, + IDataObject, +} from 'n8n-workflow'; import { proboConnectApiRequestAllItems } from '../../GenericFunctions'; export const description: INodeProperties[] = [ @@ -8,8 +13,8 @@ export const description: INodeProperties[] = [ type: 'string', displayOptions: { show: { - resource: ['member'], - operation: ['getAll'], + resource: ['user'], + operation: ['listUsers'], }, }, default: '', @@ -22,8 +27,8 @@ export const description: INodeProperties[] = [ type: 'boolean', displayOptions: { show: { - resource: ['member'], - operation: ['getAll'], + resource: ['user'], + operation: ['listUsers'], }, }, default: false, @@ -35,8 +40,8 @@ export const description: INodeProperties[] = [ type: 'number', displayOptions: { show: { - resource: ['member'], - operation: ['getAll'], + resource: ['user'], + operation: ['listUsers'], returnAll: [false], }, }, @@ -57,34 +62,26 @@ export async function execute( const limit = this.getNodeParameter('limit', itemIndex, 50) as number; const query = ` - query GetMembers($organizationId: ID!, $first: Int, $after: CursorKey) { + query ListUsers($organizationId: ID!, $first: Int, $after: CursorKey, $orderBy: ProfileOrder) { node(id: $organizationId) { ... on Organization { - members(first: $first, after: $after) { + profiles(first: $first, after: $after, orderBy: $orderBy) { edges { node { id - createdAt - role + fullName + emailAddress source state - identity { - id - email - fullName - emailVerified - } - profile { - id - fullName - createdAt - updatedAt - } - organization { - id - name - email - } + additionalEmailAddresses + kind + position + contractStartDate + contractEndDate + createdAt + updatedAt + organization { id name } + membership { id role createdAt } } } pageInfo { @@ -97,21 +94,22 @@ export async function execute( } `; - const members = await proboConnectApiRequestAllItems.call( + const users = await proboConnectApiRequestAllItems.call( this, query, { organizationId }, - (response) => { + (response: IDataObject) => { const data = response?.data as IDataObject | undefined; const node = data?.node as IDataObject | undefined; - return node?.members as IDataObject | undefined; + const org = node as IDataObject | undefined; + return org?.profiles as IDataObject | undefined; }, returnAll, limit, ); return { - json: { members }, + json: { users }, pairedItem: { item: itemIndex }, }; } diff --git a/packages/n8n-node/nodes/Probo/actions/member/delete.operation.ts b/packages/n8n-node/nodes/Probo/actions/user/removeUser.operation.ts similarity index 64% rename from packages/n8n-node/nodes/Probo/actions/member/delete.operation.ts rename to packages/n8n-node/nodes/Probo/actions/user/removeUser.operation.ts index 3ea3d6f73..a0f6bd89b 100644 --- a/packages/n8n-node/nodes/Probo/actions/member/delete.operation.ts +++ b/packages/n8n-node/nodes/Probo/actions/user/removeUser.operation.ts @@ -8,8 +8,8 @@ export const description: INodeProperties[] = [ type: 'string', displayOptions: { show: { - resource: ['member'], - operation: ['delete'], + resource: ['user'], + operation: ['removeUser'], }, }, default: '', @@ -17,17 +17,17 @@ export const description: INodeProperties[] = [ required: true, }, { - displayName: 'Membership ID', - name: 'membershipId', + displayName: 'User ID', + name: 'userId', type: 'string', displayOptions: { show: { - resource: ['member'], - operation: ['delete'], + resource: ['user'], + operation: ['removeUser'], }, }, default: '', - description: 'The ID of the membership to remove', + description: 'The ID of the user (profile) to remove from the organization', required: true, }, ]; @@ -37,19 +37,18 @@ export async function execute( itemIndex: number, ): Promise { const organizationId = this.getNodeParameter('organizationId', itemIndex) as string; - const membershipId = this.getNodeParameter('membershipId', itemIndex) as string; + const userId = this.getNodeParameter('userId', itemIndex) as string; const query = ` - mutation RemoveMember($input: RemoveMemberInput!) { - removeMember(input: $input) { - deletedMembershipId + mutation RemoveUser($input: RemoveUserInput!) { + removeUser(input: $input) { + deletedProfileId } } `; - const responseData = await proboConnectApiRequest.call(this, query, { - input: { organizationId, membershipId }, - }); + const input = { organizationId, profileId: userId }; + const responseData = await proboConnectApiRequest.call(this, query, { input }); return { json: responseData, diff --git a/packages/n8n-node/nodes/Probo/actions/member/invite.operation.ts b/packages/n8n-node/nodes/Probo/actions/user/updateMembership.operation.ts similarity index 57% rename from packages/n8n-node/nodes/Probo/actions/member/invite.operation.ts rename to packages/n8n-node/nodes/Probo/actions/user/updateMembership.operation.ts index bc84bd0c5..9281c6864 100644 --- a/packages/n8n-node/nodes/Probo/actions/member/invite.operation.ts +++ b/packages/n8n-node/nodes/Probo/actions/user/updateMembership.operation.ts @@ -16,8 +16,8 @@ export const description: INodeProperties[] = [ type: 'string', displayOptions: { show: { - resource: ['member'], - operation: ['invite'], + resource: ['user'], + operation: ['updateMembership'], }, }, default: '', @@ -25,32 +25,17 @@ export const description: INodeProperties[] = [ required: true, }, { - displayName: 'Email', - name: 'email', + displayName: 'Membership ID', + name: 'membershipId', type: 'string', displayOptions: { show: { - resource: ['member'], - operation: ['invite'], + resource: ['user'], + operation: ['updateMembership'], }, }, default: '', - placeholder: 'name@email.com', - description: 'Email address of the person to invite', - required: true, - }, - { - displayName: 'Full Name', - name: 'fullName', - type: 'string', - displayOptions: { - show: { - resource: ['member'], - operation: ['invite'], - }, - }, - default: '', - description: 'Full name of the person to invite', + description: 'The ID of the membership to update', required: true, }, { @@ -59,13 +44,13 @@ export const description: INodeProperties[] = [ type: 'options', displayOptions: { show: { - resource: ['member'], - operation: ['invite'], + resource: ['user'], + operation: ['updateMembership'], }, }, options: roleOptions, default: 'EMPLOYEE', - description: 'Role to assign to the member', + description: 'New role for the membership', required: true, }, ]; @@ -75,35 +60,22 @@ export async function execute( itemIndex: number, ): Promise { const organizationId = this.getNodeParameter('organizationId', itemIndex) as string; - const email = this.getNodeParameter('email', itemIndex) as string; - const fullName = this.getNodeParameter('fullName', itemIndex) as string; + const membershipId = this.getNodeParameter('membershipId', itemIndex) as string; const role = this.getNodeParameter('role', itemIndex) as string; const query = ` - mutation InviteMember($input: InviteMemberInput!) { - inviteMember(input: $input) { - invitationEdge { - node { - id - email - fullName - role - expiresAt - status - createdAt - } + mutation UpdateMembership($input: UpdateMembershipInput!) { + updateMembership(input: $input) { + membership { + id + role + createdAt } } } `; - const input = { - organizationId, - email, - fullName, - role, - }; - + const input = { organizationId, membershipId, role }; const responseData = await proboConnectApiRequest.call(this, query, { input }); return { diff --git a/packages/n8n-node/nodes/Probo/actions/user/updateUser.operation.ts b/packages/n8n-node/nodes/Probo/actions/user/updateUser.operation.ts new file mode 100644 index 000000000..11c83a6a0 --- /dev/null +++ b/packages/n8n-node/nodes/Probo/actions/user/updateUser.operation.ts @@ -0,0 +1,167 @@ +import type { + INodeProperties, + IExecuteFunctions, + INodeExecutionData, + IDataObject, +} from 'n8n-workflow'; +import { proboConnectApiRequest } from '../../GenericFunctions'; + +const kindOptions = [ + { name: 'Employee', value: 'EMPLOYEE' }, + { name: 'Contractor', value: 'CONTRACTOR' }, + { name: 'Service Account', value: 'SERVICE_ACCOUNT' }, +]; + +export const description: INodeProperties[] = [ + { + displayName: 'User ID', + name: 'userId', + type: 'string', + displayOptions: { + show: { + resource: ['user'], + operation: ['updateUser'], + }, + }, + default: '', + description: 'The ID of the user (profile) to update', + required: true, + }, + { + displayName: 'Full Name', + name: 'fullName', + type: 'string', + displayOptions: { + show: { + resource: ['user'], + operation: ['updateUser'], + }, + }, + default: '', + description: 'Full name of the user', + required: true, + }, + { + displayName: 'Kind', + name: 'kind', + type: 'options', + displayOptions: { + show: { + resource: ['user'], + operation: ['updateUser'], + }, + }, + options: kindOptions, + default: 'EMPLOYEE', + description: 'User kind', + required: true, + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: ['user'], + operation: ['updateUser'], + }, + }, + options: [ + { + displayName: 'Additional Email Addresses', + name: 'additionalEmailAddresses', + type: 'string', + default: '', + description: 'Comma-separated additional email addresses', + }, + { + displayName: 'Position', + name: 'position', + type: 'string', + default: '', + description: 'Job or role position', + }, + { + displayName: 'Contract Start Date', + name: 'contractStartDate', + type: 'string', + default: '', + description: 'Contract start date (ISO 8601)', + }, + { + displayName: 'Contract End Date', + name: 'contractEndDate', + type: 'string', + default: '', + description: 'Contract end date (ISO 8601)', + }, + ], + }, +]; + +export async function execute( + this: IExecuteFunctions, + itemIndex: number, +): Promise { + const userId = this.getNodeParameter('userId', itemIndex) as string; + const fullName = this.getNodeParameter('fullName', itemIndex) as string; + const kind = this.getNodeParameter('kind', itemIndex) as string; + const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as { + additionalEmailAddresses?: string; + position?: string; + contractStartDate?: string; + contractEndDate?: string; + }; + + const input: IDataObject = { + id: userId, + fullName, + kind, + }; + if (additionalFields.additionalEmailAddresses !== undefined) { + input.additionalEmailAddresses = additionalFields.additionalEmailAddresses + ? (additionalFields.additionalEmailAddresses as string) + .split(',') + .map((e: string) => e.trim()) + .filter(Boolean) + : []; + } + if (additionalFields.position) { + input.position = additionalFields.position; + } + if (additionalFields.contractStartDate) { + input.contractStartDate = additionalFields.contractStartDate; + } + if (additionalFields.contractEndDate) { + input.contractEndDate = additionalFields.contractEndDate; + } + + const query = ` + mutation UpdateUser($input: UpdateUserInput!) { + updateUser(input: $input) { + profile { + id + fullName + emailAddress + kind + position + contractStartDate + contractEndDate + createdAt + updatedAt + organization { id name } + membership { id role createdAt } + } + } + } + `; + + const responseData = await proboConnectApiRequest.call(this, query, { input }); + + return { + json: responseData, + pairedItem: { item: itemIndex }, + }; +}