From 633959a98fee0a4fa657ff1a0486512757d81131 Mon Sep 17 00:00:00 2001 From: reshmee011 Date: Mon, 23 Dec 2024 15:34:47 +0000 Subject: [PATCH] add new cmdlet to add home site --- .../cmd/spo/tenant/tenant-homesite-add.mdx | 97 +++++++++++++++ docs/src/config/sidebars.ts | 5 + src/m365/spo/commands.ts | 1 + .../tenant/tenant-homesite-add.spec.ts | 116 ++++++++++++++++++ .../commands/tenant/tenant-homesite-add.ts | 87 +++++++++++++ 5 files changed, 306 insertions(+) create mode 100644 docs/docs/cmd/spo/tenant/tenant-homesite-add.mdx create mode 100644 src/m365/spo/commands/tenant/tenant-homesite-add.spec.ts create mode 100644 src/m365/spo/commands/tenant/tenant-homesite-add.ts diff --git a/docs/docs/cmd/spo/tenant/tenant-homesite-add.mdx b/docs/docs/cmd/spo/tenant/tenant-homesite-add.mdx new file mode 100644 index 00000000000..dac2dc98860 --- /dev/null +++ b/docs/docs/cmd/spo/tenant/tenant-homesite-add.mdx @@ -0,0 +1,97 @@ +import Global from '/docs/cmd/_global.mdx'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# spo tenant homesite add + +Add a Home Site. + +## Usage + +```sh +m365 spo tenant homesite add [options] +``` + +## Options + + + +## Examples + +Add a Home Site + +```sh +m365 spo tenant homesite add --url "https://contoso.sharepoint.com/sites/testcomms" + +``` + +## Response + + + + + ```json + { + "Audiences": [], + "IsInDraftMode": true, + "IsVivaBackendSite": false, + "SiteId": "ca49054c-85f3-41eb-a290-46ffda8f219c", + "TargetedLicenseType": 0, + "Title": "testcommsite", + "Url": "https://contoso.sharepoint.com/sites/testcomms", + "VivaConnectionsDefaultStart": false, + "WebId": "256c4f0f-e372-47b4-a891-b4888e829e20" + } + ``` + + + + + ```text + Audiences : [] + IsInDraftMode : true + IsVivaBackendSite : false + SiteId : ca49054c-85f3-41eb-a290-46ffda8f219c + TargetedLicenseType : 0 + Title : testcommsite + Url : https://contoso.sharepoint.com/sites/testcomms + VivaConnectionsDefaultStart: false + WebId : 256c4f0f-e372-47b4-a891-b4888e829e20 + ``` + + + + + ```csv + IsInDraftMode,IsVivaBackendSite,SiteId,TargetedLicenseType,Title,Url,VivaConnectionsDefaultStart,WebId + 1,0,ca49054c-85f3-41eb-a290-46ffda8f219c,0,testcommsite,https://contoso.sharepoint.com/sites/testcomms,0,256c4f0f-e372-47b4-a891-b4888e829e20 + ``` + + + + + ```md + # spo tenant homesite add --url "https://contoso.sharepoint.com/sites/testcomms" + + Date: 12/23/2024 + + ## testcommsite (https://contoso.sharepoint.com/sites/testcomms) + + Property | Value + ---------|------- + IsInDraftMode | true + IsVivaBackendSite | false + SiteId | ca49054c-85f3-41eb-a290-46ffda8f219c + TargetedLicenseType | 0 + Title | testcommsite + Url | https://contoso.sharepoint.com/sites/testcomms + VivaConnectionsDefaultStart | false + WebId | 256c4f0f-e372-47b4-a891-b4888e829e20 + ``` + + + +## More information + +- SharePoint home sites [Viva Connections set up](https://learn.microsoft.com/en-us/viva/connections/set-up-admin-center) + diff --git a/docs/src/config/sidebars.ts b/docs/src/config/sidebars.ts index 68fa5ec4249..f6162777e22 100644 --- a/docs/src/config/sidebars.ts +++ b/docs/src/config/sidebars.ts @@ -3766,6 +3766,11 @@ const sidebars: SidebarsConfig = { label: 'tenant commandset set', id: 'cmd/spo/tenant/tenant-commandset-set' }, + { + type: 'doc', + label: 'tenant homesite add', + id: 'cmd/spo/tenant/tenant-homesite-add' + }, { type: 'doc', label: 'tenant homesite list', diff --git a/src/m365/spo/commands.ts b/src/m365/spo/commands.ts index f17b2edca20..b8bbb1165cc 100644 --- a/src/m365/spo/commands.ts +++ b/src/m365/spo/commands.ts @@ -318,6 +318,7 @@ export default { TENANT_COMMANDSET_LIST: `${prefix} tenant commandset list`, TENANT_COMMANDSET_REMOVE: `${prefix} tenant commandset remove`, TENANT_COMMANDSET_SET: `${prefix} tenant commandset set`, + TENANT_HOMESITE_ADD: `${prefix} tenant homesite add`, TENANT_HOMESITE_LIST: `${prefix} tenant homesite list`, TENANT_RECYCLEBINITEM_LIST: `${prefix} tenant recyclebinitem list`, TENANT_RECYCLEBINITEM_REMOVE: `${prefix} tenant recyclebinitem remove`, diff --git a/src/m365/spo/commands/tenant/tenant-homesite-add.spec.ts b/src/m365/spo/commands/tenant/tenant-homesite-add.spec.ts new file mode 100644 index 00000000000..c86c4040323 --- /dev/null +++ b/src/m365/spo/commands/tenant/tenant-homesite-add.spec.ts @@ -0,0 +1,116 @@ +import assert from 'assert'; +import sinon from 'sinon'; +import auth from '../../../../Auth.js'; +import { cli } from '../../../../cli/cli.js'; +import { Logger } from '../../../../cli/Logger.js'; +import { CommandError } from '../../../../Command.js'; +import { CommandInfo } from '../../../../cli/CommandInfo.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 './tenant-homesite-add.js'; + +describe(commands.TENANT_HOMESITE_ADD, () => { + let log: string[]; + let logger: Logger; + let loggerLogSpy: sinon.SinonSpy; + let commandInfo: CommandInfo; + const homeSite = "https://contoso.sharepoint.com/sites/testcomms"; + const homeSites = { + "Audiences": [], + "IsInDraftMode": true, + "IsVivaBackendSite": false, + "SiteId": "ca49054c-85f3-41eb-a290-46ffda8f219c", + "TargetedLicenseType": 0, + "Title": "testcommsite", + "Url": homeSite, + "VivaConnectionsDefaultStart": false, + "WebId": "256c4f0f-e372-47b4-a891-b4888e829e20" + }; + + before(() => { + sinon.stub(auth, 'restoreAuth').resolves(); + sinon.stub(telemetry, 'trackEvent').returns(); + sinon.stub(pid, 'getProcessName').returns(''); + sinon.stub(session, 'getId').returns(''); + auth.connection.active = true; + auth.connection.spoUrl = 'https://contoso.sharepoint.com'; + }); + + beforeEach(() => { + log = []; + logger = { + log: async (msg: string) => { + log.push(msg); + }, + logRaw: async (msg: string) => { + log.push(msg); + }, + logToStderr: async (msg: string) => { + log.push(msg); + } + }; + loggerLogSpy = sinon.spy(logger, 'log'); + commandInfo = cli.getCommandInfo(command); + }); + + afterEach(() => { + sinonUtil.restore([ + request.post + ]); + }); + + after(() => { + sinon.restore(); + auth.connection.active = false; + auth.connection.spoUrl = undefined; + }); + + it('has correct name', () => { + assert.strictEqual(command.name, commands.TENANT_HOMESITE_ADD); + }); + + it('has a description', () => { + assert.notStrictEqual(command.description, null); + }); + + it('adds available home sites', async () => { + sinon.stub(request, 'post').callsFake(async (opts) => { + if (opts.url === `https://contoso-admin.sharepoint.com/_api/SPO.Tenant/AddHomeSite`) { + return homeSites; + } + + throw opts.url; + }); + + await command.action(logger, { options: { url: homeSite, verbose: true } }); + assert(loggerLogSpy.calledWith(homeSites)); + }); + + it('fails validation if the url is not a valid SharePoint url', async () => { + const actual = await command.validate({ + options: { + url: "test" + } + }, commandInfo); + assert.notStrictEqual(actual, true); + }); + + it('passes validation', async () => { + const actual = await command.validate({ + options: { + url: homeSite + } + }, commandInfo); + assert.strictEqual(actual, true); + }); + + it('correctly handles OData error when adding a home site', async () => { + sinon.stub(request, 'post').rejects({ error: { 'odata.error': { message: { value: 'An error has occurred' } } } }); + + await assert.rejects(command.action(logger, { options: {} } as any), new CommandError('An error has occurred')); + }); +}); diff --git a/src/m365/spo/commands/tenant/tenant-homesite-add.ts b/src/m365/spo/commands/tenant/tenant-homesite-add.ts new file mode 100644 index 00000000000..f3acf17581e --- /dev/null +++ b/src/m365/spo/commands/tenant/tenant-homesite-add.ts @@ -0,0 +1,87 @@ +import { Logger } from '../../../../cli/Logger.js'; +import GlobalOptions from '../../../../GlobalOptions.js'; +import { spo } from '../../../../utils/spo.js'; +import { validation } from '../../../../utils/validation.js'; +import SpoCommand from '../../../base/SpoCommand.js'; +import commands from '../../commands.js'; +import request, { CliRequestOptions } from '../../../../request.js'; + +interface CommandArgs { + options: Options; +} + +interface Options extends GlobalOptions { + url: string; +} + +class SpoTenantHomeSiteAddCommand extends SpoCommand { + public get name(): string { + return commands.TENANT_HOMESITE_ADD; + } + + public get description(): string { + return 'Add a Home Site'; + } + + constructor() { + super(); + + this.#initTelemetry(); + this.#initOptions(); + this.#initValidators(); + } + + #initTelemetry(): void { + this.telemetry.push((args: CommandArgs) => { + Object.assign(this.telemetryProperties, { + url: args.options.url + }); + }); + } + + #initOptions(): void { + this.options.unshift( + { + option: '-u, --url ' + } + ); + } + + #initValidators(): void { + this.validators.push( + async (args: CommandArgs) => { + const isValidSharePointUrl: boolean | string = validation.isValidSharePointUrl(args.options.url); + if (isValidSharePointUrl !== true) { + return isValidSharePointUrl; + } + return true; + } + ); + } + + public async commandAction(logger: Logger, args: CommandArgs): Promise { + try { + const spoAdminUrl: string = await spo.getSpoAdminUrl(logger, this.verbose); + const requestOptions: CliRequestOptions = { + url: `${spoAdminUrl}/_api/SPO.Tenant/AddHomeSite`, + headers: { + accept: 'application/json;odata=nometadata' + }, + responseType: 'json', + data: { + homeSiteUrl: args.options.url + } + }; + if (this.verbose) { + await logger.logToStderr(`Adding the home site...`); + } + const res = await request.post(requestOptions); + await logger.log(res); + } + catch (err: any) { + this.handleRejectedODataJsonPromise(err); + } + } +} + +export default new SpoTenantHomeSiteAddCommand(); \ No newline at end of file