@pnp/cli-microsoft365 7.0.0-beta.5fdb9e3 → 7.0.0-beta.607e42d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/.eslintrc.cjs +0 -2
  2. package/dist/GlobalOptions.js +1 -7
  3. package/dist/m365/aad/commands/app/app-add.js +8 -8
  4. package/dist/m365/aad/commands/app/app-role-add.js +5 -5
  5. package/dist/m365/aad/commands/app/app-set.js +5 -5
  6. package/dist/m365/aad/commands/group/group-get.js +4 -4
  7. package/dist/m365/aad/commands/group/group-list.js +1 -23
  8. package/dist/m365/aad/commands/policy/policy-list.js +5 -5
  9. package/dist/m365/cli/commands/cli-issue.js +5 -5
  10. package/dist/m365/cli/commands/config/config-get.js +5 -5
  11. package/dist/m365/cli/commands/config/config-reset.js +5 -5
  12. package/dist/m365/cli/commands/config/config-set.js +5 -5
  13. package/dist/m365/commands/login.js +5 -5
  14. package/dist/m365/commands/request.js +1 -1
  15. package/dist/m365/flow/commands/owner/owner-ensure.js +5 -5
  16. package/dist/m365/pa/commands/app/app-export.js +7 -7
  17. package/dist/m365/pa/commands/app/app-owner-set.js +5 -5
  18. package/dist/m365/pa/commands/app/app-permission-ensure.js +5 -5
  19. package/dist/m365/pa/commands.js +1 -4
  20. package/dist/m365/planner/commands/task/task-add.js +17 -11
  21. package/dist/m365/planner/commands/task/task-get.js +35 -25
  22. package/dist/m365/planner/commands/task/task-list.js +26 -19
  23. package/dist/m365/planner/commands/task/task-remove.js +39 -34
  24. package/dist/m365/planner/commands/task/task-set.js +35 -23
  25. package/dist/m365/purview/commands/retentionlabel/retentionlabel-add.js +14 -14
  26. package/dist/m365/spfx/commands/package/package-generate.js +15 -15
  27. package/dist/m365/spfx/commands/project/DeployWorkflow.js +55 -0
  28. package/dist/m365/spfx/commands/project/project-doctor.js +8 -8
  29. package/dist/m365/spfx/commands/project/project-github-workflow-add.js +157 -0
  30. package/dist/m365/spfx/commands/project/project-github-workflow-model.js +2 -0
  31. package/dist/m365/spfx/commands/project/project-upgrade.js +13 -13
  32. package/dist/m365/spfx/commands.js +1 -0
  33. package/dist/m365/spo/commands/applicationcustomizer/applicationcustomizer-add.js +5 -5
  34. package/dist/m365/spo/commands/applicationcustomizer/applicationcustomizer-list.js +5 -5
  35. package/dist/m365/spo/commands/commandset/commandset-add.js +11 -11
  36. package/dist/m365/spo/commands/commandset/commandset-get.js +8 -8
  37. package/dist/m365/spo/commands/commandset/commandset-list.js +5 -5
  38. package/dist/m365/spo/commands/commandset/commandset-remove.js +5 -5
  39. package/dist/m365/spo/commands/commandset/commandset-set.js +11 -11
  40. package/dist/m365/spo/commands/file/file-get.js +9 -6
  41. package/dist/m365/spo/commands/file/file-sharinglink-add.js +8 -8
  42. package/dist/m365/spo/commands/file/file-sharinglink-list.js +5 -5
  43. package/dist/m365/spo/commands/list/list-add.js +4 -4
  44. package/dist/m365/spo/commands/list/list-set.js +4 -4
  45. package/dist/m365/spo/commands/listitem/listitem-add.js +1 -0
  46. package/dist/m365/spo/commands/listitem/listitem-set.js +3 -2
  47. package/dist/m365/spo/commands/orgassetslibrary/orgassetslibrary-add.js +8 -8
  48. package/dist/m365/spo/commands/page/clientsidepages.js +1 -81
  49. package/dist/m365/spo/commands/page/page-get.js +1 -0
  50. package/dist/m365/spo/commands/page/page-list.js +4 -3
  51. package/dist/m365/spo/commands/serviceprincipal/serviceprincipal-set.js +30 -32
  52. package/dist/m365/spo/commands/site/site-add.js +114 -161
  53. package/dist/m365/spo/commands/site/site-apppermission-add.js +15 -18
  54. package/dist/m365/spo/commands/site/site-apppermission-remove.js +34 -38
  55. package/dist/m365/spo/commands/site/site-apppermission-set.js +11 -14
  56. package/dist/m365/spo/commands/site/site-ensure.js +13 -66
  57. package/dist/m365/spo/commands/site/site-list.js +9 -17
  58. package/dist/m365/spo/commands/site/site-recyclebinitem-list.js +6 -6
  59. package/dist/m365/spo/commands/site/site-remove.js +166 -210
  60. package/dist/m365/spo/commands/site/site-set.js +121 -153
  61. package/dist/m365/spo/commands/tenant/tenant-applicationcustomizer-list.js +3 -2
  62. package/dist/m365/spo/commands/tenant/tenant-commandset-add.js +8 -8
  63. package/dist/m365/spo/commands/tenant/tenant-commandset-list.js +3 -2
  64. package/dist/m365/spo/commands/tenant/tenant-commandset-set.js +8 -8
  65. package/dist/m365/spo/commands/tenant/tenant-settings-set.js +4 -4
  66. package/dist/m365/spo/commands/web/web-roleinheritance-break.js +3 -3
  67. package/dist/m365/spo/commands/web/web-set.js +5 -5
  68. package/dist/m365/teams/commands/app/app-list.js +5 -5
  69. package/dist/m365/teams/commands/chat/chat-member-add.js +5 -5
  70. package/dist/m365/teams/commands/funsettings/funsettings-set.js +4 -4
  71. package/dist/m365/teams/commands/guestsettings/guestsettings-set.js +4 -4
  72. package/dist/m365/teams/commands/membersettings/membersettings-set.js +4 -4
  73. package/dist/m365/teams/commands/messagingsettings/messagingsettings-set.js +5 -5
  74. package/dist/m365/teams/commands/team/team-set.js +3 -3
  75. package/dist/m365/todo/commands/task/task-add.js +6 -6
  76. package/dist/m365/yammer/commands/message/message-list.js +5 -5
  77. package/dist/m365/yammer/commands/yammer-search.js +5 -5
  78. package/dist/utils/aadGroup.js +18 -0
  79. package/dist/utils/fsUtil.js +5 -0
  80. package/dist/utils/spo.js +582 -0
  81. package/dist/utils/validation.js +0 -3
  82. package/docs/docs/cmd/aad/group/group-get.mdx +5 -5
  83. package/docs/docs/cmd/aad/group/group-list.mdx +0 -11
  84. package/docs/docs/cmd/pa/app/app-export.mdx +5 -5
  85. package/docs/docs/cmd/planner/task/task-add.mdx +22 -7
  86. package/docs/docs/cmd/planner/task/task-get.mdx +13 -4
  87. package/docs/docs/cmd/planner/task/task-list.mdx +22 -7
  88. package/docs/docs/cmd/planner/task/task-remove.mdx +25 -8
  89. package/docs/docs/cmd/planner/task/task-set.mdx +22 -7
  90. package/docs/docs/cmd/spfx/project/project-github-workflow-add.mdx +94 -0
  91. package/docs/docs/cmd/spo/listitem/listitem-add.mdx +2 -5
  92. package/docs/docs/cmd/spo/listitem/listitem-set.mdx +2 -5
  93. package/docs/docs/cmd/spo/page/page-get.mdx +0 -1
  94. package/docs/docs/cmd/spo/page/page-list.mdx +0 -1
  95. package/docs/docs/cmd/spo/site/site-list.mdx +3 -78
  96. package/docs/docs/cmd/spo/tenant/tenant-applicationcustomizer-list.mdx +2 -4
  97. package/docs/docs/cmd/spo/tenant/tenant-commandset-list.mdx +2 -4
  98. package/npm-shrinkwrap.json +239 -1416
  99. package/package.json +6 -12
  100. package/dist/m365/pa/cds-project-mutator.js +0 -91
  101. package/dist/m365/pa/commands/pcf/pcf-init/assets/control/dataset-template/generated/ManifestTypes.d.ts +0 -11
  102. package/dist/m365/pa/commands/pcf/pcf-init/assets/control/dataset-template/template_ControlManifest.Input.xml +0 -31
  103. package/dist/m365/pa/commands/pcf/pcf-init/assets/control/dataset-template/template_index.ts +0 -51
  104. package/dist/m365/pa/commands/pcf/pcf-init/assets/control/field-template/generated/ManifestTypes.d.ts +0 -12
  105. package/dist/m365/pa/commands/pcf/pcf-init/assets/control/field-template/template_ControlManifest.Input.xml +0 -37
  106. package/dist/m365/pa/commands/pcf/pcf-init/assets/control/field-template/template_index.ts +0 -48
  107. package/dist/m365/pa/commands/pcf/pcf-init/assets/control/index.ts +0 -0
  108. package/dist/m365/pa/commands/pcf/pcf-init/assets/control/virtual-dataset-template/template_ControlManifest.Input.xml +0 -31
  109. package/dist/m365/pa/commands/pcf/pcf-init/assets/control/virtual-dataset-template/template_index.tsx +0 -58
  110. package/dist/m365/pa/commands/pcf/pcf-init/assets/control/virtual-field-template/template_ControlManifest.Input.xml +0 -37
  111. package/dist/m365/pa/commands/pcf/pcf-init/assets/control/virtual-field-template/template_index.tsx +0 -55
  112. package/dist/m365/pa/commands/pcf/pcf-init/assets/package.json +0 -19
  113. package/dist/m365/pa/commands/pcf/pcf-init/assets/pcfconfig.json +0 -3
  114. package/dist/m365/pa/commands/pcf/pcf-init/assets/template_.gitignore +0 -14
  115. package/dist/m365/pa/commands/pcf/pcf-init/assets/template_pcfprojecttype.pcfproj +0 -45
  116. package/dist/m365/pa/commands/pcf/pcf-init/pcf-init-variables.js +0 -2
  117. package/dist/m365/pa/commands/pcf/pcf-init.js +0 -120
  118. package/dist/m365/pa/commands/solution/solution-init/assets/Other/Customizations.xml +0 -18
  119. package/dist/m365/pa/commands/solution/solution-init/assets/Other/Relationships.xml +0 -2
  120. package/dist/m365/pa/commands/solution/solution-init/assets/Other/template_Solution.xml +0 -94
  121. package/dist/m365/pa/commands/solution/solution-init/assets/template_.gitignore +0 -2
  122. package/dist/m365/pa/commands/solution/solution-init/assets/template_solutionprojecttype.cdsproj +0 -44
  123. package/dist/m365/pa/commands/solution/solution-init/solution-init-variables.js +0 -2
  124. package/dist/m365/pa/commands/solution/solution-init.js +0 -126
  125. package/dist/m365/pa/commands/solution/solution-reference-add.js +0 -88
  126. package/dist/m365/pa/template-instantiator.js +0 -57
  127. package/docs/docs/cmd/pa/pcf/pcf-init.mdx +0 -56
  128. package/docs/docs/cmd/pa/solution/solution-init.mdx +0 -46
  129. package/docs/docs/cmd/pa/solution/solution-reference-add.mdx +0 -42
package/dist/utils/spo.js CHANGED
@@ -8,6 +8,8 @@ import request from "../request.js";
8
8
  import { formatting } from './formatting.js';
9
9
  import { odata } from './odata.js';
10
10
  import { RoleType } from '../m365/spo/commands/roledefinition/RoleType.js';
11
+ import { aadGroup } from './aadGroup.js';
12
+ import { SharingCapabilities } from '../m365/spo/commands/site/SharingCapabilities.js';
11
13
  export const spo = {
12
14
  getRequestDigest(siteUrl) {
13
15
  const requestOptions = {
@@ -621,6 +623,586 @@ export const spo = {
621
623
  roledefinition.BasePermissionsValue = permissions.parse();
622
624
  roledefinition.RoleTypeKindValue = RoleType[roledefinition.RoleTypeKind];
623
625
  return roledefinition;
626
+ },
627
+ /**
628
+ * Adds a SharePoint site.
629
+ * @param type Type of sites to add. Allowed values TeamSite, CommunicationSite, ClassicSite, default TeamSite
630
+ * @param title Site title
631
+ * @param alias Site alias, used in the URL and in the team site group e-mail (applies to type TeamSite)
632
+ * @param url Site URL (applies to type CommunicationSite, ClassicSite)
633
+ * @param timeZone Integer representing time zone to use for the site (applies to type ClassicSite)
634
+ * @param description Site description
635
+ * @param lcid Site language in the LCID format
636
+ * @param owners Comma-separated list of users to set as site owners (applies to type TeamSite, ClassicSite)
637
+ * @param isPublic Determines if the associated group is public or not (applies to type TeamSite)
638
+ * @param classification Site classification (applies to type TeamSite, CommunicationSite)
639
+ * @param siteDesignType of communication site to create. Allowed values Topic, Showcase, Blank, default Topic. When creating a communication site, specify either siteDesign or siteDesignId (applies to type CommunicationSite)
640
+ * @param siteDesignId Id of the custom site design to use to create the site. When creating a communication site, specify either siteDesign or siteDesignId (applies to type CommunicationSite)
641
+ * @param shareByEmailEnabled Determines whether it's allowed to share file with guests (applies to type CommunicationSite)
642
+ * @param webTemplate Template to use for creating the site. Default `STS#0` (applies to type ClassicSite)
643
+ * @param resourceQuota The quota for this site collection in Sandboxed Solutions units. Default 0 (applies to type ClassicSite)
644
+ * @param resourceQuotaWarningLevel The warning level for the resource quota. Default 0 (applies to type ClassicSite)
645
+ * @param storageQuota The storage quota for this site collection in megabytes. Default 100 (applies to type ClassicSite)
646
+ * @param storageQuotaWarningLevel The warning level for the storage quota in megabytes. Default 100 (applies to type ClassicSite)
647
+ * @param removeDeletedSite Set, to remove existing deleted site with the same URL from the Recycle Bin (applies to type ClassicSite)
648
+ * @param wait Wait for the site to be provisioned before completing the command (applies to type ClassicSite)
649
+ * @param logger the Logger object
650
+ * @param verbose set if verbose logging should be logged
651
+ */
652
+ async addSite(title, logger, verbose, wait, type, alias, description, owners, shareByEmailEnabled, removeDeletedSite, classification, isPublic, lcid, url, siteDesign, siteDesignId, timeZone, webTemplate, resourceQuota, resourceQuotaWarningLevel, storageQuota, storageQuotaWarningLevel) {
653
+ if (type === 'ClassicSite') {
654
+ const spoAdminUrl = await spo.getSpoAdminUrl(logger, verbose);
655
+ let context = await spo.ensureFormDigest(spoAdminUrl, logger, undefined, verbose);
656
+ let exists;
657
+ if (removeDeletedSite) {
658
+ exists = await spo.siteExists(url, logger, verbose);
659
+ }
660
+ else {
661
+ // assume site doesn't exist
662
+ exists = false;
663
+ }
664
+ if (exists) {
665
+ if (verbose) {
666
+ await logger.logToStderr('Site exists in the recycle bin');
667
+ }
668
+ await spo.deleteSiteFromTheRecycleBin(url, logger, verbose, wait);
669
+ }
670
+ else {
671
+ if (verbose) {
672
+ await logger.logToStderr('Site not found');
673
+ }
674
+ }
675
+ context = await spo.ensureFormDigest(spoAdminUrl, logger, context, verbose);
676
+ if (verbose) {
677
+ await logger.logToStderr(`Creating site collection ${url}...`);
678
+ }
679
+ const lcidOption = typeof lcid === 'number' ? lcid : 1033;
680
+ const storageQuotaOption = typeof storageQuota === 'number' ? storageQuota : 100;
681
+ const storageQuotaWarningLevelOption = typeof storageQuotaWarningLevel === 'number' ? storageQuotaWarningLevel : 100;
682
+ const resourceQuotaOption = typeof resourceQuota === 'number' ? resourceQuota : 0;
683
+ const resourceQuotaWarningLevelOption = typeof resourceQuotaWarningLevel === 'number' ? resourceQuotaWarningLevel : 0;
684
+ const webTemplateOption = webTemplate || 'STS#0';
685
+ const requestOptions = {
686
+ url: `${spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
687
+ headers: {
688
+ 'X-RequestDigest': context.FormDigestValue
689
+ },
690
+ 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="4" ObjectPathId="3" /><ObjectPath Id="6" ObjectPathId="5" /><Query Id="7" ObjectPathId="3"><Query SelectAllProperties="true"><Properties /></Query></Query><Query Id="8" ObjectPathId="5"><Query SelectAllProperties="false"><Properties><Property Name="IsComplete" ScalarProperty="true" /><Property Name="PollingInterval" ScalarProperty="true" /></Properties></Query></Query></Actions><ObjectPaths><Constructor Id="3" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" /><Method Id="5" ParentId="3" Name="CreateSite"><Parameters><Parameter TypeId="{11f84fff-b8cf-47b6-8b50-34e692656606}"><Property Name="CompatibilityLevel" Type="Int32">0</Property><Property Name="Lcid" Type="UInt32">${lcidOption}</Property><Property Name="Owner" Type="String">${formatting.escapeXml(owners)}</Property><Property Name="StorageMaximumLevel" Type="Int64">${storageQuotaOption}</Property><Property Name="StorageWarningLevel" Type="Int64">${storageQuotaWarningLevelOption}</Property><Property Name="Template" Type="String">${formatting.escapeXml(webTemplateOption)}</Property><Property Name="TimeZoneId" Type="Int32">${timeZone}</Property><Property Name="Title" Type="String">${formatting.escapeXml(title)}</Property><Property Name="Url" Type="String">${formatting.escapeXml(url)}</Property><Property Name="UserCodeMaximumLevel" Type="Double">${resourceQuotaOption}</Property><Property Name="UserCodeWarningLevel" Type="Double">${resourceQuotaWarningLevelOption}</Property></Parameter></Parameters></Method></ObjectPaths></Request>`
691
+ };
692
+ const res = await request.post(requestOptions);
693
+ const json = JSON.parse(res);
694
+ const response = json[0];
695
+ if (response.ErrorInfo) {
696
+ throw response.ErrorInfo.ErrorMessage;
697
+ }
698
+ else {
699
+ const operation = json[json.length - 1];
700
+ const isComplete = operation.IsComplete;
701
+ if (!wait || isComplete) {
702
+ return;
703
+ }
704
+ await new Promise((resolve, reject) => {
705
+ setTimeout(() => {
706
+ spo.waitUntilFinished({
707
+ operationId: JSON.stringify(operation._ObjectIdentity_),
708
+ siteUrl: spoAdminUrl,
709
+ resolve,
710
+ reject,
711
+ logger,
712
+ currentContext: context,
713
+ verbose: verbose,
714
+ debug: verbose
715
+ });
716
+ }, operation.PollingInterval);
717
+ });
718
+ }
719
+ }
720
+ else {
721
+ const isTeamSite = type !== 'CommunicationSite';
722
+ const spoUrl = await spo.getSpoUrl(logger, verbose);
723
+ if (verbose) {
724
+ await logger.logToStderr(`Creating new site...`);
725
+ }
726
+ let requestOptions = {};
727
+ if (isTeamSite) {
728
+ requestOptions = {
729
+ url: `${spoUrl}/_api/GroupSiteManager/CreateGroupEx`,
730
+ headers: {
731
+ 'content-type': 'application/json; odata=verbose; charset=utf-8',
732
+ accept: 'application/json;odata=nometadata'
733
+ },
734
+ responseType: 'json',
735
+ data: {
736
+ displayName: title,
737
+ alias: alias,
738
+ isPublic: isPublic,
739
+ optionalParams: {
740
+ Description: description || '',
741
+ CreationOptions: {
742
+ results: [],
743
+ Classification: classification || ''
744
+ }
745
+ }
746
+ }
747
+ };
748
+ if (lcid) {
749
+ requestOptions.data.optionalParams.CreationOptions.results.push(`SPSiteLanguage:${lcid}`);
750
+ }
751
+ if (owners) {
752
+ requestOptions.data.optionalParams.Owners = {
753
+ results: owners.split(',').map(o => o.trim())
754
+ };
755
+ }
756
+ }
757
+ else {
758
+ if (siteDesignId) {
759
+ siteDesignId = siteDesignId;
760
+ }
761
+ else {
762
+ if (siteDesign) {
763
+ switch (siteDesign) {
764
+ case 'Topic':
765
+ siteDesignId = '00000000-0000-0000-0000-000000000000';
766
+ break;
767
+ case 'Showcase':
768
+ siteDesignId = '6142d2a0-63a5-4ba0-aede-d9fefca2c767';
769
+ break;
770
+ case 'Blank':
771
+ siteDesignId = 'f6cc5403-0d63-442e-96c0-285923709ffc';
772
+ break;
773
+ }
774
+ }
775
+ else {
776
+ siteDesignId = '00000000-0000-0000-0000-000000000000';
777
+ }
778
+ }
779
+ requestOptions = {
780
+ url: `${spoUrl}/_api/SPSiteManager/Create`,
781
+ headers: {
782
+ 'content-type': 'application/json;odata=nometadata',
783
+ accept: 'application/json;odata=nometadata'
784
+ },
785
+ responseType: 'json',
786
+ data: {
787
+ request: {
788
+ Title: title,
789
+ Url: url,
790
+ ShareByEmailEnabled: shareByEmailEnabled,
791
+ Description: description || '',
792
+ Classification: classification || '',
793
+ WebTemplate: 'SITEPAGEPUBLISHING#0',
794
+ SiteDesignId: siteDesignId
795
+ }
796
+ }
797
+ };
798
+ if (lcid) {
799
+ requestOptions.data.request.Lcid = lcid;
800
+ }
801
+ if (owners) {
802
+ requestOptions.data.request.Owner = owners;
803
+ }
804
+ }
805
+ const res = await request.post(requestOptions);
806
+ if (isTeamSite) {
807
+ if (res.ErrorMessage !== null) {
808
+ throw res.ErrorMessage;
809
+ }
810
+ else {
811
+ return res.SiteUrl;
812
+ }
813
+ }
814
+ else {
815
+ if (res.SiteStatus === 2) {
816
+ return res.SiteUrl;
817
+ }
818
+ else {
819
+ throw 'An error has occurred while creating the site';
820
+ }
821
+ }
822
+ }
823
+ },
824
+ /**
825
+ * Checks if a site exists
826
+ * Returns a boolean
827
+ * @param url The url of the site
828
+ * @param logger the Logger object
829
+ * @param verbose set if verbose logging should be logged
830
+ */
831
+ async siteExists(url, logger, verbose) {
832
+ const spoAdminUrl = await spo.getSpoAdminUrl(logger, verbose);
833
+ const context = await spo.ensureFormDigest(spoAdminUrl, logger, undefined, verbose);
834
+ if (verbose) {
835
+ await logger.logToStderr(`Checking if the site ${url} exists...`);
836
+ }
837
+ const requestOptions = {
838
+ url: `${spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
839
+ headers: {
840
+ 'X-RequestDigest': context.FormDigestValue
841
+ },
842
+ 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="197" ObjectPathId="196" /><ObjectPath Id="199" ObjectPathId="198" /><Query Id="200" ObjectPathId="198"><Query SelectAllProperties="true"><Properties /></Query></Query></Actions><ObjectPaths><Constructor Id="196" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" /><Method Id="198" ParentId="196" Name="GetSitePropertiesByUrl"><Parameters><Parameter Type="String">${formatting.escapeXml(url)}</Parameter><Parameter Type="Boolean">false</Parameter></Parameters></Method></ObjectPaths></Request>`
843
+ };
844
+ const res1 = await request.post(requestOptions);
845
+ const json = JSON.parse(res1);
846
+ const response = json[0];
847
+ if (response.ErrorInfo) {
848
+ if (response.ErrorInfo.ErrorTypeName === 'Microsoft.Online.SharePoint.Common.SpoNoSiteException') {
849
+ return await this.siteExistsInTheRecycleBin(url, logger, verbose);
850
+ }
851
+ else {
852
+ throw response.ErrorInfo.ErrorMessage;
853
+ }
854
+ }
855
+ else {
856
+ const site = json[json.length - 1];
857
+ return site.Status === 'Recycled';
858
+ }
859
+ },
860
+ /**
861
+ * Checks if a site exists in the recycle bin
862
+ * Returns a boolean
863
+ * @param url The url of the site
864
+ * @param logger the Logger object
865
+ * @param verbose set if verbose logging should be logged
866
+ */
867
+ async siteExistsInTheRecycleBin(url, logger, verbose) {
868
+ if (verbose) {
869
+ await logger.logToStderr(`Site doesn't exist. Checking if the site ${url} exists in the recycle bin...`);
870
+ }
871
+ const spoAdminUrl = await spo.getSpoAdminUrl(logger, verbose);
872
+ const context = await spo.ensureFormDigest(spoAdminUrl, logger, undefined, verbose);
873
+ const requestOptions = {
874
+ url: `${spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
875
+ headers: {
876
+ 'X-RequestDigest': context.FormDigestValue
877
+ },
878
+ 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="181" ObjectPathId="180" /><Query Id="182" ObjectPathId="180"><Query SelectAllProperties="true"><Properties /></Query></Query></Actions><ObjectPaths><Method Id="180" ParentId="175" Name="GetDeletedSitePropertiesByUrl"><Parameters><Parameter Type="String">${formatting.escapeXml(url)}</Parameter></Parameters></Method><Constructor Id="175" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" /></ObjectPaths></Request>`
879
+ };
880
+ const res = await request.post(requestOptions);
881
+ const json = JSON.parse(res);
882
+ const response = json[0];
883
+ if (response.ErrorInfo) {
884
+ if (response.ErrorInfo.ErrorTypeName === 'Microsoft.SharePoint.Client.UnknownError') {
885
+ return false;
886
+ }
887
+ throw response.ErrorInfo.ErrorMessage;
888
+ }
889
+ const site = json[json.length - 1];
890
+ return site.Status === 'Recycled';
891
+ },
892
+ /**
893
+ * Deletes a site from the recycle bin
894
+ * @param url The url of the site
895
+ * @param logger the Logger object
896
+ * @param verbose set if verbose logging should be logged
897
+ * @param wait set to wait until finished
898
+ */
899
+ async deleteSiteFromTheRecycleBin(url, logger, verbose, wait) {
900
+ const spoAdminUrl = await spo.getSpoAdminUrl(logger, verbose);
901
+ const context = await spo.ensureFormDigest(spoAdminUrl, logger, undefined, verbose);
902
+ if (verbose) {
903
+ await logger.logToStderr(`Deleting site ${url} from the recycle bin...`);
904
+ }
905
+ const requestOptions = {
906
+ url: `${spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
907
+ headers: {
908
+ 'X-RequestDigest': context.FormDigestValue
909
+ },
910
+ 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="185" ObjectPathId="184" /><Query Id="186" ObjectPathId="184"><Query SelectAllProperties="false"><Properties><Property Name="IsComplete" ScalarProperty="true" /><Property Name="PollingInterval" ScalarProperty="true" /></Properties></Query></Query></Actions><ObjectPaths><Method Id="184" ParentId="175" Name="RemoveDeletedSite"><Parameters><Parameter Type="String">${formatting.escapeXml(url)}</Parameter></Parameters></Method><Constructor Id="175" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" /></ObjectPaths></Request>`
911
+ };
912
+ const response = await request.post(requestOptions);
913
+ const json = JSON.parse(response);
914
+ const responseContent = json[0];
915
+ if (responseContent.ErrorInfo) {
916
+ throw responseContent.ErrorInfo.ErrorMessage;
917
+ }
918
+ const operation = json[json.length - 1];
919
+ const isComplete = operation.IsComplete;
920
+ if (!wait || isComplete) {
921
+ return;
922
+ }
923
+ await new Promise((resolve, reject) => {
924
+ setTimeout(() => {
925
+ spo.waitUntilFinished({
926
+ operationId: JSON.stringify(operation._ObjectIdentity_),
927
+ siteUrl: spoAdminUrl,
928
+ resolve,
929
+ reject,
930
+ logger,
931
+ currentContext: context,
932
+ verbose: verbose,
933
+ debug: verbose
934
+ });
935
+ }, operation.PollingInterval);
936
+ });
937
+ },
938
+ /**
939
+ * Updates a site with the given properties
940
+ * @param url The url of the site
941
+ * @param logger The logger object
942
+ * @param verbose Set for verbose logging
943
+ * @param title The new title
944
+ * @param classification The classification to be updated
945
+ * @param disableFlows If flows should be disabled or not
946
+ * @param isPublic If site should be public or private
947
+ * @param owners The owners to be updated
948
+ * @param shareByEmailEnabled If share by e-mail should be enabled or not
949
+ * @param siteDesignId The site design to be updated
950
+ * @param sharingCapability The sharing capability to be updated
951
+ */
952
+ async updateSite(url, logger, verbose, title, classification, disableFlows, isPublic, owners, shareByEmailEnabled, siteDesignId, sharingCapability) {
953
+ const tenantId = await spo.getTenantId(logger, verbose);
954
+ const spoAdminUrl = await spo.getSpoAdminUrl(logger, verbose);
955
+ let context = await spo.ensureFormDigest(spoAdminUrl, logger, undefined, verbose);
956
+ if (verbose) {
957
+ await logger.logToStderr('Loading site IDs...');
958
+ }
959
+ const requestOptions = {
960
+ url: `${url}/_api/site?$select=GroupId,Id`,
961
+ headers: {
962
+ accept: 'application/json;odata=nometadata'
963
+ },
964
+ responseType: 'json'
965
+ };
966
+ const siteInfo = await request.get(requestOptions);
967
+ const groupId = siteInfo.GroupId;
968
+ const siteId = siteInfo.Id;
969
+ const isGroupConnectedSite = groupId !== '00000000-0000-0000-0000-000000000000';
970
+ if (verbose) {
971
+ await logger.logToStderr(`Retrieved site IDs. siteId: ${siteId}, groupId: ${groupId}`);
972
+ }
973
+ if (isGroupConnectedSite) {
974
+ if (verbose) {
975
+ await logger.logToStderr(`Site attached to group ${groupId}`);
976
+ }
977
+ if (typeof title !== 'undefined' &&
978
+ typeof isPublic !== 'undefined' &&
979
+ typeof owners !== 'undefined') {
980
+ const promises = [];
981
+ if (typeof title !== 'undefined') {
982
+ const requestOptions = {
983
+ url: `${spoAdminUrl}/_api/SPOGroup/UpdateGroupPropertiesBySiteId`,
984
+ headers: {
985
+ accept: 'application/json;odata=nometadata',
986
+ 'content-type': 'application/json;charset=utf-8',
987
+ 'X-RequestDigest': context.FormDigestValue
988
+ },
989
+ data: {
990
+ groupId: groupId,
991
+ siteId: siteId,
992
+ displayName: title
993
+ },
994
+ responseType: 'json'
995
+ };
996
+ promises.push(request.post(requestOptions));
997
+ }
998
+ if (typeof isPublic !== 'undefined') {
999
+ promises.push(aadGroup.setGroup(groupId, (isPublic === false), logger, verbose));
1000
+ }
1001
+ if (typeof owners !== 'undefined') {
1002
+ promises.push(spo.setGroupifiedSiteOwners(spoAdminUrl, groupId, owners, logger, verbose));
1003
+ }
1004
+ await Promise.all(promises);
1005
+ }
1006
+ }
1007
+ else {
1008
+ if (verbose) {
1009
+ await logger.logToStderr('Site is not group connected');
1010
+ }
1011
+ if (typeof isPublic !== 'undefined') {
1012
+ throw `The isPublic option can't be set on a site that is not groupified`;
1013
+ }
1014
+ if (owners) {
1015
+ await Promise.all(owners.split(',').map(async (o) => {
1016
+ await spo.setSiteAdmin(spoAdminUrl, context, url, o.trim());
1017
+ }));
1018
+ }
1019
+ }
1020
+ context = await spo.ensureFormDigest(spoAdminUrl, logger, context, verbose);
1021
+ if (verbose) {
1022
+ await logger.logToStderr(`Updating site ${url} properties...`);
1023
+ }
1024
+ let updatedProperties = false;
1025
+ if (!isGroupConnectedSite) {
1026
+ if (title !== undefined) {
1027
+ updatedProperties = true;
1028
+ }
1029
+ }
1030
+ else {
1031
+ if (classification !== undefined || disableFlows !== undefined || shareByEmailEnabled !== undefined || sharingCapability !== undefined) {
1032
+ updatedProperties = true;
1033
+ }
1034
+ }
1035
+ if (updatedProperties) {
1036
+ let propertyId = 27;
1037
+ const payload = [];
1038
+ if (!isGroupConnectedSite) {
1039
+ if (title) {
1040
+ payload.push(`<SetProperty Id="${propertyId++}" ObjectPathId="5" Name="Title"><Parameter Type="String">${formatting.escapeXml(title)}</Parameter></SetProperty>`);
1041
+ }
1042
+ }
1043
+ if (typeof classification === 'string') {
1044
+ payload.push(`<SetProperty Id="${propertyId++}" ObjectPathId="5" Name="Classification"><Parameter Type="String">${formatting.escapeXml(classification)}</Parameter></SetProperty>`);
1045
+ }
1046
+ if (typeof disableFlows !== 'undefined') {
1047
+ payload.push(`<SetProperty Id="${propertyId++}" ObjectPathId="5" Name="DisableFlows"><Parameter Type="Boolean">${disableFlows}</Parameter></SetProperty>`);
1048
+ }
1049
+ if (typeof shareByEmailEnabled !== 'undefined') {
1050
+ payload.push(`<SetProperty Id="${propertyId++}" ObjectPathId="5" Name="ShareByEmailEnabled"><Parameter Type="Boolean">${shareByEmailEnabled}</Parameter></SetProperty>`);
1051
+ }
1052
+ if (sharingCapability) {
1053
+ const sharingCapabilityOption = SharingCapabilities[sharingCapability];
1054
+ payload.push(`<SetProperty Id="${propertyId++}" ObjectPathId="5" Name="SharingCapability"><Parameter Type="Enum">${sharingCapabilityOption}</Parameter></SetProperty>`);
1055
+ }
1056
+ const pos = tenantId.indexOf('|') + 1;
1057
+ const requestOptionsUpdateProperties = {
1058
+ url: `${spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
1059
+ headers: {
1060
+ 'X-RequestDigest': context.FormDigestValue
1061
+ },
1062
+ 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>${payload.join('')}<ObjectPath Id="14" ObjectPathId="13" /><ObjectIdentityQuery Id="15" ObjectPathId="5" /><Query Id="16" ObjectPathId="13"><Query SelectAllProperties="false"><Properties><Property Name="IsComplete" ScalarProperty="true" /><Property Name="PollingInterval" ScalarProperty="true" /></Properties></Query></Query></Actions><ObjectPaths><Identity Id="5" Name="53d8499e-d0d2-5000-cb83-9ade5be42ca4|${tenantId.substr(pos, tenantId.indexOf('&') - pos)}&#xA;SiteProperties&#xA;${formatting.encodeQueryParameter(url)}" /><Method Id="13" ParentId="5" Name="Update" /></ObjectPaths></Request>`
1063
+ };
1064
+ const res = await request.post(requestOptionsUpdateProperties);
1065
+ const json = JSON.parse(res);
1066
+ const response = json[0];
1067
+ if (response.ErrorInfo) {
1068
+ throw response.ErrorInfo.ErrorMessage;
1069
+ }
1070
+ else {
1071
+ const operation = json[json.length - 1];
1072
+ const isComplete = operation.IsComplete;
1073
+ if (!isComplete) {
1074
+ await new Promise((resolve, reject) => {
1075
+ setTimeout(() => {
1076
+ spo.waitUntilFinished({
1077
+ operationId: JSON.stringify(operation._ObjectIdentity_),
1078
+ siteUrl: spoAdminUrl,
1079
+ resolve,
1080
+ reject,
1081
+ logger,
1082
+ currentContext: context,
1083
+ verbose: verbose,
1084
+ debug: verbose
1085
+ });
1086
+ }, operation.PollingInterval);
1087
+ });
1088
+ }
1089
+ }
1090
+ }
1091
+ if (siteDesignId) {
1092
+ await spo.applySiteDesign(siteDesignId, url, logger, verbose);
1093
+ }
1094
+ },
1095
+ /**
1096
+ * Updates the groupified site owners
1097
+ * @param spoAdminUrl The SharePoint admin url
1098
+ * @param groupId The ID of the group
1099
+ * @param owners The owners to be updated
1100
+ * @param logger The logger object
1101
+ * @param verbose Set for verbose logging
1102
+ */
1103
+ async setGroupifiedSiteOwners(spoAdminUrl, groupId, owners, logger, verbose) {
1104
+ const splittedOwners = owners.split(',').map(o => o.trim());
1105
+ if (verbose) {
1106
+ await logger.logToStderr('Retrieving user information to set group owners...');
1107
+ }
1108
+ const requestOptions = {
1109
+ url: `https://graph.microsoft.com/v1.0/users?$filter=${splittedOwners.map(o => `userPrincipalName eq '${o}'`).join(' or ')}&$select=id`,
1110
+ headers: {
1111
+ 'content-type': 'application/json;odata.metadata=none'
1112
+ },
1113
+ responseType: 'json'
1114
+ };
1115
+ return request.get(requestOptions)
1116
+ .then((res) => {
1117
+ if (res.value.length === 0) {
1118
+ return Promise.resolve();
1119
+ }
1120
+ return Promise.all(res.value.map(user => {
1121
+ const requestOptions = {
1122
+ url: `${spoAdminUrl}/_api/SP.Directory.DirectorySession/Group('${groupId}')/Owners/Add(objectId='${user.id}', principalName='')`,
1123
+ headers: {
1124
+ 'content-type': 'application/json;odata=verbose'
1125
+ }
1126
+ };
1127
+ return request.post(requestOptions);
1128
+ }));
1129
+ });
1130
+ },
1131
+ /**
1132
+ * Updates the site admin
1133
+ * @param spoAdminUrl The SharePoint admin url
1134
+ * @param context The FormDigestInfo
1135
+ * @param siteUrl The url of the site where the owners has to be updated
1136
+ * @param principal The principal of the admin
1137
+ * @param logger The logger object
1138
+ * @param verbose Set for verbose logging
1139
+ */
1140
+ async setSiteAdmin(spoAdminUrl, context, siteUrl, principal, logger, verbose) {
1141
+ if (verbose && logger) {
1142
+ await logger.logToStderr(`Updating site admin ${principal} on ${siteUrl}...`);
1143
+ }
1144
+ const requestOptions = {
1145
+ url: `${spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
1146
+ headers: {
1147
+ 'X-RequestDigest': context.FormDigestValue
1148
+ },
1149
+ 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="48" ObjectPathId="47" /></Actions><ObjectPaths><Method Id="47" ParentId="34" Name="SetSiteAdmin"><Parameters><Parameter Type="String">${formatting.escapeXml(siteUrl)}</Parameter><Parameter Type="String">${formatting.escapeXml(principal)}</Parameter><Parameter Type="Boolean">true</Parameter></Parameters></Method><Constructor Id="34" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" /></ObjectPaths></Request>`
1150
+ };
1151
+ const res = await request.post(requestOptions);
1152
+ const json = JSON.parse(res);
1153
+ const response = json[0];
1154
+ if (response.ErrorInfo) {
1155
+ throw response.ErrorInfo.ErrorMessage;
1156
+ }
1157
+ else {
1158
+ return;
1159
+ }
1160
+ },
1161
+ /**
1162
+ * Applies a site design
1163
+ * @param id The ID of the site design (GUID)
1164
+ * @param webUrl The url of the site where the design should be applied
1165
+ * @param logger The logger object
1166
+ * @param verbose Set for verbose logging
1167
+ */
1168
+ async applySiteDesign(id, webUrl, logger, verbose) {
1169
+ if (verbose) {
1170
+ await logger.logToStderr(`Applying site design ${id}...`);
1171
+ }
1172
+ const spoUrl = await spo.getSpoUrl(logger, verbose);
1173
+ const requestOptions = {
1174
+ url: `${spoUrl}/_api/Microsoft.Sharepoint.Utilities.WebTemplateExtensions.SiteScriptUtility.ApplySiteDesign`,
1175
+ headers: {
1176
+ 'content-type': 'application/json;charset=utf-8',
1177
+ accept: 'application/json;odata=nometadata'
1178
+ },
1179
+ data: {
1180
+ siteDesignId: id,
1181
+ webUrl: webUrl
1182
+ },
1183
+ responseType: 'json'
1184
+ };
1185
+ await request.post(requestOptions);
1186
+ },
1187
+ /**
1188
+ * Gets the web properties for a given url
1189
+ * @param url The url of the web
1190
+ * @param logger The logger object
1191
+ * @param verbose Set for verbose logging
1192
+ */
1193
+ async getWeb(url, logger, verbose) {
1194
+ if (verbose && logger) {
1195
+ await logger.logToStderr(`Getting the web properties for ${url}`);
1196
+ }
1197
+ const requestOptions = {
1198
+ url: `${url}/_api/web`,
1199
+ headers: {
1200
+ 'accept': 'application/json;odata=nometadata'
1201
+ },
1202
+ responseType: 'json'
1203
+ };
1204
+ const webProperties = await request.get(requestOptions);
1205
+ return webProperties;
624
1206
  }
625
1207
  };
626
1208
  //# sourceMappingURL=spo.js.map
@@ -244,9 +244,6 @@ export const validation = {
244
244
  ];
245
245
  return !!input && !input.split('.').every(value => !~javascriptReservedWords.indexOf(value));
246
246
  },
247
- isValidFileName(input) {
248
- return !!input && !/^((\..*)|COM\d|CLOCK\$|LPT\d|AUX|NUL|CON|PRN|(.*[\u{d800}-\u{dfff}]+.*))$/iu.test(input) && !/^(.*\.\..*)$/i.test(input);
249
- },
250
247
  isValidTheme(input) {
251
248
  const validThemeProperties = [
252
249
  "themePrimary",
@@ -16,10 +16,10 @@ m365 aad group get [options]
16
16
 
17
17
  ```md definition-list
18
18
  `-i, --id [id]`
19
- : The object Id of the Azure AD group. Specify either `id` or `title` but not both
19
+ : The object Id of the Azure AD group. Specify either `id` or `displayName` but not both.
20
20
 
21
- `-t, --title [title]`
22
- : The display name of the Azure AD group. Specify either `id` or `title` but not both
21
+ `-n, --displayName [displayName]`
22
+ : The display name of the Azure AD group. Specify either `id` or `displayName` but not both.
23
23
  ```
24
24
 
25
25
  <Global />
@@ -32,10 +32,10 @@ Get information about an Azure AD Group by id
32
32
  m365 aad group get --id 1caf7dcd-7e83-4c3a-94f7-932a1299c844
33
33
  ```
34
34
 
35
- Get information about an Azure AD Group by title
35
+ Get information about an Azure AD Group by its display name
36
36
 
37
37
  ```sh
38
- m365 aad group get --title "Finance"
38
+ m365 aad group get --displayName Finance
39
39
  ```
40
40
 
41
41
  ## Response
@@ -14,11 +14,6 @@ m365 aad group list [options]
14
14
 
15
15
  ## Options
16
16
 
17
- ```md definition-list
18
- `-d, --deleted`
19
- : Use to retrieve deleted groups
20
- ```
21
-
22
17
  <Global />
23
18
 
24
19
  ## Examples
@@ -29,12 +24,6 @@ Lists all groups defined in Azure Active Directory.
29
24
  m365 aad group list
30
25
  ```
31
26
 
32
- List all recently deleted groups in the tenant
33
-
34
- ```sh
35
- m365 aad group list --deleted
36
- ```
37
-
38
27
  ## Response
39
28
 
40
29
  <Tabs>