Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/api/IdmConfigApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,20 @@ export async function getConfigEntities({
/**
* Get IDM config entities by type
* @param {string} type the desired type of config entity
* @param {boolean} includeDefault Include default email templates if true, false to exclude them. Default: false
* @returns {Promise} a promise that resolves to an object containing all IDM config entities of the desired type
*/
export async function getConfigEntitiesByType({
type,
includeDefault = false,
state,
}: {
type: string;
includeDefault?: boolean;
state: State;
}): Promise<PagedResult<NoIdObjectSkeletonInterface>> {
// Due to a bug (as of Ping IDM 7.5.0) with the query filter for email templates (it happens using both sw or co), in order to get all the email templates you need to use 'emailTemplat' instead.
if (type === EMAIL_TEMPLATE_TYPE) {
// Due to a bug (as of Ping IDM 7.5.0) with the query filter for email templates (it happens using both sw or co), in order to get all the email templates, including default, you need to use 'emailTemplat' instead.
if (type === EMAIL_TEMPLATE_TYPE && includeDefault) {
type = EMAIL_TEMPLATE_TYPE.substring(0, EMAIL_TEMPLATE_TYPE.length - 1);
}
const urlString = util.format(
Expand Down
95 changes: 95 additions & 0 deletions src/api/RawConfigApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import util from 'util';

import { State } from '../shared/State';
import { getHostOnlyUrl, getIdmBaseUrl } from '../utils/ForgeRockUtils';
import { generateAmApi, generateEnvApi, generateIdmApi } from './BaseApi';

const amTemplate: string = '%s/%s';
const idmTemplate: string = '%s/%s';
const envTemplate: string = '%s/environment/%s';

export type ApiVersion = {
protocol: string;
resource: string;
};

function getApiConfig(
apiVersion: ApiVersion = {
protocol: '2.0',
resource: '1.0',
}
): { apiVersion: string } {
return {
apiVersion: `protocol=${apiVersion.protocol},resource=${apiVersion.resource}`,
};
}

/**
* Performs a get request against the specified AM endpoint
* @param {string} endpoint The AM endpoint (e.g. if full URL is https://<tenant-host>/am/<endpoint>, <endpoint> is the value to pass in)
* @param {ApiVersion} apiVersion The API version to use. Defaults to 2.0 for protocol and 1.0 for resource.
* @returns {Promise<any>} The response data from the endpoint
*/
export async function getRawAm({
endpoint,
apiVersion,
state,
}: {
endpoint: string;
apiVersion?: ApiVersion;
state: State;
}): Promise<any> {
const urlString = util.format(amTemplate, state.getHost(), endpoint);
const { data } = await generateAmApi({
resource: getApiConfig(apiVersion),
state,
}).get(urlString, { withCredentials: true });

return data;
}

/**
* Performs a get request against the specified IDM endpoint
* @param {string} endpoint The IDM endpoint (e.g. if full URL is https://<tenant-host>/openidm/<endpoint>, <endpoint> is the value to pass in)
* @returns {Promise<any>} The response data from the endpoint
*/
export async function getRawIdm({
endpoint,
state,
}: {
endpoint: string;
state: State;
}): Promise<any> {
const urlString = util.format(idmTemplate, getIdmBaseUrl(state), endpoint);
const { data } = await generateIdmApi({ state }).get(urlString);

return data;
}

/**
* Performs a get request against the specified Environment endpoint
* @param {string} endpoint The Environment endpoint (e.g. if full URL is https://<tenant-host>/environment/<endpoint>, <endpoint> is the value to pass in)
* @param {ApiVersion} apiVersion The API version to use. Defaults to 2.0 for protocol and 1.0 for resource.
* @returns {Promise<any>} The response data from the endpoint
*/
export async function getRawEnv({
endpoint,
apiVersion,
state,
}: {
endpoint: string;
apiVersion?: ApiVersion;
state: State;
}): Promise<any> {
const urlString = util.format(
envTemplate,
getHostOnlyUrl(state.getHost()),
endpoint
);
const { data } = await generateEnvApi({
resource: getApiConfig(apiVersion),
state,
}).get(urlString, { withCredentials: true });

return data;
}
5 changes: 5 additions & 0 deletions src/lib/FrodoLib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import OAuth2TrustedJwtIssuerOps, {
import OrganizationOps, { Organization } from '../ops/OrganizationOps';
import PolicyOps, { Policy } from '../ops/PolicyOps';
import PolicySetOps, { PolicySet } from '../ops/PolicySetOps';
import RawConfigOps, { RawConfig } from '../ops/RawConfigOps';
import RealmOps, { Realm } from '../ops/RealmOps';
import ReconOps, { Recon } from '../ops/ReconOps';
import ResourceTypeOps, { ResourceType } from '../ops/ResourceTypeOps';
Expand Down Expand Up @@ -182,6 +183,8 @@ export type Frodo = {
issuer: OAuth2TrustedJwtIssuer;
};

rawConfig: RawConfig;

realm: Realm;

role: InternalRole;
Expand Down Expand Up @@ -354,6 +357,8 @@ const FrodoLib = (config: StateInterface = {}): Frodo => {
issuer: OAuth2TrustedJwtIssuerOps(state),
},

rawConfig: RawConfigOps(state),

realm: RealmOps(state),

role: InternalRoleOps(state),
Expand Down
2 changes: 1 addition & 1 deletion src/ops/ConfigOps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ export async function exportFullConfiguration({
emailTemplate: (
await exportWithErrorHandling(
exportEmailTemplates,
stateObj,
{ includeDefault: includeReadOnly, state },
'Email Templates',
resultCallback,
isPlatformDeployment
Expand Down
9 changes: 8 additions & 1 deletion src/ops/EmailTemplateOps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,14 @@ describe('EmailTemplateOps', () => {
});

test('1: Export email templates', async () => {
const response = await EmailTemplateOps.exportEmailTemplates({ state });
const response = await EmailTemplateOps.exportEmailTemplates({ includeDefault: false, state });
expect(response).toMatchSnapshot({
meta: expect.any(Object)
});
});

test('2: Export email templates with default templates', async () => {
const response = await EmailTemplateOps.exportEmailTemplates({ includeDefault: true, state });
expect(response).toMatchSnapshot({
meta: expect.any(Object)
});
Expand Down
29 changes: 22 additions & 7 deletions src/ops/EmailTemplateOps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@ export type EmailTemplate = {
createEmailTemplateExportTemplate(): EmailTemplateExportInterface;
/**
* Get all email templates
* @param {boolean} includeDefault Include default email templates if true, false to exclude them. Default: false
* @returns {Promise<EmailTemplateSkeleton[]>} a promise that resolves to an array of email template objects
*/
readEmailTemplates(): Promise<EmailTemplateSkeleton[]>;
readEmailTemplates(
includeDefault?: boolean
): Promise<EmailTemplateSkeleton[]>;
/**
* Get email template
* @param {string} templateId id/name of the email template without the type prefix
Expand All @@ -43,9 +46,12 @@ export type EmailTemplate = {
readEmailTemplate(templateId: string): Promise<EmailTemplateSkeleton>;
/**
* Export all email templates. The response can be saved to file as is.
* @param {boolean} includeDefault Include default email templates if true, false to exclude them. Default: false
* @returns {Promise<EmailTemplateExportInterface>} Promise resolving to a EmailTemplateExportInterface object.
*/
exportEmailTemplates(): Promise<EmailTemplateExportInterface>;
exportEmailTemplates(
includeDefault?: boolean
): Promise<EmailTemplateExportInterface>;
/**
* Create email template
* @param {string} templateId id/name of the email template without the type prefix
Expand Down Expand Up @@ -133,14 +139,16 @@ export default (state: State): EmailTemplate => {
createEmailTemplateExportTemplate(): EmailTemplateExportInterface {
return createEmailTemplateExportTemplate({ state });
},
async readEmailTemplates(): Promise<any> {
return readEmailTemplates({ state });
async readEmailTemplates(includeDefault: boolean = false): Promise<any> {
return readEmailTemplates({ includeDefault, state });
},
async readEmailTemplate(templateId: string): Promise<any> {
return readEmailTemplate({ templateId, state });
},
async exportEmailTemplates(): Promise<EmailTemplateExportInterface> {
return exportEmailTemplates({ state });
async exportEmailTemplates(
includeDefault: boolean = false
): Promise<EmailTemplateExportInterface> {
return exportEmailTemplates({ includeDefault, state });
},
async createEmailTemplate(
templateId: string,
Expand Down Expand Up @@ -218,16 +226,20 @@ export function createEmailTemplateExportTemplate({

/**
* Get all email templates
* @param {boolean} includeDefault Include default email templates if true, false to exclude them. Default: false
* @returns {Promise<EmailTemplateSkeleton[]>} a promise that resolves to an array of email template objects
*/
export async function readEmailTemplates({
includeDefault = false,
state,
}: {
includeDefault?: boolean;
state: State;
}): Promise<EmailTemplateSkeleton[]> {
try {
const templates = await readConfigEntitiesByType({
type: EMAIL_TEMPLATE_TYPE,
includeDefault,
state,
});
return templates as EmailTemplateSkeleton[];
Expand Down Expand Up @@ -260,11 +272,14 @@ export async function readEmailTemplate({

/**
* Export all email templates. The response can be saved to file as is.
* @param {boolean} includeDefault Include default email templates if true, false to exclude them. Default: false
* @returns {Promise<EmailTemplateExportInterface>} Promise resolving to a EmailTemplateExportInterface object.
*/
export async function exportEmailTemplates({
includeDefault = false,
state,
}: {
includeDefault: boolean;
state: State;
}): Promise<EmailTemplateExportInterface> {
try {
Expand All @@ -273,7 +288,7 @@ export async function exportEmailTemplates({
state,
});
const exportData = createEmailTemplateExportTemplate({ state });
const emailTemplates = await readEmailTemplates({ state });
const emailTemplates = await readEmailTemplates({ includeDefault, state });
const indicatorId = createProgressIndicator({
total: emailTemplates.length,
message: 'Exporting email templates...',
Expand Down
9 changes: 9 additions & 0 deletions src/ops/IdmConfigOps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,15 @@ describe('IdmConfigOps', () => {
});
expect(response).toMatchSnapshot();
});

test('3: Read config entity by type (emailTemplate with default templates)', async () => {
const response = await IdmConfigOps.readConfigEntitiesByType({
type: 'emailTemplate',
includeDefault: true,
state,
});
expect(response).toMatchSnapshot();
});
});

describe('readConfigEntity()', () => {
Expand Down
19 changes: 15 additions & 4 deletions src/ops/IdmConfigOps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,13 @@ export type IdmConfig = {
/**
* Read all config entities of a type
* @param {string} type config entity type
* @param {boolean} includeDefault Include default email templates if true, false to exclude them. Default: false
* @returns {IdObjectSkeletonInterface[]} promise resolving to an array of config entities of a type
*/
readConfigEntitiesByType(type: string): Promise<IdObjectSkeletonInterface[]>;
readConfigEntitiesByType(
type: string,
includeDefault?: boolean
): Promise<IdObjectSkeletonInterface[]>;
/**
* Read config entity
* @param {string} entityId config entity id/name
Expand Down Expand Up @@ -249,9 +253,10 @@ export default (state: State): IdmConfig => {
return readConfigEntities({ state });
},
async readConfigEntitiesByType(
type: string
type: string,
includeDefault: boolean = false
): Promise<IdObjectSkeletonInterface[]> {
return readConfigEntitiesByType({ type, state });
return readConfigEntitiesByType({ type, includeDefault, state });
},
async readConfigEntity(
entityId: string
Expand Down Expand Up @@ -478,13 +483,19 @@ export async function readConfigEntities({

export async function readConfigEntitiesByType({
type,
includeDefault = false,
state,
}: {
type: string;
includeDefault?: boolean;
state: State;
}): Promise<NoIdObjectSkeletonInterface[]> {
try {
const { result } = await _getConfigEntitiesByType({ type, state });
const { result } = await _getConfigEntitiesByType({
type,
includeDefault,
state,
});
return result;
} catch (error) {
throw new FrodoError(`Error reading config entities by type`, error);
Expand Down
Loading
Loading