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';
|
||||
import { ApplicationError, jsonParse, NodeApiError, NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
export async function presendTest(
|
||||
this: IExecuteSingleFunctions,
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IHttpRequestOptions> {
|
||||
console.log('requestOptions', requestOptions);
|
||||
return requestOptions;
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper function which stringifies the body before sending the request.
|
||||
|
@ -36,33 +50,17 @@ export async function presendStringifyBody(
|
|||
return requestOptions;
|
||||
}
|
||||
|
||||
export async function presendFilter(
|
||||
export async function presendFilters(
|
||||
this: IExecuteSingleFunctions,
|
||||
requestOptions: IHttpRequestOptions,
|
||||
): Promise<IHttpRequestOptions> {
|
||||
const additionalFields = this.getNodeParameter('additionalFields', {}) as IDataObject;
|
||||
const filterAttribute = additionalFields.filters as string;
|
||||
let filterType = additionalFields.filterType as string;
|
||||
const filterValue = additionalFields.filterValue as string;
|
||||
const filters = this.getNodeParameter('filters') as IDataObject;
|
||||
|
||||
const hasAnyFilter = filterAttribute || filterType || filterValue;
|
||||
if (filters.length === 0) return requestOptions;
|
||||
|
||||
if (!hasAnyFilter) {
|
||||
return requestOptions;
|
||||
}
|
||||
|
||||
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;
|
||||
const filterToSend = filters.filter as IDataObject;
|
||||
const filterAttribute = filterToSend?.attribute as string;
|
||||
const filterValue = filterToSend?.value as string;
|
||||
|
||||
let body: IDataObject;
|
||||
if (typeof requestOptions.body === 'string') {
|
||||
|
@ -72,12 +70,17 @@ export async function presendFilter(
|
|||
throw new NodeOperationError(this.getNode(), 'Failed to parse requestOptions body');
|
||||
}
|
||||
} else {
|
||||
body = requestOptions.body as IDataObject;
|
||||
body = (requestOptions.body as IDataObject) || {};
|
||||
}
|
||||
|
||||
let filter = '';
|
||||
if (filterAttribute && filterValue) {
|
||||
filter = `"${filterAttribute}"^="${filterValue}"`;
|
||||
}
|
||||
|
||||
requestOptions.body = JSON.stringify({
|
||||
...body,
|
||||
Filter: `${filterAttribute} ${filterType} "${filterValue}"`,
|
||||
Filter: filter,
|
||||
});
|
||||
|
||||
return requestOptions;
|
||||
|
@ -121,7 +124,6 @@ export async function presendVerifyPath(
|
|||
return requestOptions;
|
||||
}
|
||||
|
||||
/* Helper function to process attributes in UserAttributes */
|
||||
export async function processAttributes(
|
||||
this: IExecuteSingleFunctions,
|
||||
requestOptions: IHttpRequestOptions,
|
||||
|
@ -156,7 +158,6 @@ export async function processAttributes(
|
|||
return requestOptions;
|
||||
}
|
||||
|
||||
/* Helper function to handle pagination */
|
||||
const possibleRootProperties = ['Users', 'Groups'];
|
||||
export async function handlePagination(
|
||||
this: IExecutePaginationFunctions,
|
||||
|
@ -207,7 +208,6 @@ export async function handlePagination(
|
|||
return aggregatedResult.map((item) => ({ json: item }));
|
||||
}
|
||||
|
||||
/* Helper functions to handle errors */
|
||||
export async function handleErrorPostReceive(
|
||||
this: IExecuteSingleFunctions,
|
||||
data: INodeExecutionData[],
|
||||
|
@ -337,7 +337,6 @@ export async function handleErrorPostReceive(
|
|||
return data;
|
||||
}
|
||||
|
||||
/* Helper function used in listSearch methods */
|
||||
export async function awsRequest(
|
||||
this: ILoadOptionsFunctions | IPollFunctions | IExecuteSingleFunctions,
|
||||
opts: IHttpRequestOptions,
|
||||
|
@ -542,6 +541,20 @@ export async function searchGroups(
|
|||
return { results, paginationToken: responseData.NextToken };
|
||||
}
|
||||
|
||||
export 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 },
|
||||
);
|
||||
}
|
||||
|
||||
export async function simplifyData(
|
||||
this: IExecuteSingleFunctions,
|
||||
items: INodeExecutionData[],
|
||||
|
@ -549,42 +562,6 @@ export async function simplifyData(
|
|||
): 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;
|
||||
}
|
||||
|
@ -643,12 +620,12 @@ export async function simplifyData(
|
|||
users.forEach((user) => {
|
||||
const userAttributes = user.Attributes ? mapUserAttributes(user.Attributes) : {};
|
||||
processedUsers.push({
|
||||
Enabled: userData.Enabled,
|
||||
Enabled: user.Enabled,
|
||||
...Object.fromEntries(Object.entries(userAttributes).slice(0, 6)),
|
||||
UserCreateDate: userData.UserCreateDate,
|
||||
UserLastModifiedDate: userData.UserLastModifiedDate,
|
||||
UserStatus: userData.UserStatus,
|
||||
Username: userData.Username,
|
||||
UserCreateDate: user.UserCreateDate,
|
||||
UserLastModifiedDate: user.UserLastModifiedDate,
|
||||
UserStatus: user.UserStatus,
|
||||
Username: user.Username,
|
||||
});
|
||||
});
|
||||
return {
|
||||
|
@ -793,31 +770,3 @@ export async function processUsersForGroups(
|
|||
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,
|
||||
},
|
||||
output: {
|
||||
postReceive: [handleErrorPostReceive],
|
||||
postReceive: [
|
||||
handleErrorPostReceive,
|
||||
{
|
||||
type: 'rootProperty',
|
||||
properties: {
|
||||
property: 'Group',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
action: 'Create group',
|
||||
|
@ -215,8 +223,8 @@ const createFields: INodeProperties[] = [
|
|||
validateType: 'string',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
fetchUserPoolConfig,
|
||||
handleErrorPostReceive,
|
||||
handlePagination,
|
||||
presendFilter,
|
||||
presendTest,
|
||||
presendFilters,
|
||||
processAttributes,
|
||||
simplifyData,
|
||||
} from '../GenericFunctions';
|
||||
|
@ -55,9 +53,6 @@ export const userOperations: INodeProperties[] = [
|
|||
description: 'Create a new user',
|
||||
action: 'Create user',
|
||||
routing: {
|
||||
send: {
|
||||
preSend: [presendTest, fetchUserPoolConfig],
|
||||
},
|
||||
request: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
@ -121,7 +116,7 @@ export const userOperations: INodeProperties[] = [
|
|||
routing: {
|
||||
send: {
|
||||
paginate: true,
|
||||
preSend: [presendFilter],
|
||||
preSend: [presendFilters],
|
||||
},
|
||||
operations: { pagination: handlePagination },
|
||||
request: {
|
||||
|
@ -173,7 +168,6 @@ export const userOperations: INodeProperties[] = [
|
|||
description: 'Update a user',
|
||||
action: 'Update user',
|
||||
routing: {
|
||||
send: { preSend: [presendTest] },
|
||||
request: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
@ -395,39 +389,11 @@ const createFields: INodeProperties[] = [
|
|||
{
|
||||
displayName: 'Temporary Password',
|
||||
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',
|
||||
typeOptions: { password: true },
|
||||
default: '',
|
||||
placeholder: 'Enter a temporary password',
|
||||
description: "The user's temporary password",
|
||||
displayOptions: {
|
||||
show: {
|
||||
temporaryPasswordOptions: ['setPassword'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
"The user's temporary password that will be valid only once. If not set, Amazon Cognito will automatically generate one for you.",
|
||||
routing: {
|
||||
send: {
|
||||
property: 'TemporaryPassword',
|
||||
|
@ -641,11 +607,11 @@ const getAllFields: INodeProperties[] = [
|
|||
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: {},
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Filter',
|
||||
default: [],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
|
@ -654,43 +620,37 @@ const getAllFields: INodeProperties[] = [
|
|||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'options',
|
||||
default: 'username',
|
||||
hint: 'Make sure to select an attribute, type, and provide a value before submitting.',
|
||||
description: 'The attribute to search for',
|
||||
options: [
|
||||
{ name: 'Cognito User Status', value: 'cognito:user_status' },
|
||||
{ name: 'Email', value: 'email' },
|
||||
{ name: 'Family Name', value: 'family_name' },
|
||||
{ name: 'Given Name', value: 'given_name' },
|
||||
{ name: 'Name', value: 'name' },
|
||||
{ name: 'Phone Number', value: 'phone_number' },
|
||||
{ name: 'Preferred Username', value: 'preferred_username' },
|
||||
{ name: 'Status (Enabled)', value: 'status' },
|
||||
{ name: 'Sub', value: 'sub' },
|
||||
{ name: 'Username', value: 'username' },
|
||||
displayName: 'Filter',
|
||||
name: 'filter',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Attribute',
|
||||
name: 'attribute',
|
||||
type: 'options',
|
||||
default: 'email',
|
||||
description: 'The attribute to search for',
|
||||
options: [
|
||||
{ name: 'Cognito User Status', value: 'cognito:user_status' },
|
||||
{ name: 'Email', value: 'email' },
|
||||
{ name: 'Family Name', value: 'family_name' },
|
||||
{ name: 'Given Name', value: 'given_name' },
|
||||
{ name: 'Name', value: 'name' },
|
||||
{ name: 'Phone Number', value: 'phone_number' },
|
||||
{ name: 'Preferred Username', value: 'preferred_username' },
|
||||
{ name: 'Status (Enabled)', value: 'status' },
|
||||
{ name: 'Sub', value: 'sub' },
|
||||
{ name: 'Username', value: 'username' },
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The value of the attribute to search for',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Filter Type',
|
||||
name: 'filterType',
|
||||
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',
|
||||
default: '',
|
||||
description: 'The value of the attribute to search for',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import type { INodeProperties } from 'n8n-workflow';
|
||||
import { presendTest, simplifyData } from '../GenericFunctions';
|
||||
|
||||
import { simplifyData } from '../GenericFunctions';
|
||||
|
||||
export const userPoolOperations: INodeProperties[] = [
|
||||
{
|
||||
|
@ -14,9 +15,6 @@ export const userPoolOperations: INodeProperties[] = [
|
|||
value: 'get',
|
||||
action: 'Describe the configuration of a user pool',
|
||||
routing: {
|
||||
send: {
|
||||
preSend: [presendTest],
|
||||
},
|
||||
request: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
|
Loading…
Reference in a new issue