mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
feat(Google Workspace Admin Node): Google Admin Node Overhaul implementation (#12271)
Co-authored-by: knowa <github@libertyunion.org> Co-authored-by: Giulio Andreini <g.andreini@gmail.com>
This commit is contained in:
@@ -5,6 +5,8 @@ const scopes = [
|
|||||||
'https://www.googleapis.com/auth/admin.directory.user',
|
'https://www.googleapis.com/auth/admin.directory.user',
|
||||||
'https://www.googleapis.com/auth/admin.directory.domain.readonly',
|
'https://www.googleapis.com/auth/admin.directory.domain.readonly',
|
||||||
'https://www.googleapis.com/auth/admin.directory.userschema.readonly',
|
'https://www.googleapis.com/auth/admin.directory.userschema.readonly',
|
||||||
|
'https://www.googleapis.com/auth/admin.directory.device.chromeos',
|
||||||
|
'https://www.googleapis.com/auth/admin.directory.orgunit.readonly',
|
||||||
];
|
];
|
||||||
|
|
||||||
export class GSuiteAdminOAuth2Api implements ICredentialType {
|
export class GSuiteAdminOAuth2Api implements ICredentialType {
|
||||||
|
|||||||
@@ -0,0 +1,361 @@
|
|||||||
|
import type { INodeProperties } from 'n8n-workflow';
|
||||||
|
|
||||||
|
export const deviceOperations: INodeProperties[] = [
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
noDataExpression: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: ['device'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Get',
|
||||||
|
value: 'get',
|
||||||
|
description: 'Get a ChromeOS device',
|
||||||
|
action: 'Get ChromeOS device',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Get Many',
|
||||||
|
value: 'getAll',
|
||||||
|
description: 'Get many ChromeOS devices',
|
||||||
|
action: 'Get many ChromeOS devices',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Update',
|
||||||
|
value: 'update',
|
||||||
|
description: 'Update a ChromeOS device',
|
||||||
|
action: 'Update ChromeOS device',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Change Status',
|
||||||
|
value: 'changeStatus',
|
||||||
|
description: 'Change the status of a ChromeOS device',
|
||||||
|
action: 'Change status of ChromeOS device',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'get',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const deviceFields: INodeProperties[] = [
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* device */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Device',
|
||||||
|
name: 'deviceId',
|
||||||
|
type: 'resourceLocator',
|
||||||
|
required: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['get', 'update', 'changeStatus'],
|
||||||
|
resource: ['device'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
mode: 'list',
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
description: 'Select the device you want to retrieve',
|
||||||
|
modes: [
|
||||||
|
{
|
||||||
|
displayName: 'From List',
|
||||||
|
name: 'list',
|
||||||
|
type: 'list',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'searchDevices',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'By ID',
|
||||||
|
name: 'deviceId',
|
||||||
|
type: 'string',
|
||||||
|
hint: 'Enter the device id',
|
||||||
|
placeholder: 'e.g. 123e4567-e89b-12d3-a456-426614174000',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* device:get */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* device:getAll */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Return All',
|
||||||
|
name: 'returnAll',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: 'Whether to return all results or only up to a given limit',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['getAll'],
|
||||||
|
resource: ['device'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Limit',
|
||||||
|
name: 'limit',
|
||||||
|
type: 'number',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['getAll'],
|
||||||
|
resource: ['device'],
|
||||||
|
returnAll: [false],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 1,
|
||||||
|
maxValue: 500,
|
||||||
|
},
|
||||||
|
default: 100,
|
||||||
|
description: 'Max number of results to return',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Output',
|
||||||
|
name: 'projection',
|
||||||
|
type: 'options',
|
||||||
|
required: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Basic',
|
||||||
|
value: 'basic',
|
||||||
|
description: 'Do not include any custom fields for the user',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Full',
|
||||||
|
value: 'full',
|
||||||
|
description: 'Include all fields associated with this user',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['get', 'getAll'],
|
||||||
|
resource: ['device'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: 'basic',
|
||||||
|
description: 'What subset of fields to fetch for this device',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Include Children',
|
||||||
|
name: 'includeChildOrgunits',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description:
|
||||||
|
'Whether to include devices from organizational units below your specified organizational unit',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['getAll'],
|
||||||
|
resource: ['device'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Filter',
|
||||||
|
name: 'filter',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Filter',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['getAll'],
|
||||||
|
resource: ['device'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Organizational Unit Name or ID',
|
||||||
|
name: 'orgUnitPath',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getOrgUnits',
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
description:
|
||||||
|
'Specify the organizational unit name or ID. Choose from the list or use an expression. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Query',
|
||||||
|
name: 'query',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'e.g. name:contact* email:contact*',
|
||||||
|
default: '',
|
||||||
|
description: "Use Google's querying syntax to filter results",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Sort',
|
||||||
|
name: 'sort',
|
||||||
|
type: 'fixedCollection',
|
||||||
|
placeholder: 'Add Sort Rule',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['getAll'],
|
||||||
|
resource: ['device'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'sortRules',
|
||||||
|
displayName: 'Sort Rules',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
displayName: 'Order By',
|
||||||
|
name: 'orderBy',
|
||||||
|
type: 'options',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Annotated Location',
|
||||||
|
value: 'annotatedLocation',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Annotated User',
|
||||||
|
value: 'annotatedUser',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Last Sync',
|
||||||
|
value: 'lastSync',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Notes',
|
||||||
|
value: 'notes',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Serial Number',
|
||||||
|
value: 'serialNumber',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Status',
|
||||||
|
value: 'status',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: '',
|
||||||
|
description: 'Field to sort the results by',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Sort Order',
|
||||||
|
name: 'sortBy',
|
||||||
|
type: 'options',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Ascending',
|
||||||
|
value: 'ascending',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Descending',
|
||||||
|
value: 'descending',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: '',
|
||||||
|
description: 'Sort order direction',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
description: 'Define sorting rules for the results',
|
||||||
|
},
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* device:update */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Update Fields',
|
||||||
|
name: 'updateOptions',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Option',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['update'],
|
||||||
|
resource: ['device'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Move to Organizational Unit Name or ID',
|
||||||
|
name: 'orgUnitPath',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getOrgUnits',
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
description:
|
||||||
|
'A comma-separated list of schema names. All fields from these schemas are fetched. This should only be set when projection=custom. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Annotated User',
|
||||||
|
name: 'annotatedUser',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The annotated user of the device',
|
||||||
|
placeholder: 'e.g. help desk',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Annotated Location',
|
||||||
|
name: 'annotatedLocation',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The annotated location of the device',
|
||||||
|
placeholder: 'e.g. Mountain View help desk Chromebook',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Annotated Asset ID',
|
||||||
|
name: 'annotatedAssetId',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The annotated asset ID of a device',
|
||||||
|
placeholder: 'e.g. 1234567890',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Notes',
|
||||||
|
name: 'notes',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Add notes to a device',
|
||||||
|
placeholder: 'e.g. Loaned from support',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* device:changeStatus */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Status',
|
||||||
|
name: 'action',
|
||||||
|
type: 'options',
|
||||||
|
required: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Enabled',
|
||||||
|
value: 'reenable',
|
||||||
|
description: 'Re-enable a disabled chromebook',
|
||||||
|
action: 'Enable a device',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Disabled',
|
||||||
|
value: 'disable',
|
||||||
|
description: 'Disable a chromebook',
|
||||||
|
action: 'Disable a device',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['changeStatus'],
|
||||||
|
resource: ['device'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: 'reenable',
|
||||||
|
description: 'Set the status of a device',
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -9,16 +9,17 @@ import type {
|
|||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
|
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
|
import { deviceFields, deviceOperations } from './DeviceDescription';
|
||||||
import { googleApiRequest, googleApiRequestAllItems } from './GenericFunctions';
|
import { googleApiRequest, googleApiRequestAllItems } from './GenericFunctions';
|
||||||
import { groupFields, groupOperations } from './GroupDescripion';
|
import { groupFields, groupOperations } from './GroupDescripion';
|
||||||
|
import { searchDevices, searchGroups, searchUsers } from './SearchFunctions';
|
||||||
import { userFields, userOperations } from './UserDescription';
|
import { userFields, userOperations } from './UserDescription';
|
||||||
|
|
||||||
export class GSuiteAdmin implements INodeType {
|
export class GSuiteAdmin implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
displayName: 'Google Workspace Admin',
|
displayName: 'Google Workspace Admin',
|
||||||
name: 'gSuiteAdmin',
|
name: 'gSuiteAdmin',
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
|
icon: 'file:gSuiteAdmin.svg',
|
||||||
icon: 'file:google-workspace-admin.png',
|
|
||||||
group: ['input'],
|
group: ['input'],
|
||||||
version: 1,
|
version: 1,
|
||||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||||
@@ -42,6 +43,10 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
type: 'options',
|
type: 'options',
|
||||||
noDataExpression: true,
|
noDataExpression: true,
|
||||||
options: [
|
options: [
|
||||||
|
{
|
||||||
|
name: 'ChromeOS Device',
|
||||||
|
value: 'device',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Group',
|
name: 'Group',
|
||||||
value: 'group',
|
value: 'group',
|
||||||
@@ -53,6 +58,8 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
],
|
],
|
||||||
default: 'user',
|
default: 'user',
|
||||||
},
|
},
|
||||||
|
...deviceOperations,
|
||||||
|
...deviceFields,
|
||||||
...groupOperations,
|
...groupOperations,
|
||||||
...groupFields,
|
...groupFields,
|
||||||
...userOperations,
|
...userOperations,
|
||||||
@@ -62,16 +69,16 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
|
|
||||||
methods = {
|
methods = {
|
||||||
loadOptions: {
|
loadOptions: {
|
||||||
// Get all the domains to display them to user so that they can
|
|
||||||
// select them easily
|
|
||||||
async getDomains(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
async getDomains(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
const returnData: INodePropertyOptions[] = [];
|
const returnData: INodePropertyOptions[] = [];
|
||||||
const domains = await googleApiRequestAllItems.call(
|
const domains = (await googleApiRequestAllItems.call(
|
||||||
this,
|
this,
|
||||||
'domains',
|
'domains',
|
||||||
'GET',
|
'GET',
|
||||||
'/directory/v1/customer/my_customer/domains',
|
'/directory/v1/customer/my_customer/domains',
|
||||||
);
|
)) as Array<{
|
||||||
|
domainName: string;
|
||||||
|
}>;
|
||||||
for (const domain of domains) {
|
for (const domain of domains) {
|
||||||
const domainName = domain.domainName;
|
const domainName = domain.domainName;
|
||||||
const domainId = domain.domainName;
|
const domainId = domain.domainName;
|
||||||
@@ -82,47 +89,180 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
}
|
}
|
||||||
return returnData;
|
return returnData;
|
||||||
},
|
},
|
||||||
// Get all the schemas to display them to user so that they can
|
|
||||||
// select them easily
|
|
||||||
async getSchemas(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
async getSchemas(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
const returnData: INodePropertyOptions[] = [];
|
const schemas = (await googleApiRequestAllItems.call(
|
||||||
const schemas = await googleApiRequestAllItems.call(
|
|
||||||
this,
|
this,
|
||||||
'schemas',
|
'schemas',
|
||||||
'GET',
|
'GET',
|
||||||
'/directory/v1/customer/my_customer/schemas',
|
'/directory/v1/customer/my_customer/schemas',
|
||||||
);
|
)) as Array<{
|
||||||
for (const schema of schemas) {
|
displayName: string;
|
||||||
const schemaName = schema.displayName;
|
schemaName: string;
|
||||||
const schemaId = schema.schemaName;
|
}>;
|
||||||
|
return schemas.map((schema: { schemaName: string; displayName: string }) => ({
|
||||||
|
name: schema.displayName || schema.schemaName,
|
||||||
|
value: schema.schemaName,
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
async getOrgUnits(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
const returnData: INodePropertyOptions[] = [];
|
||||||
|
const orgUnits = (await googleApiRequest.call(
|
||||||
|
this,
|
||||||
|
'GET',
|
||||||
|
'/directory/v1/customer/my_customer/orgunits',
|
||||||
|
{},
|
||||||
|
{ orgUnitPath: '/', type: 'all' },
|
||||||
|
)) as {
|
||||||
|
organizationUnits: Array<{
|
||||||
|
name: string;
|
||||||
|
orgUnitPath: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const unit of orgUnits.organizationUnits) {
|
||||||
returnData.push({
|
returnData.push({
|
||||||
name: schemaName,
|
name: unit.name,
|
||||||
value: schemaId,
|
value: unit.orgUnitPath,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnData;
|
return returnData;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
listSearch: {
|
||||||
|
searchDevices,
|
||||||
|
searchGroups,
|
||||||
|
searchUsers,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
const items = this.getInputData();
|
const items = this.getInputData();
|
||||||
const returnData: INodeExecutionData[] = [];
|
const returnData: INodeExecutionData[] = [];
|
||||||
const length = items.length;
|
const length = items.length;
|
||||||
const qs: IDataObject = {};
|
|
||||||
let responseData;
|
let responseData;
|
||||||
const resource = this.getNodeParameter('resource', 0);
|
const resource = this.getNodeParameter('resource', 0);
|
||||||
const operation = this.getNodeParameter('operation', 0);
|
const operation = this.getNodeParameter('operation', 0);
|
||||||
|
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
|
const qs: IDataObject = {};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (resource === 'group') {
|
if (resource === 'device') {
|
||||||
|
//https://developers.google.com/admin-sdk/directory/v1/customer/my_customer/devices/chromeos/deviceId
|
||||||
|
if (operation === 'get') {
|
||||||
|
const deviceId = this.getNodeParameter('deviceId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
const output = this.getNodeParameter('projection', 1);
|
||||||
|
|
||||||
|
responseData = await googleApiRequest.call(
|
||||||
|
this,
|
||||||
|
'GET',
|
||||||
|
`/directory/v1/customer/my_customer/devices/chromeos/${deviceId}?projection=${output}`,
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//https://developers.google.com/admin-sdk/directory/reference/rest/v1/chromeosdevices/list
|
||||||
|
if (operation === 'getAll') {
|
||||||
|
const returnAll = this.getNodeParameter('returnAll', i);
|
||||||
|
const output = this.getNodeParameter('projection', 1);
|
||||||
|
const includeChildren = this.getNodeParameter('includeChildOrgunits', i);
|
||||||
|
const filter = this.getNodeParameter('filter', i, {}) as {
|
||||||
|
query?: string;
|
||||||
|
orgUnitPath?: string;
|
||||||
|
};
|
||||||
|
const sort = this.getNodeParameter('sort', i, {}) as {
|
||||||
|
sortRules?: {
|
||||||
|
orderBy?: string;
|
||||||
|
sortOrder?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
qs.projection = output;
|
||||||
|
qs.includeChildOrgunits = includeChildren;
|
||||||
|
|
||||||
|
if (qs.customer === undefined) {
|
||||||
|
qs.customer = 'my_customer';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.orgUnitPath) {
|
||||||
|
qs.orgUnitPath = filter.orgUnitPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.query) {
|
||||||
|
qs.query = filter.query.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort.sortRules) {
|
||||||
|
const { orderBy, sortOrder } = sort.sortRules;
|
||||||
|
if (orderBy) {
|
||||||
|
qs.orderBy = orderBy;
|
||||||
|
}
|
||||||
|
if (sortOrder) {
|
||||||
|
qs.sortOrder = sortOrder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!returnAll) {
|
||||||
|
qs.maxResults = this.getNodeParameter('limit', i);
|
||||||
|
}
|
||||||
|
|
||||||
|
responseData = await googleApiRequest.call(
|
||||||
|
this,
|
||||||
|
'GET',
|
||||||
|
`/directory/v1/customer/${qs.customer}/devices/chromeos/`,
|
||||||
|
{},
|
||||||
|
qs,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!Array.isArray(responseData) || responseData.length === 0) {
|
||||||
|
return [this.helpers.returnJsonArray({})];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [this.helpers.returnJsonArray(responseData)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'update') {
|
||||||
|
const deviceId = this.getNodeParameter('deviceId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
const updateOptions = this.getNodeParameter('updateOptions', 1);
|
||||||
|
|
||||||
|
Object.assign(qs, updateOptions);
|
||||||
|
|
||||||
|
responseData = await googleApiRequest.call(
|
||||||
|
this,
|
||||||
|
'PUT',
|
||||||
|
`/directory/v1/customer/my_customer/devices/chromeos/${deviceId}`,
|
||||||
|
qs,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'changeStatus') {
|
||||||
|
const deviceId = this.getNodeParameter('deviceId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
const action = this.getNodeParameter('action', 1);
|
||||||
|
|
||||||
|
qs.action = action;
|
||||||
|
responseData = await googleApiRequest.call(
|
||||||
|
this,
|
||||||
|
'POST',
|
||||||
|
`/directory/v1/customer/my_customer/devices/chromeos/${deviceId}/action`,
|
||||||
|
qs,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (resource === 'group') {
|
||||||
//https://developers.google.com/admin-sdk/directory/v1/reference/groups/insert
|
//https://developers.google.com/admin-sdk/directory/v1/reference/groups/insert
|
||||||
if (operation === 'create') {
|
if (operation === 'create') {
|
||||||
|
const name = this.getNodeParameter('name', i) as string;
|
||||||
const email = this.getNodeParameter('email', i) as string;
|
const email = this.getNodeParameter('email', i) as string;
|
||||||
|
|
||||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||||
|
|
||||||
const body: IDataObject = {
|
const body: IDataObject = {
|
||||||
|
name,
|
||||||
email,
|
email,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -133,21 +273,20 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
|
|
||||||
//https://developers.google.com/admin-sdk/directory/v1/reference/groups/delete
|
//https://developers.google.com/admin-sdk/directory/v1/reference/groups/delete
|
||||||
if (operation === 'delete') {
|
if (operation === 'delete') {
|
||||||
const groupId = this.getNodeParameter('groupId', i) as string;
|
const groupId = this.getNodeParameter('groupId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
|
||||||
responseData = await googleApiRequest.call(
|
await googleApiRequest.call(this, 'DELETE', `/directory/v1/groups/${groupId}`, {});
|
||||||
this,
|
|
||||||
'DELETE',
|
|
||||||
`/directory/v1/groups/${groupId}`,
|
|
||||||
{},
|
|
||||||
);
|
|
||||||
|
|
||||||
responseData = { success: true };
|
responseData = { success: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://developers.google.com/admin-sdk/directory/v1/reference/groups/get
|
//https://developers.google.com/admin-sdk/directory/v1/reference/groups/get
|
||||||
if (operation === 'get') {
|
if (operation === 'get') {
|
||||||
const groupId = this.getNodeParameter('groupId', i) as string;
|
const groupId = this.getNodeParameter('groupId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
|
||||||
responseData = await googleApiRequest.call(
|
responseData = await googleApiRequest.call(
|
||||||
this,
|
this,
|
||||||
@@ -156,19 +295,66 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://developers.google.com/admin-sdk/directory/v1/reference/groups/list
|
//https://developers.google.com/admin-sdk/directory/v1/reference/groups/list
|
||||||
if (operation === 'getAll') {
|
if (operation === 'getAll') {
|
||||||
const returnAll = this.getNodeParameter('returnAll', i);
|
const returnAll = this.getNodeParameter('returnAll', i);
|
||||||
|
const filter = this.getNodeParameter('filter', i, {}) as {
|
||||||
|
customer?: string;
|
||||||
|
domain?: string;
|
||||||
|
query?: string;
|
||||||
|
userId?: string;
|
||||||
|
};
|
||||||
|
const sort = this.getNodeParameter('sort', i, {}) as {
|
||||||
|
sortRules?: {
|
||||||
|
orderBy?: string;
|
||||||
|
sortOrder?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const options = this.getNodeParameter('options', i);
|
if (filter.customer) {
|
||||||
|
qs.customer = filter.customer;
|
||||||
|
}
|
||||||
|
|
||||||
Object.assign(qs, options);
|
if (filter.domain) {
|
||||||
|
qs.domain = filter.domain;
|
||||||
|
}
|
||||||
|
|
||||||
if (qs.customer === undefined) {
|
if (filter.query) {
|
||||||
|
const query = filter.query.trim();
|
||||||
|
|
||||||
|
const regex = /^(name|email):\S+$/;
|
||||||
|
if (!regex.test(query)) {
|
||||||
|
throw new NodeOperationError(
|
||||||
|
this.getNode(),
|
||||||
|
'Invalid query format. Query must follow the format "displayName:<value>" or "email:<value>".',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
qs.query = query;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.userId) {
|
||||||
|
qs.userId = filter.userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort.sortRules) {
|
||||||
|
const { orderBy, sortOrder } = sort.sortRules;
|
||||||
|
if (orderBy) {
|
||||||
|
qs.orderBy = orderBy;
|
||||||
|
}
|
||||||
|
if (sortOrder) {
|
||||||
|
qs.sortOrder = sortOrder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qs.customer) {
|
||||||
qs.customer = 'my_customer';
|
qs.customer = 'my_customer';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!returnAll) {
|
||||||
|
qs.maxResults = this.getNodeParameter('limit', i);
|
||||||
|
}
|
||||||
|
|
||||||
if (returnAll) {
|
if (returnAll) {
|
||||||
responseData = await googleApiRequestAllItems.call(
|
responseData = await googleApiRequestAllItems.call(
|
||||||
this,
|
this,
|
||||||
@@ -180,7 +366,6 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
qs.maxResults = this.getNodeParameter('limit', i);
|
qs.maxResults = this.getNodeParameter('limit', i);
|
||||||
|
|
||||||
responseData = await googleApiRequest.call(
|
responseData = await googleApiRequest.call(
|
||||||
this,
|
this,
|
||||||
'GET',
|
'GET',
|
||||||
@@ -188,14 +373,15 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
{},
|
{},
|
||||||
qs,
|
qs,
|
||||||
);
|
);
|
||||||
|
responseData = responseData.groups || [];
|
||||||
responseData = responseData.groups;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://developers.google.com/admin-sdk/directory/v1/reference/groups/update
|
//https://developers.google.com/admin-sdk/directory/v1/reference/groups/update
|
||||||
if (operation === 'update') {
|
if (operation === 'update') {
|
||||||
const groupId = this.getNodeParameter('groupId', i) as string;
|
const groupId = this.getNodeParameter('groupId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
|
||||||
const updateFields = this.getNodeParameter('updateFields', i);
|
const updateFields = this.getNodeParameter('updateFields', i);
|
||||||
|
|
||||||
@@ -210,23 +396,62 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
body,
|
body,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (resource === 'user') {
|
||||||
|
//https://developers.google.com/admin-sdk/directory/reference/rest/v1/members/insert
|
||||||
|
if (operation === 'addToGroup') {
|
||||||
|
const groupId = this.getNodeParameter('groupId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
const userId = this.getNodeParameter('userId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
|
||||||
|
let userEmail: string | undefined;
|
||||||
|
|
||||||
|
// If the user ID is not already an email, fetch the user details
|
||||||
|
if (!userId.includes('@')) {
|
||||||
|
const userDetails = (await googleApiRequest.call(
|
||||||
|
this,
|
||||||
|
'GET',
|
||||||
|
`/directory/v1/users/${userId}`,
|
||||||
|
)) as {
|
||||||
|
primaryEmail: string;
|
||||||
|
};
|
||||||
|
userEmail = userDetails.primaryEmail;
|
||||||
|
} else {
|
||||||
|
userEmail = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userEmail) {
|
||||||
|
throw new NodeOperationError(
|
||||||
|
this.getNode(),
|
||||||
|
'Unable to determine the user email for adding to the group',
|
||||||
|
{ itemIndex: i },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const body: IDataObject = {
|
||||||
|
email: userEmail,
|
||||||
|
role: 'MEMBER',
|
||||||
|
};
|
||||||
|
|
||||||
|
await googleApiRequest.call(
|
||||||
|
this,
|
||||||
|
'POST',
|
||||||
|
`/directory/v1/groups/${groupId}/members`,
|
||||||
|
body,
|
||||||
|
);
|
||||||
|
|
||||||
|
responseData = { added: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resource === 'user') {
|
|
||||||
//https://developers.google.com/admin-sdk/directory/v1/reference/users/insert
|
//https://developers.google.com/admin-sdk/directory/v1/reference/users/insert
|
||||||
if (operation === 'create') {
|
if (operation === 'create') {
|
||||||
const domain = this.getNodeParameter('domain', i) as string;
|
const domain = this.getNodeParameter('domain', i) as string;
|
||||||
|
|
||||||
const firstName = this.getNodeParameter('firstName', i) as string;
|
const firstName = this.getNodeParameter('firstName', i) as string;
|
||||||
|
|
||||||
const lastName = this.getNodeParameter('lastName', i) as string;
|
const lastName = this.getNodeParameter('lastName', i) as string;
|
||||||
|
|
||||||
const password = this.getNodeParameter('password', i) as string;
|
const password = this.getNodeParameter('password', i) as string;
|
||||||
|
|
||||||
const username = this.getNodeParameter('username', i) as string;
|
const username = this.getNodeParameter('username', i) as string;
|
||||||
|
|
||||||
const makeAdmin = this.getNodeParameter('makeAdmin', i) as boolean;
|
|
||||||
|
|
||||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||||
|
|
||||||
const body: IDataObject = {
|
const body: IDataObject = {
|
||||||
@@ -238,22 +463,63 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
primaryEmail: `${username}@${domain}`,
|
primaryEmail: `${username}@${domain}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.assign(body, additionalFields);
|
if (!username) {
|
||||||
|
throw new NodeOperationError(this.getNode(), "The parameter 'Username' is empty", {
|
||||||
|
itemIndex: i,
|
||||||
|
description: "Please fill in the 'Username' parameter to create the user",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (additionalFields.phoneUi) {
|
if (additionalFields.phoneUi) {
|
||||||
const phones = (additionalFields.phoneUi as IDataObject).phoneValues as IDataObject[];
|
body.phones = (additionalFields.phoneUi as IDataObject).phoneValues as IDataObject[];
|
||||||
|
|
||||||
body.phones = phones;
|
|
||||||
|
|
||||||
delete body.phoneUi;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (additionalFields.emailUi) {
|
if (additionalFields.emailUi) {
|
||||||
const emails = (additionalFields.emailUi as IDataObject).emailValues as IDataObject[];
|
body.emails = (additionalFields.emailUi as IDataObject).emailValues as IDataObject[];
|
||||||
|
}
|
||||||
|
|
||||||
body.emails = emails;
|
if (additionalFields.roles) {
|
||||||
|
const roles = additionalFields.roles as string[];
|
||||||
|
body.roles = {
|
||||||
|
superAdmin: roles.includes('superAdmin'),
|
||||||
|
groupsAdmin: roles.includes('groupsAdmin'),
|
||||||
|
groupsReader: roles.includes('groupsReader'),
|
||||||
|
groupsEditor: roles.includes('groupsEditor'),
|
||||||
|
userManagement: roles.includes('userManagement'),
|
||||||
|
helpDeskAdmin: roles.includes('helpDeskAdmin'),
|
||||||
|
servicesAdmin: roles.includes('servicesAdmin'),
|
||||||
|
inventoryReportingAdmin: roles.includes('inventoryReportingAdmin'),
|
||||||
|
storageAdmin: roles.includes('storageAdmin'),
|
||||||
|
directorySyncAdmin: roles.includes('directorySyncAdmin'),
|
||||||
|
mobileAdmin: roles.includes('mobileAdmin'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
delete body.emailUi;
|
if (additionalFields.customFields) {
|
||||||
|
const customFields = (additionalFields.customFields as IDataObject)
|
||||||
|
.fieldValues as IDataObject[];
|
||||||
|
const customSchemas: IDataObject = {};
|
||||||
|
customFields.forEach((field) => {
|
||||||
|
const { schemaName, fieldName, value } = field as {
|
||||||
|
schemaName: string;
|
||||||
|
fieldName: string;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!schemaName || !fieldName || !value) {
|
||||||
|
throw new NodeOperationError(this.getNode(), 'Invalid custom field data', {
|
||||||
|
itemIndex: i,
|
||||||
|
description: 'Schema name, field name, and value are required.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
customSchemas[schemaName] ??= {};
|
||||||
|
(customSchemas[schemaName] as IDataObject)[fieldName] = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Object.keys(customSchemas).length > 0) {
|
||||||
|
body.customSchemas = customSchemas;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
responseData = await googleApiRequest.call(
|
responseData = await googleApiRequest.call(
|
||||||
@@ -263,22 +529,13 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
body,
|
body,
|
||||||
qs,
|
qs,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (makeAdmin) {
|
|
||||||
await googleApiRequest.call(
|
|
||||||
this,
|
|
||||||
'POST',
|
|
||||||
`/directory/v1/users/${responseData.id}/makeAdmin`,
|
|
||||||
{ status: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
responseData.isAdmin = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://developers.google.com/admin-sdk/directory/v1/reference/users/delete
|
//https://developers.google.com/admin-sdk/directory/v1/reference/users/delete
|
||||||
if (operation === 'delete') {
|
if (operation === 'delete') {
|
||||||
const userId = this.getNodeParameter('userId', i) as string;
|
const userId = this.getNodeParameter('userId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
|
||||||
responseData = await googleApiRequest.call(
|
responseData = await googleApiRequest.call(
|
||||||
this,
|
this,
|
||||||
@@ -287,31 +544,30 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
|
|
||||||
responseData = { success: true };
|
responseData = { deleted: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://developers.google.com/admin-sdk/directory/v1/reference/users/get
|
//https://developers.google.com/admin-sdk/directory/v1/reference/users/get
|
||||||
if (operation === 'get') {
|
if (operation === 'get') {
|
||||||
const userId = this.getNodeParameter('userId', i) as string;
|
const userId = this.getNodeParameter('userId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
|
||||||
const projection = this.getNodeParameter('projection', i) as string;
|
const output = this.getNodeParameter('output', i);
|
||||||
|
const projection = this.getNodeParameter('projection', i);
|
||||||
const options = this.getNodeParameter('options', i);
|
const fields = this.getNodeParameter('fields', i, []) as string[];
|
||||||
|
|
||||||
|
if (projection) {
|
||||||
qs.projection = projection;
|
qs.projection = projection;
|
||||||
|
|
||||||
Object.assign(qs, options);
|
|
||||||
|
|
||||||
if (qs.customFieldMask) {
|
|
||||||
qs.customFieldMask = (qs.customFieldMask as string[]).join(' ');
|
|
||||||
}
|
}
|
||||||
|
if (projection === 'custom' && qs.customFieldMask) {
|
||||||
if (qs.projection === 'custom' && qs.customFieldMask === undefined) {
|
qs.customFieldMask = (qs.customFieldMask as string[]).join(',');
|
||||||
throw new NodeOperationError(
|
}
|
||||||
this.getNode(),
|
if (output === 'select') {
|
||||||
'When projection is set to custom, the custom schemas field must be defined',
|
if (!fields.includes('id')) {
|
||||||
{ itemIndex: i },
|
fields.push('id');
|
||||||
);
|
}
|
||||||
|
qs.fields = fields.join(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
responseData = await googleApiRequest.call(
|
responseData = await googleApiRequest.call(
|
||||||
@@ -321,36 +577,82 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
{},
|
{},
|
||||||
qs,
|
qs,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (output === 'simplified') {
|
||||||
|
responseData = {
|
||||||
|
kind: responseData.kind,
|
||||||
|
id: responseData.id,
|
||||||
|
primaryEmail: responseData.primaryEmail,
|
||||||
|
name: responseData.name,
|
||||||
|
isAdmin: responseData.isAdmin,
|
||||||
|
lastLoginTime: responseData.lastLoginTime,
|
||||||
|
creationTime: responseData.creationTime,
|
||||||
|
suspended: responseData.suspended,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://developers.google.com/admin-sdk/directory/v1/reference/users/list
|
//https://developers.google.com/admin-sdk/directory/v1/reference/users/list
|
||||||
if (operation === 'getAll') {
|
if (operation === 'getAll') {
|
||||||
const returnAll = this.getNodeParameter('returnAll', i);
|
const returnAll = this.getNodeParameter('returnAll', i);
|
||||||
|
const output = this.getNodeParameter('output', i);
|
||||||
|
const fields = this.getNodeParameter('fields', i, []) as string[];
|
||||||
const projection = this.getNodeParameter('projection', i) as string;
|
const projection = this.getNodeParameter('projection', i) as string;
|
||||||
|
const filter = this.getNodeParameter('filter', i, {}) as {
|
||||||
|
customer?: string;
|
||||||
|
domain?: string;
|
||||||
|
query?: string;
|
||||||
|
showDeleted?: boolean;
|
||||||
|
};
|
||||||
|
const sort = this.getNodeParameter('sort', i, {}) as {
|
||||||
|
sortRules?: {
|
||||||
|
orderBy?: string;
|
||||||
|
sortOrder?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const options = this.getNodeParameter('options', i);
|
if (filter.customer) {
|
||||||
|
qs.customer = filter.customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.domain) {
|
||||||
|
qs.domain = filter.domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.query) {
|
||||||
|
qs.query = filter.query.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.showDeleted) {
|
||||||
|
qs.showDeleted = filter.showDeleted ? 'true' : 'false';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort.sortRules) {
|
||||||
|
const { orderBy, sortOrder } = sort.sortRules;
|
||||||
|
if (orderBy) {
|
||||||
|
qs.orderBy = orderBy;
|
||||||
|
}
|
||||||
|
if (sortOrder) {
|
||||||
|
qs.sortOrder = sortOrder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
qs.projection = projection;
|
qs.projection = projection;
|
||||||
|
if (projection === 'custom' && qs.customFieldMask) {
|
||||||
|
qs.customFieldMask = (qs.customFieldMask as string[]).join(',');
|
||||||
|
}
|
||||||
|
|
||||||
Object.assign(qs, options);
|
if (output === 'select') {
|
||||||
|
if (!fields.includes('id')) {
|
||||||
|
fields.push('id');
|
||||||
|
}
|
||||||
|
qs.fields = `users(${fields.join(',')})`;
|
||||||
|
}
|
||||||
|
|
||||||
if (qs.customer === undefined) {
|
if (!qs.customer) {
|
||||||
qs.customer = 'my_customer';
|
qs.customer = 'my_customer';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qs.customFieldMask) {
|
|
||||||
qs.customFieldMask = (qs.customFieldMask as string[]).join(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qs.projection === 'custom' && qs.customFieldMask === undefined) {
|
|
||||||
throw new NodeOperationError(
|
|
||||||
this.getNode(),
|
|
||||||
'When projection is set to custom, the custom schemas field must be defined',
|
|
||||||
{ itemIndex: i },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (returnAll) {
|
if (returnAll) {
|
||||||
responseData = await googleApiRequestAllItems.call(
|
responseData = await googleApiRequestAllItems.call(
|
||||||
this,
|
this,
|
||||||
@@ -362,7 +664,6 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
qs.maxResults = this.getNodeParameter('limit', i);
|
qs.maxResults = this.getNodeParameter('limit', i);
|
||||||
|
|
||||||
responseData = await googleApiRequest.call(
|
responseData = await googleApiRequest.call(
|
||||||
this,
|
this,
|
||||||
'GET',
|
'GET',
|
||||||
@@ -373,55 +674,124 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
|
|
||||||
responseData = responseData.users;
|
responseData = responseData.users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (output === 'simplified') {
|
||||||
|
responseData = responseData.map((user: any) => ({
|
||||||
|
kind: user.kind,
|
||||||
|
id: user.id,
|
||||||
|
primaryEmail: user.primaryEmail,
|
||||||
|
name: user.name,
|
||||||
|
isAdmin: user.isAdmin,
|
||||||
|
lastLoginTime: user.lastLoginTime,
|
||||||
|
creationTime: user.creationTime,
|
||||||
|
suspended: user.suspended,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//https://developers.google.com/admin-sdk/directory/reference/rest/v1/members/delete
|
||||||
|
if (operation === 'removeFromGroup') {
|
||||||
|
const groupId = this.getNodeParameter('groupId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
const userId = this.getNodeParameter('userId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
|
||||||
|
await googleApiRequest.call(
|
||||||
|
this,
|
||||||
|
'DELETE',
|
||||||
|
`/directory/v1/groups/${groupId}/members/${userId}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
responseData = { removed: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://developers.google.com/admin-sdk/directory/v1/reference/users/update
|
//https://developers.google.com/admin-sdk/directory/v1/reference/users/update
|
||||||
if (operation === 'update') {
|
if (operation === 'update') {
|
||||||
const userId = this.getNodeParameter('userId', i) as string;
|
const userId = this.getNodeParameter('userId', i, undefined, {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
const updateFields = this.getNodeParameter('updateFields', i);
|
const updateFields = this.getNodeParameter('updateFields', i);
|
||||||
|
|
||||||
const body: {
|
const body: {
|
||||||
name: { givenName?: string; familyName?: string };
|
name?: { givenName?: string; familyName?: string };
|
||||||
emails?: IDataObject[];
|
emails?: IDataObject[];
|
||||||
|
primaryEmail?: string;
|
||||||
phones?: IDataObject[];
|
phones?: IDataObject[];
|
||||||
} = { name: {} };
|
suspended?: boolean;
|
||||||
|
roles?: { [key: string]: boolean };
|
||||||
Object.assign(body, updateFields);
|
customSchemas?: IDataObject;
|
||||||
|
} = {};
|
||||||
|
|
||||||
if (updateFields.firstName) {
|
if (updateFields.firstName) {
|
||||||
|
body.name ??= {};
|
||||||
body.name.givenName = updateFields.firstName as string;
|
body.name.givenName = updateFields.firstName as string;
|
||||||
//@ts-ignore
|
|
||||||
delete body.firstName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateFields.lastName) {
|
if (updateFields.lastName) {
|
||||||
|
body.name ??= {};
|
||||||
body.name.familyName = updateFields.lastName as string;
|
body.name.familyName = updateFields.lastName as string;
|
||||||
//@ts-ignore
|
|
||||||
delete body.lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.keys(body.name).length === 0) {
|
|
||||||
//@ts-ignore
|
|
||||||
delete body.name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateFields.phoneUi) {
|
if (updateFields.phoneUi) {
|
||||||
const phones = (updateFields.phoneUi as IDataObject).phoneValues as IDataObject[];
|
body.phones = (updateFields.phoneUi as IDataObject).phoneValues as IDataObject[];
|
||||||
|
|
||||||
body.phones = phones;
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
delete body.phoneUi;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateFields.emailUi) {
|
if (updateFields.emailUi) {
|
||||||
const emails = (updateFields.emailUi as IDataObject).emailValues as IDataObject[];
|
body.emails = (updateFields.emailUi as IDataObject).emailValues as IDataObject[];
|
||||||
|
}
|
||||||
|
|
||||||
body.emails = emails;
|
if (updateFields.primaryEmail) {
|
||||||
|
body.primaryEmail = updateFields.primaryEmail as string;
|
||||||
|
}
|
||||||
|
|
||||||
//@ts-ignore
|
if (updateFields.suspendUi) {
|
||||||
delete body.emailUi;
|
body.suspended = updateFields.suspendUi as boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateFields.roles) {
|
||||||
|
const roles = updateFields.roles as string[];
|
||||||
|
body.roles = {
|
||||||
|
superAdmin: roles.includes('superAdmin'),
|
||||||
|
groupsAdmin: roles.includes('groupsAdmin'),
|
||||||
|
groupsReader: roles.includes('groupsReader'),
|
||||||
|
groupsEditor: roles.includes('groupsEditor'),
|
||||||
|
userManagement: roles.includes('userManagement'),
|
||||||
|
helpDeskAdmin: roles.includes('helpDeskAdmin'),
|
||||||
|
servicesAdmin: roles.includes('servicesAdmin'),
|
||||||
|
inventoryReportingAdmin: roles.includes('inventoryReportingAdmin'),
|
||||||
|
storageAdmin: roles.includes('storageAdmin'),
|
||||||
|
directorySyncAdmin: roles.includes('directorySyncAdmin'),
|
||||||
|
mobileAdmin: roles.includes('mobileAdmin'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateFields.customFields) {
|
||||||
|
const customFields = (updateFields.customFields as IDataObject)
|
||||||
|
.fieldValues as IDataObject[];
|
||||||
|
const customSchemas: IDataObject = {};
|
||||||
|
customFields.forEach((field) => {
|
||||||
|
const { schemaName, fieldName, value } = field as {
|
||||||
|
schemaName: string;
|
||||||
|
fieldName: string;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!schemaName || !fieldName || !value) {
|
||||||
|
throw new NodeOperationError(this.getNode(), 'Invalid custom field data', {
|
||||||
|
itemIndex: i,
|
||||||
|
description: 'Schema name, field name, and value are required.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
customSchemas[schemaName] ??= {};
|
||||||
|
(customSchemas[schemaName] as IDataObject)[fieldName] = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Object.keys(customSchemas).length > 0) {
|
||||||
|
body.customSchemas = customSchemas;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
responseData = await googleApiRequest.call(
|
responseData = await googleApiRequest.call(
|
||||||
@@ -441,17 +811,32 @@ export class GSuiteAdmin implements INodeType {
|
|||||||
|
|
||||||
returnData.push(...executionData);
|
returnData.push(...executionData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error instanceof NodeOperationError) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
if (this.continueOnFail()) {
|
if (this.continueOnFail()) {
|
||||||
const executionErrorData = this.helpers.constructExecutionMetaData(
|
const executionErrorData = this.helpers.constructExecutionMetaData(
|
||||||
this.helpers.returnJsonArray({ error: error.message }),
|
this.helpers.returnJsonArray({
|
||||||
|
message: `Operation "${operation}" failed for resource "${resource}".`,
|
||||||
|
description: error.message,
|
||||||
|
}),
|
||||||
{ itemData: { item: i } },
|
{ itemData: { item: i } },
|
||||||
);
|
);
|
||||||
returnData.push(...executionErrorData);
|
returnData.push(...executionErrorData);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
throw error;
|
throw new NodeOperationError(
|
||||||
|
this.getNode(),
|
||||||
|
`Operation "${operation}" failed for resource "${resource}".`,
|
||||||
|
|
||||||
|
{
|
||||||
|
description: `Please check the input parameters and ensure the API request is correctly formatted. Details: ${error.description}`,
|
||||||
|
itemIndex: i,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [returnData];
|
return [returnData];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type {
|
|||||||
IDataObject,
|
IDataObject,
|
||||||
JsonObject,
|
JsonObject,
|
||||||
IHttpRequestMethods,
|
IHttpRequestMethods,
|
||||||
IRequestOptions,
|
IHttpRequestOptions,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeApiError } from 'n8n-workflow';
|
import { NodeApiError } from 'n8n-workflow';
|
||||||
|
|
||||||
@@ -12,20 +12,19 @@ export async function googleApiRequest(
|
|||||||
this: IExecuteFunctions | ILoadOptionsFunctions,
|
this: IExecuteFunctions | ILoadOptionsFunctions,
|
||||||
method: IHttpRequestMethods,
|
method: IHttpRequestMethods,
|
||||||
resource: string,
|
resource: string,
|
||||||
|
|
||||||
body: any = {},
|
body: any = {},
|
||||||
qs: IDataObject = {},
|
qs: IDataObject = {},
|
||||||
uri?: string,
|
uri?: string,
|
||||||
headers: IDataObject = {},
|
headers: IDataObject = {},
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const options: IRequestOptions = {
|
const options: IHttpRequestOptions = {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
method,
|
method,
|
||||||
body,
|
body,
|
||||||
qs,
|
qs,
|
||||||
uri: uri || `https://www.googleapis.com/admin${resource}`,
|
url: uri || `https://www.googleapis.com/admin${resource}`,
|
||||||
json: true,
|
json: true,
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
@@ -35,7 +34,11 @@ export async function googleApiRequest(
|
|||||||
if (Object.keys(body as IDataObject).length === 0) {
|
if (Object.keys(body as IDataObject).length === 0) {
|
||||||
delete options.body;
|
delete options.body;
|
||||||
}
|
}
|
||||||
return await this.helpers.requestOAuth2.call(this, 'gSuiteAdminOAuth2Api', options);
|
return await this.helpers.httpRequestWithAuthentication.call(
|
||||||
|
this,
|
||||||
|
'gSuiteAdminOAuth2Api',
|
||||||
|
options,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||||
}
|
}
|
||||||
@@ -46,7 +49,6 @@ export async function googleApiRequestAllItems(
|
|||||||
propertyName: string,
|
propertyName: string,
|
||||||
method: IHttpRequestMethods,
|
method: IHttpRequestMethods,
|
||||||
endpoint: string,
|
endpoint: string,
|
||||||
|
|
||||||
body: any = {},
|
body: any = {},
|
||||||
query: IDataObject = {},
|
query: IDataObject = {},
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
|
|||||||
@@ -48,14 +48,65 @@ export const groupOperations: INodeProperties[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const groupFields: INodeProperties[] = [
|
export const groupFields: INodeProperties[] = [
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* group */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Group',
|
||||||
|
name: 'groupId',
|
||||||
|
default: {
|
||||||
|
mode: 'list',
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
description: 'Select the group to perform the operation on',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['delete', 'get', 'update'],
|
||||||
|
resource: ['group'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modes: [
|
||||||
|
{
|
||||||
|
displayName: 'From list',
|
||||||
|
name: 'list',
|
||||||
|
type: 'list',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'searchGroups',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'By ID',
|
||||||
|
name: 'GroupId',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'e.g. 0123kx3o1habcdf',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
required: true,
|
||||||
|
type: 'resourceLocator',
|
||||||
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* group:create */
|
/* group:create */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
displayName: 'Email',
|
displayName: 'Group Name',
|
||||||
|
name: 'name',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['create'],
|
||||||
|
resource: ['group'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: "The group's display name",
|
||||||
|
placeholder: 'e.g. Sales',
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Group Email',
|
||||||
name: 'email',
|
name: 'email',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
placeholder: 'name@email.com',
|
placeholder: 'e.g. sales@example.com',
|
||||||
required: true,
|
required: true,
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
@@ -88,51 +139,13 @@ export const groupFields: INodeProperties[] = [
|
|||||||
description:
|
description:
|
||||||
'An extended description to help users determine the purpose of a group. For example, you can include information about who should join the group, the types of messages to send to the group, links to FAQs about the group, or related groups.',
|
'An extended description to help users determine the purpose of a group. For example, you can include information about who should join the group, the types of messages to send to the group, links to FAQs about the group, or related groups.',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
displayName: 'Name',
|
|
||||||
name: 'name',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
description: "The group's display name",
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* group:delete */
|
/* group:delete */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
|
||||||
displayName: 'Group ID',
|
|
||||||
name: 'groupId',
|
|
||||||
type: 'string',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: ['delete'],
|
|
||||||
resource: ['group'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: '',
|
|
||||||
description:
|
|
||||||
"Identifies the group in the API request. The value can be the group's email address, group alias, or the unique group ID.",
|
|
||||||
},
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* group:get */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
displayName: 'Group ID',
|
|
||||||
name: 'groupId',
|
|
||||||
type: 'string',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: ['get'],
|
|
||||||
resource: ['group'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: '',
|
|
||||||
description:
|
|
||||||
"Identifies the group in the API request. The value can be the group's email address, group alias, or the unique group ID.",
|
|
||||||
},
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* group:getAll */
|
/* group:getAll */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@@ -168,10 +181,10 @@ export const groupFields: INodeProperties[] = [
|
|||||||
description: 'Max number of results to return',
|
description: 'Max number of results to return',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Options',
|
displayName: 'Filter',
|
||||||
name: 'options',
|
name: 'filter',
|
||||||
type: 'collection',
|
type: 'collection',
|
||||||
placeholder: 'Add option',
|
placeholder: 'Add Filter',
|
||||||
default: {},
|
default: {},
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
@@ -185,16 +198,50 @@ export const groupFields: INodeProperties[] = [
|
|||||||
name: 'customer',
|
name: 'customer',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
description:
|
description: "The unique ID for the customer's Google Workspace account",
|
||||||
"The unique ID for the customer's Google Workspace account. In case of a multi-domain account, to fetch all groups for a customer, fill this field instead of domain.",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Domain',
|
displayName: 'Domain',
|
||||||
name: 'domain',
|
name: 'domain',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
description: 'The domain name. Use this field to get fields from only one domain.',
|
description: 'The domain name. Use this field to get groups from a specific domain.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Query',
|
||||||
|
name: 'query',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'e.g. name:contact* email:contact*',
|
||||||
|
default: '',
|
||||||
|
description:
|
||||||
|
'Query string to filter the results. Follow Google Admin SDK documentation. <a href="https://developers.google.com/admin-sdk/directory/v1/guides/search-groups#examples" target="_blank">More info</a>.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'User ID',
|
||||||
|
name: 'userId',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Email or immutable ID of a user to list groups they are a member of',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Sort',
|
||||||
|
name: 'sort',
|
||||||
|
type: 'fixedCollection',
|
||||||
|
placeholder: 'Add Sort Rule',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['getAll'],
|
||||||
|
resource: ['group'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'sortRules',
|
||||||
|
displayName: 'Sort Rules',
|
||||||
|
values: [
|
||||||
{
|
{
|
||||||
displayName: 'Order By',
|
displayName: 'Order By',
|
||||||
name: 'orderBy',
|
name: 'orderBy',
|
||||||
@@ -205,16 +252,8 @@ export const groupFields: INodeProperties[] = [
|
|||||||
value: 'email',
|
value: 'email',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
default: '',
|
default: 'email',
|
||||||
description: 'Property to use for sorting results',
|
description: 'Field to sort the results by',
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Query',
|
|
||||||
name: 'query',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
description:
|
|
||||||
'Query string search. Complete documentation is <a href="https://developers.google.com/admin-sdk/directory/v1/guides/search-groups">at</a>.',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Sort Order',
|
displayName: 'Sort Order',
|
||||||
@@ -230,37 +269,17 @@ export const groupFields: INodeProperties[] = [
|
|||||||
value: 'DESCENDING',
|
value: 'DESCENDING',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
default: '',
|
default: 'ASCENDING',
|
||||||
description: 'Whether to return results in ascending or descending order',
|
description: 'Sort order direction',
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'User ID',
|
|
||||||
name: 'userId',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
description:
|
|
||||||
"Email or immutable ID of the user if only those groups are to be listed, the given user is a member of. If it's an ID, it should match with the ID of the user object.",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* group:update */
|
/* group:update */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
|
||||||
displayName: 'Group ID',
|
|
||||||
name: 'groupId',
|
|
||||||
type: 'string',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: ['update'],
|
|
||||||
resource: ['group'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: '',
|
|
||||||
description:
|
|
||||||
"Identifies the group in the API request. The value can be the group's email address, group alias, or the unique group ID.",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
displayName: 'Update Fields',
|
displayName: 'Update Fields',
|
||||||
name: 'updateFields',
|
name: 'updateFields',
|
||||||
@@ -279,6 +298,9 @@ export const groupFields: INodeProperties[] = [
|
|||||||
name: 'description',
|
name: 'description',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
|
typeOptions: {
|
||||||
|
rows: 2,
|
||||||
|
},
|
||||||
description:
|
description:
|
||||||
'An extended description to help users determine the purpose of a group. For example, you can include information about who should join the group, the types of messages to send to the group, links to FAQs about the group, or related groups.',
|
'An extended description to help users determine the purpose of a group. For example, you can include information about who should join the group, the types of messages to send to the group, links to FAQs about the group, or related groups.',
|
||||||
},
|
},
|
||||||
@@ -286,7 +308,7 @@ export const groupFields: INodeProperties[] = [
|
|||||||
displayName: 'Email',
|
displayName: 'Email',
|
||||||
name: 'email',
|
name: 'email',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
placeholder: 'name@email.com',
|
placeholder: 'e.g. sales@example.com',
|
||||||
default: '',
|
default: '',
|
||||||
description:
|
description:
|
||||||
"The group's email address. If your account has multiple domains, select the appropriate domain for the email address. The email must be unique.",
|
"The group's email address. If your account has multiple domains, select the appropriate domain for the email address. The email must be unique.",
|
||||||
@@ -295,6 +317,7 @@ export const groupFields: INodeProperties[] = [
|
|||||||
displayName: 'Name',
|
displayName: 'Name',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
placeholder: 'e.g. Sales',
|
||||||
default: '',
|
default: '',
|
||||||
description: "The group's display name",
|
description: "The group's display name",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import type {
|
||||||
|
ILoadOptionsFunctions,
|
||||||
|
IDataObject,
|
||||||
|
INodeListSearchResult,
|
||||||
|
INodeListSearchItems,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import { googleApiRequest, googleApiRequestAllItems } from './GenericFunctions';
|
||||||
|
|
||||||
|
export async function searchUsers(this: ILoadOptionsFunctions): Promise<INodeListSearchResult> {
|
||||||
|
const qs: IDataObject = {
|
||||||
|
customer: 'my_customer',
|
||||||
|
};
|
||||||
|
|
||||||
|
const responseData = await googleApiRequestAllItems.call(
|
||||||
|
this,
|
||||||
|
'users',
|
||||||
|
'GET',
|
||||||
|
'/directory/v1/users',
|
||||||
|
{},
|
||||||
|
qs,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!Array.isArray(responseData)) {
|
||||||
|
return { results: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
const results: INodeListSearchItems[] = responseData.map(
|
||||||
|
(user: { name?: { fullName?: string }; id: string }) => ({
|
||||||
|
name: user.name?.fullName ?? user.id,
|
||||||
|
value: user.id,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return { results };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function searchGroups(this: ILoadOptionsFunctions): Promise<INodeListSearchResult> {
|
||||||
|
const qs: IDataObject = {
|
||||||
|
customer: 'my_customer',
|
||||||
|
};
|
||||||
|
|
||||||
|
const responseData = await googleApiRequestAllItems.call(
|
||||||
|
this,
|
||||||
|
'groups',
|
||||||
|
'GET',
|
||||||
|
'/directory/v1/groups',
|
||||||
|
{},
|
||||||
|
qs,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!Array.isArray(responseData)) {
|
||||||
|
return { results: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
const results: INodeListSearchItems[] = responseData.map(
|
||||||
|
(group: { name?: string; email?: string; id: string }) => ({
|
||||||
|
name: group.name || group.email || 'Unnamed Group',
|
||||||
|
value: group.id,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return { results };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function searchDevices(this: ILoadOptionsFunctions): Promise<INodeListSearchResult> {
|
||||||
|
const qs: IDataObject = {
|
||||||
|
customerId: 'my_customer',
|
||||||
|
};
|
||||||
|
|
||||||
|
const responseData = await googleApiRequest.call(
|
||||||
|
this,
|
||||||
|
'GET',
|
||||||
|
'/directory/v1/customer/my_customer/devices/chromeos/',
|
||||||
|
{},
|
||||||
|
qs,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!Array.isArray(responseData?.chromeosdevices)) {
|
||||||
|
return { results: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
const results: INodeListSearchItems[] = responseData.chromeosdevices.map(
|
||||||
|
(device: { deviceId: string; serialNumber?: string }) => ({
|
||||||
|
name: device.serialNumber || device.deviceId || 'Unknown Device',
|
||||||
|
value: device.deviceId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return { results };
|
||||||
|
}
|
||||||
@@ -1,5 +1,63 @@
|
|||||||
import type { INodeProperties } from 'n8n-workflow';
|
import type { INodeProperties } from 'n8n-workflow';
|
||||||
|
|
||||||
|
const rolesOptions = [
|
||||||
|
{
|
||||||
|
name: 'Directory Sync Admin',
|
||||||
|
value: 'directorySyncAdmin',
|
||||||
|
description: 'Whether to assign the Directory Sync Admin role',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Groups Admin',
|
||||||
|
value: 'groupsAdmin',
|
||||||
|
description: 'Whether to assign the Groups Admin role',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Groups Editor',
|
||||||
|
value: 'groupsEditor',
|
||||||
|
description: 'Whether to assign the Groups Editor role',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Groups Reader',
|
||||||
|
value: 'groupsReader',
|
||||||
|
description: 'Whether to assign the Groups Reader role',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Help Desk Admin',
|
||||||
|
value: 'helpDeskAdmin',
|
||||||
|
description: 'Whether to assign the Help Desk Admin role',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Inventory Reporting Admin',
|
||||||
|
value: 'inventoryReportingAdmin',
|
||||||
|
description: 'Whether to assign the Inventory Reporting Admin role',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Mobile Admin',
|
||||||
|
value: 'mobileAdmin',
|
||||||
|
description: 'Whether to assign the Mobile Admin role',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Services Admin',
|
||||||
|
value: 'servicesAdmin',
|
||||||
|
description: 'Whether to assign the Services Admin role',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Storage Admin',
|
||||||
|
value: 'storageAdmin',
|
||||||
|
description: 'Whether to assign the Storage Admin role',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Super Admin',
|
||||||
|
value: 'superAdmin',
|
||||||
|
description: 'Whether to assign the Super Admin role',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'User Management',
|
||||||
|
value: 'userManagement',
|
||||||
|
description: 'Whether to assign the User Management role',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export const userOperations: INodeProperties[] = [
|
export const userOperations: INodeProperties[] = [
|
||||||
{
|
{
|
||||||
displayName: 'Operation',
|
displayName: 'Operation',
|
||||||
@@ -12,6 +70,12 @@ export const userOperations: INodeProperties[] = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
options: [
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Add to Group',
|
||||||
|
value: 'addToGroup',
|
||||||
|
description: 'Add an existing user to a group',
|
||||||
|
action: 'Add user to group',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Create',
|
name: 'Create',
|
||||||
value: 'create',
|
value: 'create',
|
||||||
@@ -36,6 +100,12 @@ export const userOperations: INodeProperties[] = [
|
|||||||
description: 'Get many users',
|
description: 'Get many users',
|
||||||
action: 'Get many users',
|
action: 'Get many users',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Remove From Group',
|
||||||
|
value: 'removeFromGroup',
|
||||||
|
description: 'Remove a user from a group',
|
||||||
|
action: 'Remove user from group',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Update',
|
name: 'Update',
|
||||||
value: 'update',
|
value: 'update',
|
||||||
@@ -48,12 +118,104 @@ export const userOperations: INodeProperties[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const userFields: INodeProperties[] = [
|
export const userFields: INodeProperties[] = [
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* user */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'User',
|
||||||
|
name: 'userId',
|
||||||
|
required: true,
|
||||||
|
type: 'resourceLocator',
|
||||||
|
default: {
|
||||||
|
mode: 'list',
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
description: 'Select the user to perform the operation on',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: ['user'],
|
||||||
|
operation: ['addToGroup', 'delete', 'get', 'removeFromGroup', 'update'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modes: [
|
||||||
|
{
|
||||||
|
displayName: 'From list',
|
||||||
|
name: 'list',
|
||||||
|
type: 'list',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'searchUsers',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'By Email',
|
||||||
|
name: 'userEmail',
|
||||||
|
type: 'string',
|
||||||
|
hint: 'Enter the user email',
|
||||||
|
placeholder: 'e.g. sales@example.com',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$',
|
||||||
|
errorMessage: 'Please enter a valid email address.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'By ID',
|
||||||
|
name: 'userId',
|
||||||
|
type: 'string',
|
||||||
|
hint: 'Enter the user id',
|
||||||
|
placeholder: 'e.g. 123456789879230471055',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* user:addToGroup */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Group',
|
||||||
|
name: 'groupId',
|
||||||
|
required: true,
|
||||||
|
type: 'resourceLocator',
|
||||||
|
default: {
|
||||||
|
mode: 'list',
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
description: 'Select the group to perform the operation on',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: ['user'],
|
||||||
|
operation: ['addToGroup', 'removeFromGroup'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modes: [
|
||||||
|
{
|
||||||
|
displayName: 'From list',
|
||||||
|
name: 'list',
|
||||||
|
type: 'list',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'searchGroups',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'By ID',
|
||||||
|
name: 'groupId',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'e.g. 0123kx3o1habcdf',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* user:create */
|
/* user:create */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
displayName: 'First Name',
|
displayName: 'First Name',
|
||||||
name: 'firstName',
|
name: 'firstName',
|
||||||
|
placeholder: 'e.g. Nathan',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: true,
|
required: true,
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
@@ -69,6 +231,7 @@ export const userFields: INodeProperties[] = [
|
|||||||
name: 'lastName',
|
name: 'lastName',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: true,
|
required: true,
|
||||||
|
placeholder: 'e.g. Smith',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
operation: ['create'],
|
operation: ['create'],
|
||||||
@@ -95,6 +258,21 @@ export const userFields: INodeProperties[] = [
|
|||||||
description:
|
description:
|
||||||
'Stores the password for the user account. A minimum of 8 characters is required. The maximum length is 100 characters.',
|
'Stores the password for the user account. A minimum of 8 characters is required. The maximum length is 100 characters.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Username',
|
||||||
|
name: 'username',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'e.g. n.smith',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['create'],
|
||||||
|
resource: ['user'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description:
|
||||||
|
"The username that will be set to the user. Example: If you domain is example.com and you set the username to n.smith then the user's final email address will be n.smith@example.com.",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Domain Name or ID',
|
displayName: 'Domain Name or ID',
|
||||||
name: 'domain',
|
name: 'domain',
|
||||||
@@ -113,34 +291,6 @@ export const userFields: INodeProperties[] = [
|
|||||||
},
|
},
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
displayName: 'Username',
|
|
||||||
name: 'username',
|
|
||||||
type: 'string',
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: ['create'],
|
|
||||||
resource: ['user'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: '',
|
|
||||||
description:
|
|
||||||
"The username that will be set to the user. Example: If you domain is example.com and you set the username to jhon then the user's final email address will be jhon@example.com.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Make Admin',
|
|
||||||
name: 'makeAdmin',
|
|
||||||
type: 'boolean',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: ['create'],
|
|
||||||
resource: ['user'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: false,
|
|
||||||
description: 'Whether to make a user a super administrator',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
displayName: 'Additional Fields',
|
displayName: 'Additional Fields',
|
||||||
name: 'additionalFields',
|
name: 'additionalFields',
|
||||||
@@ -155,9 +305,8 @@ export const userFields: INodeProperties[] = [
|
|||||||
},
|
},
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
displayName: 'Change Password At Next Login',
|
displayName: 'Change Password at Next Login',
|
||||||
name: 'changePasswordAtNextLogin',
|
name: 'changePasswordAtNextLogin',
|
||||||
|
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: false,
|
default: false,
|
||||||
description: 'Whether the user is forced to change their password at next login',
|
description: 'Whether the user is forced to change their password at next login',
|
||||||
@@ -214,8 +363,7 @@ export const userFields: INodeProperties[] = [
|
|||||||
value: 'home_fax',
|
value: 'home_fax',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
|
name: 'ISDN',
|
||||||
name: 'isdn',
|
|
||||||
value: 'isdn',
|
value: 'isdn',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -247,8 +395,7 @@ export const userFields: INodeProperties[] = [
|
|||||||
value: 'telex',
|
value: 'telex',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
|
name: 'TTY TDD',
|
||||||
name: 'tty tdd',
|
|
||||||
value: 'tty_tdd',
|
value: 'tty_tdd',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -282,8 +429,7 @@ export const userFields: INodeProperties[] = [
|
|||||||
name: 'primary',
|
name: 'primary',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: false,
|
default: false,
|
||||||
description:
|
description: "Whether this is the user's primary phone number",
|
||||||
"Whether this is the user's primary phone number. A user may only have one primary phone number.",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -334,94 +480,181 @@ export const userFields: INodeProperties[] = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* user:delete */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
{
|
{
|
||||||
displayName: 'User ID',
|
displayName: 'Roles',
|
||||||
name: 'userId',
|
name: 'roles',
|
||||||
type: 'string',
|
type: 'multiOptions',
|
||||||
required: true,
|
default: [],
|
||||||
displayOptions: {
|
description: 'Select the roles you want to assign to the user',
|
||||||
show: {
|
options: rolesOptions,
|
||||||
operation: ['delete'],
|
|
||||||
resource: ['user'],
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Custom Fields',
|
||||||
|
name: 'customFields',
|
||||||
|
placeholder: 'Add or Edit Custom Fields',
|
||||||
|
type: 'fixedCollection',
|
||||||
|
typeOptions: {
|
||||||
|
multipleValues: true,
|
||||||
|
},
|
||||||
|
default: {},
|
||||||
|
description: 'Allows editing and adding of custom fields',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'fieldValues',
|
||||||
|
displayName: 'Field',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
displayName: 'Schema Name or ID',
|
||||||
|
name: 'schemaName',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getSchemas',
|
||||||
},
|
},
|
||||||
default: '',
|
default: '',
|
||||||
description:
|
description:
|
||||||
"The value can be the user's primary email address, alias email address, or unique user ID",
|
'Select the schema to use for custom fields. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Field Name or ID',
|
||||||
|
name: 'fieldName',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'Enter a field name from the selected schema',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Value',
|
||||||
|
name: 'value',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'Provide a value for the selected field',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* user:get */
|
/* user:get */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
displayName: 'User ID',
|
displayName: 'Output',
|
||||||
name: 'userId',
|
name: 'output',
|
||||||
type: 'string',
|
type: 'options',
|
||||||
required: true,
|
required: true,
|
||||||
|
default: 'simplified',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
operation: ['get'],
|
operation: ['get'],
|
||||||
resource: ['user'],
|
resource: ['user'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
default: '',
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Simplified',
|
||||||
|
value: 'simplified',
|
||||||
description:
|
description:
|
||||||
"The value can be the user's primary email address, alias email address, or unique user ID",
|
'Only return specific fields: kind, ID, primaryEmail, name (with subfields), isAdmin, lastLoginTime, creationTime, and suspended',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Projection',
|
name: 'Raw',
|
||||||
|
value: 'raw',
|
||||||
|
description: 'Return all fields from the API response',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Select Included Fields',
|
||||||
|
value: 'select',
|
||||||
|
description: 'Choose specific fields to include',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Fields',
|
||||||
|
name: 'fields',
|
||||||
|
type: 'multiOptions',
|
||||||
|
default: [],
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
output: ['select'],
|
||||||
|
operation: ['get'],
|
||||||
|
resource: ['user'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Creation Time',
|
||||||
|
value: 'creationTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Is Admin',
|
||||||
|
value: 'isAdmin',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Kind',
|
||||||
|
value: 'kind',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Last Login Time',
|
||||||
|
value: 'lastLoginTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Name',
|
||||||
|
value: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Primary Email',
|
||||||
|
value: 'primaryEmail',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Suspended',
|
||||||
|
value: 'suspended',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
description: 'Fields to include in the response when "Select Included Fields" is chosen',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Custom Fields',
|
||||||
name: 'projection',
|
name: 'projection',
|
||||||
type: 'options',
|
type: 'options',
|
||||||
required: true,
|
required: true,
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Basic',
|
name: "Don't Include",
|
||||||
value: 'basic',
|
value: 'basic',
|
||||||
description: 'Do not include any custom fields for the user',
|
description: 'Do not include any custom fields for the user',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Custom',
|
name: 'Custom',
|
||||||
value: 'custom',
|
value: 'custom',
|
||||||
description: 'Include custom fields from schemas requested in customField',
|
description: 'Include custom fields from schemas requested in Custom Schema Names or IDs',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Full',
|
name: 'Include All',
|
||||||
value: 'full',
|
value: 'full',
|
||||||
description: 'Include all fields associated with this user',
|
description: 'Include all fields associated with this user',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
default: 'basic',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
operation: ['get'],
|
operation: ['get'],
|
||||||
resource: ['user'],
|
resource: ['user'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
default: 'basic',
|
|
||||||
description: 'What subset of fields to fetch for this user',
|
description: 'What subset of fields to fetch for this user',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
displayName: 'Options',
|
|
||||||
name: 'options',
|
|
||||||
type: 'collection',
|
|
||||||
placeholder: 'Add option',
|
|
||||||
default: {},
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: ['get'],
|
|
||||||
resource: ['user'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
options: [
|
|
||||||
{
|
{
|
||||||
displayName: 'Custom Schema Names or IDs',
|
displayName: 'Custom Schema Names or IDs',
|
||||||
name: 'customFieldMask',
|
name: 'customFieldMask',
|
||||||
type: 'multiOptions',
|
type: 'multiOptions',
|
||||||
|
required: true,
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
|
operation: ['get'],
|
||||||
|
resource: ['user'],
|
||||||
'/projection': ['custom'],
|
'/projection': ['custom'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -430,32 +663,9 @@ export const userFields: INodeProperties[] = [
|
|||||||
},
|
},
|
||||||
default: [],
|
default: [],
|
||||||
description:
|
description:
|
||||||
'A comma-separated list of schema names. All fields from these schemas are fetched. This should only be set when projection=custom. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
'A comma-separated list of schema names. All fields from these schemas are fetched. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'View Type',
|
|
||||||
name: 'viewType',
|
|
||||||
type: 'options',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
name: 'Admin View',
|
|
||||||
value: 'admin_view',
|
|
||||||
description:
|
|
||||||
'Results include both administrator-only and domain-public fields for the user',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Descending',
|
|
||||||
value: 'DESCENDING',
|
|
||||||
description:
|
|
||||||
'Results only include fields for the user that are publicly visible to other users in the domain',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
default: 'admin_view',
|
|
||||||
description:
|
|
||||||
'Whether to fetch the administrator-only or domain-wide public view of the user. For more information, see Retrieve a user as a non-administrator.',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* user:getAll */
|
/* user:getAll */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@@ -491,41 +701,135 @@ export const userFields: INodeProperties[] = [
|
|||||||
description: 'Max number of results to return',
|
description: 'Max number of results to return',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Projection',
|
displayName: 'Output',
|
||||||
name: 'projection',
|
name: 'output',
|
||||||
type: 'options',
|
type: 'options',
|
||||||
required: true,
|
required: true,
|
||||||
options: [
|
default: 'simplified',
|
||||||
{
|
|
||||||
name: 'Basic',
|
|
||||||
value: 'basic',
|
|
||||||
description: 'Do not include any custom fields for the user',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Custom',
|
|
||||||
value: 'custom',
|
|
||||||
description: 'Include custom fields from schemas requested in customField',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Full',
|
|
||||||
value: 'full',
|
|
||||||
description: 'Include all fields associated with this user',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
operation: ['getAll'],
|
operation: ['getAll'],
|
||||||
resource: ['user'],
|
resource: ['user'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Simplified',
|
||||||
|
value: 'simplified',
|
||||||
|
description:
|
||||||
|
'Only return specific fields: kind, ID, primaryEmail, name (with subfields), isAdmin, lastLoginTime, creationTime, and suspended',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Raw',
|
||||||
|
value: 'raw',
|
||||||
|
description: 'Return all fields from the API response',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Select Included Fields',
|
||||||
|
value: 'select',
|
||||||
|
description: 'Choose specific fields to include',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Fields',
|
||||||
|
name: 'fields',
|
||||||
|
type: 'multiOptions',
|
||||||
|
default: [],
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
output: ['select'],
|
||||||
|
operation: ['getAll'],
|
||||||
|
resource: ['user'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Creation Time',
|
||||||
|
value: 'creationTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Is Admin',
|
||||||
|
value: 'isAdmin',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Kind',
|
||||||
|
value: 'kind',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Last Login Time',
|
||||||
|
value: 'lastLoginTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Name',
|
||||||
|
value: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Primary Email',
|
||||||
|
value: 'primaryEmail',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Suspended',
|
||||||
|
value: 'suspended',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
description: 'Fields to include in the response when "Select Included Fields" is chosen',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Custom Fields',
|
||||||
|
name: 'projection',
|
||||||
|
type: 'options',
|
||||||
|
required: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['getAll'],
|
||||||
|
resource: ['user'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: "Don't Include",
|
||||||
|
value: 'basic',
|
||||||
|
description: 'Do not include any custom fields for the user',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Custom',
|
||||||
|
value: 'custom',
|
||||||
|
description: 'Include custom fields from schemas requested in Custom Schema Names or IDs',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Include All',
|
||||||
|
value: 'full',
|
||||||
|
description: 'Include all fields associated with this user',
|
||||||
|
},
|
||||||
|
],
|
||||||
default: 'basic',
|
default: 'basic',
|
||||||
description: 'What subset of fields to fetch for this user',
|
description: 'What subset of fields to fetch for this user',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Options',
|
displayName: 'Custom Schema Names or IDs',
|
||||||
name: 'options',
|
name: 'customFieldMask',
|
||||||
|
type: 'multiOptions',
|
||||||
|
required: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['getAll'],
|
||||||
|
resource: ['user'],
|
||||||
|
'/projection': ['custom'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getSchemas',
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
description:
|
||||||
|
'A comma-separated list of schema names. All fields from these schemas are fetched. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Filter',
|
||||||
|
name: 'filter',
|
||||||
type: 'collection',
|
type: 'collection',
|
||||||
placeholder: 'Add option',
|
placeholder: 'Add Filter',
|
||||||
default: {},
|
default: {},
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
@@ -534,37 +838,55 @@ export const userFields: INodeProperties[] = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
options: [
|
options: [
|
||||||
{
|
|
||||||
displayName: 'Custom Schema Names or IDs',
|
|
||||||
name: 'customFieldMask',
|
|
||||||
type: 'multiOptions',
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
'/projection': ['custom'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
typeOptions: {
|
|
||||||
loadOptionsMethod: 'getSchemas',
|
|
||||||
},
|
|
||||||
default: [],
|
|
||||||
description:
|
|
||||||
'A comma-separated list of schema names. All fields from these schemas are fetched. This should only be set when projection=custom. Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
displayName: 'Customer',
|
displayName: 'Customer',
|
||||||
name: 'customer',
|
name: 'customer',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
description:
|
description: "The unique ID for the customer's Google Workspace account",
|
||||||
"The unique ID for the customer's Google Workspace account. In case of a multi-domain account, to fetch all groups for a customer, fill this field instead of domain.",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Domain',
|
displayName: 'Domain',
|
||||||
name: 'domain',
|
name: 'domain',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
description: 'The domain name. Use this field to get fields from only one domain.',
|
description: 'The domain name. Use this field to get groups from a specific domain.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Query',
|
||||||
|
name: 'query',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'e.g. name:contact* email:contact*',
|
||||||
|
default: '',
|
||||||
|
description:
|
||||||
|
'Query string to filter the results. Follow Google Admin SDK documentation. <a href="https://developers.google.com/admin-sdk/directory/v1/guides/search-users#examples" target="_blank">More info</a>.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Show Deleted',
|
||||||
|
name: 'showDeleted',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: 'Whether retrieve the list of deleted users',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Sort',
|
||||||
|
name: 'sort',
|
||||||
|
type: 'fixedCollection',
|
||||||
|
placeholder: 'Add Sort Rule',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['getAll'],
|
||||||
|
resource: ['user'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'sortRules',
|
||||||
|
displayName: 'Sort Rules',
|
||||||
|
values: [
|
||||||
{
|
{
|
||||||
displayName: 'Order By',
|
displayName: 'Order By',
|
||||||
name: 'orderBy',
|
name: 'orderBy',
|
||||||
@@ -584,22 +906,7 @@ export const userFields: INodeProperties[] = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
default: '',
|
default: '',
|
||||||
description: 'Property to use for sorting results',
|
description: 'Field to sort the results by',
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Query',
|
|
||||||
name: 'query',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
description:
|
|
||||||
'Free text search terms to find users that match these terms in any field, except for extended properties. For more information on constructing user queries, see <a href="https://developers.google.com/admin-sdk/directory/v1/guides/search-users">Search for Users</a>.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Show Deleted',
|
|
||||||
name: 'showDeleted',
|
|
||||||
type: 'boolean',
|
|
||||||
default: false,
|
|
||||||
description: 'Whether to retrieve the list of deleted users',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Sort Order',
|
displayName: 'Sort Order',
|
||||||
@@ -615,51 +922,18 @@ export const userFields: INodeProperties[] = [
|
|||||||
value: 'DESCENDING',
|
value: 'DESCENDING',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
default: '',
|
default: 'ASCENDING',
|
||||||
description: 'Whether to return results in ascending or descending order',
|
description: 'Sort order direction',
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'View Type',
|
|
||||||
name: 'viewType',
|
|
||||||
type: 'options',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
name: 'Admin View',
|
|
||||||
value: 'admin_view',
|
|
||||||
description:
|
|
||||||
'Results include both administrator-only and domain-public fields for the user',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Descending',
|
|
||||||
value: 'DESCENDING',
|
|
||||||
description:
|
|
||||||
'Results only include fields for the user that are publicly visible to other users in the domain',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
default: 'admin_view',
|
|
||||||
description:
|
|
||||||
'Whether to fetch the administrator-only or domain-wide public view of the user. For more information, see Retrieve a user as a non-administrator.',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
description: 'Define sorting rules for the results',
|
||||||
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* user:update */
|
/* user:update */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
|
||||||
displayName: 'User ID',
|
|
||||||
name: 'userId',
|
|
||||||
type: 'string',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: ['update'],
|
|
||||||
resource: ['user'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: '',
|
|
||||||
description:
|
|
||||||
"The value can be the user's primary email address, alias email address, or unique user ID",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
displayName: 'Update Fields',
|
displayName: 'Update Fields',
|
||||||
name: 'updateFields',
|
name: 'updateFields',
|
||||||
@@ -681,9 +955,16 @@ export const userFields: INodeProperties[] = [
|
|||||||
description: 'Whether user is archived',
|
description: 'Whether user is archived',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Change Password At Next Login',
|
displayName: 'Suspend',
|
||||||
|
name: 'suspendUi',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description:
|
||||||
|
'Whether to set the user as suspended. If set to OFF, the user will be reactivated. If not added, the status will remain unchanged.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Change Password at Next Login',
|
||||||
name: 'changePasswordAtNextLogin',
|
name: 'changePasswordAtNextLogin',
|
||||||
|
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: false,
|
default: false,
|
||||||
description: 'Whether the user is forced to change their password at next login',
|
description: 'Whether the user is forced to change their password at next login',
|
||||||
@@ -693,12 +974,14 @@ export const userFields: INodeProperties[] = [
|
|||||||
name: 'firstName',
|
name: 'firstName',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
|
placeholder: 'e.g. John',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Last Name',
|
displayName: 'Last Name',
|
||||||
name: 'lastName',
|
name: 'lastName',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
|
placeholder: 'e.g. Doe',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Password',
|
displayName: 'Password',
|
||||||
@@ -706,6 +989,7 @@ export const userFields: INodeProperties[] = [
|
|||||||
type: 'string',
|
type: 'string',
|
||||||
typeOptions: { password: true },
|
typeOptions: { password: true },
|
||||||
default: '',
|
default: '',
|
||||||
|
placeholder: 'e.g. MyStrongP@ssword123',
|
||||||
description:
|
description:
|
||||||
'Stores the password for the user account. A minimum of 8 characters is required. The maximum length is 100 characters.',
|
'Stores the password for the user account. A minimum of 8 characters is required. The maximum length is 100 characters.',
|
||||||
},
|
},
|
||||||
@@ -761,7 +1045,7 @@ export const userFields: INodeProperties[] = [
|
|||||||
value: 'home_fax',
|
value: 'home_fax',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Isdn',
|
name: 'ISDN',
|
||||||
value: 'isdn',
|
value: 'isdn',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -793,7 +1077,7 @@ export const userFields: INodeProperties[] = [
|
|||||||
value: 'telex',
|
value: 'telex',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Tty Tdd',
|
name: 'TTY TDD',
|
||||||
value: 'tty_tdd',
|
value: 'tty_tdd',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -821,6 +1105,7 @@ export const userFields: INodeProperties[] = [
|
|||||||
name: 'value',
|
name: 'value',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
|
placeholder: 'e.g. +1234567890',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Primary',
|
displayName: 'Primary',
|
||||||
@@ -839,6 +1124,7 @@ export const userFields: INodeProperties[] = [
|
|||||||
name: 'primaryEmail',
|
name: 'primaryEmail',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
|
placeholder: 'e.g. john.doe@example.com',
|
||||||
description:
|
description:
|
||||||
"The user's primary email address. This property is required in a request to create a user account. The primaryEmail must be unique and cannot be an alias of another user.",
|
"The user's primary email address. This property is required in a request to create a user account. The primaryEmail must be unique and cannot be an alias of another user.",
|
||||||
},
|
},
|
||||||
@@ -882,6 +1168,61 @@ export const userFields: INodeProperties[] = [
|
|||||||
name: 'address',
|
name: 'address',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
|
placeholder: 'e.g. john.doe.work@example.com',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Roles',
|
||||||
|
name: 'roles',
|
||||||
|
type: 'multiOptions',
|
||||||
|
default: [],
|
||||||
|
description: 'Select the roles you want to assign to the user',
|
||||||
|
options: rolesOptions,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Custom Fields',
|
||||||
|
name: 'customFields',
|
||||||
|
placeholder: 'Add or Edit Custom Fields',
|
||||||
|
type: 'fixedCollection',
|
||||||
|
typeOptions: {
|
||||||
|
multipleValues: true,
|
||||||
|
},
|
||||||
|
default: {},
|
||||||
|
description: 'Allows editing and adding of custom fields',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'fieldValues',
|
||||||
|
displayName: 'Field',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
displayName: 'Schema Name or ID',
|
||||||
|
name: 'schemaName',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getSchemas',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description:
|
||||||
|
'Select the schema to use for custom fields. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Field Name or ID',
|
||||||
|
name: 'fieldName',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'Enter a field name from the selected schema',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Value',
|
||||||
|
name: 'value',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'Provide a value for the selected field',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 192 192" height="192" viewBox="0 0 192 192" width="192"><rect fill="none" height="192" width="192"/><g><g><path d="M24.53,130l20.69,35.84c3.27,5.67,9.32,9.16,15.86,9.16h44.06l-7.93-24.07L78.15,130l-26.81-4.66 L24.53,130z" fill="#1967D2"/><path d="M182.06,86.84l-20.09-34.8l-17.28,19.13L134.49,96l11.08,26.57l16.27,17.6l20.22-35.01 C185.33,99.49,185.33,92.51,182.06,86.84z" fill="#1967D2"/><path d="M105.15,17H61.09c-6.54,0-12.59,3.49-15.86,9.16L24.53,62l26.81,4.66L78.15,62l19.57-20.93L105.15,17z" fill="#1967D2"/><path d="M57.75,96l20.4-34H24.53L10.19,86.84c-3.27,5.67-3.27,12.65,0,18.32L24.53,130h53.62L57.75,96z" fill="#4285F4"/><path d="M114.09,62l20.4,34l27.47-43.96l-14.94-25.88c-3.27-5.67-9.32-9.16-15.86-9.16h-26.01l-27,45H114.09z" fill="#4285F4"/><path d="M114.09,130H78.15l27,45h26.01c6.54,0,12.59-3.49,15.86-9.16l14.82-25.67L134.49,96L114.09,130z" fill="#4285F4"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 956 B |
Binary file not shown.
|
Before Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,538 @@
|
|||||||
|
import type { ILoadOptionsFunctions, IExecuteFunctions } from 'n8n-workflow';
|
||||||
|
import { NodeOperationError } from 'n8n-workflow';
|
||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { returnData } from '../../../E2eTest/mock';
|
||||||
|
import { googleApiRequest, googleApiRequestAllItems } from '../GenericFunctions';
|
||||||
|
import { GSuiteAdmin } from '../GSuiteAdmin.node';
|
||||||
|
|
||||||
|
jest.mock('../GenericFunctions', () => ({
|
||||||
|
getGoogleAuth: jest.fn().mockImplementation(() => ({
|
||||||
|
oauth2Client: {
|
||||||
|
setCredentials: jest.fn(),
|
||||||
|
getAccessToken: jest.fn().mockResolvedValue('mock-access-token'),
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
googleApiRequest: jest.fn(),
|
||||||
|
googleApiRequestAllItems: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const node = new GSuiteAdmin();
|
||||||
|
|
||||||
|
const mockThis = {
|
||||||
|
getNode: () => ({
|
||||||
|
name: 'Google Workspace Admin',
|
||||||
|
parameters: {},
|
||||||
|
}),
|
||||||
|
helpers: {
|
||||||
|
httpRequestWithAuthentication: jest.fn(),
|
||||||
|
returnJsonArray: (data: any) => data,
|
||||||
|
constructExecutionMetaData: (data: any) => data,
|
||||||
|
},
|
||||||
|
continueOnFail: () => false,
|
||||||
|
getNodeParameter: jest.fn((name: string) => {
|
||||||
|
if (name === 'limit') return 50;
|
||||||
|
return undefined;
|
||||||
|
}),
|
||||||
|
} as unknown as ILoadOptionsFunctions;
|
||||||
|
|
||||||
|
describe('GSuiteAdmin Node - loadOptions', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
nock.cleanAll();
|
||||||
|
nock.disableNetConnect();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getDomains', () => {
|
||||||
|
it('should return a list of domains', async () => {
|
||||||
|
(googleApiRequestAllItems as jest.Mock).mockResolvedValue([
|
||||||
|
{ domainName: 'example.com' },
|
||||||
|
{ domainName: 'test.com' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await node.methods.loadOptions.getDomains.call(mockThis);
|
||||||
|
expect(result).toEqual([
|
||||||
|
{ name: 'example.com', value: 'example.com' },
|
||||||
|
{ name: 'test.com', value: 'test.com' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getSchemas', () => {
|
||||||
|
it('should return a list of schemas', async () => {
|
||||||
|
(googleApiRequestAllItems as jest.Mock).mockResolvedValue([
|
||||||
|
{ displayName: 'Employee Info', schemaName: 'EmployeeSchema' },
|
||||||
|
{ displayName: '', schemaName: 'CustomSchema' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await node.methods.loadOptions.getSchemas.call(mockThis);
|
||||||
|
expect(result).toEqual([
|
||||||
|
{ name: 'Employee Info', value: 'EmployeeSchema' },
|
||||||
|
{ name: 'CustomSchema', value: 'CustomSchema' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly iterate over schemas and return expected values', async () => {
|
||||||
|
const schemas = [
|
||||||
|
{ displayName: 'Employee Info', schemaName: 'EmployeeSchema' },
|
||||||
|
{ displayName: 'Custom Schema', schemaName: 'CustomSchema' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const result = schemas.map((schema) => ({
|
||||||
|
name: schema.displayName,
|
||||||
|
value: schema.schemaName,
|
||||||
|
}));
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{ name: 'Employee Info', value: 'EmployeeSchema' },
|
||||||
|
{ name: 'Custom Schema', value: 'CustomSchema' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getOrgUnits', () => {
|
||||||
|
it('should return a list of organizational units', async () => {
|
||||||
|
(googleApiRequest as jest.Mock).mockResolvedValue({
|
||||||
|
organizationUnits: [
|
||||||
|
{ name: 'Engineering', orgUnitPath: '/engineering' },
|
||||||
|
{ name: 'HR', orgUnitPath: '/hr' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await node.methods.loadOptions.getOrgUnits.call(mockThis);
|
||||||
|
expect(result).toEqual([
|
||||||
|
{ name: 'Engineering', value: '/engineering' },
|
||||||
|
{ name: 'HR', value: '/hr' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('GSuiteAdmin Node - logic coverage', () => {
|
||||||
|
it('should apply all filters correctly into qs', () => {
|
||||||
|
const filter = {
|
||||||
|
customer: 'my_customer',
|
||||||
|
domain: 'example.com',
|
||||||
|
query: 'name:admin',
|
||||||
|
userId: 'user@example.com',
|
||||||
|
showDeleted: true,
|
||||||
|
};
|
||||||
|
const sort = {
|
||||||
|
sortRules: { orderBy: 'email', sortOrder: 'ASCENDING' },
|
||||||
|
};
|
||||||
|
const qs: Record<string, any> = {};
|
||||||
|
|
||||||
|
if (filter.customer) qs.customer = filter.customer;
|
||||||
|
if (filter.domain) qs.domain = filter.domain;
|
||||||
|
if (filter.query) {
|
||||||
|
const query = filter.query.trim();
|
||||||
|
const regex = /^(name|email):\S+$/;
|
||||||
|
if (!regex.test(query)) {
|
||||||
|
throw new NodeOperationError(
|
||||||
|
mockThis.getNode(),
|
||||||
|
'Invalid query format. Query must follow the format "displayName:<value>" or "email:<value>".',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
qs.query = query;
|
||||||
|
}
|
||||||
|
if (filter.userId) qs.userId = filter.userId;
|
||||||
|
if (filter.showDeleted) qs.showDeleted = 'true';
|
||||||
|
if (sort.sortRules) {
|
||||||
|
const { orderBy, sortOrder } = sort.sortRules;
|
||||||
|
if (orderBy) qs.orderBy = orderBy;
|
||||||
|
if (sortOrder) qs.sortOrder = sortOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(qs).toEqual({
|
||||||
|
customer: 'my_customer',
|
||||||
|
domain: 'example.com',
|
||||||
|
query: 'name:admin',
|
||||||
|
userId: 'user@example.com',
|
||||||
|
showDeleted: 'true',
|
||||||
|
orderBy: 'email',
|
||||||
|
sortOrder: 'ASCENDING',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error for invalid query format', () => {
|
||||||
|
const filter = {
|
||||||
|
query: 'invalidQuery',
|
||||||
|
};
|
||||||
|
|
||||||
|
const qs: Record<string, any> = {};
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
if (filter.query) {
|
||||||
|
const query = filter.query.trim();
|
||||||
|
const regex = /^(name|email):\S+$/;
|
||||||
|
if (!regex.test(query)) {
|
||||||
|
throw new NodeOperationError(
|
||||||
|
mockThis.getNode(),
|
||||||
|
'Invalid query format. Query must follow the format "displayName:<value>" or "email:<value>".',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
qs.query = query;
|
||||||
|
}
|
||||||
|
}).toThrow(
|
||||||
|
'Invalid query format. Query must follow the format "displayName:<value>" or "email:<value>".',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should assign my_customer when customer is not defined', () => {
|
||||||
|
const qs: Record<string, any> = {};
|
||||||
|
if (!qs.customer) qs.customer = 'my_customer';
|
||||||
|
expect(qs.customer).toBe('my_customer');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if username is empty', () => {
|
||||||
|
const mock = { getNode: () => ({}) } as IExecuteFunctions;
|
||||||
|
expect(() => {
|
||||||
|
const username = '';
|
||||||
|
if (!username) {
|
||||||
|
throw new NodeOperationError(mock.getNode(), "The parameter 'Username' is empty", {
|
||||||
|
itemIndex: 0,
|
||||||
|
description: "Please fill in the 'Username' parameter to create the user",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).toThrow("The parameter 'Username' is empty");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set phones, emails, roles, and custom fields', () => {
|
||||||
|
const additionalFields = {
|
||||||
|
phoneUi: { phoneValues: [{ type: 'work', value: '123' }] },
|
||||||
|
emailUi: { emailValues: [{ address: 'test@example.com', type: 'home' }] },
|
||||||
|
roles: ['superAdmin', 'groupsAdmin'],
|
||||||
|
customFields: {
|
||||||
|
fieldValues: [{ schemaName: 'CustomSchema', fieldName: 'customField', value: 'abc' }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const body: Record<string, any> = {};
|
||||||
|
if (additionalFields.phoneUi) {
|
||||||
|
body.phones = additionalFields.phoneUi.phoneValues;
|
||||||
|
}
|
||||||
|
if (additionalFields.emailUi) {
|
||||||
|
body.emails = additionalFields.emailUi.emailValues;
|
||||||
|
}
|
||||||
|
if (additionalFields.roles) {
|
||||||
|
const roles = additionalFields.roles;
|
||||||
|
body.roles = {
|
||||||
|
superAdmin: roles.includes('superAdmin'),
|
||||||
|
groupsAdmin: roles.includes('groupsAdmin'),
|
||||||
|
groupsReader: false,
|
||||||
|
groupsEditor: false,
|
||||||
|
userManagement: false,
|
||||||
|
helpDeskAdmin: false,
|
||||||
|
servicesAdmin: false,
|
||||||
|
inventoryReportingAdmin: false,
|
||||||
|
storageAdmin: false,
|
||||||
|
directorySyncAdmin: false,
|
||||||
|
mobileAdmin: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (additionalFields.customFields) {
|
||||||
|
const customSchemas: Record<string, any> = {};
|
||||||
|
for (const field of additionalFields.customFields.fieldValues) {
|
||||||
|
if (
|
||||||
|
!field.schemaName ||
|
||||||
|
!field.fieldName ||
|
||||||
|
field.value === undefined ||
|
||||||
|
field.value === ''
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!customSchemas[field.schemaName]) customSchemas[field.schemaName] = {};
|
||||||
|
customSchemas[field.schemaName][field.fieldName] = field.value;
|
||||||
|
}
|
||||||
|
if (Object.keys(customSchemas).length > 0) {
|
||||||
|
body.customSchemas = customSchemas;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(body).toEqual({
|
||||||
|
phones: [{ type: 'work', value: '123' }],
|
||||||
|
emails: [{ address: 'test@example.com', type: 'home' }],
|
||||||
|
roles: {
|
||||||
|
superAdmin: true,
|
||||||
|
groupsAdmin: true,
|
||||||
|
groupsReader: false,
|
||||||
|
groupsEditor: false,
|
||||||
|
userManagement: false,
|
||||||
|
helpDeskAdmin: false,
|
||||||
|
servicesAdmin: false,
|
||||||
|
inventoryReportingAdmin: false,
|
||||||
|
storageAdmin: false,
|
||||||
|
directorySyncAdmin: false,
|
||||||
|
mobileAdmin: false,
|
||||||
|
},
|
||||||
|
customSchemas: {
|
||||||
|
CustomSchema: { customField: 'abc' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set customFieldMask and fields if projection is custom and output is select', () => {
|
||||||
|
const projection = 'custom';
|
||||||
|
const output = 'select';
|
||||||
|
const fields = ['primaryEmail'];
|
||||||
|
const qs: Record<string, any> = {
|
||||||
|
customFieldMask: ['Custom1', 'Custom2'],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (projection === 'custom' && qs.customFieldMask) {
|
||||||
|
qs.customFieldMask = (qs.customFieldMask as string[]).join(',');
|
||||||
|
}
|
||||||
|
if (output === 'select') {
|
||||||
|
if (!fields.includes('id')) fields.push('id');
|
||||||
|
qs.fields = fields.join(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(qs).toEqual({
|
||||||
|
customFieldMask: 'Custom1,Custom2',
|
||||||
|
fields: 'primaryEmail,id',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set fields for user getAll when returnAll is false', () => {
|
||||||
|
const qs: Record<string, any> = {};
|
||||||
|
const returnAll = false;
|
||||||
|
const fields = ['primaryEmail'];
|
||||||
|
const output = 'select';
|
||||||
|
const projection = 'custom';
|
||||||
|
qs.customFieldMask = ['Custom1', 'Custom2'];
|
||||||
|
|
||||||
|
if (projection === 'custom' && qs.customFieldMask) {
|
||||||
|
qs.customFieldMask = (qs.customFieldMask as string[]).join(',');
|
||||||
|
}
|
||||||
|
if (output === 'select') {
|
||||||
|
if (!fields.includes('id')) fields.push('id');
|
||||||
|
qs.fields = `users(${fields.join(',')})`;
|
||||||
|
}
|
||||||
|
if (!qs.customer) qs.customer = 'my_customer';
|
||||||
|
if (!returnAll) qs.maxResults = 50;
|
||||||
|
|
||||||
|
expect(qs).toEqual({
|
||||||
|
customFieldMask: 'Custom1,Custom2',
|
||||||
|
fields: 'users(primaryEmail,id)',
|
||||||
|
customer: 'my_customer',
|
||||||
|
maxResults: 50,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('GSuiteAdmin Node - user:update logic', () => {
|
||||||
|
it('should build suspended, roles, and customSchemas', async () => {
|
||||||
|
const mockCall = jest.fn().mockResolvedValue([{ success: true }]);
|
||||||
|
(googleApiRequest as jest.Mock).mockImplementation(mockCall);
|
||||||
|
|
||||||
|
const mockContext = {
|
||||||
|
getNode: () => ({ name: 'GSuiteAdmin' }),
|
||||||
|
getNodeParameter: jest.fn((paramName: string) => {
|
||||||
|
switch (paramName) {
|
||||||
|
case 'resource':
|
||||||
|
return 'user';
|
||||||
|
case 'operation':
|
||||||
|
return 'update';
|
||||||
|
case 'userId':
|
||||||
|
return 'user-id-123';
|
||||||
|
case 'updateFields':
|
||||||
|
return {
|
||||||
|
suspendUi: true,
|
||||||
|
roles: ['superAdmin', 'groupsReader'],
|
||||||
|
customFields: {
|
||||||
|
fieldValues: [
|
||||||
|
{ schemaName: 'CustomSchema1', fieldName: 'fieldA', value: 'valueA' },
|
||||||
|
{ schemaName: 'CustomSchema1', fieldName: 'fieldB', value: 'valueB' },
|
||||||
|
{ schemaName: 'CustomSchema2', fieldName: 'fieldX', value: 'valueX' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
helpers: {
|
||||||
|
returnJsonArray: (data: any) => data,
|
||||||
|
constructExecutionMetaData: (data: any) => data,
|
||||||
|
},
|
||||||
|
continueOnFail: () => false,
|
||||||
|
getInputData: () => [{ json: {} }],
|
||||||
|
} as unknown as IExecuteFunctions;
|
||||||
|
|
||||||
|
await new GSuiteAdmin().execute.call(mockContext);
|
||||||
|
|
||||||
|
const calledBody = mockCall.mock.calls[0][2];
|
||||||
|
|
||||||
|
expect(calledBody.suspended).toBe(true);
|
||||||
|
expect(calledBody.roles).toEqual({
|
||||||
|
superAdmin: true,
|
||||||
|
groupsAdmin: false,
|
||||||
|
groupsReader: true,
|
||||||
|
groupsEditor: false,
|
||||||
|
userManagement: false,
|
||||||
|
helpDeskAdmin: false,
|
||||||
|
servicesAdmin: false,
|
||||||
|
inventoryReportingAdmin: false,
|
||||||
|
storageAdmin: false,
|
||||||
|
directorySyncAdmin: false,
|
||||||
|
mobileAdmin: false,
|
||||||
|
});
|
||||||
|
expect(calledBody.customSchemas).toEqual({
|
||||||
|
CustomSchema1: {
|
||||||
|
fieldA: 'valueA',
|
||||||
|
fieldB: 'valueB',
|
||||||
|
},
|
||||||
|
CustomSchema2: {
|
||||||
|
fieldX: 'valueX',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for invalid custom fields', async () => {
|
||||||
|
const mockCall = jest.fn();
|
||||||
|
(googleApiRequest as jest.Mock).mockImplementation(mockCall);
|
||||||
|
|
||||||
|
const mockContextInvalidFields = {
|
||||||
|
getNode: () => ({ name: 'GSuiteAdmin' }),
|
||||||
|
getNodeParameter: jest.fn((paramName: string) => {
|
||||||
|
switch (paramName) {
|
||||||
|
case 'resource':
|
||||||
|
return 'user';
|
||||||
|
case 'operation':
|
||||||
|
return 'update';
|
||||||
|
case 'userId':
|
||||||
|
return 'user-id-456';
|
||||||
|
case 'updateFields':
|
||||||
|
return {
|
||||||
|
customFields: {
|
||||||
|
fieldValues: [
|
||||||
|
{ schemaName: '', fieldName: 'valid', value: 'ok' },
|
||||||
|
{ schemaName: 'ValidSchema', fieldName: 'valid', value: 'ok' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
helpers: {
|
||||||
|
returnJsonArray: (data: any) => data,
|
||||||
|
constructExecutionMetaData: (data: any) => data,
|
||||||
|
},
|
||||||
|
continueOnFail: () => false,
|
||||||
|
getInputData: () => [{ json: {} }],
|
||||||
|
} as unknown as IExecuteFunctions;
|
||||||
|
|
||||||
|
await expect(new GSuiteAdmin().execute.call(mockContextInvalidFields)).rejects.toThrow(
|
||||||
|
'Invalid custom field data',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(mockCall).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if username is empty', () => {
|
||||||
|
const mock = { getNode: () => ({}) } as IExecuteFunctions;
|
||||||
|
expect(() => {
|
||||||
|
const username = '';
|
||||||
|
if (!username) {
|
||||||
|
throw new NodeOperationError(mock.getNode(), "The parameter 'Username' is empty", {
|
||||||
|
itemIndex: 0,
|
||||||
|
description: "Please fill in the 'Username' parameter to create the user",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).toThrow("The parameter 'Username' is empty");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('GSuiteAdmin Node - Error Handling', () => {
|
||||||
|
it('should throw a NodeOperationError if the error is an instance of NodeOperationError', async () => {
|
||||||
|
const mockContext = {
|
||||||
|
getNode: () => ({ name: 'GSuiteAdmin' }),
|
||||||
|
continueOnFail: () => false,
|
||||||
|
helpers: {
|
||||||
|
constructExecutionMetaData: jest.fn(),
|
||||||
|
returnJsonArray: jest.fn(),
|
||||||
|
},
|
||||||
|
} as unknown as IExecuteFunctions;
|
||||||
|
|
||||||
|
const error = new NodeOperationError(mockContext.getNode(), 'Some error message');
|
||||||
|
|
||||||
|
await expect(async () => {
|
||||||
|
throw error;
|
||||||
|
}).rejects.toThrow(NodeOperationError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle error when continueOnFail is true and constructExecutionMetaData is called', async () => {
|
||||||
|
const mockContext = {
|
||||||
|
getNode: () => ({ name: 'GSuiteAdmin' }),
|
||||||
|
continueOnFail: () => true,
|
||||||
|
helpers: {
|
||||||
|
constructExecutionMetaData: jest.fn().mockReturnValue([{ message: 'mock error data' }]),
|
||||||
|
returnJsonArray: jest.fn().mockReturnValue([]),
|
||||||
|
},
|
||||||
|
} as unknown as IExecuteFunctions;
|
||||||
|
|
||||||
|
const error = new Error('Some error message');
|
||||||
|
|
||||||
|
await expect(async () => {
|
||||||
|
if (error instanceof NodeOperationError) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mockContext.continueOnFail()) {
|
||||||
|
const executionErrorData = mockContext.helpers.constructExecutionMetaData(
|
||||||
|
mockContext.helpers.returnJsonArray({
|
||||||
|
message: 'Operation "update" failed for resource "user".',
|
||||||
|
description: error.message,
|
||||||
|
}),
|
||||||
|
{ itemData: { item: 0 } },
|
||||||
|
);
|
||||||
|
|
||||||
|
if (executionErrorData) {
|
||||||
|
returnData.push(...executionErrorData);
|
||||||
|
} else {
|
||||||
|
console.error('executionErrorData is not iterable:', executionErrorData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NodeOperationError(
|
||||||
|
mockContext.getNode(),
|
||||||
|
'Operation "update" failed for resource "user".',
|
||||||
|
{
|
||||||
|
description: `Please check the input parameters and ensure the API request is correctly formatted. Details: ${error.message}`,
|
||||||
|
itemIndex: 0,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}).rejects.toThrow(NodeOperationError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw a NodeOperationError if an unknown error is thrown and continueOnFail is false', async () => {
|
||||||
|
const mockContext = {
|
||||||
|
getNode: () => ({ name: 'GSuiteAdmin' }),
|
||||||
|
continueOnFail: () => false,
|
||||||
|
helpers: {
|
||||||
|
constructExecutionMetaData: jest.fn(),
|
||||||
|
returnJsonArray: jest.fn(),
|
||||||
|
},
|
||||||
|
} as unknown as IExecuteFunctions;
|
||||||
|
|
||||||
|
const error = new Error('Some unknown error');
|
||||||
|
|
||||||
|
await expect(async () => {
|
||||||
|
if (error instanceof NodeOperationError) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mockContext.continueOnFail()) {
|
||||||
|
throw new NodeOperationError(
|
||||||
|
mockContext.getNode(),
|
||||||
|
'Operation "update" failed for resource "user".',
|
||||||
|
{
|
||||||
|
description: `Please check the input parameters and ensure the API request is correctly formatted. Details: ${error.message}`,
|
||||||
|
itemIndex: 0,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}).rejects.toThrow(NodeOperationError);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
import type { IExecuteFunctions, ILoadOptionsFunctions } from 'n8n-workflow';
|
||||||
|
import { NodeApiError } from 'n8n-workflow';
|
||||||
|
|
||||||
|
import { googleApiRequest, googleApiRequestAllItems } from '../GenericFunctions';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node', () => {
|
||||||
|
let mockContext: IExecuteFunctions | ILoadOptionsFunctions;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockContext = {
|
||||||
|
helpers: {
|
||||||
|
httpRequestWithAuthentication: jest.fn(),
|
||||||
|
},
|
||||||
|
getNode: jest.fn(),
|
||||||
|
} as unknown as IExecuteFunctions | ILoadOptionsFunctions;
|
||||||
|
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should make a successful API request with default options', async () => {
|
||||||
|
(mockContext.helpers.httpRequestWithAuthentication as jest.Mock).mockResolvedValueOnce({
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await googleApiRequest.call(mockContext, 'GET', '/example/resource');
|
||||||
|
|
||||||
|
expect(mockContext.helpers.httpRequestWithAuthentication).toHaveBeenCalledWith(
|
||||||
|
'gSuiteAdminOAuth2Api',
|
||||||
|
expect.objectContaining({
|
||||||
|
method: 'GET',
|
||||||
|
url: 'https://www.googleapis.com/admin/example/resource',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
json: true,
|
||||||
|
qs: {},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
expect(result).toEqual({ success: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should omit the body if it is empty', async () => {
|
||||||
|
(mockContext.helpers.httpRequestWithAuthentication as jest.Mock).mockResolvedValueOnce({
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
await googleApiRequest.call(mockContext, 'GET', '/example/resource', {});
|
||||||
|
|
||||||
|
expect(mockContext.helpers.httpRequestWithAuthentication).toHaveBeenCalledWith(
|
||||||
|
'gSuiteAdminOAuth2Api',
|
||||||
|
expect.not.objectContaining({ body: expect.anything() }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw a NodeApiError if the request fails', async () => {
|
||||||
|
const errorResponse = { message: 'API Error' };
|
||||||
|
(mockContext.helpers.httpRequestWithAuthentication as jest.Mock).mockRejectedValueOnce(
|
||||||
|
errorResponse,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(googleApiRequest.call(mockContext, 'GET', '/example/resource')).rejects.toThrow(
|
||||||
|
NodeApiError,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(mockContext.getNode).toHaveBeenCalled();
|
||||||
|
expect(mockContext.helpers.httpRequestWithAuthentication).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return all items across multiple pages', async () => {
|
||||||
|
(mockContext.helpers.httpRequestWithAuthentication as jest.Mock)
|
||||||
|
.mockResolvedValueOnce({
|
||||||
|
nextPageToken: 'pageToken1',
|
||||||
|
items: [{ id: '1' }, { id: '2' }],
|
||||||
|
})
|
||||||
|
.mockResolvedValueOnce({
|
||||||
|
nextPageToken: 'pageToken2',
|
||||||
|
items: [{ id: '3' }, { id: '4' }],
|
||||||
|
})
|
||||||
|
.mockResolvedValueOnce({
|
||||||
|
nextPageToken: '',
|
||||||
|
items: [{ id: '5' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await googleApiRequestAllItems.call(
|
||||||
|
mockContext,
|
||||||
|
'items',
|
||||||
|
'GET',
|
||||||
|
'/example/resource',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual([{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }, { id: '5' }]);
|
||||||
|
expect(mockContext.helpers.httpRequestWithAuthentication).toHaveBeenCalledTimes(3);
|
||||||
|
expect(mockContext.helpers.httpRequestWithAuthentication).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
|
'gSuiteAdminOAuth2Api',
|
||||||
|
expect.objectContaining({
|
||||||
|
method: 'GET',
|
||||||
|
qs: { maxResults: 100, pageToken: '' },
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
url: 'https://www.googleapis.com/admin/example/resource',
|
||||||
|
json: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
expect(mockContext.helpers.httpRequestWithAuthentication).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
'gSuiteAdminOAuth2Api',
|
||||||
|
expect.objectContaining({
|
||||||
|
method: 'GET',
|
||||||
|
qs: { maxResults: 100, pageToken: '' },
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
url: 'https://www.googleapis.com/admin/example/resource',
|
||||||
|
json: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
expect(mockContext.helpers.httpRequestWithAuthentication).toHaveBeenNthCalledWith(
|
||||||
|
3,
|
||||||
|
'gSuiteAdminOAuth2Api',
|
||||||
|
expect.objectContaining({
|
||||||
|
method: 'GET',
|
||||||
|
qs: { maxResults: 100, pageToken: '' },
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
url: 'https://www.googleapis.com/admin/example/resource',
|
||||||
|
json: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle single-page responses', async () => {
|
||||||
|
(mockContext.helpers.httpRequestWithAuthentication as jest.Mock).mockResolvedValueOnce({
|
||||||
|
nextPageToken: '',
|
||||||
|
items: [{ id: '1' }, { id: '2' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await googleApiRequestAllItems.call(
|
||||||
|
mockContext,
|
||||||
|
'items',
|
||||||
|
'GET',
|
||||||
|
'/example/resource',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual([{ id: '1' }, { id: '2' }]);
|
||||||
|
expect(mockContext.helpers.httpRequestWithAuthentication).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty responses', async () => {
|
||||||
|
(mockContext.helpers.httpRequestWithAuthentication as jest.Mock).mockResolvedValueOnce({
|
||||||
|
nextPageToken: '',
|
||||||
|
items: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await googleApiRequestAllItems.call(
|
||||||
|
mockContext,
|
||||||
|
'items',
|
||||||
|
'GET',
|
||||||
|
'/example/resource',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual([]);
|
||||||
|
expect(mockContext.helpers.httpRequestWithAuthentication).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw a NodeApiError if a request fails', async () => {
|
||||||
|
const errorResponse = { message: 'API Error' };
|
||||||
|
(mockContext.helpers.httpRequestWithAuthentication as jest.Mock).mockRejectedValueOnce(
|
||||||
|
errorResponse,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
googleApiRequestAllItems.call(mockContext, 'items', 'GET', '/example/resource'),
|
||||||
|
).rejects.toThrow();
|
||||||
|
|
||||||
|
expect(mockContext.getNode).toHaveBeenCalled();
|
||||||
|
expect(mockContext.helpers.httpRequestWithAuthentication).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
import type { ILoadOptionsFunctions } from 'n8n-workflow';
|
||||||
|
|
||||||
|
import { googleApiRequest, googleApiRequestAllItems } from '../GenericFunctions';
|
||||||
|
import { searchUsers, searchGroups, searchDevices } from '../SearchFunctions';
|
||||||
|
|
||||||
|
jest.mock('../GenericFunctions');
|
||||||
|
|
||||||
|
describe('searchFunctions', () => {
|
||||||
|
let mockContext: ILoadOptionsFunctions;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockContext = {
|
||||||
|
getNodeParameter: jest.fn(),
|
||||||
|
} as unknown as ILoadOptionsFunctions;
|
||||||
|
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('searchUsers', () => {
|
||||||
|
it('should return formatted user search results', async () => {
|
||||||
|
(googleApiRequestAllItems as jest.Mock).mockResolvedValueOnce([
|
||||||
|
{ id: '123', name: { fullName: 'John Doe' } },
|
||||||
|
{ id: '456' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await searchUsers.call(mockContext);
|
||||||
|
|
||||||
|
expect(googleApiRequestAllItems).toHaveBeenCalledWith(
|
||||||
|
expect.anything(),
|
||||||
|
'GET',
|
||||||
|
'/directory/v1/users',
|
||||||
|
{},
|
||||||
|
{ customer: 'my_customer' },
|
||||||
|
);
|
||||||
|
expect(result).toEqual({
|
||||||
|
results: [
|
||||||
|
{ name: 'John Doe', value: '123' },
|
||||||
|
{ name: '456', value: '456' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an empty array if no users found', async () => {
|
||||||
|
(googleApiRequestAllItems as jest.Mock).mockResolvedValueOnce([]);
|
||||||
|
const result = await searchUsers.call(mockContext);
|
||||||
|
expect(result).toEqual({ results: [] });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('searchGroups', () => {
|
||||||
|
it('should return formatted group search results', async () => {
|
||||||
|
(googleApiRequestAllItems as jest.Mock).mockResolvedValueOnce([
|
||||||
|
{ id: 'group1', name: 'Group One' },
|
||||||
|
{ id: 'group2', email: 'group@example.com' },
|
||||||
|
{ id: 'group3' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await searchGroups.call(mockContext);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
results: [
|
||||||
|
{ name: 'Group One', value: 'group1' },
|
||||||
|
{ name: 'group@example.com', value: 'group2' },
|
||||||
|
{ name: 'Unnamed Group', value: 'group3' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty results if no groups found', async () => {
|
||||||
|
(googleApiRequestAllItems as jest.Mock).mockResolvedValueOnce([]);
|
||||||
|
const result = await searchGroups.call(mockContext);
|
||||||
|
expect(result).toEqual({ results: [] });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('searchDevices', () => {
|
||||||
|
it('should return formatted device search results', async () => {
|
||||||
|
(googleApiRequest as jest.Mock).mockResolvedValueOnce({
|
||||||
|
chromeosdevices: [{ deviceId: 'dev1', serialNumber: 'SN123' }, { deviceId: 'Dev2' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await searchDevices.call(mockContext);
|
||||||
|
|
||||||
|
expect(googleApiRequest).toHaveBeenCalledWith(
|
||||||
|
'GET',
|
||||||
|
'/directory/v1/customer/my_customer/devices/chromeos/',
|
||||||
|
{},
|
||||||
|
{ customerId: 'my_customer' },
|
||||||
|
);
|
||||||
|
expect(result).toEqual({
|
||||||
|
results: [
|
||||||
|
{ name: 'SN123', value: 'dev1' },
|
||||||
|
{ name: 'Dev2', value: 'Dev2' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty results if no devices found', async () => {
|
||||||
|
(googleApiRequest as jest.Mock).mockResolvedValueOnce({ chromeosdevices: [] });
|
||||||
|
const result = await searchDevices.call(mockContext);
|
||||||
|
expect(result).toEqual({ results: [] });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('changeStatus.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.post(
|
||||||
|
'/directory/v1/customer/my_customer/devices/chromeos/9140fcff-7ba7-4324-8552-f7de68481b4c/action',
|
||||||
|
{
|
||||||
|
action: 'reenable',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#chromeosdeviceAction',
|
||||||
|
action: 'reenable',
|
||||||
|
status: 'SUCCESS',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [-180, 240],
|
||||||
|
"id": "db450654-d59c-4fb4-a06c-af7b971f0c14",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "device",
|
||||||
|
"operation": "changeStatus",
|
||||||
|
"deviceId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "9140fcff-7ba7-4324-8552-f7de68481b4c",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "5CC115NN33"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [-320, 680],
|
||||||
|
"id": "d441de38-e340-495d-8177-f8bd8bb33e50",
|
||||||
|
"name": "Change Status",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Change Status",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Change Status": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#chromeosdeviceAction",
|
||||||
|
"action": "reenable",
|
||||||
|
"status": "SUCCESS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('get.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.get(
|
||||||
|
'/directory/v1/customer/my_customer/devices/chromeos/9999ffff-7aa7-4444-8555-f7de48484b4a?projection=basic',
|
||||||
|
)
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#chromeosdevice',
|
||||||
|
etag: '"example"',
|
||||||
|
deviceId: '9999ffff-7aa7-4444-8555-f7de48484b4a',
|
||||||
|
serialNumber: '5DD1155DD44',
|
||||||
|
status: 'DISABLED',
|
||||||
|
lastSync: '2025-02-12T07:17:16.950Z',
|
||||||
|
annotatedUser: 'my user',
|
||||||
|
annotatedLocation: 'test',
|
||||||
|
annotatedAssetId: '1234567788',
|
||||||
|
notes: 'test',
|
||||||
|
orgUnitPath: '/',
|
||||||
|
orgUnitId: '00pp8a2z1uu85pp',
|
||||||
|
extendedSupportEligible: false,
|
||||||
|
chromeOsType: 'chromeOs',
|
||||||
|
diskSpaceUsage: {
|
||||||
|
capacityBytes: '549755813888',
|
||||||
|
usedBytes: '549755813888',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0ffead0b-d690-48b8-b406-bea5e0029c15",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "device",
|
||||||
|
"deviceId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "9999ffff-7aa7-4444-8555-f7de48484b4a",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "5DD1155DD44"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [0, 1120],
|
||||||
|
"id": "cda57e63-1620-4f75-b11e-48b83565ad80",
|
||||||
|
"name": "Get Device",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Get Device",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Get Device": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#chromeosdevice",
|
||||||
|
"etag": "\"example\"",
|
||||||
|
"deviceId": "9999ffff-7aa7-4444-8555-f7de48484b4a",
|
||||||
|
"serialNumber": "5DD1155DD44",
|
||||||
|
"status": "DISABLED",
|
||||||
|
"lastSync": "2025-02-12T07:17:16.950Z",
|
||||||
|
"annotatedUser": "my user",
|
||||||
|
"annotatedLocation": "test",
|
||||||
|
"annotatedAssetId": "1234567788",
|
||||||
|
"notes": "test",
|
||||||
|
"orgUnitPath": "/",
|
||||||
|
"orgUnitId": "00pp8a2z1uu85pp",
|
||||||
|
"extendedSupportEligible": false,
|
||||||
|
"chromeOsType": "chromeOs",
|
||||||
|
"diskSpaceUsage": {
|
||||||
|
"capacityBytes": "549755813888",
|
||||||
|
"usedBytes": "549755813888"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('getAll.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.get('/directory/v1/customer/my_customer/devices/chromeos/')
|
||||||
|
.query({
|
||||||
|
customer: 'my_customer',
|
||||||
|
includeChildOrgunits: false,
|
||||||
|
maxResults: 100,
|
||||||
|
orderBy: 'notes',
|
||||||
|
orgUnitPath: '/admin-google Testing OU/Child OU',
|
||||||
|
projection: 'basic',
|
||||||
|
})
|
||||||
|
.reply(200, [
|
||||||
|
{
|
||||||
|
kind: 'admin#directory#chromeosdevices',
|
||||||
|
etag: '"example"',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "device",
|
||||||
|
"operation": "getAll",
|
||||||
|
"filter": {
|
||||||
|
"orgUnitPath": "/admin-google Testing OU/Child OU"
|
||||||
|
},
|
||||||
|
"sort": {
|
||||||
|
"sortRules": {
|
||||||
|
"orderBy": "notes",
|
||||||
|
"sortBy": "ascending"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [40, 1120],
|
||||||
|
"id": "b8a51950-2fdb-4161-9dc3-09f73de5a45b",
|
||||||
|
"name": "Get Many Device",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Get Many Device",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Get Many Device": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#chromeosdevices",
|
||||||
|
"etag": "\"example\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,627 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('update.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.put(
|
||||||
|
'/directory/v1/customer/my_customer/devices/chromeos/9990fpff-8ba8-4444-8555-f7ee88881b4c',
|
||||||
|
)
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#chromeosdevice',
|
||||||
|
etag: '"example"',
|
||||||
|
deviceId: '9990fpff-8ba8-4444-8555-f7ee88881b4c',
|
||||||
|
serialNumber: '5CC115NN33',
|
||||||
|
status: 'DISABLED',
|
||||||
|
lastSync: '2025-02-12T07:17:16.950Z',
|
||||||
|
annotatedUser: 'my user',
|
||||||
|
annotatedLocation: 'test',
|
||||||
|
annotatedAssetId: '1234567788',
|
||||||
|
notes: 'test',
|
||||||
|
model: 'Test Model',
|
||||||
|
osVersion: '129.0.6668.99',
|
||||||
|
platformVersion: '16002.51.0 (Official Build) stable-channel reven',
|
||||||
|
firmwareVersion: 'FirmwareNotParsed',
|
||||||
|
macAddress: '666c8888ffccf',
|
||||||
|
lastEnrollmentTime: '2025-02-10T17:03:10.324Z',
|
||||||
|
firstEnrollmentTime: '2025-02-10T17:03:10.324Z',
|
||||||
|
orgUnitPath: '/',
|
||||||
|
orgUnitId: '00pp88a2z2uu88pp',
|
||||||
|
recentUsers: [
|
||||||
|
{
|
||||||
|
type: 'USER_TYPE_MANAGED',
|
||||||
|
email: 'admin-google@example.com',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
activeTimeRanges: [
|
||||||
|
{
|
||||||
|
date: '2025-02-10',
|
||||||
|
activeTime: 300000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-02-11',
|
||||||
|
activeTime: 1920025,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-02-12',
|
||||||
|
activeTime: 30000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tpmVersionInfo: {
|
||||||
|
family: '0',
|
||||||
|
specLevel: '0',
|
||||||
|
manufacturer: '0',
|
||||||
|
tpmModel: '0',
|
||||||
|
firmwareVersion: '0',
|
||||||
|
vendorSpecific: '',
|
||||||
|
},
|
||||||
|
cpuStatusReports: [
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T17:03:13.233Z',
|
||||||
|
cpuUtilizationPercentageInfo: [12],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T17:04:13.233Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 42,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 42,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 43,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T17:11:01.943Z',
|
||||||
|
cpuUtilizationPercentageInfo: [28],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T17:12:02.223Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 42,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 51,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 43,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T17:47:32.621Z',
|
||||||
|
cpuUtilizationPercentageInfo: [28],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T17:48:42.770Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 43,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 44,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 44,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T18:56:24.294Z',
|
||||||
|
cpuUtilizationPercentageInfo: [29],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T18:57:27.841Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 34,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 35,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 35,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T23:04:56.582Z',
|
||||||
|
cpuUtilizationPercentageInfo: [27],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T23:05:56.563Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 27,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 28,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 27,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T23:56:47.138Z',
|
||||||
|
cpuUtilizationPercentageInfo: [28],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T23:57:50.717Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 39,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 39,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 40,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T07:49:44.333Z',
|
||||||
|
cpuUtilizationPercentageInfo: [26],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T07:50:48.473Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 26,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 27,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 27,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T15:46:23.530Z',
|
||||||
|
cpuUtilizationPercentageInfo: [27],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T15:47:22.723Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 27,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 28,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 27,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T15:52:40.368Z',
|
||||||
|
cpuUtilizationPercentageInfo: [28],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T15:53:41.233Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 34,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 35,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 35,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:06:07.349Z',
|
||||||
|
cpuUtilizationPercentageInfo: [30],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:07:07.921Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 39,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 39,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 40,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:13:28.511Z',
|
||||||
|
cpuUtilizationPercentageInfo: [25],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:14:27.628Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 36,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 37,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 37,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:17:06.188Z',
|
||||||
|
cpuUtilizationPercentageInfo: [27],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:18:06.375Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 40,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 41,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 42,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:36:20.232Z',
|
||||||
|
cpuUtilizationPercentageInfo: [27],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:37:20.599Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 45,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 58,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 45,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:48:45.267Z',
|
||||||
|
cpuUtilizationPercentageInfo: [27],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:49:44.854Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 42,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 44,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 44,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-12T06:35:29.337Z',
|
||||||
|
cpuUtilizationPercentageInfo: [30],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-12T06:36:28.433Z',
|
||||||
|
cpuTemperatureInfo: [
|
||||||
|
{
|
||||||
|
temperature: 42,
|
||||||
|
label: 'edge\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 42,
|
||||||
|
label: 'Tctl\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temperature: 42,
|
||||||
|
label: 'acpitz\n',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
systemRamTotal: '16089374720',
|
||||||
|
systemRamFreeReports: [
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T17:03:13.230Z',
|
||||||
|
systemRamFreeInfo: ['13905453056'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T17:11:01.697Z',
|
||||||
|
systemRamFreeInfo: ['15221055488'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T17:47:32.153Z',
|
||||||
|
systemRamFreeInfo: ['15237283840'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T18:56:23.878Z',
|
||||||
|
systemRamFreeInfo: ['15228760064'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T23:04:56.127Z',
|
||||||
|
systemRamFreeInfo: ['15228022784'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-10T23:56:46.839Z',
|
||||||
|
systemRamFreeInfo: ['15226499072'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T07:49:43.939Z',
|
||||||
|
systemRamFreeInfo: ['15229087744'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T15:46:23.165Z',
|
||||||
|
systemRamFreeInfo: ['15226187776'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T15:52:39.966Z',
|
||||||
|
systemRamFreeInfo: ['15226843136'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:06:06.871Z',
|
||||||
|
systemRamFreeInfo: ['15225753600'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:13:28.176Z',
|
||||||
|
systemRamFreeInfo: ['15228182528'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:17:05.936Z',
|
||||||
|
systemRamFreeInfo: ['15223095296'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:36:19.897Z',
|
||||||
|
systemRamFreeInfo: ['15226126336'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-11T16:48:44.934Z',
|
||||||
|
systemRamFreeInfo: ['15226707968'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reportTime: '2025-02-12T06:35:28.949Z',
|
||||||
|
systemRamFreeInfo: ['15222706176'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
diskVolumeReports: [
|
||||||
|
{
|
||||||
|
volumeInfo: [
|
||||||
|
{
|
||||||
|
volumeId: '/media/archive',
|
||||||
|
storageTotal: '8044687360',
|
||||||
|
storageFree: '8044687360',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
volumeId: '/media/removable',
|
||||||
|
storageTotal: '8044687360',
|
||||||
|
storageFree: '8044687360',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
lastKnownNetwork: [
|
||||||
|
{
|
||||||
|
ipAddress: '192.168.0.106',
|
||||||
|
wanIpAddress: '87.121.13.137',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
cpuInfo: [
|
||||||
|
{
|
||||||
|
model: 'AMD Ryzen 5 4500U with Radeon Graphics',
|
||||||
|
architecture: 'x64',
|
||||||
|
maxClockSpeedKhz: 2375000,
|
||||||
|
logicalCpus: [
|
||||||
|
{
|
||||||
|
maxScalingFrequencyKhz: 2375000,
|
||||||
|
currentScalingFrequencyKhz: 1397253,
|
||||||
|
idleDuration: '60s',
|
||||||
|
cStates: [
|
||||||
|
{
|
||||||
|
displayName: 'C3',
|
||||||
|
sessionDuration: '59.509354s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C1',
|
||||||
|
sessionDuration: '1.338153s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C2',
|
||||||
|
sessionDuration: '0.241264s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'POLL',
|
||||||
|
sessionDuration: '0.004477s',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
maxScalingFrequencyKhz: 2375000,
|
||||||
|
currentScalingFrequencyKhz: 1397372,
|
||||||
|
idleDuration: '60s',
|
||||||
|
cStates: [
|
||||||
|
{
|
||||||
|
displayName: 'C3',
|
||||||
|
sessionDuration: '58.861175s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C1',
|
||||||
|
sessionDuration: '1.335068s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C2',
|
||||||
|
sessionDuration: '0.761853s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'POLL',
|
||||||
|
sessionDuration: '0.007583s',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
maxScalingFrequencyKhz: 2375000,
|
||||||
|
currentScalingFrequencyKhz: 1397454,
|
||||||
|
idleDuration: '58s',
|
||||||
|
cStates: [
|
||||||
|
{
|
||||||
|
displayName: 'C3',
|
||||||
|
sessionDuration: '57.457528s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C1',
|
||||||
|
sessionDuration: '1.280076s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C2',
|
||||||
|
sessionDuration: '0.167642s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'POLL',
|
||||||
|
sessionDuration: '0.003444s',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
maxScalingFrequencyKhz: 2375000,
|
||||||
|
currentScalingFrequencyKhz: 1397348,
|
||||||
|
idleDuration: '59s',
|
||||||
|
cStates: [
|
||||||
|
{
|
||||||
|
displayName: 'C3',
|
||||||
|
sessionDuration: '58.906343s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C1',
|
||||||
|
sessionDuration: '1.101873s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C2',
|
||||||
|
sessionDuration: '0.119013s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'POLL',
|
||||||
|
sessionDuration: '0.009095s',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
maxScalingFrequencyKhz: 2375000,
|
||||||
|
currentScalingFrequencyKhz: 1383188,
|
||||||
|
idleDuration: '60s',
|
||||||
|
cStates: [
|
||||||
|
{
|
||||||
|
displayName: 'C3',
|
||||||
|
sessionDuration: '59.476621s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C1',
|
||||||
|
sessionDuration: '1.048691s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C2',
|
||||||
|
sessionDuration: '0.192808s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'POLL',
|
||||||
|
sessionDuration: '0.003546s',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
maxScalingFrequencyKhz: 2375000,
|
||||||
|
currentScalingFrequencyKhz: 1397437,
|
||||||
|
idleDuration: '60s',
|
||||||
|
cStates: [
|
||||||
|
{
|
||||||
|
displayName: 'C3',
|
||||||
|
sessionDuration: '60.155800s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C1',
|
||||||
|
sessionDuration: '0.681644s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'C2',
|
||||||
|
sessionDuration: '0.143131s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'POLL',
|
||||||
|
sessionDuration: '0.004276s',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extendedSupportEligible: false,
|
||||||
|
chromeOsType: 'chromeOsFlex',
|
||||||
|
diskSpaceUsage: {
|
||||||
|
capacityBytes: '549755813888',
|
||||||
|
usedBytes: '85613068288',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,661 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "device",
|
||||||
|
"operation": "update",
|
||||||
|
"deviceId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "9990fpff-8ba8-4444-8555-f7ee88881b4c",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "5CC115NN33"
|
||||||
|
},
|
||||||
|
"updateOptions": {
|
||||||
|
"notes": "test"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [40, 1140],
|
||||||
|
"id": "52f7a4b5-7ab5-4bd1-b6eb-230341ab6057",
|
||||||
|
"name": "Update Device",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Update Device",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Update Device": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#chromeosdevice",
|
||||||
|
"etag": "\"example\"",
|
||||||
|
"deviceId": "9990fpff-8ba8-4444-8555-f7ee88881b4c",
|
||||||
|
"serialNumber": "5CC115NN33",
|
||||||
|
"status": "DISABLED",
|
||||||
|
"lastSync": "2025-02-12T07:17:16.950Z",
|
||||||
|
"annotatedUser": "my user",
|
||||||
|
"annotatedLocation": "test",
|
||||||
|
"annotatedAssetId": "1234567788",
|
||||||
|
"notes": "test",
|
||||||
|
"model": "Test Model",
|
||||||
|
"osVersion": "129.0.6668.99",
|
||||||
|
"platformVersion": "16002.51.0 (Official Build) stable-channel reven",
|
||||||
|
"firmwareVersion": "FirmwareNotParsed",
|
||||||
|
"macAddress": "666c8888ffccf",
|
||||||
|
"lastEnrollmentTime": "2025-02-10T17:03:10.324Z",
|
||||||
|
"firstEnrollmentTime": "2025-02-10T17:03:10.324Z",
|
||||||
|
"orgUnitPath": "/",
|
||||||
|
"orgUnitId": "00pp88a2z2uu88pp",
|
||||||
|
"recentUsers": [
|
||||||
|
{
|
||||||
|
"type": "USER_TYPE_MANAGED",
|
||||||
|
"email": "admin-google@example.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"activeTimeRanges": [
|
||||||
|
{
|
||||||
|
"date": "2025-02-10",
|
||||||
|
"activeTime": 300000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2025-02-11",
|
||||||
|
"activeTime": 1920025
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2025-02-12",
|
||||||
|
"activeTime": 30000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tpmVersionInfo": {
|
||||||
|
"family": "0",
|
||||||
|
"specLevel": "0",
|
||||||
|
"manufacturer": "0",
|
||||||
|
"tpmModel": "0",
|
||||||
|
"firmwareVersion": "0",
|
||||||
|
"vendorSpecific": ""
|
||||||
|
},
|
||||||
|
"cpuStatusReports": [
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T17:03:13.233Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [12]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T17:04:13.233Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 42,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 42,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 43,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T17:11:01.943Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [28]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T17:12:02.223Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 42,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 51,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 43,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T17:47:32.621Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [28]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T17:48:42.770Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 43,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 44,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 44,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T18:56:24.294Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [29]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T18:57:27.841Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 34,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 35,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 35,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T23:04:56.582Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [27]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T23:05:56.563Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 27,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 28,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 27,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T23:56:47.138Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [28]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T23:57:50.717Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 39,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 39,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 40,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T07:49:44.333Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [26]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T07:50:48.473Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 26,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 27,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 27,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T15:46:23.530Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [27]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T15:47:22.723Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 27,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 28,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 27,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T15:52:40.368Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [28]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T15:53:41.233Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 34,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 35,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 35,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:06:07.349Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [30]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:07:07.921Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 39,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 39,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 40,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:13:28.511Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [25]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:14:27.628Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 36,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 37,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 37,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:17:06.188Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [27]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:18:06.375Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 40,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 41,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 42,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:36:20.232Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [27]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:37:20.599Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 45,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 58,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 45,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:48:45.267Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [27]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:49:44.854Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 42,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 44,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 44,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-12T06:35:29.337Z",
|
||||||
|
"cpuUtilizationPercentageInfo": [30]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-12T06:36:28.433Z",
|
||||||
|
"cpuTemperatureInfo": [
|
||||||
|
{
|
||||||
|
"temperature": 42,
|
||||||
|
"label": "edge\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 42,
|
||||||
|
"label": "Tctl\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"temperature": 42,
|
||||||
|
"label": "acpitz\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"systemRamTotal": "16089374720",
|
||||||
|
"systemRamFreeReports": [
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T17:03:13.230Z",
|
||||||
|
"systemRamFreeInfo": ["13905453056"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T17:11:01.697Z",
|
||||||
|
"systemRamFreeInfo": ["15221055488"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T17:47:32.153Z",
|
||||||
|
"systemRamFreeInfo": ["15237283840"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T18:56:23.878Z",
|
||||||
|
"systemRamFreeInfo": ["15228760064"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T23:04:56.127Z",
|
||||||
|
"systemRamFreeInfo": ["15228022784"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-10T23:56:46.839Z",
|
||||||
|
"systemRamFreeInfo": ["15226499072"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T07:49:43.939Z",
|
||||||
|
"systemRamFreeInfo": ["15229087744"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T15:46:23.165Z",
|
||||||
|
"systemRamFreeInfo": ["15226187776"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T15:52:39.966Z",
|
||||||
|
"systemRamFreeInfo": ["15226843136"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:06:06.871Z",
|
||||||
|
"systemRamFreeInfo": ["15225753600"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:13:28.176Z",
|
||||||
|
"systemRamFreeInfo": ["15228182528"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:17:05.936Z",
|
||||||
|
"systemRamFreeInfo": ["15223095296"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:36:19.897Z",
|
||||||
|
"systemRamFreeInfo": ["15226126336"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-11T16:48:44.934Z",
|
||||||
|
"systemRamFreeInfo": ["15226707968"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reportTime": "2025-02-12T06:35:28.949Z",
|
||||||
|
"systemRamFreeInfo": ["15222706176"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"diskVolumeReports": [
|
||||||
|
{
|
||||||
|
"volumeInfo": [
|
||||||
|
{
|
||||||
|
"volumeId": "/media/archive",
|
||||||
|
"storageTotal": "8044687360",
|
||||||
|
"storageFree": "8044687360"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"volumeId": "/media/removable",
|
||||||
|
"storageTotal": "8044687360",
|
||||||
|
"storageFree": "8044687360"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lastKnownNetwork": [
|
||||||
|
{
|
||||||
|
"ipAddress": "192.168.0.106",
|
||||||
|
"wanIpAddress": "87.121.13.137"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cpuInfo": [
|
||||||
|
{
|
||||||
|
"model": "AMD Ryzen 5 4500U with Radeon Graphics",
|
||||||
|
"architecture": "x64",
|
||||||
|
"maxClockSpeedKhz": 2375000,
|
||||||
|
"logicalCpus": [
|
||||||
|
{
|
||||||
|
"maxScalingFrequencyKhz": 2375000,
|
||||||
|
"currentScalingFrequencyKhz": 1397253,
|
||||||
|
"idleDuration": "60s",
|
||||||
|
"cStates": [
|
||||||
|
{
|
||||||
|
"displayName": "C3",
|
||||||
|
"sessionDuration": "59.509354s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C1",
|
||||||
|
"sessionDuration": "1.338153s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C2",
|
||||||
|
"sessionDuration": "0.241264s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "POLL",
|
||||||
|
"sessionDuration": "0.004477s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"maxScalingFrequencyKhz": 2375000,
|
||||||
|
"currentScalingFrequencyKhz": 1397372,
|
||||||
|
"idleDuration": "60s",
|
||||||
|
"cStates": [
|
||||||
|
{
|
||||||
|
"displayName": "C3",
|
||||||
|
"sessionDuration": "58.861175s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C1",
|
||||||
|
"sessionDuration": "1.335068s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C2",
|
||||||
|
"sessionDuration": "0.761853s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "POLL",
|
||||||
|
"sessionDuration": "0.007583s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"maxScalingFrequencyKhz": 2375000,
|
||||||
|
"currentScalingFrequencyKhz": 1397454,
|
||||||
|
"idleDuration": "58s",
|
||||||
|
"cStates": [
|
||||||
|
{
|
||||||
|
"displayName": "C3",
|
||||||
|
"sessionDuration": "57.457528s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C1",
|
||||||
|
"sessionDuration": "1.280076s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C2",
|
||||||
|
"sessionDuration": "0.167642s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "POLL",
|
||||||
|
"sessionDuration": "0.003444s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"maxScalingFrequencyKhz": 2375000,
|
||||||
|
"currentScalingFrequencyKhz": 1397348,
|
||||||
|
"idleDuration": "59s",
|
||||||
|
"cStates": [
|
||||||
|
{
|
||||||
|
"displayName": "C3",
|
||||||
|
"sessionDuration": "58.906343s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C1",
|
||||||
|
"sessionDuration": "1.101873s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C2",
|
||||||
|
"sessionDuration": "0.119013s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "POLL",
|
||||||
|
"sessionDuration": "0.009095s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"maxScalingFrequencyKhz": 2375000,
|
||||||
|
"currentScalingFrequencyKhz": 1383188,
|
||||||
|
"idleDuration": "60s",
|
||||||
|
"cStates": [
|
||||||
|
{
|
||||||
|
"displayName": "C3",
|
||||||
|
"sessionDuration": "59.476621s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C1",
|
||||||
|
"sessionDuration": "1.048691s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C2",
|
||||||
|
"sessionDuration": "0.192808s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "POLL",
|
||||||
|
"sessionDuration": "0.003546s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"maxScalingFrequencyKhz": 2375000,
|
||||||
|
"currentScalingFrequencyKhz": 1397437,
|
||||||
|
"idleDuration": "60s",
|
||||||
|
"cStates": [
|
||||||
|
{
|
||||||
|
"displayName": "C3",
|
||||||
|
"sessionDuration": "60.155800s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C1",
|
||||||
|
"sessionDuration": "0.681644s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "C2",
|
||||||
|
"sessionDuration": "0.143131s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "POLL",
|
||||||
|
"sessionDuration": "0.004276s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extendedSupportEligible": false,
|
||||||
|
"chromeOsType": "chromeOsFlex",
|
||||||
|
"diskSpaceUsage": {
|
||||||
|
"capacityBytes": "549755813888",
|
||||||
|
"usedBytes": "85613068288"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Create Group', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('create.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.post('/directory/v1/groups', {
|
||||||
|
email: 'NewOnes22@example.com',
|
||||||
|
name: 'Test',
|
||||||
|
description: 'test',
|
||||||
|
})
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#group',
|
||||||
|
id: '03mzq4wv15cepg2',
|
||||||
|
etag: '"example"',
|
||||||
|
email: 'NewOnes22@example.com',
|
||||||
|
name: 'Test',
|
||||||
|
description: 'test',
|
||||||
|
adminCreated: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "group",
|
||||||
|
"name": "Test",
|
||||||
|
"email": "NewOnes22@example.com",
|
||||||
|
"additionalFields": {
|
||||||
|
"description": "test"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [60, 1140],
|
||||||
|
"id": "54a9e564-bff5-4d86-b684-e5cf5b34b48c",
|
||||||
|
"name": "Create Group",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Create Group",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Create Group": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#group",
|
||||||
|
"id": "03mzq4wv15cepg2",
|
||||||
|
"etag": "\"example\"",
|
||||||
|
"email": "NewOnes22@example.com",
|
||||||
|
"name": "Test",
|
||||||
|
"description": "test",
|
||||||
|
"adminCreated": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Delete Group', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('delete.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.delete('/directory/v1/groups/01302m922pmp3e4')
|
||||||
|
.reply(204, '');
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "group",
|
||||||
|
"operation": "delete",
|
||||||
|
"groupId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "01302m922pmp3e4",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "new2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [60, 1140],
|
||||||
|
"id": "9d6f8739-8a1b-4b85-9e5c-84a184e6dbaf",
|
||||||
|
"name": "Delete Group",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Delete Group",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Delete Group": [
|
||||||
|
{
|
||||||
|
"json": { "success": true }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Get Group', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('get.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.get('/directory/v1/groups/01302m922pmp3e4')
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#group',
|
||||||
|
id: '01302m922pmp3e4',
|
||||||
|
etag: '"example"',
|
||||||
|
email: 'new3@example.com',
|
||||||
|
name: 'new2',
|
||||||
|
directMembersCount: '2',
|
||||||
|
description: 'new1',
|
||||||
|
adminCreated: true,
|
||||||
|
aliases: ['new2@example.com', 'new@example.com', 'NewOnes@example.com'],
|
||||||
|
nonEditableAliases: [
|
||||||
|
'NewOnes@example.com.test-google-a.com',
|
||||||
|
'new@example.com.test-google-a.com',
|
||||||
|
'new2@example.com.test-google-a.com',
|
||||||
|
'new3@example.com.test-google-a.com',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "group",
|
||||||
|
"operation": "get",
|
||||||
|
"groupId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "01302m922pmp3e4",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "new2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [80, 1120],
|
||||||
|
"id": "8d47d64b-80df-479a-8e1d-d63991f5d23b",
|
||||||
|
"name": "Get Group",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Get Group",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Get Group": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#group",
|
||||||
|
"id": "01302m922pmp3e4",
|
||||||
|
"etag": "\"example\"",
|
||||||
|
"email": "new3@example.com",
|
||||||
|
"name": "new2",
|
||||||
|
"directMembersCount": "2",
|
||||||
|
"description": "new1",
|
||||||
|
"adminCreated": true,
|
||||||
|
"aliases": ["new2@example.com", "new@example.com", "NewOnes@example.com"],
|
||||||
|
"nonEditableAliases": [
|
||||||
|
"NewOnes@example.com.test-google-a.com",
|
||||||
|
"new@example.com.test-google-a.com",
|
||||||
|
"new2@example.com.test-google-a.com",
|
||||||
|
"new3@example.com.test-google-a.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Get All Groups', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('getAll.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.get('/directory/v1/groups')
|
||||||
|
.query({
|
||||||
|
customer: 'my_customer',
|
||||||
|
maxResults: '100',
|
||||||
|
})
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#groups',
|
||||||
|
etag: '"test_etag"',
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
kind: 'admin#directory#group',
|
||||||
|
id: '01x0gk373c9z46j',
|
||||||
|
etag: '"example"',
|
||||||
|
email: 'newoness@example.com',
|
||||||
|
name: 'NewOness',
|
||||||
|
directMembersCount: '1',
|
||||||
|
description: 'test',
|
||||||
|
adminCreated: true,
|
||||||
|
nonEditableAliases: ['NewOness@example.com.test-google-a.com'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'admin#directory#group',
|
||||||
|
id: '01tuee742txc3k4',
|
||||||
|
etag: '"example"',
|
||||||
|
email: 'newonesss@example.com',
|
||||||
|
name: 'NewOne3',
|
||||||
|
directMembersCount: '0',
|
||||||
|
description: 'test',
|
||||||
|
adminCreated: true,
|
||||||
|
nonEditableAliases: ['NewOnesss@example.com.test-google-a.com'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "group",
|
||||||
|
"operation": "getAll",
|
||||||
|
"returnAll": true,
|
||||||
|
"filter": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [100, 1120],
|
||||||
|
"id": "30263040-3578-4ce6-b19c-f665b85ca301",
|
||||||
|
"name": "Get Many",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Get Many",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Get Many": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#group",
|
||||||
|
"id": "01x0gk373c9z46j",
|
||||||
|
"etag": "\"example\"",
|
||||||
|
"email": "newoness@example.com",
|
||||||
|
"name": "NewOness",
|
||||||
|
"directMembersCount": "1",
|
||||||
|
"description": "test",
|
||||||
|
"adminCreated": true,
|
||||||
|
"nonEditableAliases": ["NewOness@example.com.test-google-a.com"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#group",
|
||||||
|
"id": "01tuee742txc3k4",
|
||||||
|
"etag": "\"example\"",
|
||||||
|
"email": "newonesss@example.com",
|
||||||
|
"name": "NewOne3",
|
||||||
|
"directMembersCount": "0",
|
||||||
|
"description": "test",
|
||||||
|
"adminCreated": true,
|
||||||
|
"nonEditableAliases": ["NewOnesss@example.com.test-google-a.com"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Update Group', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('update.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.put('/directory/v1/groups/01302m922p525286')
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#group',
|
||||||
|
id: '01302m922p525286',
|
||||||
|
etag: '"example"',
|
||||||
|
email: 'new3@example.com',
|
||||||
|
name: 'new2',
|
||||||
|
description: 'new1',
|
||||||
|
adminCreated: true,
|
||||||
|
aliases: ['new@example.com', 'NewOnes@example.com', 'new2@example.com'],
|
||||||
|
nonEditableAliases: [
|
||||||
|
'NewOnes@example.com.test-google-a.com',
|
||||||
|
'new@example.com.test-google-a.com',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "group",
|
||||||
|
"operation": "update",
|
||||||
|
"groupId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "01302m922p525286",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "new"
|
||||||
|
},
|
||||||
|
"updateFields": {
|
||||||
|
"description": "new1",
|
||||||
|
"email": "new3@example.com",
|
||||||
|
"name": "new2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [80, 1100],
|
||||||
|
"id": "013eec82-8d52-4485-88eb-d9caf112d539",
|
||||||
|
"name": "Update Group",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Update Group",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Update Group": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#group",
|
||||||
|
"id": "01302m922p525286",
|
||||||
|
"etag": "\"example\"",
|
||||||
|
"email": "new3@example.com",
|
||||||
|
"name": "new2",
|
||||||
|
"description": "new1",
|
||||||
|
"adminCreated": true,
|
||||||
|
"aliases": ["new@example.com", "NewOnes@example.com", "new2@example.com"],
|
||||||
|
"nonEditableAliases": [
|
||||||
|
"NewOnes@example.com.test-google-a.com",
|
||||||
|
"new@example.com.test-google-a.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Add User to Group', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('addToGroup.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.get('/directory/v1/users/114393134535981252528')
|
||||||
|
.reply(200, { primaryEmail: 'newone@example.com' });
|
||||||
|
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.post('/directory/v1/groups/01302m922pmp3e4/members', {
|
||||||
|
email: 'newone@example.com',
|
||||||
|
role: 'MEMBER',
|
||||||
|
})
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#member',
|
||||||
|
status: 'ACTIVE',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "addToGroup",
|
||||||
|
"userId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "114393134535981252528",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "NewOne User"
|
||||||
|
},
|
||||||
|
"groupId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "01302m922pmp3e4",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "new"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [80, 1100],
|
||||||
|
"id": "b0c8042f-4ce1-41f1-9d14-876d5cac3ccf",
|
||||||
|
"name": "Add To Group",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Add To Group",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Add To Group": [
|
||||||
|
{
|
||||||
|
"json": { "added": true }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Create User', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('create.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.post('/directory/v1/users')
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#user',
|
||||||
|
id: '112507770188715525288',
|
||||||
|
etag: '"example"',
|
||||||
|
primaryEmail: 'new@example.com',
|
||||||
|
name: {
|
||||||
|
givenName: 'NewOne',
|
||||||
|
familyName: 'User',
|
||||||
|
},
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
address: 'test@mail.com',
|
||||||
|
type: 'work',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
phones: [
|
||||||
|
{
|
||||||
|
primary: false,
|
||||||
|
type: 'work',
|
||||||
|
value: '+1-202-555-0123',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
isAdmin: false,
|
||||||
|
isDelegatedAdmin: false,
|
||||||
|
creationTime: '2024-12-20T20:48:53.000Z',
|
||||||
|
customerId: 'C4444hnz2',
|
||||||
|
orgUnitPath: '/',
|
||||||
|
isMailboxSetup: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"firstName": "NewOne",
|
||||||
|
"lastName": "User",
|
||||||
|
"password": "12345678",
|
||||||
|
"username": "new",
|
||||||
|
"domain": "example.com",
|
||||||
|
"additionalFields": {
|
||||||
|
"changePasswordAtNextLogin": true,
|
||||||
|
"phoneUi": {
|
||||||
|
"phoneValues": [
|
||||||
|
{
|
||||||
|
"value": "+1-202-555-0123"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"emailUi": {
|
||||||
|
"emailValues": [
|
||||||
|
{
|
||||||
|
"address": "test@mail.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"roles": ["groupsAdmin"],
|
||||||
|
"customFields": {
|
||||||
|
"fieldValues": [
|
||||||
|
{
|
||||||
|
"schemaName": "NewTest",
|
||||||
|
"fieldName": "test",
|
||||||
|
"value": "test"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [100, 1100],
|
||||||
|
"id": "54227da8-70ad-456a-8d75-f7e28d514e90",
|
||||||
|
"name": "Create User",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Create User",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Create User": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#user",
|
||||||
|
"id": "112507770188715525288",
|
||||||
|
"etag": "\"example\"",
|
||||||
|
"primaryEmail": "new@example.com",
|
||||||
|
"name": {
|
||||||
|
"givenName": "NewOne",
|
||||||
|
"familyName": "User"
|
||||||
|
},
|
||||||
|
"isAdmin": false,
|
||||||
|
"isDelegatedAdmin": false,
|
||||||
|
"creationTime": "2024-12-20T20:48:53.000Z",
|
||||||
|
"emails": [
|
||||||
|
{
|
||||||
|
"address": "test@mail.com",
|
||||||
|
"type": "work"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"phones": [
|
||||||
|
{
|
||||||
|
"value": "+1-202-555-0123",
|
||||||
|
"primary": false,
|
||||||
|
"type": "work"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"customerId": "C4444hnz2",
|
||||||
|
"orgUnitPath": "/",
|
||||||
|
"isMailboxSetup": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Delete User', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('delete.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.delete('/directory/v1/users/114393134535981252212')
|
||||||
|
.reply(200, {});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "delete",
|
||||||
|
"userId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "114393134535981252212",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "NewOne22 User22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 1100],
|
||||||
|
"id": "39f9a9c0-2ea5-45b2-a346-55017dfa4e43",
|
||||||
|
"name": "Delete User",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Delete User",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Delete User": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"deleted": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Get User', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('get.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.get('/directory/v1/users/112507770188715252026')
|
||||||
|
.query({ projection: 'basic' })
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#user',
|
||||||
|
id: '112507770188715252026',
|
||||||
|
primaryEmail: 'new@example.com',
|
||||||
|
name: {
|
||||||
|
givenName: 'New One',
|
||||||
|
familyName: 'User',
|
||||||
|
fullName: 'New One User',
|
||||||
|
},
|
||||||
|
isAdmin: false,
|
||||||
|
lastLoginTime: '1970-01-01T00:00:00.000Z',
|
||||||
|
creationTime: '2024-12-20T20:48:53.000Z',
|
||||||
|
suspended: true,
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
address: 'new@example.com',
|
||||||
|
primary: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "get",
|
||||||
|
"userId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "112507770188715252026",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "NewOne22 User22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 1100],
|
||||||
|
"id": "b39d3a72-6e81-4219-82eb-f39d99eace16",
|
||||||
|
"name": "Get User",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Get User",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Get User": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#user",
|
||||||
|
"id": "112507770188715252026",
|
||||||
|
"primaryEmail": "new@example.com",
|
||||||
|
"name": {
|
||||||
|
"givenName": "New One",
|
||||||
|
"familyName": "User",
|
||||||
|
"fullName": "New One User"
|
||||||
|
},
|
||||||
|
"isAdmin": false,
|
||||||
|
"lastLoginTime": "1970-01-01T00:00:00.000Z",
|
||||||
|
"creationTime": "2024-12-20T20:48:53.000Z",
|
||||||
|
"suspended": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Get All Users', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('getAll.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.get('/directory/v1/users')
|
||||||
|
.query({
|
||||||
|
projection: 'basic',
|
||||||
|
customer: 'my_customer',
|
||||||
|
maxResults: '100',
|
||||||
|
})
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#users',
|
||||||
|
users: [
|
||||||
|
{
|
||||||
|
kind: 'admin#directory#user',
|
||||||
|
id: '112507770188715252055',
|
||||||
|
primaryEmail: 'new@example.com',
|
||||||
|
name: {
|
||||||
|
givenName: 'New',
|
||||||
|
familyName: 'User',
|
||||||
|
fullName: 'New User',
|
||||||
|
},
|
||||||
|
isAdmin: false,
|
||||||
|
lastLoginTime: '1970-01-01T00:00:00.000Z',
|
||||||
|
creationTime: '2024-12-20T20:48:53.000Z',
|
||||||
|
suspended: true,
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
address: 'new@example.com',
|
||||||
|
primary: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'admin#directory#user',
|
||||||
|
id: '222459372679230452528',
|
||||||
|
primaryEmail: 'test33@example.com',
|
||||||
|
name: {
|
||||||
|
givenName: 'New',
|
||||||
|
familyName: 'Test',
|
||||||
|
fullName: 'New Test',
|
||||||
|
},
|
||||||
|
isAdmin: true,
|
||||||
|
lastLoginTime: '2024-12-19T08:39:56.000Z',
|
||||||
|
creationTime: '2024-09-06T11:48:38.000Z',
|
||||||
|
suspended: false,
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
address: 'test33@example.com',
|
||||||
|
primary: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "getAll",
|
||||||
|
"filter": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [140, 1100],
|
||||||
|
"id": "4107ee9d-37e1-4d85-9099-25ec13211ee1",
|
||||||
|
"name": "Get Many",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Get Many",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Get Many": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#user",
|
||||||
|
"id": "112507770188715252055",
|
||||||
|
"primaryEmail": "new@example.com",
|
||||||
|
"name": {
|
||||||
|
"givenName": "New",
|
||||||
|
"familyName": "User",
|
||||||
|
"fullName": "New User"
|
||||||
|
},
|
||||||
|
"isAdmin": false,
|
||||||
|
"lastLoginTime": "1970-01-01T00:00:00.000Z",
|
||||||
|
"creationTime": "2024-12-20T20:48:53.000Z",
|
||||||
|
"suspended": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#user",
|
||||||
|
"id": "222459372679230452528",
|
||||||
|
"primaryEmail": "test33@example.com",
|
||||||
|
"name": {
|
||||||
|
"givenName": "New",
|
||||||
|
"familyName": "Test",
|
||||||
|
"fullName": "New Test"
|
||||||
|
},
|
||||||
|
"isAdmin": true,
|
||||||
|
"lastLoginTime": "2024-12-19T08:39:56.000Z",
|
||||||
|
"creationTime": "2024-09-06T11:48:38.000Z",
|
||||||
|
"suspended": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Remove User from Group', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('removeFromGroup.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.delete('/directory/v1/groups/01302m922pmp3e4/members/114393134535981252528')
|
||||||
|
.reply(200, {});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "removeFromGroup",
|
||||||
|
"userId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "114393134535981252528",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "New User"
|
||||||
|
},
|
||||||
|
"groupId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "01302m922pmp3e4",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "new2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [140, 1100],
|
||||||
|
"id": "9a323b95-1495-487f-ba27-2df737bd5bdf",
|
||||||
|
"name": "Remove From Group",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Remove From Group",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Remove From Group": [
|
||||||
|
{
|
||||||
|
"json": { "removed": true }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { initBinaryDataService, testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
|
||||||
|
describe('Google GSuiteAdmin Node - Update User', () => {
|
||||||
|
const workflows = getWorkflowFilenames(__dirname).filter((filename) =>
|
||||||
|
filename.includes('update.workflow.json'),
|
||||||
|
);
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initBinaryDataService();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
|
||||||
|
nock('https://www.googleapis.com/admin')
|
||||||
|
.put('/directory/v1/users/101071249467630629404', {
|
||||||
|
name: {
|
||||||
|
givenName: 'test',
|
||||||
|
familyName: 'new',
|
||||||
|
},
|
||||||
|
primaryEmail: 'one@example.com',
|
||||||
|
phones: [
|
||||||
|
{
|
||||||
|
type: 'assistant',
|
||||||
|
value: '123',
|
||||||
|
primary: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
address: 'newone@example.com',
|
||||||
|
type: 'home',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.reply(200, {
|
||||||
|
kind: 'admin#directory#user',
|
||||||
|
id: '101071249467630629404',
|
||||||
|
etag: '"example"',
|
||||||
|
primaryEmail: 'one@example.com',
|
||||||
|
name: {
|
||||||
|
givenName: 'test',
|
||||||
|
familyName: 'new',
|
||||||
|
},
|
||||||
|
isAdmin: false,
|
||||||
|
isDelegatedAdmin: false,
|
||||||
|
lastLoginTime: '1970-01-01T00:00:00.000Z',
|
||||||
|
creationTime: '2025-03-26T21:28:53.000Z',
|
||||||
|
agreedToTerms: false,
|
||||||
|
suspended: false,
|
||||||
|
archived: false,
|
||||||
|
changePasswordAtNextLogin: false,
|
||||||
|
ipWhitelisted: false,
|
||||||
|
emails: [
|
||||||
|
{
|
||||||
|
address: 'newone@example.com',
|
||||||
|
type: 'home',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
phones: [
|
||||||
|
{
|
||||||
|
value: '123',
|
||||||
|
primary: true,
|
||||||
|
type: 'assistant',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
aliases: ['new22@example.com'],
|
||||||
|
nonEditableAliases: ['new22@example.com.test-google-a.com'],
|
||||||
|
customerId: 'C0442hnz1',
|
||||||
|
orgUnitPath: '/',
|
||||||
|
isMailboxSetup: false,
|
||||||
|
includeInGlobalAddressList: true,
|
||||||
|
thumbnailPhotoUrl: '//example',
|
||||||
|
thumbnailPhotoEtag: '"example"',
|
||||||
|
recoveryEmail: '',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
testWorkflows(workflows);
|
||||||
|
});
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [120, 700],
|
||||||
|
"id": "0e76b314-4994-4141-975f-9614c6094c80",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "update",
|
||||||
|
"userId": {
|
||||||
|
"__rl": true,
|
||||||
|
"value": "101071249467630629404",
|
||||||
|
"mode": "list",
|
||||||
|
"cachedResultName": "NewOne22 User22"
|
||||||
|
},
|
||||||
|
"updateFields": {
|
||||||
|
"archived": true,
|
||||||
|
"firstName": "test",
|
||||||
|
"lastName": "new",
|
||||||
|
"phoneUi": {
|
||||||
|
"phoneValues": [
|
||||||
|
{
|
||||||
|
"type": "assistant",
|
||||||
|
"value": "123",
|
||||||
|
"primary": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"primaryEmail": "one@example.com",
|
||||||
|
"emailUi": {
|
||||||
|
"emailValues": [
|
||||||
|
{
|
||||||
|
"type": "home",
|
||||||
|
"address": "newone@example.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.gSuiteAdmin",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [140, 1100],
|
||||||
|
"id": "b4cd1391-cfdc-4f36-8c2f-f18a9ad4f795",
|
||||||
|
"name": "Update User",
|
||||||
|
"credentials": {
|
||||||
|
"gSuiteAdminOAuth2Api": {
|
||||||
|
"id": "OXfPMaggXFJ0RLkw",
|
||||||
|
"name": "Google Workspace Admin account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Update User",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Update User": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"kind": "admin#directory#user",
|
||||||
|
"id": "101071249467630629404",
|
||||||
|
"etag": "\"example\"",
|
||||||
|
"primaryEmail": "one@example.com",
|
||||||
|
"name": {
|
||||||
|
"givenName": "test",
|
||||||
|
"familyName": "new"
|
||||||
|
},
|
||||||
|
"isAdmin": false,
|
||||||
|
"isDelegatedAdmin": false,
|
||||||
|
"lastLoginTime": "1970-01-01T00:00:00.000Z",
|
||||||
|
"creationTime": "2025-03-26T21:28:53.000Z",
|
||||||
|
"agreedToTerms": false,
|
||||||
|
"suspended": false,
|
||||||
|
"archived": false,
|
||||||
|
"changePasswordAtNextLogin": false,
|
||||||
|
"ipWhitelisted": false,
|
||||||
|
"emails": [
|
||||||
|
{
|
||||||
|
"address": "newone@example.com",
|
||||||
|
"type": "home"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"phones": [
|
||||||
|
{
|
||||||
|
"value": "123",
|
||||||
|
"primary": true,
|
||||||
|
"type": "assistant"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"aliases": ["new22@example.com"],
|
||||||
|
"nonEditableAliases": ["new22@example.com.test-google-a.com"],
|
||||||
|
"customerId": "C0442hnz1",
|
||||||
|
"orgUnitPath": "/",
|
||||||
|
"isMailboxSetup": false,
|
||||||
|
"includeInGlobalAddressList": true,
|
||||||
|
"thumbnailPhotoUrl": "//example",
|
||||||
|
"thumbnailPhotoEtag": "\"example\"",
|
||||||
|
"recoveryEmail": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user