mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
Fixed some issues after feedback
This commit is contained in:
parent
f3bcf18ce5
commit
abdd1521c0
|
@ -14,6 +14,14 @@ import type {
|
|||
} from 'n8n-workflow';
|
||||
import { ApplicationError, jsonParse, NodeApiError, NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
export async function presendTest(
|
||||
this: IExecuteSingleFunctions,
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IHttpRequestOptions> {
|
||||
console.log('requestOptions', requestOptions);
|
||||
return requestOptions;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function which stringifies the body before sending the request.
|
||||
* It is added to the routing property in the "resource" parameter thus for all requests.
|
||||
|
@ -33,14 +41,20 @@ export async function presendFilter(
|
|||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IHttpRequestOptions> {
|
||||
const additionalFields = this.getNodeParameter('additionalFields', {}) as IDataObject;
|
||||
const filterAttribute = additionalFields.filterAttribute as string;
|
||||
const filterAttribute = additionalFields.filters as string;
|
||||
let filterType = additionalFields.filterType as string;
|
||||
const filterValue = additionalFields.filterValue as string;
|
||||
|
||||
if (!filterAttribute || !filterType || !filterValue) {
|
||||
const hasAnyFilter = filterAttribute || filterType || filterValue;
|
||||
|
||||
if (!hasAnyFilter) {
|
||||
return requestOptions;
|
||||
}
|
||||
|
||||
if (hasAnyFilter && (!filterAttribute || !filterType || !filterValue)) {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'Please provide Filter Attribute, Filter Type, and Filter Value to use filtering.',
|
||||
'If filtering is used, please provide Filter Attribute, Filter Type, and Filter Value.',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -69,25 +83,25 @@ export async function presendFilter(
|
|||
return requestOptions;
|
||||
}
|
||||
|
||||
export async function presendOptions(
|
||||
export async function presendAdditionalFields(
|
||||
this: IExecuteSingleFunctions,
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IHttpRequestOptions> {
|
||||
const options = this.getNodeParameter('options', {}) as IDataObject;
|
||||
const additionalFields = this.getNodeParameter('additionalFields', {}) as IDataObject;
|
||||
|
||||
const hasOptions = options.Description || options.Precedence || options.Path || options.RoleArn;
|
||||
const hasOptions = Object.keys(additionalFields).length > 0;
|
||||
|
||||
if (!hasOptions) {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
'At least one of the options (Description, Precedence, Path, or RoleArn) must be provided to update the group.',
|
||||
'At least one of the additional fields must be provided to update the group.',
|
||||
);
|
||||
}
|
||||
|
||||
return requestOptions;
|
||||
}
|
||||
|
||||
export async function presendPath(
|
||||
export async function presendVerifyPath(
|
||||
this: IExecuteSingleFunctions,
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IHttpRequestOptions> {
|
||||
|
@ -325,7 +339,7 @@ export async function handleErrorPostReceive(
|
|||
|
||||
/* Helper function used in listSearch methods */
|
||||
export async function awsRequest(
|
||||
this: ILoadOptionsFunctions | IPollFunctions,
|
||||
this: ILoadOptionsFunctions | IPollFunctions | IExecuteSingleFunctions,
|
||||
opts: IHttpRequestOptions,
|
||||
): Promise<IDataObject> {
|
||||
const region = (await this.getCredentials('aws')).region as string;
|
||||
|
@ -376,7 +390,6 @@ export async function awsRequest(
|
|||
}
|
||||
}
|
||||
|
||||
/* listSearch methods */
|
||||
export async function searchUserPools(
|
||||
this: ILoadOptionsFunctions,
|
||||
filter?: string,
|
||||
|
@ -448,7 +461,6 @@ export async function searchUsers(
|
|||
const users = responseData.Users as IDataObject[] | undefined;
|
||||
|
||||
if (!users) {
|
||||
console.warn('No users found in the response');
|
||||
return { results: [] };
|
||||
}
|
||||
|
||||
|
@ -529,3 +541,283 @@ export async function searchGroups(
|
|||
|
||||
return { results, paginationToken: responseData.NextToken };
|
||||
}
|
||||
|
||||
export async function simplifyData(
|
||||
this: IExecuteSingleFunctions,
|
||||
items: INodeExecutionData[],
|
||||
response: IN8nHttpFullResponse,
|
||||
): Promise<INodeExecutionData[]> {
|
||||
const simple = this.getNodeParameter('simple') as boolean;
|
||||
|
||||
type UserPool = {
|
||||
Arn: string;
|
||||
CreationDate: number;
|
||||
DeletionProtection: string;
|
||||
Domain: string;
|
||||
EstimatedNumberOfUsers: number;
|
||||
Id: string;
|
||||
LastModifiedDate: number;
|
||||
MfaConfiguration: string;
|
||||
Name: string;
|
||||
};
|
||||
|
||||
type User = {
|
||||
Enabled: boolean;
|
||||
UserAttributes?: Array<{ Name: string; Value: string }>;
|
||||
Attributes?: Array<{ Name: string; Value: string }>;
|
||||
UserCreateDate: number;
|
||||
UserLastModifiedDate: number;
|
||||
UserStatus: string;
|
||||
Username: string;
|
||||
};
|
||||
|
||||
function mapUserAttributes(userAttributes: Array<{ Name: string; Value: string }>): {
|
||||
[key: string]: string;
|
||||
} {
|
||||
return userAttributes?.reduce(
|
||||
(acc, { Name, Value }) => {
|
||||
if (Name !== 'sub') {
|
||||
acc[Name] = Value;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{} as { [key: string]: string },
|
||||
);
|
||||
}
|
||||
|
||||
if (!simple) {
|
||||
return items;
|
||||
}
|
||||
|
||||
const resource = this.getNodeParameter('resource');
|
||||
const operation = this.getNodeParameter('operation');
|
||||
|
||||
const simplifiedItems = items
|
||||
.map((item) => {
|
||||
const data = item.json?.UserPool as UserPool | undefined;
|
||||
const userData = item.json as User | undefined;
|
||||
const users = item.json?.Users as User[] | undefined;
|
||||
|
||||
switch (resource) {
|
||||
case 'userPool':
|
||||
if (data) {
|
||||
return {
|
||||
json: {
|
||||
UserPool: {
|
||||
Arn: data.Arn,
|
||||
CreationDate: data.CreationDate,
|
||||
DeletionProtection: data.DeletionProtection,
|
||||
Domain: data.Domain,
|
||||
EstimatedNumberOfUsers: data.EstimatedNumberOfUsers,
|
||||
Id: data.Id,
|
||||
LastModifiedDate: data.LastModifiedDate,
|
||||
MfaConfiguration: data.MfaConfiguration,
|
||||
Name: data.Name,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
case 'user':
|
||||
if (userData) {
|
||||
if (operation === 'get') {
|
||||
const userAttributes = userData.UserAttributes
|
||||
? mapUserAttributes(userData.UserAttributes)
|
||||
: {};
|
||||
return {
|
||||
json: {
|
||||
User: {
|
||||
Enabled: userData.Enabled,
|
||||
...Object.fromEntries(Object.entries(userAttributes).slice(0, 6)),
|
||||
UserCreateDate: userData.UserCreateDate,
|
||||
UserLastModifiedDate: userData.UserLastModifiedDate,
|
||||
UserStatus: userData.UserStatus,
|
||||
Username: userData.Username,
|
||||
},
|
||||
},
|
||||
};
|
||||
} else if (operation === 'getAll') {
|
||||
if (users && Array.isArray(users)) {
|
||||
const processedUsers: User[] = [];
|
||||
users.forEach((user) => {
|
||||
const userAttributes = user.Attributes ? mapUserAttributes(user.Attributes) : {};
|
||||
processedUsers.push({
|
||||
Enabled: userData.Enabled,
|
||||
...Object.fromEntries(Object.entries(userAttributes).slice(0, 6)),
|
||||
UserCreateDate: userData.UserCreateDate,
|
||||
UserLastModifiedDate: userData.UserLastModifiedDate,
|
||||
UserStatus: userData.UserStatus,
|
||||
Username: userData.Username,
|
||||
});
|
||||
});
|
||||
return {
|
||||
json: {
|
||||
Users: processedUsers,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
})
|
||||
.filter((item) => item !== undefined)
|
||||
.flat();
|
||||
|
||||
return simplifiedItems;
|
||||
}
|
||||
|
||||
export async function listUsersInGroup(
|
||||
this: IExecuteSingleFunctions,
|
||||
groupName: string,
|
||||
userPoolId: string,
|
||||
): Promise<IDataObject> {
|
||||
if (!userPoolId) {
|
||||
throw new ApplicationError('User Pool ID is required');
|
||||
}
|
||||
|
||||
const opts: IHttpRequestOptions = {
|
||||
url: '',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Amz-Target': 'AWSCognitoIdentityProviderService.ListUsersInGroup',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
UserPoolId: userPoolId,
|
||||
GroupName: groupName,
|
||||
MaxResults: 60,
|
||||
}),
|
||||
};
|
||||
|
||||
const responseData: IDataObject = await awsRequest.call(this, opts);
|
||||
|
||||
const users = responseData.Users as IDataObject[] | undefined;
|
||||
|
||||
if (!users) {
|
||||
return { results: [] };
|
||||
}
|
||||
|
||||
const results: INodeListSearchItems[] = users
|
||||
.map((user) => {
|
||||
const attributes = user.Attributes as Array<{ Name: string; Value: string }> | undefined;
|
||||
|
||||
const email = attributes?.find((attr) => attr.Name === 'email')?.Value;
|
||||
const sub = attributes?.find((attr) => attr.Name === 'sub')?.Value;
|
||||
const username = user.Username as string;
|
||||
|
||||
const name = email || sub || username;
|
||||
const value = username;
|
||||
|
||||
return { name, value };
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
|
||||
});
|
||||
|
||||
return { results, paginationToken: responseData.NextToken as string | undefined };
|
||||
}
|
||||
|
||||
export async function getUsersForGroup(
|
||||
this: IExecuteSingleFunctions,
|
||||
groupName: string,
|
||||
userPoolId: string,
|
||||
): Promise<IDataObject[]> {
|
||||
const users = await listUsersInGroup.call(this, groupName, userPoolId);
|
||||
|
||||
if (users && users.results && Array.isArray(users.results) && users.results.length > 0) {
|
||||
return users.results as IDataObject[];
|
||||
}
|
||||
|
||||
return [] as IDataObject[];
|
||||
}
|
||||
|
||||
export async function processUsersForGroups(
|
||||
this: IExecuteSingleFunctions,
|
||||
items: INodeExecutionData[],
|
||||
response: IN8nHttpFullResponse,
|
||||
): Promise<INodeExecutionData[]> {
|
||||
const userPoolIdRaw = this.getNodeParameter('userPoolId') as IDataObject;
|
||||
const userPoolId = userPoolIdRaw.value as string;
|
||||
const include = this.getNodeParameter('includeUsers', 0) as boolean;
|
||||
|
||||
if (!include) {
|
||||
return items;
|
||||
}
|
||||
|
||||
const processedGroups: IDataObject[] = [];
|
||||
|
||||
if (response.body && typeof response.body === 'object') {
|
||||
if ('Group' in response.body) {
|
||||
const group = (response.body as { Group: IDataObject }).Group;
|
||||
const usersResponse = await getUsersForGroup.call(
|
||||
this,
|
||||
group.GroupName as string,
|
||||
userPoolId,
|
||||
);
|
||||
|
||||
if (usersResponse.length > 0) {
|
||||
return items.map((item) => ({
|
||||
json: { ...item.json, Users: usersResponse },
|
||||
}));
|
||||
} else {
|
||||
return items.map((item) => ({
|
||||
json: { ...item.json },
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
const groups = (response.body as { Groups: IDataObject[] }).Groups;
|
||||
|
||||
for (const group of groups) {
|
||||
const usersResponse = await getUsersForGroup.call(
|
||||
this,
|
||||
group.GroupName as string,
|
||||
userPoolId,
|
||||
);
|
||||
|
||||
if (usersResponse.length > 0) {
|
||||
processedGroups.push({
|
||||
...group,
|
||||
Users: usersResponse,
|
||||
});
|
||||
} else {
|
||||
processedGroups.push(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items.map((item) => ({
|
||||
json: { ...item.json, Groups: processedGroups },
|
||||
}));
|
||||
}
|
||||
|
||||
//Check if needed
|
||||
export async function fetchUserPoolConfig(
|
||||
this: IExecuteSingleFunctions,
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IHttpRequestOptions> {
|
||||
const userPoolIdRaw = this.getNodeParameter('userPoolId') as IDataObject;
|
||||
const userPoolId = userPoolIdRaw.value as string;
|
||||
|
||||
if (!userPoolId) {
|
||||
throw new ApplicationError('User Pool ID is required');
|
||||
}
|
||||
|
||||
const opts: IHttpRequestOptions = {
|
||||
url: '',
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
UserPoolId: userPoolId,
|
||||
}),
|
||||
headers: {
|
||||
'X-Amz-Target': 'AWSCognitoIdentityProviderService.DescribeUserPool',
|
||||
},
|
||||
};
|
||||
|
||||
const responseData: IDataObject = await awsRequest.call(this, opts);
|
||||
|
||||
return requestOptions;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,9 @@ import type { INodeProperties } from 'n8n-workflow';
|
|||
import {
|
||||
handleErrorPostReceive,
|
||||
handlePagination,
|
||||
presendOptions,
|
||||
presendPath,
|
||||
presendAdditionalFields,
|
||||
presendVerifyPath,
|
||||
processUsersForGroups,
|
||||
} from '../GenericFunctions';
|
||||
|
||||
export const groupOperations: INodeProperties[] = [
|
||||
|
@ -77,7 +78,7 @@ export const groupOperations: INodeProperties[] = [
|
|||
ignoreHttpStatusErrors: true,
|
||||
},
|
||||
output: {
|
||||
postReceive: [handleErrorPostReceive],
|
||||
postReceive: [processUsersForGroups, handleErrorPostReceive],
|
||||
},
|
||||
},
|
||||
action: 'Get group',
|
||||
|
@ -101,7 +102,7 @@ export const groupOperations: INodeProperties[] = [
|
|||
ignoreHttpStatusErrors: true,
|
||||
},
|
||||
output: {
|
||||
postReceive: [handleErrorPostReceive],
|
||||
postReceive: [processUsersForGroups, handleErrorPostReceive],
|
||||
},
|
||||
},
|
||||
action: 'Get many groups',
|
||||
|
@ -112,7 +113,7 @@ export const groupOperations: INodeProperties[] = [
|
|||
description: 'Update an existing group',
|
||||
routing: {
|
||||
send: {
|
||||
preSend: [presendOptions],
|
||||
preSend: [presendAdditionalFields],
|
||||
},
|
||||
request: {
|
||||
method: 'POST',
|
||||
|
@ -264,7 +265,7 @@ const createFields: INodeProperties[] = [
|
|||
send: {
|
||||
property: 'Path',
|
||||
type: 'body',
|
||||
preSend: [presendPath],
|
||||
preSend: [presendVerifyPath],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -492,6 +493,19 @@ const getFields: INodeProperties[] = [
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Include User List',
|
||||
name: 'includeUsers',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['group'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to include a list of users in the group',
|
||||
},
|
||||
];
|
||||
|
||||
const getAllFields: INodeProperties[] = [
|
||||
|
@ -553,6 +567,19 @@ const getAllFields: INodeProperties[] = [
|
|||
displayOptions: { show: { resource: ['group'], operation: ['getAll'], returnAll: [false] } },
|
||||
routing: { send: { type: 'body', property: 'Limit' } },
|
||||
},
|
||||
{
|
||||
displayName: 'Include User List',
|
||||
name: 'includeUsers',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['group'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to include a list of users in the group',
|
||||
},
|
||||
];
|
||||
|
||||
const updateFields: INodeProperties[] = [
|
||||
|
@ -657,8 +684,8 @@ const updateFields: INodeProperties[] = [
|
|||
type: 'resourceLocator',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
|
@ -708,7 +735,7 @@ const updateFields: INodeProperties[] = [
|
|||
send: {
|
||||
property: 'Path',
|
||||
type: 'body',
|
||||
preSend: [presendPath],
|
||||
preSend: [presendVerifyPath],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
fetchUserPoolConfig,
|
||||
handleErrorPostReceive,
|
||||
handlePagination,
|
||||
presendFilter,
|
||||
presendTest,
|
||||
processAttributes,
|
||||
simplifyData,
|
||||
} from '../GenericFunctions';
|
||||
|
||||
export const userOperations: INodeProperties[] = [
|
||||
|
@ -52,6 +55,9 @@ export const userOperations: INodeProperties[] = [
|
|||
description: 'Create a new user',
|
||||
action: 'Create user',
|
||||
routing: {
|
||||
send: {
|
||||
preSend: [presendTest, fetchUserPoolConfig],
|
||||
},
|
||||
request: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
@ -104,7 +110,7 @@ export const userOperations: INodeProperties[] = [
|
|||
ignoreHttpStatusErrors: true,
|
||||
},
|
||||
output: {
|
||||
postReceive: [handleErrorPostReceive],
|
||||
postReceive: [simplifyData, handleErrorPostReceive],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -130,7 +136,7 @@ export const userOperations: INodeProperties[] = [
|
|||
ignoreHttpStatusErrors: true,
|
||||
},
|
||||
output: {
|
||||
postReceive: [handleErrorPostReceive],
|
||||
postReceive: [simplifyData, handleErrorPostReceive],
|
||||
},
|
||||
},
|
||||
action: 'Get many users',
|
||||
|
@ -167,6 +173,7 @@ export const userOperations: INodeProperties[] = [
|
|||
description: 'Update a user',
|
||||
action: 'Update user',
|
||||
routing: {
|
||||
send: { preSend: [presendTest] },
|
||||
request: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
@ -246,7 +253,7 @@ const createFields: INodeProperties[] = [
|
|||
displayName: 'User Name',
|
||||
name: 'Username',
|
||||
default: '',
|
||||
description: 'The username of the new user to create',
|
||||
description: 'The username of the new user to create. No whitespace is allowed.',
|
||||
placeholder: 'e.g. JohnSmith',
|
||||
displayOptions: {
|
||||
show: {
|
||||
|
@ -277,61 +284,51 @@ const createFields: INodeProperties[] = [
|
|||
},
|
||||
},
|
||||
options: [
|
||||
//doesn't work
|
||||
{
|
||||
displayName: 'Client Metadata',
|
||||
name: 'clientMetadata',
|
||||
displayName: 'User Attributes',
|
||||
name: 'UserAttributes',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Metadata',
|
||||
default: { metadata: [] },
|
||||
description: 'A map of custom key-value pairs for workflows triggered by this action',
|
||||
placeholder: 'Add Attribute',
|
||||
default: {
|
||||
attributes: [],
|
||||
},
|
||||
description: 'Attributes to add for the user',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Metadata',
|
||||
name: 'metadata',
|
||||
displayName: 'Attributes',
|
||||
name: 'attributes',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Key',
|
||||
name: 'key',
|
||||
displayName: 'Name',
|
||||
name: 'Name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The key of the metadata attribute',
|
||||
description: 'The name of the attribute (e.g., custom:deliverables)',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
name: 'Value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The value of the metadata attribute',
|
||||
description: 'The value of the attribute',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
routing: {
|
||||
send: {
|
||||
preSend: [processAttributes],
|
||||
type: 'body',
|
||||
property: 'ClientMetadata',
|
||||
property: 'UserAttributes',
|
||||
value:
|
||||
'={{ $value.metadata && $value.metadata.length > 0 ? Object.fromEntries($value.metadata.map(attribute => [attribute.Name, attribute.Value])) : {} }}',
|
||||
'={{ $value.attributes?.map(attribute => ({ Name: attribute.Name, Value: attribute.Value })) || [] }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Temporary Password',
|
||||
name: 'TemporaryPassword',
|
||||
default: '',
|
||||
description: "The user's temporary password",
|
||||
routing: {
|
||||
send: {
|
||||
property: 'TemporaryPassword',
|
||||
type: 'body',
|
||||
},
|
||||
},
|
||||
type: 'string',
|
||||
typeOptions: { password: true },
|
||||
},
|
||||
{
|
||||
displayName: 'Message Action',
|
||||
name: 'MessageAction',
|
||||
|
@ -396,88 +393,45 @@ const createFields: INodeProperties[] = [
|
|||
},
|
||||
},
|
||||
{
|
||||
displayName: 'User Attributes',
|
||||
name: 'UserAttributes',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Attribute',
|
||||
default: {
|
||||
attributes: [],
|
||||
},
|
||||
description: 'Attributes to add for the user',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
displayName: 'Temporary Password',
|
||||
name: 'temporaryPasswordOptions',
|
||||
type: 'options',
|
||||
default: 'generatePassword',
|
||||
description: 'Choose to set a password manually or one will be automatically generated',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Attributes',
|
||||
name: 'attributes',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Name',
|
||||
name: 'Name',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The name of the attribute (e.g., custom:deliverables)',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'Value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The value of the attribute',
|
||||
},
|
||||
],
|
||||
name: 'Set a Password',
|
||||
value: 'setPassword',
|
||||
},
|
||||
{
|
||||
name: 'Generate a Password',
|
||||
value: 'generatePassword',
|
||||
},
|
||||
],
|
||||
routing: {
|
||||
send: {
|
||||
preSend: [processAttributes],
|
||||
property: 'TemporaryPassword',
|
||||
type: 'body',
|
||||
property: 'UserAttributes',
|
||||
value:
|
||||
'={{ $value.attributes?.map(attribute => ({ Name: attribute.Name, Value: attribute.Value })) || [] }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Validation Data',
|
||||
name: 'ValidationData',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Attribute',
|
||||
default: {
|
||||
attributes: [],
|
||||
},
|
||||
description: 'Validation data to add for the user',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Data',
|
||||
name: 'data',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Key',
|
||||
name: 'Key',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The name of the data (e.g., custom:deliverables)',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'Value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The value of the data',
|
||||
},
|
||||
],
|
||||
displayName: 'Password',
|
||||
name: 'password',
|
||||
type: 'string',
|
||||
typeOptions: { password: true },
|
||||
default: '',
|
||||
placeholder: 'Enter a temporary password',
|
||||
description: "The user's temporary password",
|
||||
displayOptions: {
|
||||
show: {
|
||||
temporaryPasswordOptions: ['setPassword'],
|
||||
},
|
||||
],
|
||||
},
|
||||
routing: {
|
||||
send: {
|
||||
property: 'TemporaryPassword',
|
||||
type: 'body',
|
||||
property: 'ValidationData',
|
||||
value: '={{ $value.data?.map(data => ({ Name: data.Key, Value: data.Value })) || [] }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -586,6 +540,19 @@ const getFields: INodeProperties[] = [
|
|||
required: true,
|
||||
type: 'resourceLocator',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
];
|
||||
|
||||
const getAllFields: INodeProperties[] = [
|
||||
|
@ -660,48 +627,35 @@ const getAllFields: INodeProperties[] = [
|
|||
displayOptions: { show: { resource: ['user'], operation: ['getAll'], returnAll: [false] } },
|
||||
routing: { send: { type: 'body', property: 'Limit' } },
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: { show: { resource: ['user'], operation: ['getAll'] } },
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Attributes To Get',
|
||||
name: 'attributesToGet',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: { multipleValues: true },
|
||||
default: {},
|
||||
placeholder: 'Add Attribute',
|
||||
description: 'The attributes to return in the response',
|
||||
options: [
|
||||
{
|
||||
name: 'metadataValues',
|
||||
displayName: 'Metadata',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Attribute',
|
||||
name: 'attribute',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The attribute name to return',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
routing: {
|
||||
send: {
|
||||
type: 'body',
|
||||
property: 'AttributesToGet',
|
||||
value: '={{ $value.metadataValues.map(attribute => attribute.attribute) }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Filter Attribute',
|
||||
name: 'filterAttribute',
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'options',
|
||||
default: 'username',
|
||||
hint: 'Make sure to select an attribute, type, and provide a value before submitting.',
|
||||
|
@ -896,7 +850,7 @@ const updateFields: INodeProperties[] = [
|
|||
],
|
||||
},
|
||||
{
|
||||
displayName: 'User',
|
||||
displayName: 'User Name',
|
||||
name: 'Username',
|
||||
default: {
|
||||
mode: 'list',
|
||||
|
@ -988,6 +942,7 @@ const updateFields: INodeProperties[] = [
|
|||
],
|
||||
routing: {
|
||||
send: {
|
||||
preSend: [processAttributes],
|
||||
type: 'body',
|
||||
property: 'UserAttributes',
|
||||
value:
|
||||
|
@ -995,62 +950,6 @@ const updateFields: INodeProperties[] = [
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Client Metadata',
|
||||
name: 'clientMetadata',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Metadata Pair',
|
||||
default: { metadata: [] },
|
||||
description: 'A map of custom key-value pairs for workflows triggered by this action',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Metadata',
|
||||
name: 'metadata',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Key',
|
||||
name: 'key',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The key of the metadata attribute',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The value of the metadata attribute',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
routing: {
|
||||
send: {
|
||||
type: 'body',
|
||||
property: 'ClientMetadata',
|
||||
value:
|
||||
'={{ $value.metadata && $value.metadata.length > 0 ? Object.fromEntries($value.metadata.map(attribute => [attribute.Name, attribute.Value])) : {} }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const addToGroupFields: INodeProperties[] = [
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { INodeProperties } from 'n8n-workflow';
|
||||
import { presendTest, simplifyData } from '../GenericFunctions';
|
||||
|
||||
export const userPoolOperations: INodeProperties[] = [
|
||||
{
|
||||
|
@ -13,12 +14,26 @@ export const userPoolOperations: INodeProperties[] = [
|
|||
value: 'get',
|
||||
action: 'Describe the configuration of a user pool',
|
||||
routing: {
|
||||
send: {
|
||||
preSend: [presendTest],
|
||||
},
|
||||
request: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Amz-Target': 'AWSCognitoIdentityProviderService.DescribeUserPool',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
postReceive: [
|
||||
simplifyData,
|
||||
{
|
||||
type: 'rootProperty',
|
||||
properties: {
|
||||
property: 'UserPool',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -28,7 +43,7 @@ export const userPoolOperations: INodeProperties[] = [
|
|||
|
||||
export const userPoolFields: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'User Pool ID',
|
||||
displayName: 'User Pool',
|
||||
name: 'userPoolId',
|
||||
required: true,
|
||||
type: 'resourceLocator',
|
||||
|
@ -69,4 +84,17 @@ export const userPoolFields: INodeProperties[] = [
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['userPool'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
];
|
||||
|
|
Loading…
Reference in a new issue