UNPKG

@pnp/cli-microsoft365

Version:

Manage Microsoft 365 and SharePoint Framework projects on any platform

158 lines • 8.82 kB
import config from '../../../../config.js'; import request from '../../../../request.js'; import { formatting } from '../../../../utils/formatting.js'; import { spo } from '../../../../utils/spo.js'; import SpoCommand from '../../../base/SpoCommand.js'; import { PermissionKind } from '../../base-permissions.js'; export class SpoPropertyBagBaseCommand extends SpoCommand { constructor() { super(); this.formDigestValue = ''; } /** * Gets property bag for a folder or site rootFolder of a site where return type is "_ObjectType_\":\"SP.Folder\". * This method is executed when folder option is specified. PnP PowerShell behaves the same way. */ async getFolderPropertyBag(identityResp, webUrl, folder, logger) { let serverRelativeUrl = folder; if (identityResp.serverRelativeUrl !== '/') { serverRelativeUrl = `${identityResp.serverRelativeUrl}${serverRelativeUrl}`; } const requestOptions = { url: `${webUrl}/_vti_bin/client.svc/ProcessQuery`, headers: { 'X-RequestDigest': this.formDigestValue }, data: `<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="${config.applicationName}" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009"><Actions><ObjectPath Id="10" ObjectPathId="9" /><ObjectIdentityQuery Id="11" ObjectPathId="9" /><Query Id="12" ObjectPathId="9"><Query SelectAllProperties="false"><Properties><Property Name="Properties" SelectAll="true"><Query SelectAllProperties="false"><Properties /></Query></Property></Properties></Query></Query></Actions><ObjectPaths><Method Id="9" ParentId="5" Name="GetFolderByServerRelativeUrl"><Parameters><Parameter Type="String">${serverRelativeUrl}</Parameter></Parameters></Method><Identity Id="5" Name="${identityResp.objectIdentity}" /></ObjectPaths></Request>` }; try { const res = await request.post(requestOptions); if (this.debug) { await logger.logToStderr('Attempt to get Properties key values'); } const json = JSON.parse(res); const contents = json.find(x => { return x['ErrorInfo']; }); if (contents && contents.ErrorInfo) { throw contents.ErrorInfo.ErrorMessage || 'ClientSvc unknown error'; } const propertiesObj = json.find(x => { return x['Properties']; }); if (propertiesObj) { return propertiesObj['Properties']; } throw 'Cannot proceed. Properties not found'; // this is not suppose to happen } catch (err) { throw err; } } /** * Gets property bag for site or sitecollection where return type is "_ObjectType_\":\"SP.Web\". * This method is executed when no folder specified. PnP PowerShell behaves the same way. */ async getWebPropertyBag(identityResp, webUrl, logger) { const requestOptions = { url: `${webUrl}/_vti_bin/client.svc/ProcessQuery`, headers: { 'X-RequestDigest': this.formDigestValue }, data: `<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="${config.applicationName}" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009"><Actions><Query Id="97" ObjectPathId="5"><Query SelectAllProperties="false"><Properties><Property Name="ServerRelativeUrl" ScalarProperty="true" /><Property Name="AllProperties" SelectAll="true"><Query SelectAllProperties="false"><Properties /></Query></Property></Properties></Query></Query></Actions><ObjectPaths><Identity Id="5" Name="${identityResp.objectIdentity}" /></ObjectPaths></Request>` }; try { const res = await request.post(requestOptions); if (this.debug) { await logger.logToStderr('Attempt to get AllProperties key values'); } const json = JSON.parse(res); const contents = json.find(x => { return x['ErrorInfo']; }); if (contents && contents.ErrorInfo) { throw contents.ErrorInfo.ErrorMessage || 'ClientSvc unknown error'; } const allPropertiesObj = json.find(x => { return x['AllProperties']; }); if (allPropertiesObj) { return allPropertiesObj['AllProperties']; } throw 'Cannot proceed. AllProperties not found'; // this is not supposed to happen } catch (err) { throw err; } } /** * The property bag item data returned from the client.svc/ProcessQuery response * has to be formatted before displayed since the key, value objects * carry extra information or there might be a value, * that should to be formatted depending on the data type. */ formatProperty(objKey, objValue) { if (objKey.indexOf('$ Int32') > -1) { // format if the propery value is integer // the int returned has the following format of the property key, // 'vti_folderitemcount$ Int32'. To normalize that, the extra string // '$ Int32' has to be removed from the key, also parseInt is used to // ensure the json object returns number objKey = objKey.replace('$ Int32', ''); objValue = parseInt(objValue); } else { if (typeof objValue === 'string' && objValue.indexOf('/Date(') > -1) { // format if the property value is date // the date returned has the following format ex. /Date(2017,10,7,11,29,31,0)/. // That has to be turned into JavaScript Date object const date = objValue.replace('/Date(', '').replace(')/', '').split(',').map(Number); objValue = new Date(date[0], date[1], date[2], date[3], date[4], date[5], date[6]); } else { if (objValue === 'true' || objValue === 'false') { // format if the property value is boolean objValue = (objValue === 'true'); } } } return { key: objKey, value: objValue }; } static async setProperty(name, value, webUrl, formDigest, identityResp, logger, debug, folder) { let objectType = 'AllProperties'; if (folder) { objectType = 'Properties'; } const requestOptions = { url: `${webUrl}/_vti_bin/client.svc/ProcessQuery`, headers: { 'X-RequestDigest': formDigest }, data: `<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="${config.applicationName}" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009"><Actions><Method Name="SetFieldValue" Id="206" ObjectPathId="205"><Parameters><Parameter Type="String">${formatting.escapeXml(name)}</Parameter><Parameter Type="String">${formatting.escapeXml(value)}</Parameter></Parameters></Method><Method Name="Update" Id="207" ObjectPathId="198" /></Actions><ObjectPaths><Property Id="205" ParentId="198" Name="${objectType}" /><Identity Id="198" Name="${identityResp.objectIdentity}" /></ObjectPaths></Request>` }; try { const res = await request.post(requestOptions); const json = JSON.parse(res); const contents = json.find(x => { return x['ErrorInfo']; }); if (contents && contents.ErrorInfo) { throw contents.ErrorInfo.ErrorMessage || 'ClientSvc unknown error'; } else { return res; } } catch (err) { throw err; } } /** * Detects if the site in question has no script enabled or not. Detection is done * by verifying if the AddAndCustomizePages permission is missing * Note: Can later be moved as common method if required for other cli checks. * @param webIdentityResp web object identity response returned from client.svc/ProcessQuery. Has format like <GUID>|<GUID>:site:<GUID>:web:<GUID> * @param options command options * @param cmd command instance */ static async isNoScriptSite(webUrl, formDigest, webIdentityResp, logger, debug) { try { const basePermissionsResp = await spo.getEffectiveBasePermissions(webIdentityResp.objectIdentity, webUrl, formDigest, logger, debug); return basePermissionsResp.has(PermissionKind.AddAndCustomizePages) === false; } catch (err) { throw err; } } } //# sourceMappingURL=propertybag-base.js.map