Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe(commands.APPROLEASSIGNMENT_ADD, () => {
sinon.stub(session, 'getId').returns('');
auth.connection.active = true;
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse()! as typeof options;
commandOptionsSchema = commandInfo.command.getSchemaToParse() as typeof options;
});

beforeEach(() => {
Expand Down Expand Up @@ -311,4 +311,3 @@ describe(commands.APPROLEASSIGNMENT_ADD, () => {
assert.strictEqual(actual.success, true);
});
});

Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const options = z.strictObject({
appObjectId: z.uuid().optional(),
appDisplayName: z.string().optional(),
resource: z.string().alias('r'),
scopes: z.string().alias('s')
scopes: z.string().transform((value) => value.split(',').map(String)).alias('s')
});

declare type Options = z.infer<typeof options>;
Expand Down Expand Up @@ -143,8 +143,10 @@ class EntraAppRoleAssignmentAddCommand extends GraphCommand {
throw `The resource '${args.options.resource}' does not have any application permissions available.`;
}

const scopes = `${args.options.scopes}`.split(',').map(String);

// search for match between the found app roles and the specified scopes option value
for (const scope of args.options.scopes.split(',')) {
for (const scope of scopes) {
const existingRoles = appRolesFound.filter((role: AppRole) => {
return role.value.toLocaleLowerCase() === scope.toLocaleLowerCase().trim();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ describe(commands.APPROLEASSIGNMENT_LIST, () => {
sinon.stub(session, 'getId').returns('');
auth.connection.active = true;
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse()! as typeof options;
commandOptionsSchema = commandInfo.command.getSchemaToParse() as typeof options;
});

beforeEach(() => {
Expand Down Expand Up @@ -577,4 +577,3 @@ describe(commands.APPROLEASSIGNMENT_LIST, () => {
assert.strictEqual(actual.success, true);
});
});

Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe(commands.APPROLEASSIGNMENT_REMOVE, () => {
sinon.stub(session, 'getId').returns('');
auth.connection.active = true;
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse()! as typeof options;
commandOptionsSchema = commandInfo.command.getSchemaToParse() as typeof options;
});

beforeEach(() => {
Expand Down Expand Up @@ -279,4 +279,3 @@ describe(commands.APPROLEASSIGNMENT_REMOVE, () => {
assert.strictEqual(actual.success, true);
});
});

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const options = z.strictObject({
appObjectId: z.uuid().optional(),
appDisplayName: z.string().optional(),
resource: z.string().alias('r'),
scopes: z.string().alias('s'),
scopes: z.string().transform((value) => value.split(',').map(String)).alias('s'),
force: z.boolean().optional().alias('f')
});

Expand Down Expand Up @@ -115,7 +115,9 @@ class EntraAppRoleAssignmentRemoveCommand extends GraphCommand {
throw `The resource '${args.options.resource}' does not have any application permissions available.`;
}

for (const scope of args.options.scopes.split(',')) {
const scopes = `${args.options.scopes}`.split(',').map(String);

for (const scope of scopes) {
const existingRoles = appRolesFound.filter((role: AppRole) => {
return role.value!.toLocaleLowerCase() === scope.toLocaleLowerCase().trim();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe(commands.ENTERPRISEAPP_GET, () => {
sinon.stub(session, 'getId').returns('');
auth.connection.active = true;
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse()! as typeof options;
commandOptionsSchema = commandInfo.command.getSchemaToParse() as typeof options;
});

beforeEach(() => {
Expand Down Expand Up @@ -307,6 +307,11 @@ describe(commands.ENTERPRISEAPP_GET, () => {
assert.strictEqual(actual.success, false);
});

it('fails validation if both id and objectId are specified', () => {
const actual = commandOptionsSchema.safeParse({ id: '6a7b1395-d313-4682-8ed4-65a6265a6320', objectId: 'dbf32ef1-ea3e-4e3c-968f-79fbe57ea4d8' });
assert.strictEqual(actual.success, false);
});

it('fails validation if objectId and displayName are specified', () => {
const actual = commandOptionsSchema.safeParse({ displayName: 'abc', objectId: '6a7b1395-d313-4682-8ed4-65a6265a6320' });
assert.strictEqual(actual.success, false);
Expand Down
28 changes: 27 additions & 1 deletion src/m365/entra/commands/enterpriseapp/enterpriseapp-list.spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import assert from 'assert';
import sinon from 'sinon';
import auth from '../../../../Auth.js';
import { cli } from '../../../../cli/cli.js';
import { CommandInfo } from '../../../../cli/CommandInfo.js';
import { Logger } from '../../../../cli/Logger.js';
import request from '../../../../request.js';
import { telemetry } from '../../../../telemetry.js';
import { pid } from '../../../../utils/pid.js';
import { session } from '../../../../utils/session.js';
import { sinonUtil } from '../../../../utils/sinonUtil.js';
import commands from '../../commands.js';
import command from './enterpriseapp-list.js';
import command, { options } from './enterpriseapp-list.js';

describe(commands.ENTERPRISEAPP_LIST, () => {
let log: string[];
let logger: Logger;
let loggerLogSpy: sinon.SinonSpy;
let commandInfo: CommandInfo;
let commandOptionsSchema: typeof options;

const displayName = "My custom enterprise application";
const tag = "WindowsAzureActiveDirectoryIntegratedApp";
Expand Down Expand Up @@ -97,6 +101,8 @@ describe(commands.ENTERPRISEAPP_LIST, () => {
sinon.stub(pid, 'getProcessName').callsFake(() => '');
sinon.stub(session, 'getId').callsFake(() => '');
auth.connection.active = true;
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse() as typeof options;
});

beforeEach(() => {
Expand Down Expand Up @@ -197,4 +203,24 @@ describe(commands.ENTERPRISEAPP_LIST, () => {

await assert.rejects(command.action(logger, { options: {} } as any), error['odata.error'].message.value);
});

it('passes validation when displayName is specified', () => {
const actual = commandOptionsSchema.safeParse({ displayName: 'My custom enterprise application' });
assert.strictEqual(actual.success, true);
});

it('passes validation when tag is specified', () => {
const actual = commandOptionsSchema.safeParse({ tag: 'WindowsAzureActiveDirectoryIntegratedApp' });
assert.strictEqual(actual.success, true);
});

it('fails validation if displayName is not a string', () => {
const actual = commandOptionsSchema.safeParse({ displayName: 1 });
assert.strictEqual(actual.success, false);
});

it('fails validation if tag is not a string', () => {
const actual = commandOptionsSchema.safeParse({ tag: 1 });
assert.strictEqual(actual.success, false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ describe(commands.ENTERPRISEAPP_REMOVE, () => {
sinon.stub(session, 'getId').returns('');
auth.connection.active = true;
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse()! as typeof options;
commandOptionsSchema = commandInfo.command.getSchemaToParse() as typeof options;
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => settingName === settingsNames.prompt ? false : defaultValue);
});

Expand Down