Skip to content
35 changes: 18 additions & 17 deletions src/tasks/demo-url-processor/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,31 @@ const TASK_TYPE = 'demo-url-processor';

/**
* Gets the IMS tenant ID from the organization
* @param {string} imsOrgId - The IMS organization ID
* @param {object} organization - The organization object
* @param {object} context - The context object
* @param {object} log - The log object
* @param {object} env - The environment object
* @param {object} slackContext - The Slack context object
* @returns {string} The IMS tenant ID
*/
function getImsTenantId(imsOrgId, organization, context, log) {
const { name } = organization;
try {
const imsOrgToTenantMapping = context.env.IMS_ORG_TENANT_ID_MAPPINGS;
if (imsOrgToTenantMapping) {
const mapping = JSON.parse(imsOrgToTenantMapping);
if (mapping[imsOrgId]) {
return mapping[imsOrgId];
}
}
} catch (error) {
log.error('Error loading IMS_ORG_TENANT_ID_MAPPINGS mapping:', error.message);
async function getImsTenantId(imsOrgId, organization, context, log, env, slackContext) {
const { name, tenantId } = organization;

// If tenantId is there, return it
if (tenantId) {
return tenantId;
}
if (!name) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please take note to remove these stale secres from Secret Manager after deployment

log.error('Organization name is missing, using default tenant ID');
return context.env.DEFAULT_TENANT_ID;
} else {

// If tenantId isn't there, use name to generate (backward compatible for existing orgs)
if (name) {
return name.toLowerCase().replace(/\s+/g, '');
}

// If name is also not there, log an error and return DEFAULT_TENANT_ID
log.error('Organization name and tenantId are missing, using default tenant ID');
await say(env, log, slackContext, ':x: Organization name and tenantId are missing, using default tenant ID');
return context.env.DEFAULT_TENANT_ID;
}

/**
Expand Down Expand Up @@ -72,7 +73,7 @@ export async function runDemoUrlProcessor(message, context) {
return ok({ message: 'Organization not found' });
}

const imsTenantId = getImsTenantId(imsOrgId, organization, context, log);
const imsTenantId = await getImsTenantId(imsOrgId, organization, context, log, env, slackContext);
const demoUrl = `${experienceUrl}?organizationId=${organizationId}#/@${imsTenantId}/sites-optimizer/sites/${siteId}/home`;
const slackMessage = `:white_check_mark: Setup complete! Access your demo environment here: ${demoUrl}`;
await say(env, log, slackContext, slackMessage);
Expand Down
122 changes: 51 additions & 71 deletions test/tasks/demo-url-processor/demo-url-processor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,110 +64,90 @@ describe('Demo URL Processor', () => {
});

describe('runDemoUrlProcessor', () => {
it('should process demo URL successfully', async () => {
// Set up the IMS_ORG_TENANT_ID_MAPPINGS secret in context
context.env.IMS_ORG_TENANT_ID_MAPPINGS = JSON.stringify({
'8C6043F15F43B6390A49401A@AdobeOrg': 'aem-sites-engineering',
});
it('should handle organization not found error', async () => {
// Mock Organization.findById to return null
context.dataAccess.Organization.findById.resolves(null);

await runDemoUrlProcessor(message, context);
expect(context.log.info.calledWith('Processing demo url for site:', {
taskType: 'demo-url-processor',
siteId: 'test-site-id',
experienceUrl: 'https://example.com',
organizationId: 'test-org-id',
})).to.be.true;
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@aem-sites-engineering/sites-optimizer/sites/test-site-id/home';
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
});

it('should handle missing slackContext in taskContext', async () => {
// Set up the IMS_ORG_TENANT_ID_MAPPINGS secret in context
context.env.IMS_ORG_TENANT_ID_MAPPINGS = JSON.stringify({
'8C6043F15F43B6390A49401A@AdobeOrg': 'aem-sites-engineering',
});

delete message.taskContext.slackContext;
await runDemoUrlProcessor(message, context);
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@aem-sites-engineering/sites-optimizer/sites/test-site-id/home';
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
// Should log error and return early
expect(context.log.error.calledWith('Organization not found for organizationId: test-org-id')).to.be.true;
// Should not log the success message
expect(context.log.info.calledWithMatch(sinon.match('Setup complete!'))).to.be.false;
});

it('should use IMS_ORG_TENANT_ID_MAPPINGS mapping when available', async () => {
// Set up the IMS_ORG_TENANT_ID_MAPPINGS secret in context
context.env.IMS_ORG_TENANT_ID_MAPPINGS = JSON.stringify({
'8C6043F15F43B6390A49401A@AdobeOrg': 'aem-sites-engineering',
it('should handle organization with missing name property', async () => {
// Mock Organization.findById to return organization without name
context.dataAccess.Organization.findById.resolves({
imsOrgId: '8C6043F15F43B6390A49401A@AdobeOrg',
// name property is missing
});

await runDemoUrlProcessor(message, context);

// Should use the mapped tenant name instead of the fallback
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@aem-sites-engineering/sites-optimizer/sites/test-site-id/home';
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
});

it('should fallback to name-based tenant when IMS_ORG_TENANT_ID_MAPPINGS mapping is not available', async () => {
// Don't set IMS_ORG_TENANT_ID_MAPPINGS secret
delete context.env.IMS_ORG_TENANT_ID_MAPPINGS;
// Set default tenant ID
context.env.DEFAULT_TENANT_ID = 'default-tenant';

await runDemoUrlProcessor(message, context);

// Should use the fallback name-based tenant (lowercase, no spaces)
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@adobesitesengineering/sites-optimizer/sites/test-site-id/home';
// Should log error about missing name and use fallback
expect(context.log.error.calledWith('Organization name is missing, using default tenant ID')).to.be.true;
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@default-tenant/sites-optimizer/sites/test-site-id/home';
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
});

it('should fallback to name-based tenant when IMS_ORG_TENANT_ID_MAPPINGS mapping is invalid JSON', async () => {
// Set invalid JSON in IMS_ORG_TENANT_ID_MAPPINGS secret
context.env.IMS_ORG_TENANT_ID_MAPPINGS = 'invalid-json';
it('should handle organization with missing tenantId property', async () => {
// Mock Organization.findById to return organization without tenantId
context.dataAccess.Organization.findById.resolves({
name: 'Adobe Sites Engineering',
imsOrgId: '8C6043F15F43B6390A49401A@AdobeOrg',
// tenantId property is missing
});

// Set default tenant ID
context.env.DEFAULT_TENANT_ID = 'default-tenant';

await runDemoUrlProcessor(message, context);

// Should use the fallback name-based tenant
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@adobesitesengineering/sites-optimizer/sites/test-site-id/home';
// Should log error about missing name and use fallback
expect(context.log.error.calledWith('Organization name is missing, using default tenant ID')).to.be.true;
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@default-tenant/sites-optimizer/sites/test-site-id/home';
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
});

it('should fallback to name-based tenant when IMS_ORG_TENANT_ID_MAPPINGS mapping does not contain the imsOrgId', async () => {
// Set IMS_ORG_TENANT_ID_MAPPINGS secret with different mapping
context.env.IMS_ORG_TENANT_ID_MAPPINGS = JSON.stringify({
'DIFFERENT_ORG_ID@AdobeOrg': 'different-team',
it('should use organization name when both name and tenantId are present', async () => {
// Mock Organization.findById to return organization with both name and tenantId
context.dataAccess.Organization.findById.resolves({
name: 'Adobe Sites Engineering',
tenantId: 'adobe-sites-engineering',
imsOrgId: '8C6043F15F43B6390A49401A@AdobeOrg',
});

await runDemoUrlProcessor(message, context);

// Should use the fallback name-based tenant since the imsOrgId is not in the mapping
// Should use the name-based tenant (lowercase, no spaces)
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@adobesitesengineering/sites-optimizer/sites/test-site-id/home';
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
});

it('should handle organization not found error', async () => {
// Mock Organization.findById to return null
context.dataAccess.Organization.findById.resolves(null);

await runDemoUrlProcessor(message, context);

// Should log error and return early
expect(context.log.error.calledWith('Organization not found for organizationId: test-org-id')).to.be.true;
// Should not log the success message
expect(context.log.info.calledWithMatch(sinon.match('Setup complete!'))).to.be.false;
});

it('should handle organization with missing name property', async () => {
// Mock Organization.findById to return organization without name
it('should handle successful demo URL processing', async () => {
// Mock Organization.findById to return organization with both name and tenantId
context.dataAccess.Organization.findById.resolves({
name: 'Adobe Sites Engineering',
tenantId: 'adobe-sites-engineering',
imsOrgId: '8C6043F15F43B6390A49401A@AdobeOrg',
// name property is missing
});

// Set default tenant ID
context.env.DEFAULT_TENANT_ID = 'default-tenant';

await runDemoUrlProcessor(message, context);

// Should log error about missing name and use fallback
expect(context.log.error.calledWith('Organization name is missing, using default tenant ID')).to.be.true;
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@default-tenant/sites-optimizer/sites/test-site-id/home';
// Should log the processing message
expect(context.log.info.calledWith('Processing demo url for site:', {
taskType: 'demo-url-processor',
siteId: 'test-site-id',
experienceUrl: 'https://example.com',
organizationId: 'test-org-id',
})).to.be.true;

// Should log the completion message
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@adobesitesengineering/sites-optimizer/sites/test-site-id/home';
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
});
});
Expand Down
Loading