import type { DeclarativeRestApiSettings, IDataObject, IExecuteFunctions, IExecutePaginationFunctions, IExecuteSingleFunctions, IHookFunctions, IHttpRequestMethods, IHttpRequestOptions, ILoadOptionsFunctions, IN8nHttpFullResponse, INodeExecutionData, INodeListSearchResult, INodePropertyOptions, } from 'n8n-workflow'; type OktaUser = { status: string; created: string; activated: string; lastLogin: string; lastUpdated: string; passwordChanged: string; profile: { login: string; email: string; firstName: string; lastName: string; }; id: string; }; export async function oktaApiRequest( this: IExecuteFunctions | IExecuteSingleFunctions | IHookFunctions | ILoadOptionsFunctions, method: IHttpRequestMethods, resource: string, body: IDataObject = {}, qs: IDataObject = {}, url?: string, option: IDataObject = {}, ): Promise { const credentials = await this.getCredentials('oktaApi'); const baseUrl = `${credentials.url as string}/api/v1/${resource}`; const options: IHttpRequestOptions = { headers: { 'Content-Type': 'application/json', }, method, body: Object.keys(body).length ? body : undefined, qs: Object.keys(qs).length ? qs : undefined, url: url ?? baseUrl, json: true, ...option, }; return await (this.helpers.httpRequestWithAuthentication.call( this, 'oktaApi', options, ) as Promise); } export async function getUsers( this: ILoadOptionsFunctions, filter?: string, ): Promise { const responseData: OktaUser[] = await oktaApiRequest.call(this, 'GET', '/users/'); const filteredUsers = responseData.filter((user) => { if (!filter) return true; const username = `${user.profile.login}`.toLowerCase(); return username.includes(filter.toLowerCase()); }); const users: INodePropertyOptions[] = filteredUsers.map((user) => ({ name: `${user.profile.login}`, value: user.id, })); return { results: users, }; } function simplifyOktaUser(item: OktaUser): IDataObject { return { id: item.id, status: item.status, created: item.created, activated: item.activated, lastLogin: item.lastLogin, lastUpdated: item.lastUpdated, passwordChanged: item.passwordChanged, profile: { firstName: item.profile.firstName, lastName: item.profile.lastName, login: item.profile.login, email: item.profile.email, }, }; } export async function simplifyGetAllResponse( this: IExecuteSingleFunctions, items: INodeExecutionData[], _response: IN8nHttpFullResponse, ): Promise { if (items.length === 0) return items; const simplify = this.getNodeParameter('simplify'); if (!simplify) return ((items[0].json as unknown as IDataObject[]) ?? []).map((item: IDataObject) => ({ json: item, headers: _response.headers, })) as INodeExecutionData[]; let simplifiedItems: INodeExecutionData[] = []; if (items[0].json) { const jsonArray = items[0].json as unknown; simplifiedItems = (jsonArray as OktaUser[]).map((item: OktaUser) => { const simplifiedItem = simplifyOktaUser(item); return { json: simplifiedItem, headers: _response.headers, }; }); } return simplifiedItems; } export async function simplifyGetResponse( this: IExecuteSingleFunctions, items: INodeExecutionData[], _response: IN8nHttpFullResponse, ): Promise { const simplify = this.getNodeParameter('simplify'); if (!simplify) return items; const item = items[0].json as OktaUser; const simplifiedItem = simplifyOktaUser(item); return [ { json: simplifiedItem, }, ] as INodeExecutionData[]; } export const getCursorPaginator = () => { return async function cursorPagination( this: IExecutePaginationFunctions, requestOptions: DeclarativeRestApiSettings.ResultOptions, ): Promise { if (!requestOptions.options.qs) { requestOptions.options.qs = {}; } let items: INodeExecutionData[] = []; let responseData: INodeExecutionData[]; let nextCursor: string | undefined = undefined; const returnAll = this.getNodeParameter('returnAll', true) as boolean; do { requestOptions.options.qs.limit = 200; requestOptions.options.qs.after = nextCursor; responseData = await this.makeRoutingRequest(requestOptions); if (responseData.length > 0) { const headers = responseData[responseData.length - 1].headers; const headersLink = (headers as IDataObject)?.link as string | undefined; nextCursor = headersLink?.split('after=')[1]?.split('&')[0]?.split('>')[0]; } items = items.concat(responseData); } while (returnAll && nextCursor); return items; }; };