mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
Modified temporaryPassword and filters for User, and 'options' to additionalFields' for Group
This commit is contained in:
parent
abdd1521c0
commit
2d5eb7ce24
|
@ -14,13 +14,27 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { ApplicationError, jsonParse, NodeApiError, NodeOperationError } from 'n8n-workflow';
|
import { ApplicationError, jsonParse, NodeApiError, NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
export async function presendTest(
|
type UserPool = {
|
||||||
this: IExecuteSingleFunctions,
|
Arn: string;
|
||||||
requestOptions: IHttpRequestOptions,
|
CreationDate: number;
|
||||||
): Promise<IHttpRequestOptions> {
|
DeletionProtection: string;
|
||||||
console.log('requestOptions', requestOptions);
|
Domain: string;
|
||||||
return requestOptions;
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper function which stringifies the body before sending the request.
|
* Helper function which stringifies the body before sending the request.
|
||||||
|
@ -36,33 +50,17 @@ export async function presendStringifyBody(
|
||||||
return requestOptions;
|
return requestOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function presendFilter(
|
export async function presendFilters(
|
||||||
this: IExecuteSingleFunctions,
|
this: IExecuteSingleFunctions,
|
||||||
requestOptions: IHttpRequestOptions,
|
requestOptions: IHttpRequestOptions,
|
||||||
): Promise<IHttpRequestOptions> {
|
): Promise<IHttpRequestOptions> {
|
||||||
const additionalFields = this.getNodeParameter('additionalFields', {}) as IDataObject;
|
const filters = this.getNodeParameter('filters') as IDataObject;
|
||||||
const filterAttribute = additionalFields.filters as string;
|
|
||||||
let filterType = additionalFields.filterType as string;
|
|
||||||
const filterValue = additionalFields.filterValue as string;
|
|
||||||
|
|
||||||
const hasAnyFilter = filterAttribute || filterType || filterValue;
|
if (filters.length === 0) return requestOptions;
|
||||||
|
|
||||||
if (!hasAnyFilter) {
|
const filterToSend = filters.filter as IDataObject;
|
||||||
return requestOptions;
|
const filterAttribute = filterToSend?.attribute as string;
|
||||||
}
|
const filterValue = filterToSend?.value as string;
|
||||||
|
|
||||||
if (hasAnyFilter && (!filterAttribute || !filterType || !filterValue)) {
|
|
||||||
throw new NodeOperationError(
|
|
||||||
this.getNode(),
|
|
||||||
'If filtering is used, please provide Filter Attribute, Filter Type, and Filter Value.',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const filterTypeMapping: { [key: string]: string } = {
|
|
||||||
exactMatch: '=',
|
|
||||||
startsWith: '^=',
|
|
||||||
};
|
|
||||||
filterType = filterTypeMapping[filterType] || filterType;
|
|
||||||
|
|
||||||
let body: IDataObject;
|
let body: IDataObject;
|
||||||
if (typeof requestOptions.body === 'string') {
|
if (typeof requestOptions.body === 'string') {
|
||||||
|
@ -72,12 +70,17 @@ export async function presendFilter(
|
||||||
throw new NodeOperationError(this.getNode(), 'Failed to parse requestOptions body');
|
throw new NodeOperationError(this.getNode(), 'Failed to parse requestOptions body');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
body = requestOptions.body as IDataObject;
|
body = (requestOptions.body as IDataObject) || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
let filter = '';
|
||||||
|
if (filterAttribute && filterValue) {
|
||||||
|
filter = `"${filterAttribute}"^="${filterValue}"`;
|
||||||
}
|
}
|
||||||
|
|
||||||
requestOptions.body = JSON.stringify({
|
requestOptions.body = JSON.stringify({
|
||||||
...body,
|
...body,
|
||||||
Filter: `${filterAttribute} ${filterType} "${filterValue}"`,
|
Filter: filter,
|
||||||
});
|
});
|
||||||
|
|
||||||
return requestOptions;
|
return requestOptions;
|
||||||
|
@ -121,7 +124,6 @@ export async function presendVerifyPath(
|
||||||
return requestOptions;
|
return requestOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function to process attributes in UserAttributes */
|
|
||||||
export async function processAttributes(
|
export async function processAttributes(
|
||||||
this: IExecuteSingleFunctions,
|
this: IExecuteSingleFunctions,
|
||||||
requestOptions: IHttpRequestOptions,
|
requestOptions: IHttpRequestOptions,
|
||||||
|
@ -156,7 +158,6 @@ export async function processAttributes(
|
||||||
return requestOptions;
|
return requestOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function to handle pagination */
|
|
||||||
const possibleRootProperties = ['Users', 'Groups'];
|
const possibleRootProperties = ['Users', 'Groups'];
|
||||||
export async function handlePagination(
|
export async function handlePagination(
|
||||||
this: IExecutePaginationFunctions,
|
this: IExecutePaginationFunctions,
|
||||||
|
@ -207,7 +208,6 @@ export async function handlePagination(
|
||||||
return aggregatedResult.map((item) => ({ json: item }));
|
return aggregatedResult.map((item) => ({ json: item }));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper functions to handle errors */
|
|
||||||
export async function handleErrorPostReceive(
|
export async function handleErrorPostReceive(
|
||||||
this: IExecuteSingleFunctions,
|
this: IExecuteSingleFunctions,
|
||||||
data: INodeExecutionData[],
|
data: INodeExecutionData[],
|
||||||
|
@ -337,7 +337,6 @@ export async function handleErrorPostReceive(
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function used in listSearch methods */
|
|
||||||
export async function awsRequest(
|
export async function awsRequest(
|
||||||
this: ILoadOptionsFunctions | IPollFunctions | IExecuteSingleFunctions,
|
this: ILoadOptionsFunctions | IPollFunctions | IExecuteSingleFunctions,
|
||||||
opts: IHttpRequestOptions,
|
opts: IHttpRequestOptions,
|
||||||
|
@ -542,36 +541,7 @@ export async function searchGroups(
|
||||||
return { results, paginationToken: responseData.NextToken };
|
return { results, paginationToken: responseData.NextToken };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function simplifyData(
|
export function mapUserAttributes(userAttributes: Array<{ Name: string; Value: string }>): {
|
||||||
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;
|
[key: string]: string;
|
||||||
} {
|
} {
|
||||||
return userAttributes?.reduce(
|
return userAttributes?.reduce(
|
||||||
|
@ -585,6 +555,13 @@ export async function simplifyData(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function simplifyData(
|
||||||
|
this: IExecuteSingleFunctions,
|
||||||
|
items: INodeExecutionData[],
|
||||||
|
response: IN8nHttpFullResponse,
|
||||||
|
): Promise<INodeExecutionData[]> {
|
||||||
|
const simple = this.getNodeParameter('simple') as boolean;
|
||||||
|
|
||||||
if (!simple) {
|
if (!simple) {
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
@ -643,12 +620,12 @@ export async function simplifyData(
|
||||||
users.forEach((user) => {
|
users.forEach((user) => {
|
||||||
const userAttributes = user.Attributes ? mapUserAttributes(user.Attributes) : {};
|
const userAttributes = user.Attributes ? mapUserAttributes(user.Attributes) : {};
|
||||||
processedUsers.push({
|
processedUsers.push({
|
||||||
Enabled: userData.Enabled,
|
Enabled: user.Enabled,
|
||||||
...Object.fromEntries(Object.entries(userAttributes).slice(0, 6)),
|
...Object.fromEntries(Object.entries(userAttributes).slice(0, 6)),
|
||||||
UserCreateDate: userData.UserCreateDate,
|
UserCreateDate: user.UserCreateDate,
|
||||||
UserLastModifiedDate: userData.UserLastModifiedDate,
|
UserLastModifiedDate: user.UserLastModifiedDate,
|
||||||
UserStatus: userData.UserStatus,
|
UserStatus: user.UserStatus,
|
||||||
Username: userData.Username,
|
Username: user.Username,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
|
@ -793,31 +770,3 @@ export async function processUsersForGroups(
|
||||||
json: { ...item.json, Groups: processedGroups },
|
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,7 +34,15 @@ export const groupOperations: INodeProperties[] = [
|
||||||
ignoreHttpStatusErrors: true,
|
ignoreHttpStatusErrors: true,
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
postReceive: [handleErrorPostReceive],
|
postReceive: [
|
||||||
|
handleErrorPostReceive,
|
||||||
|
{
|
||||||
|
type: 'rootProperty',
|
||||||
|
properties: {
|
||||||
|
property: 'Group',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
action: 'Create group',
|
action: 'Create group',
|
||||||
|
@ -215,8 +223,8 @@ const createFields: INodeProperties[] = [
|
||||||
validateType: 'string',
|
validateType: 'string',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Options',
|
displayName: 'Additional Fields',
|
||||||
name: 'options',
|
name: 'additionalFields',
|
||||||
default: {},
|
default: {},
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import type { INodeProperties } from 'n8n-workflow';
|
import type { INodeProperties } from 'n8n-workflow';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
fetchUserPoolConfig,
|
|
||||||
handleErrorPostReceive,
|
handleErrorPostReceive,
|
||||||
handlePagination,
|
handlePagination,
|
||||||
presendFilter,
|
presendFilters,
|
||||||
presendTest,
|
|
||||||
processAttributes,
|
processAttributes,
|
||||||
simplifyData,
|
simplifyData,
|
||||||
} from '../GenericFunctions';
|
} from '../GenericFunctions';
|
||||||
|
@ -55,9 +53,6 @@ export const userOperations: INodeProperties[] = [
|
||||||
description: 'Create a new user',
|
description: 'Create a new user',
|
||||||
action: 'Create user',
|
action: 'Create user',
|
||||||
routing: {
|
routing: {
|
||||||
send: {
|
|
||||||
preSend: [presendTest, fetchUserPoolConfig],
|
|
||||||
},
|
|
||||||
request: {
|
request: {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -121,7 +116,7 @@ export const userOperations: INodeProperties[] = [
|
||||||
routing: {
|
routing: {
|
||||||
send: {
|
send: {
|
||||||
paginate: true,
|
paginate: true,
|
||||||
preSend: [presendFilter],
|
preSend: [presendFilters],
|
||||||
},
|
},
|
||||||
operations: { pagination: handlePagination },
|
operations: { pagination: handlePagination },
|
||||||
request: {
|
request: {
|
||||||
|
@ -173,7 +168,6 @@ export const userOperations: INodeProperties[] = [
|
||||||
description: 'Update a user',
|
description: 'Update a user',
|
||||||
action: 'Update user',
|
action: 'Update user',
|
||||||
routing: {
|
routing: {
|
||||||
send: { preSend: [presendTest] },
|
|
||||||
request: {
|
request: {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -395,39 +389,11 @@ const createFields: INodeProperties[] = [
|
||||||
{
|
{
|
||||||
displayName: 'Temporary Password',
|
displayName: 'Temporary Password',
|
||||||
name: 'temporaryPasswordOptions',
|
name: 'temporaryPasswordOptions',
|
||||||
type: 'options',
|
|
||||||
default: 'generatePassword',
|
|
||||||
description: 'Choose to set a password manually or one will be automatically generated',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
name: 'Set a Password',
|
|
||||||
value: 'setPassword',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Generate a Password',
|
|
||||||
value: 'generatePassword',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
routing: {
|
|
||||||
send: {
|
|
||||||
property: 'TemporaryPassword',
|
|
||||||
type: 'body',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Password',
|
|
||||||
name: 'password',
|
|
||||||
type: 'string',
|
type: 'string',
|
||||||
typeOptions: { password: true },
|
typeOptions: { password: true },
|
||||||
default: '',
|
default: '',
|
||||||
placeholder: 'Enter a temporary password',
|
description:
|
||||||
description: "The user's temporary password",
|
"The user's temporary password that will be valid only once. If not set, Amazon Cognito will automatically generate one for you.",
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
temporaryPasswordOptions: ['setPassword'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
routing: {
|
routing: {
|
||||||
send: {
|
send: {
|
||||||
property: 'TemporaryPassword',
|
property: 'TemporaryPassword',
|
||||||
|
@ -641,11 +607,11 @@ const getAllFields: INodeProperties[] = [
|
||||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Additional Fields',
|
displayName: 'Filters',
|
||||||
name: 'additionalFields',
|
name: 'filters',
|
||||||
type: 'collection',
|
type: 'fixedCollection',
|
||||||
placeholder: 'Add Field',
|
placeholder: 'Add Filter',
|
||||||
default: {},
|
default: [],
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
resource: ['user'],
|
resource: ['user'],
|
||||||
|
@ -654,11 +620,14 @@ const getAllFields: INodeProperties[] = [
|
||||||
},
|
},
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
displayName: 'Filters',
|
displayName: 'Filter',
|
||||||
name: 'filters',
|
name: 'filter',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
displayName: 'Attribute',
|
||||||
|
name: 'attribute',
|
||||||
type: 'options',
|
type: 'options',
|
||||||
default: 'username',
|
default: 'email',
|
||||||
hint: 'Make sure to select an attribute, type, and provide a value before submitting.',
|
|
||||||
description: 'The attribute to search for',
|
description: 'The attribute to search for',
|
||||||
options: [
|
options: [
|
||||||
{ name: 'Cognito User Status', value: 'cognito:user_status' },
|
{ name: 'Cognito User Status', value: 'cognito:user_status' },
|
||||||
|
@ -674,25 +643,16 @@ const getAllFields: INodeProperties[] = [
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Filter Type',
|
displayName: 'Value',
|
||||||
name: 'filterType',
|
name: 'value',
|
||||||
type: 'options',
|
|
||||||
default: 'exactMatch',
|
|
||||||
description: 'The matching strategy of the filter',
|
|
||||||
options: [
|
|
||||||
{ name: 'Exact Match', value: 'exactMatch' },
|
|
||||||
{ name: 'Starts With', value: 'startsWith' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Filter Value',
|
|
||||||
name: 'filterValue',
|
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
description: 'The value of the attribute to search for',
|
description: 'The value of the attribute to search for',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const deleteFields: INodeProperties[] = [
|
const deleteFields: INodeProperties[] = [
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import type { INodeProperties } from 'n8n-workflow';
|
import type { INodeProperties } from 'n8n-workflow';
|
||||||
import { presendTest, simplifyData } from '../GenericFunctions';
|
|
||||||
|
import { simplifyData } from '../GenericFunctions';
|
||||||
|
|
||||||
export const userPoolOperations: INodeProperties[] = [
|
export const userPoolOperations: INodeProperties[] = [
|
||||||
{
|
{
|
||||||
|
@ -14,9 +15,6 @@ export const userPoolOperations: INodeProperties[] = [
|
||||||
value: 'get',
|
value: 'get',
|
||||||
action: 'Describe the configuration of a user pool',
|
action: 'Describe the configuration of a user pool',
|
||||||
routing: {
|
routing: {
|
||||||
send: {
|
|
||||||
preSend: [presendTest],
|
|
||||||
},
|
|
||||||
request: {
|
request: {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
Loading…
Reference in a new issue