forked from pnp/cli-microsoft365
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds command 'spo folder sharinglink set'. Closes pnp#5964
- Loading branch information
1 parent
7af59ba
commit f7c2295
Showing
5 changed files
with
426 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import Global from '/docs/cmd/_global.mdx'; | ||
import Tabs from '@theme/Tabs'; | ||
import TabItem from '@theme/TabItem'; | ||
|
||
# spo folder sharinglink set | ||
|
||
Updates a sharing link of a folder | ||
|
||
## Usage | ||
|
||
```sh | ||
m365 spo folder sharinglink set [options] | ||
``` | ||
|
||
## Options | ||
|
||
```md definition-list | ||
`-u, --webUrl <webUrl>` | ||
: The URL of the site where the folder is located. | ||
|
||
`--folderUrl [folderUrl]` | ||
: The server- or site-relative decoded URL of the folder. Specify either `folderUrl` or `folderId` but not both. | ||
|
||
`--folderId [folderId]` | ||
: The unique ID (GUID) of the folder. Specify either `folderUrl` or `folderId` but not both. | ||
|
||
`--id <id>` | ||
: The sharing link ID. | ||
|
||
`--expirationDateTime <expirationDateTime>` | ||
: The date and time to set the expiration. This should be defined as a valid ISO 8601 string. This option only works for anonymous links. | ||
``` | ||
|
||
<Global /> | ||
|
||
## Examples | ||
|
||
Updates the expiration datetime of an anonymous sharing link for a folder specific by folder ID. | ||
|
||
```sh | ||
m365 spo folder sharinglink set --webUrl https://contoso.sharepoint.com/sites/demo --folderId daebb04b-a773-4baa-b1d1-3625418e3234 --id 7c9f97c9-1bda-433c-9364-bb83e81771ee --expirationDateTime '2022-11-30T00:00:00Z' | ||
``` | ||
|
||
Updates the expiration datetime of an anonymous sharing link for a folder specific by folder URL. | ||
|
||
```sh | ||
m365 spo folder sharinglink set --webUrl https://contoso.sharepoint.com/sites/demo --folderUrl /sites/demo/shared%20documents/Folder --id 7c9f97c9-1bda-433c-9364-bb83e81771ee --expirationDateTime '2022-11-30T00:00:00Z' | ||
``` | ||
|
||
## Response | ||
|
||
<Tabs> | ||
<TabItem value="JSON"> | ||
|
||
```json | ||
{ | ||
"id": "bd1481e9-958b-4c1a-a33c-fb021f4ed444", | ||
"roles": [ | ||
"write" | ||
], | ||
"shareId": "u!aHR0cHM6Ly83NTY2YXZhLnNoYXJlcG9pbnQuY29tLzpmOi9nL0VwLVpGUHF2YkVsQnNnWXJhRjJBNG1jQmZWM1A3cU00eGZVVXJRZHdnSXllNGc", | ||
"expirationDateTime": "2024-05-05T16:57:00Z", | ||
"hasPassword": false, | ||
"grantedToIdentitiesV2": [], | ||
"grantedToIdentities": [], | ||
"link": { | ||
"scope": "anonymous", | ||
"type": "edit", | ||
"webUrl": "https://contoso.sharepoint.com/:f:/g/Ep-ZFPqvbElBsgYraF2A4mcBfV3P7qM4xfUUrQdwgIye4g", | ||
"preventsDownload": false | ||
} | ||
} | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="Text"> | ||
|
||
```text | ||
expirationDateTime : 2024-05-05T16:57:00Z | ||
grantedToIdentities : [] | ||
grantedToIdentitiesV2: [] | ||
hasPassword : false | ||
id : bd1481e9-958b-4c1a-a33c-fb021f4ed444 | ||
link : {"scope":"anonymous","type":"edit","webUrl":"https://contoso.sharepoint.com/:f:/g/Ep-ZFPqvbElBsgYraF2A4mcBfV3P7qM4xfUUrQdwgIye4g","preventsDownload":false} | ||
roles : ["write"] | ||
shareId : u!aHR0cHM6Ly83NTY2YXZhLnNoYXJlcG9pbnQuY29tLzpmOi9nL0VwLVpGUHF2YkVsQnNnWXJhRjJBNG1jQmZWM1A3cU00eGZVVXJRZHdnSXllNGc | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="CSV"> | ||
|
||
```csv | ||
id,shareId,expirationDateTime,hasPassword | ||
bd1481e9-958b-4c1a-a33c-fb021f4ed444,u!aHR0cHM6Ly83NTY2YXZhLnNoYXJlcG9pbnQuY29tLzpmOi9nL0VwLVpGUHF2YkVsQnNnWXJhRjJBNG1jQmZWM1A3cU00eGZVVXJRZHdnSXllNGc,2024-05-05T16:57:00Z, | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="Markdown"> | ||
|
||
```md | ||
# spo folder sharinglink set --webUrl "https://contoso.sharepoint.com" --folderUrl "/shared documents/f1" --id "bd1481e9-958b-4c1a-a33c-fb021f4ed444" --expirationDateTime "2024-05-05T16:57:00.000Z" | ||
|
||
Date: 03/05/2024 | ||
|
||
## bd1481e9-958b-4c1a-a33c-fb021f4ed444 | ||
|
||
Property | Value | ||
---------|------- | ||
id | bd1481e9-958b-4c1a-a33c-fb021f4ed444 | ||
shareId | u!aHR0cHM6Ly83NTY2YXZhLnNoYXJlcG9pbnQuY29tLzpmOi9nL0VwLVpGUHF2YkVsQnNnWXJhRjJBNG1jQmZWM1A3cU00eGZVVXJRZHdnSXllNGc | ||
expirationDateTime | 2024-05-05T16:57:00Z | ||
hasPassword | false | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
176 changes: 176 additions & 0 deletions
176
src/m365/spo/commands/folder/folder-sharinglink-set.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
import assert from 'assert'; | ||
import sinon from 'sinon'; | ||
import auth from '../../../../Auth.js'; | ||
import { cli } from '../../../../cli/cli.js'; | ||
import { CommandError } from '../../../../Command.js'; | ||
import { telemetry } from '../../../../telemetry.js'; | ||
import { Logger } from '../../../../cli/Logger.js'; | ||
import request from '../../../../request.js'; | ||
import { pid } from '../../../../utils/pid.js'; | ||
import { session } from '../../../../utils/session.js'; | ||
import { sinonUtil } from '../../../../utils/sinonUtil.js'; | ||
import { CommandInfo } from '../../../../cli/CommandInfo.js'; | ||
import commands from '../../commands.js'; | ||
import command from './folder-sharinglink-set.js'; | ||
import { spo } from '../../../../utils/spo.js'; | ||
import { drive } from '../../../../utils/drive.js'; | ||
import { Drive } from '@microsoft/microsoft-graph-types'; | ||
|
||
describe(commands.FOLDER_SHARINGLINK_SET, () => { | ||
let log: any[]; | ||
let logger: Logger; | ||
let loggerLogSpy: sinon.SinonSpy; | ||
let commandInfo: CommandInfo; | ||
|
||
const webUrl = 'https://contoso.sharepoint.com/sites/project-x'; | ||
const folderId = 'f09c4efe-b8c0-4e89-a166-03418661b89b'; | ||
const folderUrl = '/sites/project-x/shared documents/folder1'; | ||
const siteId = '0f9b8f4f-0e8e-4630-bb0a-501442db9b64'; | ||
const driveId = '013TMHP6UOOSLON57HT5GLKEU7R5UGWZVK'; | ||
const itemId = 'b!T4-bD44OMEa7ClAUQtubZID9tc40pGJKpguycvELod_Gx-lo4ZQiRJ7vylonTufG'; | ||
const id = 'ef1cddaa-b74a-4aae-8a7a-5c16b4da67f2'; | ||
|
||
const graphResponse = { | ||
"id": "2a021f54-90a2-4016-b3b3-5f34d2e7d932", | ||
"roles": [ | ||
"read" | ||
], | ||
"hasPassword": false, | ||
"grantedToIdentitiesV2": [], | ||
"grantedToIdentities": [], | ||
"link": { | ||
"scope": "anonymous", | ||
"type": "view", | ||
"webUrl": "https://contoso.sharepoint.com/:b:/s/pnpcoresdktestgroup/EY50lub3559MtRKfj2hrZqoBWnHOpGIcgi4gzw9XiWYJ-A", | ||
"preventsDownload": false | ||
} | ||
}; | ||
|
||
const driveDetails: Drive = { | ||
id: driveId, | ||
webUrl: `${webUrl}/Shared%20Documents` | ||
}; | ||
|
||
const getStubs: any = (options: any) => { | ||
sinon.stub(spo, 'getFolderServerRelativeUrl').resolves(options.folderUrl); | ||
sinon.stub(spo, 'getSiteId').resolves(options.siteId); | ||
sinon.stub(drive, 'getDriveByUrl').resolves(options.drive); | ||
sinon.stub(drive, 'getDriveItemId').resolves(options.itemId); | ||
}; | ||
|
||
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; | ||
commandInfo = cli.getCommandInfo(command); | ||
}); | ||
|
||
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'); | ||
}); | ||
|
||
afterEach(() => { | ||
sinonUtil.restore([ | ||
request.get, | ||
request.patch, | ||
spo.getSiteId, | ||
spo.getFolderServerRelativeUrl, | ||
drive.getDriveByUrl, | ||
drive.getDriveItemId | ||
]); | ||
}); | ||
|
||
after(() => { | ||
sinon.restore(); | ||
auth.connection.active = false; | ||
}); | ||
|
||
it('has correct name', () => { | ||
assert.strictEqual(command.name, commands.FOLDER_SHARINGLINK_SET); | ||
}); | ||
|
||
it('has a description', () => { | ||
assert.notStrictEqual(command.description, null); | ||
}); | ||
|
||
it('fails validation if the webUrl option is not a valid SharePoint site URL', async () => { | ||
const actual = await command.validate({ options: { webUrl: 'foo', folderId: folderId, id: id } }, commandInfo); | ||
assert.notStrictEqual(actual, true); | ||
}); | ||
|
||
it('fails validation if the folderId option is not a valid GUID', async () => { | ||
const actual = await command.validate({ options: { webUrl: webUrl, folderId: 'invalid', id: id } }, commandInfo); | ||
assert.notStrictEqual(actual, true); | ||
}); | ||
|
||
it('fails validation if the expirationDateTime option is not a valid date', async () => { | ||
const actual = await command.validate({ options: { webUrl: 'https://contoso.sharepoint.com', folderId: folderId, expirationDateTime: 'invalid date', id: id } }, commandInfo); | ||
assert.notStrictEqual(actual, true); | ||
}); | ||
|
||
it('passes validation if options are valid', async () => { | ||
const actual = await command.validate({ options: { webUrl: 'https://contoso.sharepoint.com', folderId: folderId, expirationDateTime: '2024-05-05T16:57:00.000Z', id: id } }, commandInfo); | ||
assert.strictEqual(actual, true); | ||
}); | ||
|
||
it('updates a sharing link to a folder specified by the id', async () => { | ||
getStubs({ folderUrl: folderUrl, siteId: siteId, drive: driveDetails, itemId: itemId }); | ||
|
||
sinon.stub(request, 'patch').callsFake(async (opts) => { | ||
if (opts.url === `https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/permissions/${id}`) { | ||
return graphResponse; | ||
} | ||
|
||
throw 'Invalid request'; | ||
}); | ||
|
||
await command.action(logger, { options: { webUrl: webUrl, folderId: folderId, expirationDateTime: '2024-05-05T16:57:00.000Z', id: id, verbose: true } } as any); | ||
assert(loggerLogSpy.calledWith(graphResponse)); | ||
}); | ||
|
||
it('updates a sharing link to a folder specified by the URL', async () => { | ||
getStubs({ folderUrl: folderUrl, siteId: siteId, drive: driveDetails, itemId: itemId }); | ||
|
||
sinon.stub(request, 'patch').callsFake(async (opts) => { | ||
if (opts.url === `https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/permissions/${id}`) { | ||
return graphResponse; | ||
} | ||
|
||
throw 'Invalid request'; | ||
}); | ||
|
||
await command.action(logger, { options: { webUrl: webUrl, folderUrl: folderUrl, expirationDateTime: '2024-05-05T16:57:00.000Z', id: id, verbose: true } } as any); | ||
assert(loggerLogSpy.calledWith(graphResponse)); | ||
}); | ||
|
||
it('throws error when drive not found by url', async () => { | ||
sinon.stub(spo, 'getFolderServerRelativeUrl').resolves(folderUrl); | ||
sinon.stub(spo, 'getSiteId').resolves(siteId); | ||
sinon.stub(request, 'get').callsFake(async opts => { | ||
if (opts.url === `https://graph.microsoft.com/v1.0/sites/${siteId}/drives?$select=webUrl,id`) { | ||
return { | ||
value: [] | ||
}; | ||
} | ||
|
||
throw 'Invalid request'; | ||
}); | ||
|
||
await assert.rejects(command.action(logger, { options: { webUrl: webUrl, folderUrl: folderUrl, expirationDateTime: '2024-05-05T16:57:00.000Z', id: id, verbose: true } } as any), | ||
new CommandError(`Drive 'https://contoso.sharepoint.com/sites/project-x/shared%20documents/folder1' not found`)); | ||
}); | ||
}); |
Oops, something went wrong.