Skip to content

Commit

Permalink
Merge pull request #97 from adobe/cod18017/enhanced-ims-context-handling
Browse files Browse the repository at this point in the history
leverage enhanced ims context handling
  • Loading branch information
RemoLiechti authored Oct 16, 2024
2 parents d678985 + 40fb983 commit f6fb81e
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 87 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ For build environments, include below into the scripts.
```

> **Note**:
> Working with multiple environments: it is highly recommend to use the flag `-l` or `--local` together with the `config:set` so that the configuration is stored in the local directory (i.e. the config is only effective in the current directory). For details on different config locations refer to [aio-lib-core-config's README](https://github.com/adobe/aio-lib-core-config#persistent-file-locations).
> Working with multiple environments: it is highly recommend to use the flag `-l` or `--local` together with the `config:set` so that the configuration is stored in the local directory (i.e. the config is only effective in the current directory). For details on different config locations refer to [aio-lib-core-config's README](https://github.com/adobe/aio-lib-core-config#persistent-file-locations). Also, make use of the possibility to store the login information in seperate contexts locally. [Follow the RDE documentation](https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/implementing/developing/rapid-development-environments#installing-the-rde-command-line-tools) for further information, take a close look to the step 3 details.
### Configuration for `aio aem rde inspect` commands \*

Expand Down
9 changes: 5 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@adobe/aio-lib-core-config": "^5.0.1",
"@adobe/aio-lib-core-errors": "^4.0.1",
"@adobe/aio-lib-core-networking": "^5.0.1",
"@adobe/aio-lib-ims": "^7.0.1",
"@adobe/aio-lib-ims": "^7.0.2",
"@azure/storage-file-share": "^12.12.0",
"@oclif/core": "^1.20.4",
"adm-zip": "^0.5.9",
Expand Down Expand Up @@ -86,4 +86,4 @@
}
}
}
}
}
39 changes: 12 additions & 27 deletions src/commands/aem/rde/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class SetupCommand extends BaseCommand {

async withCloudSdkBase(fn) {
if (!this._cloudSdkAPIBase) {
const { accessToken, apiKey } = await this.getTokenAndKey();
const cloudManagerUrl = this.getBaseUrl();
const { accessToken, apiKey, data } = await this.getTokenAndKey();
const cloudManagerUrl = this.getBaseUrl(data?.env === 'stage');
const orgId = this.getCliOrgId();
if (!orgId) {
throw new validationCodes.MISSING_ORG_ID();
Expand All @@ -73,18 +73,15 @@ class SetupCommand extends BaseCommand {
return fn(this._cloudSdkAPIBase);
}

getImsInstance() {
return new Ims(); // allow for easy mocking in tests
async getOrganizationsFromIms(accessToken) {
const { ims } = await Ims.fromToken(accessToken);
return await ims.getOrganizations(accessToken);
}

/**
*
*/
async getOrganizationsFromToken() {
try {
const { accessToken } = await this.getTokenAndKey();
const ims = this.getImsInstance();
const organizations = await ims.getOrganizations(accessToken);
const organizations = await this.getOrganizationsFromIms(accessToken);
const orgMap = organizations.reduce((map, org) => {
map[org.orgName] = org.orgRef.ident + '@' + org.orgRef.authSrc;
return map;
Expand Down Expand Up @@ -300,7 +297,7 @@ class SetupCommand extends BaseCommand {
`Setup the CLI configuration necessary to use the RDE commands.`
);

const storeLocal = await inquirer.prompt([
const { storeLocal } = await inquirer.prompt([
{
type: 'confirm',
name: 'storeLocal',
Expand All @@ -312,7 +309,7 @@ class SetupCommand extends BaseCommand {

const orgId = await this.getOrgId();
const prevOrgId = Config.get(CONFIG_ORG);
Config.set(CONFIG_ORG, orgId, storeLocal.storeLocal);
Config.set(CONFIG_ORG, orgId, storeLocal);

let selectedEnvironmentId = null;
let selectedProgramId = null;
Expand Down Expand Up @@ -351,23 +348,11 @@ class SetupCommand extends BaseCommand {

const { prevProgramId, prevProgramName } = this.getProgramFromConf();
const { prevEnvId, prevEnvName } = this.getEnvironmentFromConf();
Config.set(CONFIG_PROGRAM, selectedProgramId, storeLocal.storeLocal);
Config.set(
CONFIG_ENVIRONMENT,
selectedEnvironmentId,
storeLocal.storeLocal
);
Config.set(CONFIG_PROGRAM, selectedProgramId, storeLocal);
Config.set(CONFIG_ENVIRONMENT, selectedEnvironmentId, storeLocal);

Config.set(
CONFIG_PROGRAM_NAME,
selectedProgramName,
storeLocal.storeLocal
);
Config.set(
CONFIG_ENVIRONMENT_NAME,
selectedEnvironmentName,
storeLocal.storeLocal
);
Config.set(CONFIG_PROGRAM_NAME, selectedProgramName, storeLocal);
Config.set(CONFIG_ENVIRONMENT_NAME, selectedEnvironmentName, storeLocal);

this.logPreviousConfig(
prevOrgId,
Expand Down
70 changes: 36 additions & 34 deletions src/lib/base-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ class BaseCommand extends Command {
this.doLog(this.getLogHeader());
const lastAction = Config.get('rde_lastaction');
if (lastAction && Date.now() - lastAction > 24 * 60 * 60 * 1000) {
const executeCommand = await inquirer.prompt([
const { executeCommand } = await inquirer.prompt([
{
type: 'confirm',
name: 'executeCommand',
message: `The last RDE command ran more than 24h ago, do you want to continue running the command on ${concatEnvironemntId(this._programId, this._environmentId)}?`,
default: true,
},
]);
if (!executeCommand.executeCommand) {
if (!executeCommand) {
this.doLog('Command execution aborted.');
return;
}
Expand Down Expand Up @@ -150,58 +150,58 @@ class BaseCommand extends Command {
/**
*
*/
getBaseUrl() {
const configStr = Config.get('cloudmanager.base_url');
return configStr || 'https://cloudmanager.adobe.io';
getBaseUrl(stage) {
return !stage
? 'https://cloudmanager.adobe.io'
: 'https://cloudmanager-stage.adobe.io';
}

/**
*
*/
async getTokenAndKey() {
let accessToken;
let apiKey;

try {
const contextName = 'aio-cli-plugin-cloudmanager';
accessToken = await getToken(contextName);
const contextData = await context.get(contextName);
if (!contextData || !contextData.data) {
throw new configurationCodes.NO_IMS_CONTEXT({
messageValues: contextName,
});
}
apiKey = contextData.data.client_id;
} catch (err) {
accessToken = await getToken('cli');
const decodedToken = jwt.decode(accessToken);
if (!decodedToken) {
// TODO - support context flag
const contextName = (await context.getCurrent()) || 'cli';
const contextData = await context.get(contextName);
const local = contextData?.local || false;
const data = contextData?.data;
if (!data) {
throw new configurationCodes.NO_IMS_CONTEXT({
messageValues: contextName,
});
}
const accessToken = await getToken(contextName);
const apiKey = data.client_id
? data.client_id
: jwt.decode(accessToken)?.client_id;
if (!apiKey) {
if (!jwt.decode(accessToken)) {
throw new configurationCodes.CLI_AUTH_CONTEXT_CANNOT_DECODE();
}
apiKey = decodedToken.client_id;
if (!apiKey) {
throw new configurationCodes.CLI_AUTH_CONTEXT_NO_CLIENT_ID();
}
throw new configurationCodes.CLI_AUTH_CONTEXT_NO_CLIENT_ID();
}
return { accessToken, apiKey };
return { accessToken, apiKey, local, data };
}

/**
* @param cloudManagerUrl
* @param orgId
* @param accessToken
* @param apiKey
*/
async initSdk(cloudManagerUrl, orgId) {
const { accessToken, apiKey } = await this.getTokenAndKey();
async initSdk(cloudManagerUrl, orgId, accessToken, apiKey) {
return await init(orgId, apiKey, accessToken, cloudManagerUrl);
}

async getDeveloperConsoleUrl(
cloudManagerUrl,
orgId,
programId,
environmentId
environmentId,
accessToken,
apiKey
) {
const sdk = await this.initSdk(cloudManagerUrl, orgId);
const sdk = await this.initSdk(cloudManagerUrl, orgId, accessToken, apiKey);
return sdk.getDeveloperConsoleUrl(programId, environmentId);
}

Expand All @@ -213,8 +213,8 @@ class BaseCommand extends Command {
if (!this._environmentId) {
throw new validationCodes.MISSING_ENVIRONMENT_ID();
}
const { accessToken, apiKey } = await this.getTokenAndKey();
const cloudManagerUrl = this.getBaseUrl();
const { accessToken, apiKey, data } = await this.getTokenAndKey();
const cloudManagerUrl = this.getBaseUrl(data?.env === 'stage');
const orgId = this.getCliOrgId();
const cacheKey = `aem-rde.dev-console-url-cache.${concatEnvironemntId(this._programId, this._environmentId)}`;
let cacheEntry = Config.get(cacheKey);
Expand All @@ -228,7 +228,9 @@ class BaseCommand extends Command {
cloudManagerUrl,
orgId,
this._programId,
this._environmentId
this._environmentId,
accessToken,
apiKey
);
const url = new URL(developerConsoleUrl);
url.hash = '';
Expand Down
12 changes: 6 additions & 6 deletions test/commands/aem/rde/setup.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,26 +65,24 @@ describe('SetupCommand - withCloudSdkBase', function () {

describe('SetupCommand - getOrganizationsFromToken', function () {
let setupCommand;
let imsInstanceStub;

beforeEach(function () {
setupCommand = new SetupCommand();
imsInstanceStub = sinon.createStubInstance(Ims);
sinon
.stub(setupCommand, 'getTokenAndKey')
.resolves({ accessToken: 'testAccessToken' });
sinon.stub(setupCommand, 'getImsInstance').returns(imsInstanceStub);
});

afterEach(function () {
sinon.restore();
});

it('should return the correct organization map when IMS returns organizations', async function () {
imsInstanceStub.getOrganizations.resolves([
sinon.stub(setupCommand, 'getOrganizationsFromIms').resolves([
{ orgName: 'Org1', orgRef: { ident: '123', authSrc: 'AuthSrc1' } },
{ orgName: 'Org2', orgRef: { ident: '456', authSrc: 'AuthSrc2' } },
]);

const expectedOrgMap = {
Org1: '123@AuthSrc1',
Org2: '456@AuthSrc2',
Expand All @@ -95,7 +93,7 @@ describe('SetupCommand - getOrganizationsFromToken', function () {

it('should log a message and return null when no IMS context is found', async function () {
const logStub = sinon.stub(setupCommand, 'doLog');
imsInstanceStub.getOrganizations.rejects({
sinon.stub(setupCommand, 'getOrganizationsFromIms').rejects({
code: 'CONTEXT_NOT_CONFIGURED',
});
const orgMap = await setupCommand.getOrganizationsFromToken();
Expand All @@ -106,7 +104,9 @@ describe('SetupCommand - getOrganizationsFromToken', function () {
});

it('should return null when IMS throws an error other than "CONTEXT_NOT_CONFIGURED"', async function () {
imsInstanceStub.getOrganizations.rejects(new Error('Some other error'));
sinon
.stub(setupCommand, 'getOrganizationsFromIms')
.rejects(new Error('Some other error'));
const orgMap = await setupCommand.getOrganizationsFromToken();
assert.strictEqual(orgMap, null);
});
Expand Down
Loading

0 comments on commit f6fb81e

Please sign in to comment.