From c27e722c028a44d3a700937fe575b056e27c3f80 Mon Sep 17 00:00:00 2001 From: Bert Jansen Date: Thu, 21 Dec 2023 10:56:04 +0100 Subject: [PATCH] Merge of #1334. Thanks @kfircs --- src/sdk/CHANGELOG.md | 8 + ...llectionWithTimeZome-0-00000.response.json | 1 + ...llectionWithTimeZome-0-00001.response.json | 1 + ...llectionWithTimeZome-0-00002.response.json | 1 + ...SetSiteCollectionWithTimeZome-0.properties | 1 + ...llectionWithTimeZome-1-00000.response.json | 1 + ...llectionWithTimeZome-1-00001.response.json | 1 + ...ectionWithTimeZome-100-00000.response.json | 1 + ...ectionWithTimeZome-100-00001.response.json | 1 + ...ectionWithTimeZome-100-00002.response.json | 1 + ...ectionWithTimeZome-101-00000.response.json | 1 + ...ectionWithTimeZome-101-00001.response.json | 1 + ...ectionWithTimeZome-101-00002.response.json | 1 + ...ectionWithTimeZome-200-00000.response.json | 1 + ...ectionWithTimeZome-200-00001.response.json | 1 + ...ectionWithTimeZome-200-00002.response.json | 1 + ...ectionWithTimeZome-201-00000.response.json | 1 + ...ectionWithTimeZome-201-00001.response.json | 1 + ...ectionWithTimeZome-201-00002.response.json | 1 + ...ectionWithTimeZome-301-00000.response.json | 1 + ...ectionWithTimeZome-301-00001.response.json | 1 + .../SharePoint/SiteManagerTests.cs | 10 +- .../Core/Internal/SiteCollectionCreator.cs | 1302 ++++++++--------- 23 files changed, 685 insertions(+), 655 deletions(-) create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00000.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00001.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00002.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0.properties create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-1-00000.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-1-00001.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00000.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00001.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00002.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00000.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00001.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00002.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00000.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00001.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00002.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00000.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00001.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00002.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-301-00000.response.json create mode 100644 src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-301-00001.response.json diff --git a/src/sdk/CHANGELOG.md b/src/sdk/CHANGELOG.md index 5a3e22ba08..ae818bf272 100644 --- a/src/sdk/CHANGELOG.md +++ b/src/sdk/CHANGELOG.md @@ -6,6 +6,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). +## [Unreleased] + +### Added + +### Changed + +- Admin library: added support to specify the timezone when creating a site collection #1334 [kfircs - Kfir Chen] + ## [1.11.0] ### Added diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00000.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00000.response.json new file mode 100644 index 0000000000..00005f1644 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00000.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"58dff9a0-202c-7000-ce2b-c7d1d295926a","SPClientServiceRequestDuration":"14","X-SharePointHealthScore":"2","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022RegionalSettings\u0022:{\u0022TimeZone\u0022:{\u0022Description\u0022:\u0022(UTC\u002B01:00) Brussels, Copenhagen, Madrid, Paris\u0022,\u0022Id\u0022:3,\u0022Information\u0022:{\u0022Bias\u0022:-60,\u0022DaylightBias\u0022:-60,\u0022StandardBias\u0022:0}},\u0022AdjustHijriDays\u0022:0,\u0022AlternateCalendarType\u0022:0,\u0022AM\u0022:\u0022\u0022,\u0022CalendarType\u0022:1,\u0022Collation\u0022:25,\u0022CollationLCID\u0022:2070,\u0022DateFormat\u0022:1,\u0022DateSeparator\u0022:\u0022/\u0022,\u0022DecimalSeparator\u0022:\u0022,\u0022,\u0022DigitGrouping\u0022:\u00223;0\u0022,\u0022FirstDayOfWeek\u0022:1,\u0022FirstWeekOfYear\u0022:2,\u0022IsEastAsia\u0022:false,\u0022IsRightToLeft\u0022:false,\u0022IsUIRightToLeft\u0022:false,\u0022ListSeparator\u0022:\u0022;\u0022,\u0022LocaleId\u0022:2067,\u0022NegativeSign\u0022:\u0022-\u0022,\u0022NegNumberMode\u0022:1,\u0022PM\u0022:\u0022\u0022,\u0022PositiveSign\u0022:\u0022\u0022,\u0022ShowWeeks\u0022:false,\u0022ThousandSeparator\u0022:\u0022.\u0022,\u0022Time24\u0022:true,\u0022TimeMarkerPosition\u0022:0,\u0022TimeSeparator\u0022:\u0022:\u0022,\u0022WorkDayEndHour\u0022:1020,\u0022WorkDays\u0022:62,\u0022WorkDayStartHour\u0022:480},\u0022Id\u0022:\u00228c8e101c-1b0d-4253-85e7-c30039bf46e2\u0022,\u0022Url\u0022:\u0022https://bertonline.sharepoint.com/sites/prov-1\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00001.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00001.response.json new file mode 100644 index 0000000000..ec6f8d5033 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00001.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"58dff9a0-c03a-7000-d664-eb1d4c4969b1","SPClientServiceRequestDuration":"10","X-SharePointHealthScore":"0","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022GroupId\u0022:\u0022b32780e9-df70-4548-a735-4e7f055415a1\u0022,\u0022Id\u0022:\u0022b56adf79-ff6a-4964-a63a-ff1fa23be9f8\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00002.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00002.response.json new file mode 100644 index 0000000000..a707993903 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0-00002.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"5cdff9a0-d0f4-7000-d664-e7a25cc1db8e","SPClientServiceRequestDuration":"2945","X-SharePointHealthScore":"0","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022SiteId\u0022:\u0022b3c93a74-48a0-47c8-89d8-96f24c5f49fb\u0022,\u0022SiteStatus\u0022:2,\u0022SiteUrl\u0022:\u0022https://bertonline.sharepoint.com/sites/pnpcoresdktestcommsitee5c1e4eb821049dab80410a1e69f58e2\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0.properties b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0.properties new file mode 100644 index 0000000000..b4b5fecdcd --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-0.properties @@ -0,0 +1 @@ +{"SiteUrl":"https://bertonline.sharepoint.com/sites/pnpcoresdktestcommsitee5c1e4eb821049dab80410a1e69f58e2"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-1-00000.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-1-00000.response.json new file mode 100644 index 0000000000..3ea9f99942 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-1-00000.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"71dff9a0-60ab-7000-d664-e8e23376adb5","SPClientServiceRequestDuration":"11","X-SharePointHealthScore":"0","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022RegionalSettings\u0022:{\u0022TimeZone\u0022:{\u0022Description\u0022:\u0022(UTC\u002B01:00) Brussels, Copenhagen, Madrid, Paris\u0022,\u0022Id\u0022:3,\u0022Information\u0022:{\u0022Bias\u0022:-60,\u0022DaylightBias\u0022:-60,\u0022StandardBias\u0022:0}},\u0022AdjustHijriDays\u0022:0,\u0022AlternateCalendarType\u0022:0,\u0022AM\u0022:\u0022\u0022,\u0022CalendarType\u0022:1,\u0022Collation\u0022:25,\u0022CollationLCID\u0022:2070,\u0022DateFormat\u0022:1,\u0022DateSeparator\u0022:\u0022/\u0022,\u0022DecimalSeparator\u0022:\u0022,\u0022,\u0022DigitGrouping\u0022:\u00223;0\u0022,\u0022FirstDayOfWeek\u0022:1,\u0022FirstWeekOfYear\u0022:2,\u0022IsEastAsia\u0022:false,\u0022IsRightToLeft\u0022:false,\u0022IsUIRightToLeft\u0022:false,\u0022ListSeparator\u0022:\u0022;\u0022,\u0022LocaleId\u0022:2067,\u0022NegativeSign\u0022:\u0022-\u0022,\u0022NegNumberMode\u0022:1,\u0022PM\u0022:\u0022\u0022,\u0022PositiveSign\u0022:\u0022\u0022,\u0022ShowWeeks\u0022:false,\u0022ThousandSeparator\u0022:\u0022.\u0022,\u0022Time24\u0022:true,\u0022TimeMarkerPosition\u0022:0,\u0022TimeSeparator\u0022:\u0022:\u0022,\u0022WorkDayEndHour\u0022:1020,\u0022WorkDays\u0022:62,\u0022WorkDayStartHour\u0022:480},\u0022Id\u0022:\u00228c8e101c-1b0d-4253-85e7-c30039bf46e2\u0022,\u0022Url\u0022:\u0022https://bertonline.sharepoint.com/sites/prov-1\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-1-00001.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-1-00001.response.json new file mode 100644 index 0000000000..8ad7c067e7 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-1-00001.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"71dff9a0-20b3-7000-e61f-0e52ad78aa88","SPClientServiceRequestDuration":"8","X-SharePointHealthScore":"0","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022GroupId\u0022:\u0022b32780e9-df70-4548-a735-4e7f055415a1\u0022,\u0022Id\u0022:\u0022b56adf79-ff6a-4964-a63a-ff1fa23be9f8\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00000.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00000.response.json new file mode 100644 index 0000000000..b84c12dadd --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00000.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"5ddff9a0-20b6-7000-ce2b-ccc1b97080b1","SPClientServiceRequestDuration":"61","X-SharePointHealthScore":"3","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022RegionalSettings\u0022:{\u0022TimeZone\u0022:{\u0022Description\u0022:\u0022(UTC\u002B02:00) Jerusalem\u0022,\u0022Id\u0022:27,\u0022Information\u0022:{\u0022Bias\u0022:-120,\u0022DaylightBias\u0022:-60,\u0022StandardBias\u0022:0}},\u0022AdjustHijriDays\u0022:0,\u0022AlternateCalendarType\u0022:0,\u0022AM\u0022:\u0022AM\u0022,\u0022CalendarType\u0022:1,\u0022Collation\u0022:25,\u0022CollationLCID\u0022:2070,\u0022DateFormat\u0022:0,\u0022DateSeparator\u0022:\u0022/\u0022,\u0022DecimalSeparator\u0022:\u0022.\u0022,\u0022DigitGrouping\u0022:\u00223;0\u0022,\u0022FirstDayOfWeek\u0022:0,\u0022FirstWeekOfYear\u0022:0,\u0022IsEastAsia\u0022:false,\u0022IsRightToLeft\u0022:false,\u0022IsUIRightToLeft\u0022:false,\u0022ListSeparator\u0022:\u0022,\u0022,\u0022LocaleId\u0022:1033,\u0022NegativeSign\u0022:\u0022-\u0022,\u0022NegNumberMode\u0022:1,\u0022PM\u0022:\u0022PM\u0022,\u0022PositiveSign\u0022:\u0022\u0022,\u0022ShowWeeks\u0022:false,\u0022ThousandSeparator\u0022:\u0022,\u0022,\u0022Time24\u0022:false,\u0022TimeMarkerPosition\u0022:0,\u0022TimeSeparator\u0022:\u0022:\u0022,\u0022WorkDayEndHour\u0022:1020,\u0022WorkDays\u0022:62,\u0022WorkDayStartHour\u0022:480},\u0022Id\u0022:\u00228fef796d-1c2e-481e-a950-9d08c7772624\u0022,\u0022Url\u0022:\u0022https://bertonline.sharepoint.com/sites/pnpcoresdktestcommsitee5c1e4eb821049dab80410a1e69f58e2\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00001.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00001.response.json new file mode 100644 index 0000000000..f68901d4f5 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00001.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"5ddff9a0-f0c0-7000-d664-eb1d8b4a8c66","SPClientServiceRequestDuration":"9","X-SharePointHealthScore":"2","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022GroupId\u0022:\u002200000000-0000-0000-0000-000000000000\u0022,\u0022Id\u0022:\u0022b3c93a74-48a0-47c8-89d8-96f24c5f49fb\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00002.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00002.response.json new file mode 100644 index 0000000000..4ee0d067cc --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-100-00002.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"2bdff9a0-608d-7000-d664-e39424162ca4","SPClientServiceRequestDuration":"652","X-SharePointHealthScore":"0","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"[\r{\r\u0022SchemaVersion\u0022:\u002215.0.0.0\u0022,\u0022LibraryVersion\u0022:\u002216.0.24329.12004\u0022,\u0022ErrorInfo\u0022:null,\u0022TraceCorrelationId\u0022:\u00222bdff9a0-608d-7000-d664-e39424162ca4\u0022\r},4,{\r\u0022IsNull\u0022:false\r},5,{\r\u0022IsNull\u0022:false\r},2,{\r\u0022_ObjectType_\u0022:\u0022Microsoft.Online.SharePoint.TenantAdministration.SiteProperties\u0022,\u0022_ObjectIdentity_\u0022:\u00222bdff9a0-608d-7000-d664-e39424162ca4|908bed80-a04a-4433-b4a0-883d9847d110:6492ece7-7f5d-4499-8130-50e761e25bd9\\nSiteProperties\\nhttps%3a%2f%2fbertonline.sharepoint.com%2fsites%2fprov-1\u0022,\u0022AllowDownloadingNonWebViewableFiles\u0022:false,\u0022AllowEditing\u0022:true,\u0022AllowSelfServiceUpgrade\u0022:true,\u0022AnonymousLinkExpirationInDays\u0022:0,\u0022ArchiveStatus\u0022:\u0022NotArchived\u0022,\u0022AuthContextStrength\u0022:null,\u0022AuthenticationContextLimitedAccess\u0022:false,\u0022AuthenticationContextName\u0022:null,\u0022AverageResourceUsage\u0022:0,\u0022BlockDownloadLinksFileType\u0022:1,\u0022BlockDownloadMicrosoft365GroupIds\u0022:null,\u0022BlockDownloadPolicy\u0022:false,\u0022BlockGuestsAsSiteAdmin\u0022:0,\u0022BonusDiskQuota\u0022:0,\u0022ClearRestrictedAccessControl\u0022:false,\u0022CommentsOnSitePagesDisabled\u0022:false,\u0022CompatibilityLevel\u0022:15,\u0022ConditionalAccessPolicy\u0022:0,\u0022CurrentResourceUsage\u0022:0,\u0022DefaultLinkPermission\u0022:0,\u0022DefaultLinkToExistingAccess\u0022:false,\u0022DefaultLinkToExistingAccessReset\u0022:false,\u0022DefaultShareLinkRole\u0022:0,\u0022DefaultShareLinkScope\u0022:-1,\u0022DefaultSharingLinkType\u0022:0,\u0022DenyAddAndCustomizePages\u0022:2,\u0022Description\u0022:\u0022prov-1\u0022,\u0022DisableAppViews\u0022:2,\u0022DisableCompanyWideSharingLinks\u0022:2,\u0022DisableFlows\u0022:2,\u0022ExcludeBlockDownloadPolicySiteOwners\u0022:false,\u0022ExcludeBlockDownloadSharePointGroups\u0022:[\r\r],\u0022ExcludedBlockDownloadGroupIds\u0022:[\r\r],\u0022ExternalUserExpirationInDays\u0022:0,\u0022GroupId\u0022:\u0022\\/Guid(b32780e9-df70-4548-a735-4e7f055415a1)\\/\u0022,\u0022GroupOwnerLoginName\u0022:\u0022c:0o.c|federateddirectoryclaimprovider|b32780e9-df70-4548-a735-4e7f055415a1_o\u0022,\u0022HasHolds\u0022:false,\u0022HubSiteId\u0022:\u0022\\/Guid(00000000-0000-0000-0000-000000000000)\\/\u0022,\u0022IBMode\u0022:\u0022\u0022,\u0022IBSegments\u0022:[\r\r],\u0022IBSegmentsToAdd\u0022:null,\u0022IBSegmentsToRemove\u0022:null,\u0022IsGroupOwnerSiteAdmin\u0022:true,\u0022IsHubSite\u0022:false,\u0022IsTeamsChannelConnected\u0022:false,\u0022IsTeamsConnected\u0022:true,\u0022LastContentModifiedDate\u0022:\u0022\\/Date(2023,11,13,8,6,28,713)\\/\u0022,\u0022Lcid\u0022:2067,\u0022LimitedAccessFileType\u0022:1,\u0022ListsShowHeaderAndNavigation\u0022:false,\u0022LockIssue\u0022:null,\u0022LockState\u0022:\u0022Unlock\u0022,\u0022LoopDefaultSharingLinkRole\u0022:0,\u0022LoopDefaultSharingLinkScope\u0022:-1,\u0022LoopOverrideSharingCapability\u0022:false,\u0022LoopSharingCapability\u0022:1,\u0022MediaTranscription\u0022:0,\u0022OverrideBlockUserInfoVisibility\u0022:0,\u0022OverrideSharingCapability\u0022:false,\u0022OverrideTenantAnonymousLinkExpirationPolicy\u0022:false,\u0022OverrideTenantExternalUserExpirationPolicy\u0022:false,\u0022Owner\u0022:\u0022b32780e9-df70-4548-a735-4e7f055415a1_o\u0022,\u0022OwnerEmail\u0022:\u0022prov-1@bertonline.onmicrosoft.com\u0022,\u0022OwnerLoginName\u0022:\u0022c:0o.c|federateddirectoryclaimprovider|b32780e9-df70-4548-a735-4e7f055415a1_o\u0022,\u0022OwnerName\u0022:\u0022prov-1\u0022,\u0022PWAEnabled\u0022:1,\u0022ReadOnlyAccessPolicy\u0022:false,\u0022ReadOnlyForBlockDownloadPolicy\u0022:false,\u0022ReadOnlyForUnmanagedDevices\u0022:false,\u0022RelatedGroupId\u0022:\u0022\\/Guid(b32780e9-df70-4548-a735-4e7f055415a1)\\/\u0022,\u0022RequestFilesLinkEnabled\u0022:false,\u0022RequestFilesLinkExpirationInDays\u0022:-1,\u0022RestrictedAccessControl\u0022:false,\u0022RestrictedAccessControlGroups\u0022:[\r\u0022\\/Guid(b32780e9-df70-4548-a735-4e7f055415a1)\\/\u0022\r],\u0022RestrictedAccessControlGroupsToAdd\u0022:null,\u0022RestrictedAccessControlGroupsToRemove\u0022:null,\u0022RestrictedToRegion\u0022:3,\u0022SandboxedCodeActivationCapability\u0022:2,\u0022SensitivityLabel\u0022:\u0022\\/Guid(00000000-0000-0000-0000-000000000000)\\/\u0022,\u0022SensitivityLabel2\u0022:\u0022\u0022,\u0022SetOwnerWithoutUpdatingSecondaryAdmin\u0022:false,\u0022SharingAllowedDomainList\u0022:\u0022\u0022,\u0022SharingBlockedDomainList\u0022:\u0022\u0022,\u0022SharingCapability\u0022:1,\u0022SharingDomainRestrictionMode\u0022:0,\u0022SharingLockDownCanBeCleared\u0022:true,\u0022SharingLockDownEnabled\u0022:false,\u0022ShowPeoplePickerSuggestionsForGuestUsers\u0022:false,\u0022SiteDefinedSharingCapability\u0022:1,\u0022SiteId\u0022:\u0022\\/Guid(b56adf79-ff6a-4964-a63a-ff1fa23be9f8)\\/\u0022,\u0022SocialBarOnSitePagesDisabled\u0022:false,\u0022Status\u0022:\u0022Active\u0022,\u0022StorageMaximumLevel\u0022:26214400,\u0022StorageQuotaType\u0022:null,\u0022StorageUsage\u0022:5129,\u0022StorageWarningLevel\u0022:25574400,\u0022TeamsChannelType\u0022:0,\u0022Template\u0022:\u0022GROUP#0\u0022,\u0022TimeZoneId\u0022:3,\u0022Title\u0022:\u0022prov-1\u0022,\u0022TitleTranslations\u0022:[\r{\r\u0022_ObjectType_\u0022:\u0022SP.SPResourceEntry\u0022,\u0022LCID\u0022:1033,\u0022Value\u0022:\u0022prov-1\u0022\r},{\r\u0022_ObjectType_\u0022:\u0022SP.SPResourceEntry\u0022,\u0022LCID\u0022:1043,\u0022Value\u0022:\u0022Teamsite\u0022\r}\r],\u0022Url\u0022:\u0022https:\\u002f\\u002fbertonline.sharepoint.com\\u002fsites\\u002fprov-1\u0022,\u0022UserCodeMaximumLevel\u0022:300,\u0022UserCodeWarningLevel\u0022:200,\u0022WebsCount\u0022:8\r}\r]"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00000.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00000.response.json new file mode 100644 index 0000000000..202ffae887 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00000.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"72dff9a0-8000-7000-e61f-03b20e1024a6","SPClientServiceRequestDuration":"22","X-SharePointHealthScore":"3","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022RegionalSettings\u0022:{\u0022TimeZone\u0022:{\u0022Description\u0022:\u0022(UTC-08:00) Pacific Time (US and Canada)\u0022,\u0022Id\u0022:13,\u0022Information\u0022:{\u0022Bias\u0022:480,\u0022DaylightBias\u0022:-60,\u0022StandardBias\u0022:0}},\u0022AdjustHijriDays\u0022:0,\u0022AlternateCalendarType\u0022:0,\u0022AM\u0022:\u0022AM\u0022,\u0022CalendarType\u0022:1,\u0022Collation\u0022:25,\u0022CollationLCID\u0022:2070,\u0022DateFormat\u0022:0,\u0022DateSeparator\u0022:\u0022/\u0022,\u0022DecimalSeparator\u0022:\u0022.\u0022,\u0022DigitGrouping\u0022:\u00223;0\u0022,\u0022FirstDayOfWeek\u0022:0,\u0022FirstWeekOfYear\u0022:0,\u0022IsEastAsia\u0022:false,\u0022IsRightToLeft\u0022:false,\u0022IsUIRightToLeft\u0022:false,\u0022ListSeparator\u0022:\u0022,\u0022,\u0022LocaleId\u0022:1033,\u0022NegativeSign\u0022:\u0022-\u0022,\u0022NegNumberMode\u0022:1,\u0022PM\u0022:\u0022PM\u0022,\u0022PositiveSign\u0022:\u0022\u0022,\u0022ShowWeeks\u0022:false,\u0022ThousandSeparator\u0022:\u0022,\u0022,\u0022Time24\u0022:false,\u0022TimeMarkerPosition\u0022:0,\u0022TimeSeparator\u0022:\u0022:\u0022,\u0022WorkDayEndHour\u0022:1020,\u0022WorkDays\u0022:62,\u0022WorkDayStartHour\u0022:480},\u0022Id\u0022:\u0022a5f687e3-6783-4295-8e6f-f95fb09c1d83\u0022,\u0022Url\u0022:\u0022https://bertonline-admin.sharepoint.com\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00001.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00001.response.json new file mode 100644 index 0000000000..559c7d0483 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00001.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"72dff9a0-2008-7000-ce2b-cc367f72d31a","SPClientServiceRequestDuration":"27","X-SharePointHealthScore":"0","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022GroupId\u0022:\u002200000000-0000-0000-0000-000000000000\u0022,\u0022Id\u0022:\u0022159c6b93-32dc-45d5-a376-7b03ea9ad542\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00002.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00002.response.json new file mode 100644 index 0000000000..af2e17114e --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-101-00002.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"72dff9a0-806b-7000-e61f-045fc42bdd37","SPClientServiceRequestDuration":"1318","X-SharePointHealthScore":"2","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"[\r{\r\u0022SchemaVersion\u0022:\u002215.0.0.0\u0022,\u0022LibraryVersion\u0022:\u002216.0.24329.12003\u0022,\u0022ErrorInfo\u0022:null,\u0022TraceCorrelationId\u0022:\u002272dff9a0-806b-7000-e61f-045fc42bdd37\u0022\r},3,{\r\u0022_ObjectType_\u0022:\u0022Microsoft.Online.SharePoint.TenantAdministration.SpoOperation\u0022,\u0022_ObjectIdentity_\u0022:\u002272dff9a0-806b-7000-e61f-045fc42bdd37|908bed80-a04a-4433-b4a0-883d9847d110:6492ece7-7f5d-4499-8130-50e761e25bd9\\nSpoOperation\\nRemoveDeletedSite\\n638387491419923740\\nhttps%3a%2f%2fbertonline.sharepoint.com%2fsites%2fpnpcoresdktestcommsitee5c1e4eb821049dab80410a1e69f58e2\\nb3c93a74-48a0-47c8-89d8-96f24c5f49fb\u0022,\u0022PollingInterval\u0022:15000,\u0022IsComplete\u0022:true\r}\r]"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00000.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00000.response.json new file mode 100644 index 0000000000..c9b7246956 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00000.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"5edff9a0-70f3-7000-ce2b-ca179f20a6ce","SPClientServiceRequestDuration":"20","X-SharePointHealthScore":"1","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022RegionalSettings\u0022:{\u0022TimeZone\u0022:{\u0022Description\u0022:\u0022(UTC-08:00) Pacific Time (US and Canada)\u0022,\u0022Id\u0022:13,\u0022Information\u0022:{\u0022Bias\u0022:480,\u0022DaylightBias\u0022:-60,\u0022StandardBias\u0022:0}},\u0022AdjustHijriDays\u0022:0,\u0022AlternateCalendarType\u0022:0,\u0022AM\u0022:\u0022AM\u0022,\u0022CalendarType\u0022:1,\u0022Collation\u0022:25,\u0022CollationLCID\u0022:2070,\u0022DateFormat\u0022:0,\u0022DateSeparator\u0022:\u0022/\u0022,\u0022DecimalSeparator\u0022:\u0022.\u0022,\u0022DigitGrouping\u0022:\u00223;0\u0022,\u0022FirstDayOfWeek\u0022:0,\u0022FirstWeekOfYear\u0022:0,\u0022IsEastAsia\u0022:false,\u0022IsRightToLeft\u0022:false,\u0022IsUIRightToLeft\u0022:false,\u0022ListSeparator\u0022:\u0022,\u0022,\u0022LocaleId\u0022:1033,\u0022NegativeSign\u0022:\u0022-\u0022,\u0022NegNumberMode\u0022:1,\u0022PM\u0022:\u0022PM\u0022,\u0022PositiveSign\u0022:\u0022\u0022,\u0022ShowWeeks\u0022:false,\u0022ThousandSeparator\u0022:\u0022,\u0022,\u0022Time24\u0022:false,\u0022TimeMarkerPosition\u0022:0,\u0022TimeSeparator\u0022:\u0022:\u0022,\u0022WorkDayEndHour\u0022:1020,\u0022WorkDays\u0022:62,\u0022WorkDayStartHour\u0022:480},\u0022Id\u0022:\u0022a5f687e3-6783-4295-8e6f-f95fb09c1d83\u0022,\u0022Url\u0022:\u0022https://bertonline-admin.sharepoint.com\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00001.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00001.response.json new file mode 100644 index 0000000000..bff9557808 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00001.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"5edff9a0-50fb-7000-ce2b-c30ea0aea4e4","SPClientServiceRequestDuration":"26","X-SharePointHealthScore":"3","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022GroupId\u0022:\u002200000000-0000-0000-0000-000000000000\u0022,\u0022Id\u0022:\u0022159c6b93-32dc-45d5-a376-7b03ea9ad542\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00002.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00002.response.json new file mode 100644 index 0000000000..dd9ba25ef5 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-200-00002.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"5fdff9a0-5005-7000-e61f-0845d262a1f5","SPClientServiceRequestDuration":"630","X-SharePointHealthScore":"0","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"[\r{\r\u0022SchemaVersion\u0022:\u002215.0.0.0\u0022,\u0022LibraryVersion\u0022:\u002216.0.24329.12003\u0022,\u0022ErrorInfo\u0022:null,\u0022TraceCorrelationId\u0022:\u00225fdff9a0-5005-7000-e61f-0845d262a1f5\u0022\r},4,{\r\u0022IsNull\u0022:false\r},5,{\r\u0022IsNull\u0022:false\r},2,{\r\u0022_ObjectType_\u0022:\u0022Microsoft.Online.SharePoint.TenantAdministration.SiteProperties\u0022,\u0022_ObjectIdentity_\u0022:\u00225fdff9a0-5005-7000-e61f-0845d262a1f5|908bed80-a04a-4433-b4a0-883d9847d110:6492ece7-7f5d-4499-8130-50e761e25bd9\\nSiteProperties\\nhttps%3a%2f%2fbertonline.sharepoint.com%2fsites%2fpnpcoresdktestcommsitee5c1e4eb821049dab80410a1e69f58e2\u0022,\u0022AllowDownloadingNonWebViewableFiles\u0022:false,\u0022AllowEditing\u0022:true,\u0022AllowSelfServiceUpgrade\u0022:true,\u0022AnonymousLinkExpirationInDays\u0022:0,\u0022ArchiveStatus\u0022:\u0022NotArchived\u0022,\u0022AuthContextStrength\u0022:null,\u0022AuthenticationContextLimitedAccess\u0022:false,\u0022AuthenticationContextName\u0022:null,\u0022AverageResourceUsage\u0022:0,\u0022BlockDownloadLinksFileType\u0022:1,\u0022BlockDownloadMicrosoft365GroupIds\u0022:null,\u0022BlockDownloadPolicy\u0022:false,\u0022BlockGuestsAsSiteAdmin\u0022:0,\u0022BonusDiskQuota\u0022:0,\u0022ClearRestrictedAccessControl\u0022:false,\u0022CommentsOnSitePagesDisabled\u0022:false,\u0022CompatibilityLevel\u0022:15,\u0022ConditionalAccessPolicy\u0022:0,\u0022CurrentResourceUsage\u0022:0,\u0022DefaultLinkPermission\u0022:0,\u0022DefaultLinkToExistingAccess\u0022:false,\u0022DefaultLinkToExistingAccessReset\u0022:false,\u0022DefaultShareLinkRole\u0022:0,\u0022DefaultShareLinkScope\u0022:-1,\u0022DefaultSharingLinkType\u0022:0,\u0022DenyAddAndCustomizePages\u0022:2,\u0022Description\u0022:\u0022This is a test site collection\u0022,\u0022DisableAppViews\u0022:2,\u0022DisableCompanyWideSharingLinks\u0022:2,\u0022DisableFlows\u0022:2,\u0022ExcludeBlockDownloadPolicySiteOwners\u0022:false,\u0022ExcludeBlockDownloadSharePointGroups\u0022:[\r\r],\u0022ExcludedBlockDownloadGroupIds\u0022:[\r\r],\u0022ExternalUserExpirationInDays\u0022:0,\u0022GroupId\u0022:\u0022\\/Guid(00000000-0000-0000-0000-000000000000)\\/\u0022,\u0022GroupOwnerLoginName\u0022:\u0022c:0o.c|federateddirectoryclaimprovider|00000000-0000-0000-0000-000000000000_o\u0022,\u0022HasHolds\u0022:false,\u0022HubSiteId\u0022:\u0022\\/Guid(00000000-0000-0000-0000-000000000000)\\/\u0022,\u0022IBMode\u0022:\u0022\u0022,\u0022IBSegments\u0022:[\r\r],\u0022IBSegmentsToAdd\u0022:null,\u0022IBSegmentsToRemove\u0022:null,\u0022IsGroupOwnerSiteAdmin\u0022:false,\u0022IsHubSite\u0022:false,\u0022IsTeamsChannelConnected\u0022:false,\u0022IsTeamsConnected\u0022:false,\u0022LastContentModifiedDate\u0022:\u0022\\/Date(2023,11,21,9,51,1,140)\\/\u0022,\u0022Lcid\u0022:1033,\u0022LimitedAccessFileType\u0022:1,\u0022ListsShowHeaderAndNavigation\u0022:false,\u0022LockIssue\u0022:null,\u0022LockState\u0022:\u0022Unlock\u0022,\u0022LoopDefaultSharingLinkRole\u0022:0,\u0022LoopDefaultSharingLinkScope\u0022:-1,\u0022LoopOverrideSharingCapability\u0022:false,\u0022LoopSharingCapability\u0022:0,\u0022MediaTranscription\u0022:0,\u0022OverrideBlockUserInfoVisibility\u0022:0,\u0022OverrideSharingCapability\u0022:false,\u0022OverrideTenantAnonymousLinkExpirationPolicy\u0022:false,\u0022OverrideTenantExternalUserExpirationPolicy\u0022:false,\u0022Owner\u0022:\u0022bert.jansen@bertonline.onmicrosoft.com\u0022,\u0022OwnerEmail\u0022:\u0022bert.jansen@bertonline.onmicrosoft.com\u0022,\u0022OwnerLoginName\u0022:\u0022i:0#.f|membership|bert.jansen@bertonline.onmicrosoft.com\u0022,\u0022OwnerName\u0022:\u0022Bert Jansen (Cloud)\u0022,\u0022PWAEnabled\u0022:1,\u0022ReadOnlyAccessPolicy\u0022:false,\u0022ReadOnlyForBlockDownloadPolicy\u0022:false,\u0022ReadOnlyForUnmanagedDevices\u0022:false,\u0022RelatedGroupId\u0022:\u0022\\/Guid(00000000-0000-0000-0000-000000000000)\\/\u0022,\u0022RequestFilesLinkEnabled\u0022:false,\u0022RequestFilesLinkExpirationInDays\u0022:-1,\u0022RestrictedAccessControl\u0022:false,\u0022RestrictedAccessControlGroups\u0022:[\r\r],\u0022RestrictedAccessControlGroupsToAdd\u0022:null,\u0022RestrictedAccessControlGroupsToRemove\u0022:null,\u0022RestrictedToRegion\u0022:3,\u0022SandboxedCodeActivationCapability\u0022:2,\u0022SensitivityLabel\u0022:\u0022\\/Guid(00000000-0000-0000-0000-000000000000)\\/\u0022,\u0022SensitivityLabel2\u0022:\u0022\u0022,\u0022SetOwnerWithoutUpdatingSecondaryAdmin\u0022:false,\u0022SharingAllowedDomainList\u0022:\u0022\u0022,\u0022SharingBlockedDomainList\u0022:\u0022\u0022,\u0022SharingCapability\u0022:0,\u0022SharingDomainRestrictionMode\u0022:0,\u0022SharingLockDownCanBeCleared\u0022:true,\u0022SharingLockDownEnabled\u0022:false,\u0022ShowPeoplePickerSuggestionsForGuestUsers\u0022:false,\u0022SiteDefinedSharingCapability\u0022:0,\u0022SiteId\u0022:\u0022\\/Guid(b3c93a74-48a0-47c8-89d8-96f24c5f49fb)\\/\u0022,\u0022SocialBarOnSitePagesDisabled\u0022:false,\u0022Status\u0022:\u0022Active\u0022,\u0022StorageMaximumLevel\u0022:1048576,\u0022StorageQuotaType\u0022:null,\u0022StorageUsage\u0022:0,\u0022StorageWarningLevel\u0022:1022361,\u0022TeamsChannelType\u0022:0,\u0022Template\u0022:\u0022SITEPAGEPUBLISHING#0\u0022,\u0022TimeZoneId\u0022:27,\u0022Title\u0022:\u0022PnP Core SDK Test\u0022,\u0022TitleTranslations\u0022:null,\u0022Url\u0022:\u0022https:\\u002f\\u002fbertonline.sharepoint.com\\u002fsites\\u002fpnpcoresdktestcommsitee5c1e4eb821049dab80410a1e69f58e2\u0022,\u0022UserCodeMaximumLevel\u0022:300,\u0022UserCodeWarningLevel\u0022:200,\u0022WebsCount\u0022:1\r}\r]"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00000.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00000.response.json new file mode 100644 index 0000000000..8bb56edf1e --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00000.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"72dff9a0-8010-7000-d664-ef59aac6f8b7","SPClientServiceRequestDuration":"21","X-SharePointHealthScore":"1","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022RegionalSettings\u0022:{\u0022TimeZone\u0022:{\u0022Description\u0022:\u0022(UTC-08:00) Pacific Time (US and Canada)\u0022,\u0022Id\u0022:13,\u0022Information\u0022:{\u0022Bias\u0022:480,\u0022DaylightBias\u0022:-60,\u0022StandardBias\u0022:0}},\u0022AdjustHijriDays\u0022:0,\u0022AlternateCalendarType\u0022:0,\u0022AM\u0022:\u0022AM\u0022,\u0022CalendarType\u0022:1,\u0022Collation\u0022:25,\u0022CollationLCID\u0022:2070,\u0022DateFormat\u0022:0,\u0022DateSeparator\u0022:\u0022/\u0022,\u0022DecimalSeparator\u0022:\u0022.\u0022,\u0022DigitGrouping\u0022:\u00223;0\u0022,\u0022FirstDayOfWeek\u0022:0,\u0022FirstWeekOfYear\u0022:0,\u0022IsEastAsia\u0022:false,\u0022IsRightToLeft\u0022:false,\u0022IsUIRightToLeft\u0022:false,\u0022ListSeparator\u0022:\u0022,\u0022,\u0022LocaleId\u0022:1033,\u0022NegativeSign\u0022:\u0022-\u0022,\u0022NegNumberMode\u0022:1,\u0022PM\u0022:\u0022PM\u0022,\u0022PositiveSign\u0022:\u0022\u0022,\u0022ShowWeeks\u0022:false,\u0022ThousandSeparator\u0022:\u0022,\u0022,\u0022Time24\u0022:false,\u0022TimeMarkerPosition\u0022:0,\u0022TimeSeparator\u0022:\u0022:\u0022,\u0022WorkDayEndHour\u0022:1020,\u0022WorkDays\u0022:62,\u0022WorkDayStartHour\u0022:480},\u0022Id\u0022:\u0022a5f687e3-6783-4295-8e6f-f95fb09c1d83\u0022,\u0022Url\u0022:\u0022https://bertonline-admin.sharepoint.com\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00001.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00001.response.json new file mode 100644 index 0000000000..bcdbb2d003 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00001.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"72dff9a0-b018-7000-e61f-0179c3b086c9","SPClientServiceRequestDuration":"22","X-SharePointHealthScore":"3","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022GroupId\u0022:\u002200000000-0000-0000-0000-000000000000\u0022,\u0022Id\u0022:\u0022159c6b93-32dc-45d5-a376-7b03ea9ad542\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00002.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00002.response.json new file mode 100644 index 0000000000..ee568834f5 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-201-00002.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"72dff9a0-3030-7000-d664-eec808551372","SPClientServiceRequestDuration":"819","X-SharePointHealthScore":"0","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"[\r{\r\u0022SchemaVersion\u0022:\u002215.0.0.0\u0022,\u0022LibraryVersion\u0022:\u002216.0.24329.12007\u0022,\u0022ErrorInfo\u0022:null,\u0022TraceCorrelationId\u0022:\u002272dff9a0-3030-7000-d664-eec808551372\u0022\r},3,{\r\u0022_ObjectType_\u0022:\u0022Microsoft.Online.SharePoint.TenantAdministration.SpoOperation\u0022,\u0022_ObjectIdentity_\u0022:\u002272dff9a0-3030-7000-d664-eec808551372|908bed80-a04a-4433-b4a0-883d9847d110:6492ece7-7f5d-4499-8130-50e761e25bd9\\nSpoOperation\\nRemoveSite\\n638387491402003322\\nhttps%3a%2f%2fbertonline.sharepoint.com%2fsites%2fpnpcoresdktestcommsitee5c1e4eb821049dab80410a1e69f58e2\\nb3c93a74-48a0-47c8-89d8-96f24c5f49fb\u0022,\u0022PollingInterval\u0022:15000,\u0022IsComplete\u0022:true\r}\r]"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-301-00000.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-301-00000.response.json new file mode 100644 index 0000000000..258913595b --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-301-00000.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"72dff9a0-8022-7000-e61f-099149a16493","SPClientServiceRequestDuration":"10","X-SharePointHealthScore":"0","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022RegionalSettings\u0022:{\u0022TimeZone\u0022:{\u0022Description\u0022:\u0022(UTC\u002B02:00) Jerusalem\u0022,\u0022Id\u0022:27,\u0022Information\u0022:{\u0022Bias\u0022:-120,\u0022DaylightBias\u0022:-60,\u0022StandardBias\u0022:0}},\u0022AdjustHijriDays\u0022:0,\u0022AlternateCalendarType\u0022:0,\u0022AM\u0022:\u0022AM\u0022,\u0022CalendarType\u0022:1,\u0022Collation\u0022:25,\u0022CollationLCID\u0022:2070,\u0022DateFormat\u0022:0,\u0022DateSeparator\u0022:\u0022/\u0022,\u0022DecimalSeparator\u0022:\u0022.\u0022,\u0022DigitGrouping\u0022:\u00223;0\u0022,\u0022FirstDayOfWeek\u0022:0,\u0022FirstWeekOfYear\u0022:0,\u0022IsEastAsia\u0022:false,\u0022IsRightToLeft\u0022:false,\u0022IsUIRightToLeft\u0022:false,\u0022ListSeparator\u0022:\u0022,\u0022,\u0022LocaleId\u0022:1033,\u0022NegativeSign\u0022:\u0022-\u0022,\u0022NegNumberMode\u0022:1,\u0022PM\u0022:\u0022PM\u0022,\u0022PositiveSign\u0022:\u0022\u0022,\u0022ShowWeeks\u0022:false,\u0022ThousandSeparator\u0022:\u0022,\u0022,\u0022Time24\u0022:false,\u0022TimeMarkerPosition\u0022:0,\u0022TimeSeparator\u0022:\u0022:\u0022,\u0022WorkDayEndHour\u0022:1020,\u0022WorkDays\u0022:62,\u0022WorkDayStartHour\u0022:480},\u0022Id\u0022:\u00228fef796d-1c2e-481e-a950-9d08c7772624\u0022,\u0022Url\u0022:\u0022https://bertonline.sharepoint.com/sites/pnpcoresdktestcommsitee5c1e4eb821049dab80410a1e69f58e2\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-301-00001.response.json b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-301-00001.response.json new file mode 100644 index 0000000000..f66703f314 --- /dev/null +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/MockData/SiteManagerTests/SetSiteCollectionWithTimeZome-301-00001.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"72dff9a0-102a-7000-d664-eb9f30d65ed6","SPClientServiceRequestDuration":"8","X-SharePointHealthScore":"2","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022GroupId\u0022:\u002200000000-0000-0000-0000-000000000000\u0022,\u0022Id\u0022:\u0022b3c93a74-48a0-47c8-89d8-96f24c5f49fb\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Admin.Test/SharePoint/SiteManagerTests.cs b/src/sdk/PnP.Core.Admin.Test/SharePoint/SiteManagerTests.cs index 2a74b4e625..6f0644969b 100644 --- a/src/sdk/PnP.Core.Admin.Test/SharePoint/SiteManagerTests.cs +++ b/src/sdk/PnP.Core.Admin.Test/SharePoint/SiteManagerTests.cs @@ -1171,12 +1171,12 @@ await context.GetSiteCollectionManager().SetSiteCollectionAdminsAsync( [TestMethod] public async Task SetSiteCollectionWithTimeZome_Async() { - //Time zone object to test with - var selectedTimeZone = TimeZone.UTCPLUS0200_JERUSALEM; - //TestCommon.Instance.Mocking = false; TestCommon.Instance.UseApplicationPermissions = false; + //Time zone object to test with + var selectedTimeZone = TimeZone.UTCPLUS0200_JERUSALEM; + CommunicationSiteOptions communicationSiteToCreate = null; // Create the site collection @@ -1212,7 +1212,9 @@ public async Task SetSiteCollectionWithTimeZome_Async() UsingApplicationPermissions = false }; - var siteProperties = context.GetSiteCollectionManager().GetSiteCollectionProperties(context.Uri); + var createdSiteContext = await context.GetSiteCollectionManager().CreateSiteCollectionAsync(communicationSiteToCreate, siteCreationOptions); + + var siteProperties = context.GetSiteCollectionManager().GetSiteCollectionProperties(createdSiteContext.Uri); //Validating time zone set as expected Assert.IsTrue(siteProperties.TimeZoneId == selectedTimeZone); diff --git a/src/sdk/PnP.Core.Admin/Model/SharePoint/Core/Internal/SiteCollectionCreator.cs b/src/sdk/PnP.Core.Admin/Model/SharePoint/Core/Internal/SiteCollectionCreator.cs index 81512a92e5..537b3ab6f2 100644 --- a/src/sdk/PnP.Core.Admin/Model/SharePoint/Core/Internal/SiteCollectionCreator.cs +++ b/src/sdk/PnP.Core.Admin/Model/SharePoint/Core/Internal/SiteCollectionCreator.cs @@ -1,654 +1,654 @@ -using Microsoft.Extensions.Logging; -using PnP.Core.Admin.Model.Microsoft365; -using PnP.Core.Admin.Services.Core.CSOM.Requests.Tenant; -using PnP.Core.Admin.Utilities; -using PnP.Core.Model.Security; -using PnP.Core.Model.SharePoint; -using PnP.Core.Services; -using PnP.Core.Services.Core.CSOM.Requests; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Dynamic; -using System.Linq; -using System.Net.Http; -using System.Text.Json; -using System.Threading.Tasks; -using System.Web; - -namespace PnP.Core.Admin.Model.SharePoint -{ - internal static class SiteCollectionCreator - { - private enum SiteCreationModel - { - SPSiteManagerCreate, - GroupSiteManagerCreateGroupEx, - GroupSiteManagerCreateGroupForSite, - } - - internal static async Task CreateSiteCollectionAsync(PnPContext context, CommonSiteOptions siteToCreate, SiteCreationOptions creationOptions, VanityUrlOptions vanityUrlOptions) - { - // Provide default creation options as input - creationOptions = await EnsureSiteCreationOptionsAsync(context, creationOptions).ConfigureAwait(false); - - if (siteToCreate is ClassicSiteOptions classicSite) - { - return await CreateClassicSiteAsync(context, classicSite, creationOptions, vanityUrlOptions).ConfigureAwait(false); - } - else if (siteToCreate is TeamSiteOptions teamSite) - { - return await CreateTeamSiteAsync(context, teamSite, creationOptions).ConfigureAwait(false); - } - else if (siteToCreate is CommonNoGroupSiteOptions noGroupSite) - { - return await CreateCommonNoGroupSiteAsync(context, noGroupSite, creationOptions).ConfigureAwait(false); - } - - throw new ArgumentException("Provided site options are not implemented"); - } - - internal static async Task ConnectGroupToSiteAsync(PnPContext contextIn, ConnectSiteToGroupOptions siteToGroupify, CreationOptions creationOptions) - { - using (var context = await GetContextForGroupConnectAsync(contextIn, siteToGroupify.Url).ConfigureAwait(false)) - { - // Provide default creation options as input - creationOptions = await EnsureCreationOptionsAsync(context, creationOptions).ConfigureAwait(false); - - // SharePoint does not support group connecting via application permissions - if (creationOptions.UsingApplicationPermissions.Value) - { - throw new NotSupportedException("Group connecting sites using application permissions is not supported"); - } - else - { - var creationOptionsValues = new List(); - Dictionary payload = new Dictionary - { - { "displayName", siteToGroupify.DisplayName }, - { "alias", NormalizeSiteAlias(siteToGroupify.Alias) }, - { "isPublic", siteToGroupify.IsPublic } - }; - - var optionalParams = new Dictionary - { - { "Description", siteToGroupify.Description ?? "" } - }; - - // Sensitivity labels have replaced classification (see https://docs.microsoft.com/en-us/microsoft-365/compliance/sensitivity-labels-teams-groups-sites?view=o365-worldwide#classic-azure-ad-group-classification) - // once enabled. Therefore we prefer setting a sensitivity label id over classification when specified. Also note that for setting sensitivity labels on - // group connected sites one needs to have at least one Azure AD P1 license. See https://docs.microsoft.com/en-us/azure/active-directory/enterprise-users/groups-assign-sensitivity-labels - if (siteToGroupify.SensitivityLabelId != Guid.Empty) - { - creationOptionsValues.Add($"SensitivityLabel:{siteToGroupify.SensitivityLabelId}"); - } - else - { - optionalParams.Add("Classification", siteToGroupify.Classification ?? ""); - } - - if (siteToGroupify.Language != Language.Default) - { - creationOptionsValues.Add($"SPSiteLanguage:{(int)siteToGroupify.Language}"); - } - if (!string.IsNullOrEmpty(siteToGroupify.SiteAlias)) - { - creationOptionsValues.Add($"SiteAlias:{siteToGroupify.SiteAlias}"); - } - creationOptionsValues.Add($"HubSiteId:{siteToGroupify.HubSiteId}"); - - if (siteToGroupify.Owners != null && siteToGroupify.Owners.Length > 0) - { - var ownersBody = new - { - __metadata = new { type = "Collection(Edm.String)" }, - results = siteToGroupify.Owners - }.AsExpando(); - - optionalParams.Add("Owners", ownersBody); - } - if (siteToGroupify.PreferredDataLocation.HasValue) - { - optionalParams.Add("PreferredDataLocation", siteToGroupify.PreferredDataLocation.Value.ToString()); - } - - if (creationOptionsValues.Any()) - { - var creationOptionsValuesBody = new - { - __metadata = new { type = "Collection(Edm.String)" }, - results = creationOptionsValues - }.AsExpando(); - optionalParams.Add("CreationOptions", creationOptionsValuesBody); - } - - payload.Add("optionalParams", optionalParams); - - SiteCreationOptions siteCreationOptions = new SiteCreationOptions() - { - UsingApplicationPermissions = creationOptions.UsingApplicationPermissions, - MaxStatusChecks = creationOptions.MaxStatusChecks, - WaitAfterStatusCheck = creationOptions.WaitAfterStatusCheck, - }; - - // Delegated permissions can use the SharePoint endpoints for site collection creation - return await CreateSiteUsingSpoRestImplementationAsync(context, SiteCreationModel.GroupSiteManagerCreateGroupForSite, payload, siteCreationOptions).ConfigureAwait(false); - } - } - } - - private static async Task GetContextForGroupConnectAsync(PnPContext context, Uri url) - { - if (context.Uri == url) - { - return context; - } - else - { - return await context.CloneAsync(url).ConfigureAwait(false); - } - } - - private static async Task CreateCommonNoGroupSiteAsync(PnPContext context, CommonNoGroupSiteOptions siteToCreate, SiteCreationOptions creationOptions) - { - - if (string.IsNullOrEmpty(siteToCreate.Owner) && creationOptions.UsingApplicationPermissions.Value) - { - throw new ClientException(ErrorType.Unsupported, "You need to set an owner when using Application permissions to create a communication site"); - } - - var payload = BuildBaseCommonNoGroupSiteRequestPayload(siteToCreate); - - var siteDesignId = GetSiteDesignId(siteToCreate); - if (siteDesignId != Guid.Empty) - { - payload.Add("SiteDesignId", siteDesignId); - - // As per https://github.com/SharePoint/sp-dev-docs/issues/4810 the WebTemplateExtensionId property - // is what currently drives the application of a custom site design during the creation of a modern site. - payload["WebTemplateExtensionId"] = siteDesignId; - } - - payload.Add("HubSiteId", siteToCreate.HubSiteId); - - // Sensitivity labels have replaced classification (see https://docs.microsoft.com/en-us/microsoft-365/compliance/sensitivity-labels-teams-groups-sites?view=o365-worldwide#classic-azure-ad-group-classification) - // once enabled. Therefore we prefer setting a sensitivity label id over classification when specified. - if (siteToCreate.SensitivityLabelId != Guid.Empty) - { - payload.Add("SensitivityLabel", siteToCreate.SensitivityLabelId); - } - else - { - payload["Classification"] = siteToCreate.Classification ?? ""; - } - +using Microsoft.Extensions.Logging; +using PnP.Core.Admin.Model.Microsoft365; +using PnP.Core.Admin.Services.Core.CSOM.Requests.Tenant; +using PnP.Core.Admin.Utilities; +using PnP.Core.Model.Security; +using PnP.Core.Model.SharePoint; +using PnP.Core.Services; +using PnP.Core.Services.Core.CSOM.Requests; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Dynamic; +using System.Linq; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using System.Web; + +namespace PnP.Core.Admin.Model.SharePoint +{ + internal static class SiteCollectionCreator + { + private enum SiteCreationModel + { + SPSiteManagerCreate, + GroupSiteManagerCreateGroupEx, + GroupSiteManagerCreateGroupForSite, + } + + internal static async Task CreateSiteCollectionAsync(PnPContext context, CommonSiteOptions siteToCreate, SiteCreationOptions creationOptions, VanityUrlOptions vanityUrlOptions) + { + // Provide default creation options as input + creationOptions = await EnsureSiteCreationOptionsAsync(context, creationOptions).ConfigureAwait(false); + + if (siteToCreate is ClassicSiteOptions classicSite) + { + return await CreateClassicSiteAsync(context, classicSite, creationOptions, vanityUrlOptions).ConfigureAwait(false); + } + else if (siteToCreate is TeamSiteOptions teamSite) + { + return await CreateTeamSiteAsync(context, teamSite, creationOptions).ConfigureAwait(false); + } + else if (siteToCreate is CommonNoGroupSiteOptions noGroupSite) + { + return await CreateCommonNoGroupSiteAsync(context, noGroupSite, creationOptions).ConfigureAwait(false); + } + + throw new ArgumentException("Provided site options are not implemented"); + } + + internal static async Task ConnectGroupToSiteAsync(PnPContext contextIn, ConnectSiteToGroupOptions siteToGroupify, CreationOptions creationOptions) + { + using (var context = await GetContextForGroupConnectAsync(contextIn, siteToGroupify.Url).ConfigureAwait(false)) + { + // Provide default creation options as input + creationOptions = await EnsureCreationOptionsAsync(context, creationOptions).ConfigureAwait(false); + + // SharePoint does not support group connecting via application permissions + if (creationOptions.UsingApplicationPermissions.Value) + { + throw new NotSupportedException("Group connecting sites using application permissions is not supported"); + } + else + { + var creationOptionsValues = new List(); + Dictionary payload = new Dictionary + { + { "displayName", siteToGroupify.DisplayName }, + { "alias", NormalizeSiteAlias(siteToGroupify.Alias) }, + { "isPublic", siteToGroupify.IsPublic } + }; + + var optionalParams = new Dictionary + { + { "Description", siteToGroupify.Description ?? "" } + }; + + // Sensitivity labels have replaced classification (see https://docs.microsoft.com/en-us/microsoft-365/compliance/sensitivity-labels-teams-groups-sites?view=o365-worldwide#classic-azure-ad-group-classification) + // once enabled. Therefore we prefer setting a sensitivity label id over classification when specified. Also note that for setting sensitivity labels on + // group connected sites one needs to have at least one Azure AD P1 license. See https://docs.microsoft.com/en-us/azure/active-directory/enterprise-users/groups-assign-sensitivity-labels + if (siteToGroupify.SensitivityLabelId != Guid.Empty) + { + creationOptionsValues.Add($"SensitivityLabel:{siteToGroupify.SensitivityLabelId}"); + } + else + { + optionalParams.Add("Classification", siteToGroupify.Classification ?? ""); + } + + if (siteToGroupify.Language != Language.Default) + { + creationOptionsValues.Add($"SPSiteLanguage:{(int)siteToGroupify.Language}"); + } + if (!string.IsNullOrEmpty(siteToGroupify.SiteAlias)) + { + creationOptionsValues.Add($"SiteAlias:{siteToGroupify.SiteAlias}"); + } + creationOptionsValues.Add($"HubSiteId:{siteToGroupify.HubSiteId}"); + + if (siteToGroupify.Owners != null && siteToGroupify.Owners.Length > 0) + { + var ownersBody = new + { + __metadata = new { type = "Collection(Edm.String)" }, + results = siteToGroupify.Owners + }.AsExpando(); + + optionalParams.Add("Owners", ownersBody); + } + if (siteToGroupify.PreferredDataLocation.HasValue) + { + optionalParams.Add("PreferredDataLocation", siteToGroupify.PreferredDataLocation.Value.ToString()); + } + + if (creationOptionsValues.Any()) + { + var creationOptionsValuesBody = new + { + __metadata = new { type = "Collection(Edm.String)" }, + results = creationOptionsValues + }.AsExpando(); + optionalParams.Add("CreationOptions", creationOptionsValuesBody); + } + + payload.Add("optionalParams", optionalParams); + + SiteCreationOptions siteCreationOptions = new SiteCreationOptions() + { + UsingApplicationPermissions = creationOptions.UsingApplicationPermissions, + MaxStatusChecks = creationOptions.MaxStatusChecks, + WaitAfterStatusCheck = creationOptions.WaitAfterStatusCheck, + }; + + // Delegated permissions can use the SharePoint endpoints for site collection creation + return await CreateSiteUsingSpoRestImplementationAsync(context, SiteCreationModel.GroupSiteManagerCreateGroupForSite, payload, siteCreationOptions).ConfigureAwait(false); + } + } + } + + private static async Task GetContextForGroupConnectAsync(PnPContext context, Uri url) + { + if (context.Uri == url) + { + return context; + } + else + { + return await context.CloneAsync(url).ConfigureAwait(false); + } + } + + private static async Task CreateCommonNoGroupSiteAsync(PnPContext context, CommonNoGroupSiteOptions siteToCreate, SiteCreationOptions creationOptions) + { + + if (string.IsNullOrEmpty(siteToCreate.Owner) && creationOptions.UsingApplicationPermissions.Value) + { + throw new ClientException(ErrorType.Unsupported, "You need to set an owner when using Application permissions to create a communication site"); + } + + var payload = BuildBaseCommonNoGroupSiteRequestPayload(siteToCreate); + + var siteDesignId = GetSiteDesignId(siteToCreate); + if (siteDesignId != Guid.Empty) + { + payload.Add("SiteDesignId", siteDesignId); + + // As per https://github.com/SharePoint/sp-dev-docs/issues/4810 the WebTemplateExtensionId property + // is what currently drives the application of a custom site design during the creation of a modern site. + payload["WebTemplateExtensionId"] = siteDesignId; + } + + payload.Add("HubSiteId", siteToCreate.HubSiteId); + + // Sensitivity labels have replaced classification (see https://docs.microsoft.com/en-us/microsoft-365/compliance/sensitivity-labels-teams-groups-sites?view=o365-worldwide#classic-azure-ad-group-classification) + // once enabled. Therefore we prefer setting a sensitivity label id over classification when specified. + if (siteToCreate.SensitivityLabelId != Guid.Empty) + { + payload.Add("SensitivityLabel", siteToCreate.SensitivityLabelId); + } + else + { + payload["Classification"] = siteToCreate.Classification ?? ""; + } + if (siteToCreate.TimeZone.HasValue) { payload.Add("TimeZoneId", (int)siteToCreate.TimeZone.Value); - } - - - return await CreateSiteUsingSpoRestImplementationAsync(context, SiteCreationModel.SPSiteManagerCreate, payload, creationOptions).ConfigureAwait(false); - } - - private static async Task CreateTeamSiteAsync(PnPContext context, TeamSiteOptions siteToCreate, SiteCreationOptions creationOptions) - { - var newGroup = new GraphGroupOptions - { - DisplayName = siteToCreate.DisplayName, - MailNickname = siteToCreate.Alias, - MailEnabled = true, - Visibility = siteToCreate.IsPublic ? GroupVisibility.Public.ToString() : GroupVisibility.Private.ToString(), - GroupTypes = new List { "Unified" }, - Owners = siteToCreate.Owners, - Members = siteToCreate.Members, - ResourceBehaviorOptions = new List(), - CreationOptions = new List(), - }; - - if (!string.IsNullOrEmpty(siteToCreate.Description)) - { - newGroup.Description = siteToCreate.Description; - } - - if (siteToCreate.AllowOnlyMembersToPost.GetValueOrDefault(false)) - { - newGroup.ResourceBehaviorOptions.Add("AllowOnlyMembersToPost"); - } - - if (siteToCreate.CalendarMemberReadOnly.GetValueOrDefault(false)) - { - newGroup.ResourceBehaviorOptions.Add("CalendarMemberReadOnly"); - } - - if (siteToCreate.ConnectorsDisabled.GetValueOrDefault(false)) - { - newGroup.ResourceBehaviorOptions.Add("ConnectorsDisabled"); - } - - if (siteToCreate.HideGroupInOutlook.GetValueOrDefault(false)) - { - newGroup.ResourceBehaviorOptions.Add("HideGroupInOutlook"); - } - - if (siteToCreate.SubscribeMembersToCalendarEventsDisabled.GetValueOrDefault(false)) - { - newGroup.ResourceBehaviorOptions.Add("SubscribeMembersToCalendarEventsDisabled"); - } - - if (siteToCreate.SubscribeNewGroupMembers.GetValueOrDefault(false)) - { - newGroup.ResourceBehaviorOptions.Add("SubscribeNewGroupMembers"); - } - - if (siteToCreate.WelcomeEmailDisabled.GetValueOrDefault(false)) - { - newGroup.ResourceBehaviorOptions.Add("WelcomeEmailDisabled"); - } - - if (siteToCreate.PreferredDataLocation.HasValue) - { - newGroup.PreferredDataLocation = siteToCreate.PreferredDataLocation.Value.ToString(); - } - - if (!string.IsNullOrEmpty(siteToCreate.Classification)) - { - newGroup.Classification = siteToCreate.Classification; - } - - if (siteToCreate.SensitivityLabelId != Guid.Empty) - { - newGroup.CreationOptions.Add($"SensitivityLabel:{siteToCreate.SensitivityLabelId}"); - } - - if (siteToCreate.SiteDesignId.HasValue) - { - newGroup.CreationOptions.Add($"implicit_formula_292aa8a00786498a87a5ca52d9f4214a_{siteToCreate.SiteDesignId.Value.ToString("D").ToLower()}"); - } - if (siteToCreate.Language != Language.Default) - { - newGroup.CreationOptions.Add($"SPSiteLanguage:{(int)siteToCreate.Language}"); - } - if (!string.IsNullOrEmpty(siteToCreate.SiteAlias)) - { - newGroup.CreationOptions.Add($"SiteAlias:{siteToCreate.SiteAlias}"); - } - - newGroup.CreationOptions.Add($"HubSiteId:{siteToCreate.HubSiteId}"); - - Microsoft365.CreationOptions groupCreationOptions = new Microsoft365.CreationOptions - { - MaxStatusChecks = creationOptions.MaxStatusChecks, - WaitAfterStatusCheck = creationOptions.WaitAfterStatusCheck, - }; - - return await context.GetMicrosoft365Admin().CreateGroupAsync(newGroup, groupCreationOptions).ConfigureAwait(false); - } - - private static async Task CreateClassicSiteAsync(PnPContext context, ClassicSiteOptions siteToCreate, SiteCreationOptions creationOptions, VanityUrlOptions vanityUrlOptions) - { - using (var tenantAdminContext = await context.GetSharePointAdmin().GetTenantAdminCenterContextAsync(vanityUrlOptions).ConfigureAwait(false)) - { - string owner = siteToCreate.Owner; - var splitOwner = owner.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries); - if (splitOwner.Length == 3) - { - owner = splitOwner[2]; - } - - List> csomRequests = new List> - { - new CreateSiteRequest(siteToCreate.Url, siteToCreate.Title, owner, siteToCreate.WebTemplate, (int)siteToCreate.Language, (int)siteToCreate.TimeZone) - }; - - var result = await (tenantAdminContext.Web as Web).RawRequestAsync(new ApiCall(csomRequests), HttpMethod.Post).ConfigureAwait(false); - - SpoOperation op = result.ApiCall.CSOMRequests[0].Result as SpoOperation; - - if (!op.IsComplete) - { - await SiteCollectionManagement.WaitForSpoOperationCompleteAsync(tenantAdminContext, op).ConfigureAwait(false); - } - - return await context.CloneAsync(siteToCreate.Url).ConfigureAwait(false); - } - } - - private static async Task EnsureSiteCreationOptionsAsync(PnPContext context, SiteCreationOptions creationOptions) - { - if (creationOptions == null) - { - creationOptions = new SiteCreationOptions(); - } - - await ProcessCreationOptionsAsync(context, creationOptions).ConfigureAwait(false); - - // Configure the defaults for the wait on async provisioning complete - if (!creationOptions.MaxAsyncProvisioningStatusChecks.HasValue) - { - creationOptions.MaxAsyncProvisioningStatusChecks = 80; - } - if (!creationOptions.WaitAfterAsyncProvisioningStatusCheck.HasValue) - { - creationOptions.WaitAfterAsyncProvisioningStatusCheck = 15; - } - - return creationOptions; - } - - private static async Task EnsureCreationOptionsAsync(PnPContext context, CreationOptions creationOptions) - { - if (creationOptions == null) - { - creationOptions = new CreationOptions(); - } - - await ProcessCreationOptionsAsync(context, creationOptions).ConfigureAwait(false); - - return creationOptions; - } - - private static async Task ProcessCreationOptionsAsync(PnPContext context, CreationOptions creationOptions) - { - // Ensure there's a value set for UsingApplicationPermissions - if (!creationOptions.UsingApplicationPermissions.HasValue) - { - creationOptions.UsingApplicationPermissions = await context.GetMicrosoft365Admin().AccessTokenUsesApplicationPermissionsAsync().ConfigureAwait(false); - } - - // Configure the defaults for the status check - if (!creationOptions.MaxStatusChecks.HasValue) - { - creationOptions.MaxStatusChecks = 12; - } - if (!creationOptions.WaitAfterStatusCheck.HasValue) - { - creationOptions.WaitAfterStatusCheck = 10; - } - } - - private static async Task CreateSiteUsingSpoRestImplementationAsync(PnPContext context, SiteCreationModel siteCreationModel, Dictionary payload, SiteCreationOptions creationOptions) - { - string apiCall; - string body; - - if (siteCreationModel == SiteCreationModel.SPSiteManagerCreate) - { - apiCall = $"_api/SPSiteManager/Create"; - var json = new { request = payload }.AsExpando(); - body = JsonSerializer.Serialize(json, typeof(ExpandoObject)); - } - else if (siteCreationModel == SiteCreationModel.GroupSiteManagerCreateGroupEx) - { - apiCall = $"_api/GroupSiteManager/CreateGroupEx"; - body = JsonSerializer.Serialize(payload, PnPConstants.JsonSerializer_IgnoreNullValues_CamelCase); - } - else if (siteCreationModel == SiteCreationModel.GroupSiteManagerCreateGroupForSite) - { - apiCall = $"_api/GroupSiteManager/CreateGroupForSite"; - body = JsonSerializer.Serialize(payload, PnPConstants.JsonSerializer_IgnoreNullValues_CamelCase); - } - else - { - throw new ClientException(ErrorType.Unsupported, "The requested site creation model does not exist"); - } - - var result = await (context.Web as Web).RawRequestAsync(new ApiCall(apiCall, ApiType.SPORest, body), HttpMethod.Post).ConfigureAwait(false); - - var responseJson = JsonSerializer.Deserialize(result.Json); - - #region Json Response - /* - Success => SiteStatus = 2 - Provisioning => SiteStatus = 1 - Error => all other values - - { - "d": { - "Create": { - "__metadata": { - "type": "Microsoft.SharePoint.Portal.SPSiteCreationResponse" - }, - "SiteId": "12befc2b-4c17-46a4-985e-530e6745cf35", - "SiteStatus": 2, - "SiteUrl": "https://bertonline.sharepoint.com/sites/pnpcoresdktestcommsite1" - } - } - } - - */ - #endregion - - int siteStatus = responseJson.GetProperty("SiteStatus").GetInt32(); - - PnPContext responseContext; - if (siteStatus == 2) - { - // Site creation succeeded - responseContext = await context.CloneAsync(new Uri(responseJson.GetProperty("SiteUrl").ToString())).ConfigureAwait(false); - } - else if (siteStatus == 1) - { - Guid groupId = Guid.Empty; - if (siteCreationModel != SiteCreationModel.SPSiteManagerCreate) - { - groupId = responseJson.GetProperty("GroupId").GetGuid(); - } - - // Site creation in progress, let's wait for it to finish - responseContext = await VerifySiteStatusAsync(context, siteCreationModel != SiteCreationModel.SPSiteManagerCreate ? groupId.ToString() : payload["Url"].ToString(), - siteCreationModel, creationOptions.MaxStatusChecks.Value, creationOptions.WaitAfterStatusCheck.Value).ConfigureAwait(false); - } - else - { - // Something went wrong - throw new ClientException(ErrorType.SharePointRestServiceError, string.Format(PnPCoreAdminResources.Exception_SiteCreation, payload["Url"].ToString(), siteStatus)); - } - - // Apply our "wait" strategy - if (creationOptions.WaitAfterCreation.HasValue && creationOptions.WaitAfterCreation.Value > 0) - { - await responseContext.WaitAsync(TimeSpan.FromSeconds(creationOptions.WaitAfterCreation.Value)).ConfigureAwait(false); - } - else - { - if (creationOptions.WaitForAsyncProvisioning.HasValue && creationOptions.WaitForAsyncProvisioning.Value) - { - // Let's wait for the async provisioning of features, site scripts and content types to be done before we allow API's to further update the created site - await WaitForProvisioningToCompleteAsync(responseContext, creationOptions).ConfigureAwait(false); - } - } - - return responseContext; - } - - private static async Task WaitForProvisioningToCompleteAsync(PnPContext context, SiteCreationOptions creationOptions) - { - context.Logger.LogInformation($"Started waiting for the async provisioning of site {context.Uri} to be complete"); - - var stopwatch = new Stopwatch(); - stopwatch.Start(); - - bool isProvisioningComplete = false; - bool validatePendingWebTemplateExtensionCalled = false; - var retryAttempt = 1; - do - { - context.Logger.LogDebug($"Elapsed: {stopwatch.Elapsed:mm\\:ss\\.fff} | Attempt {retryAttempt}/{creationOptions.MaxAsyncProvisioningStatusChecks}"); - - if (retryAttempt > 1) - { - context.Logger.LogDebug($"Elapsed: {stopwatch.Elapsed:mm\\:ss\\.fff} | Waiting {creationOptions.WaitAfterAsyncProvisioningStatusCheck.Value} seconds"); - - await context.WaitAsync(TimeSpan.FromSeconds(creationOptions.WaitAfterAsyncProvisioningStatusCheck.Value)).ConfigureAwait(false); - } - - var web = await context.Web.GetAsync(p => p.IsProvisioningComplete).ConfigureAwait(false); - if (web.IsProvisioningComplete) - { - isProvisioningComplete = true; - } - - // We waited for more than 90 seconds - if (!isProvisioningComplete && !validatePendingWebTemplateExtensionCalled && retryAttempt * creationOptions.WaitAfterAsyncProvisioningStatusCheck.Value > 90) - { - context.Logger.LogDebug($"Calling ValidatePendingWebTemplateExtension for site {context.Uri}"); - - // Try "push" the process - await (context.Web as Web).RawRequestAsync( - new ApiCall("_api/Microsoft.Sharepoint.Utilities.WebTemplateExtensions.SiteScriptUtility.ValidatePendingWebTemplateExtension", ApiType.SPORest), - HttpMethod.Post).ConfigureAwait(false); - validatePendingWebTemplateExtensionCalled = true; - - context.Logger.LogDebug($"Calling ValidatePendingWebTemplateExtension for site {context.Uri} done"); - } - - retryAttempt++; - - } - while (!isProvisioningComplete && retryAttempt <= creationOptions.MaxAsyncProvisioningStatusChecks); - - stopwatch.Stop(); - - context.Logger.LogDebug($"Elapsed: {stopwatch.Elapsed:mm\\:ss\\.fff} | Finished"); - - if (!isProvisioningComplete) - { - // Bummer, sites seems to be still not ready...log a warning but let's not fail - context.Logger.LogWarning($"Async provisioning of site {context.Uri} did not complete in {stopwatch.Elapsed:mm\\:ss\\.fff}"); - } - else - { - context.Logger.LogInformation($"Async provisioning of site {context.Uri} is complete"); - } - } - - private static async Task VerifySiteStatusAsync(PnPContext context, string urlOrGroupToCheck, SiteCreationModel siteCreationModel, int maxStatusChecks, int waitAfterStatusCheck) - { - var siteCreated = false; - var siteUrl = string.Empty; - var statusCheckAttempt = 1; - int lastSiteStatus = -1; - - string apiCall; - - if (siteCreationModel == SiteCreationModel.SPSiteManagerCreate) - { - apiCall = $"_api/SPSiteManager/status?url='{HttpUtility.UrlEncode(urlOrGroupToCheck)}'"; - } - else - { - apiCall = $"_api/groupsitemanager/GetSiteStatus('{urlOrGroupToCheck}')"; - } - - do - { - if (statusCheckAttempt > 1) - { - await context.WaitAsync(TimeSpan.FromSeconds(statusCheckAttempt * waitAfterStatusCheck)).ConfigureAwait(false); - } - - try - { - var result = await (context.Web as Web).RawRequestAsync(new ApiCall(apiCall, ApiType.SPORest), HttpMethod.Get).ConfigureAwait(false); - var responseJson = JsonSerializer.Deserialize(result.Json); - - #region Json response - /* - { - "d": { - "Status": { - "__metadata": { - "type": "Microsoft.SharePoint.Portal.SPSiteCreationResponse" - }, - "SiteId": "b1ec46e2-c26a-423f-ab01-3aeb951c1c82", - "SiteStatus": 2, - "SiteUrl": "https://bertonline.sharepoint.com/sites/pnpcoresdktestcommsite1" - } - } - } - */ - #endregion - - int siteStatus = responseJson.GetProperty("SiteStatus").GetInt32(); - lastSiteStatus = siteStatus; - if (siteStatus == 2) - { - siteCreated = true; - siteUrl = responseJson.GetProperty("SiteUrl").GetString(); - } - } - catch (Exception ex) - { - // Log and eat exception here - context.Logger.LogWarning(PnPCoreAdminResources.Log_Warning_ExceptionWhileGettingSiteStatus, urlOrGroupToCheck, ex.ToString()); - } - - statusCheckAttempt++; - } - while (!siteCreated && statusCheckAttempt <= maxStatusChecks); - - if (siteCreated) - { - return await context.CloneAsync(new Uri(siteUrl)).ConfigureAwait(false); - } - else - { - throw new ClientException(ErrorType.SharePointRestServiceError, string.Format(PnPCoreAdminResources.Exception_SiteCreationStatusCheck, siteUrl, lastSiteStatus)); - } - } - - private static Dictionary BuildBaseCommonNoGroupSiteRequestPayload(CommonNoGroupSiteOptions siteCollectionCreationInformation) - { - return new Dictionary - { - { "Title", siteCollectionCreationInformation.Title }, - { "Lcid", (int)siteCollectionCreationInformation.Language }, - { "ShareByEmailEnabled", siteCollectionCreationInformation.ShareByEmailEnabled }, - { "Url", siteCollectionCreationInformation.Url }, - { "Classification", siteCollectionCreationInformation.Classification ?? "" }, - { "Description", siteCollectionCreationInformation.Description ?? "" }, - { "WebTemplate", siteCollectionCreationInformation.WebTemplate }, - { "WebTemplateExtensionId", Guid.Empty }, - { "Owner", siteCollectionCreationInformation.Owner } - }; - } - - private static Guid GetSiteDesignId(CommonNoGroupSiteOptions siteCollectionCreationInformation) - { - if (siteCollectionCreationInformation.SiteDesignId != Guid.Empty) - { - return siteCollectionCreationInformation.SiteDesignId; - } - else if (siteCollectionCreationInformation is CommunicationSiteOptions communicationSiteOptions) - { - switch (communicationSiteOptions.SiteDesign) - { - case CommunicationSiteDesign.Topic: - { - return Guid.Empty; - } - case CommunicationSiteDesign.Showcase: - { - return Guid.Parse("6142d2a0-63a5-4ba0-aede-d9fefca2c767"); - } - case CommunicationSiteDesign.Blank: - { - return Guid.Parse("f6cc5403-0d63-442e-96c0-285923709ffc"); - } - } - } - - return Guid.Empty; - } - - private static string NormalizeSiteAlias(string alias) - { - alias = NormalizeInput.RemoveUnallowedCharacters(alias); - alias = NormalizeInput.ReplaceAccentedCharactersWithLatin(alias); - return alias; - } - - - } -} + } + + + return await CreateSiteUsingSpoRestImplementationAsync(context, SiteCreationModel.SPSiteManagerCreate, payload, creationOptions).ConfigureAwait(false); + } + + private static async Task CreateTeamSiteAsync(PnPContext context, TeamSiteOptions siteToCreate, SiteCreationOptions creationOptions) + { + var newGroup = new GraphGroupOptions + { + DisplayName = siteToCreate.DisplayName, + MailNickname = siteToCreate.Alias, + MailEnabled = true, + Visibility = siteToCreate.IsPublic ? GroupVisibility.Public.ToString() : GroupVisibility.Private.ToString(), + GroupTypes = new List { "Unified" }, + Owners = siteToCreate.Owners, + Members = siteToCreate.Members, + ResourceBehaviorOptions = new List(), + CreationOptions = new List(), + }; + + if (!string.IsNullOrEmpty(siteToCreate.Description)) + { + newGroup.Description = siteToCreate.Description; + } + + if (siteToCreate.AllowOnlyMembersToPost.GetValueOrDefault(false)) + { + newGroup.ResourceBehaviorOptions.Add("AllowOnlyMembersToPost"); + } + + if (siteToCreate.CalendarMemberReadOnly.GetValueOrDefault(false)) + { + newGroup.ResourceBehaviorOptions.Add("CalendarMemberReadOnly"); + } + + if (siteToCreate.ConnectorsDisabled.GetValueOrDefault(false)) + { + newGroup.ResourceBehaviorOptions.Add("ConnectorsDisabled"); + } + + if (siteToCreate.HideGroupInOutlook.GetValueOrDefault(false)) + { + newGroup.ResourceBehaviorOptions.Add("HideGroupInOutlook"); + } + + if (siteToCreate.SubscribeMembersToCalendarEventsDisabled.GetValueOrDefault(false)) + { + newGroup.ResourceBehaviorOptions.Add("SubscribeMembersToCalendarEventsDisabled"); + } + + if (siteToCreate.SubscribeNewGroupMembers.GetValueOrDefault(false)) + { + newGroup.ResourceBehaviorOptions.Add("SubscribeNewGroupMembers"); + } + + if (siteToCreate.WelcomeEmailDisabled.GetValueOrDefault(false)) + { + newGroup.ResourceBehaviorOptions.Add("WelcomeEmailDisabled"); + } + + if (siteToCreate.PreferredDataLocation.HasValue) + { + newGroup.PreferredDataLocation = siteToCreate.PreferredDataLocation.Value.ToString(); + } + + if (!string.IsNullOrEmpty(siteToCreate.Classification)) + { + newGroup.Classification = siteToCreate.Classification; + } + + if (siteToCreate.SensitivityLabelId != Guid.Empty) + { + newGroup.CreationOptions.Add($"SensitivityLabel:{siteToCreate.SensitivityLabelId}"); + } + + if (siteToCreate.SiteDesignId.HasValue) + { + newGroup.CreationOptions.Add($"implicit_formula_292aa8a00786498a87a5ca52d9f4214a_{siteToCreate.SiteDesignId.Value.ToString("D").ToLower()}"); + } + if (siteToCreate.Language != Language.Default) + { + newGroup.CreationOptions.Add($"SPSiteLanguage:{(int)siteToCreate.Language}"); + } + if (!string.IsNullOrEmpty(siteToCreate.SiteAlias)) + { + newGroup.CreationOptions.Add($"SiteAlias:{siteToCreate.SiteAlias}"); + } + + newGroup.CreationOptions.Add($"HubSiteId:{siteToCreate.HubSiteId}"); + + Microsoft365.CreationOptions groupCreationOptions = new Microsoft365.CreationOptions + { + MaxStatusChecks = creationOptions.MaxStatusChecks, + WaitAfterStatusCheck = creationOptions.WaitAfterStatusCheck, + }; + + return await context.GetMicrosoft365Admin().CreateGroupAsync(newGroup, groupCreationOptions).ConfigureAwait(false); + } + + private static async Task CreateClassicSiteAsync(PnPContext context, ClassicSiteOptions siteToCreate, SiteCreationOptions creationOptions, VanityUrlOptions vanityUrlOptions) + { + using (var tenantAdminContext = await context.GetSharePointAdmin().GetTenantAdminCenterContextAsync(vanityUrlOptions).ConfigureAwait(false)) + { + string owner = siteToCreate.Owner; + var splitOwner = owner.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries); + if (splitOwner.Length == 3) + { + owner = splitOwner[2]; + } + + List> csomRequests = new List> + { + new CreateSiteRequest(siteToCreate.Url, siteToCreate.Title, owner, siteToCreate.WebTemplate, (int)siteToCreate.Language, (int)siteToCreate.TimeZone) + }; + + var result = await (tenantAdminContext.Web as Web).RawRequestAsync(new ApiCall(csomRequests), HttpMethod.Post).ConfigureAwait(false); + + SpoOperation op = result.ApiCall.CSOMRequests[0].Result as SpoOperation; + + if (!op.IsComplete) + { + await SiteCollectionManagement.WaitForSpoOperationCompleteAsync(tenantAdminContext, op).ConfigureAwait(false); + } + + return await context.CloneAsync(siteToCreate.Url).ConfigureAwait(false); + } + } + + private static async Task EnsureSiteCreationOptionsAsync(PnPContext context, SiteCreationOptions creationOptions) + { + if (creationOptions == null) + { + creationOptions = new SiteCreationOptions(); + } + + await ProcessCreationOptionsAsync(context, creationOptions).ConfigureAwait(false); + + // Configure the defaults for the wait on async provisioning complete + if (!creationOptions.MaxAsyncProvisioningStatusChecks.HasValue) + { + creationOptions.MaxAsyncProvisioningStatusChecks = 80; + } + if (!creationOptions.WaitAfterAsyncProvisioningStatusCheck.HasValue) + { + creationOptions.WaitAfterAsyncProvisioningStatusCheck = 15; + } + + return creationOptions; + } + + private static async Task EnsureCreationOptionsAsync(PnPContext context, CreationOptions creationOptions) + { + if (creationOptions == null) + { + creationOptions = new CreationOptions(); + } + + await ProcessCreationOptionsAsync(context, creationOptions).ConfigureAwait(false); + + return creationOptions; + } + + private static async Task ProcessCreationOptionsAsync(PnPContext context, CreationOptions creationOptions) + { + // Ensure there's a value set for UsingApplicationPermissions + if (!creationOptions.UsingApplicationPermissions.HasValue) + { + creationOptions.UsingApplicationPermissions = await context.GetMicrosoft365Admin().AccessTokenUsesApplicationPermissionsAsync().ConfigureAwait(false); + } + + // Configure the defaults for the status check + if (!creationOptions.MaxStatusChecks.HasValue) + { + creationOptions.MaxStatusChecks = 12; + } + if (!creationOptions.WaitAfterStatusCheck.HasValue) + { + creationOptions.WaitAfterStatusCheck = 10; + } + } + + private static async Task CreateSiteUsingSpoRestImplementationAsync(PnPContext context, SiteCreationModel siteCreationModel, Dictionary payload, SiteCreationOptions creationOptions) + { + string apiCall; + string body; + + if (siteCreationModel == SiteCreationModel.SPSiteManagerCreate) + { + apiCall = $"_api/SPSiteManager/Create"; + var json = new { request = payload }.AsExpando(); + body = JsonSerializer.Serialize(json, typeof(ExpandoObject)); + } + else if (siteCreationModel == SiteCreationModel.GroupSiteManagerCreateGroupEx) + { + apiCall = $"_api/GroupSiteManager/CreateGroupEx"; + body = JsonSerializer.Serialize(payload, PnPConstants.JsonSerializer_IgnoreNullValues_CamelCase); + } + else if (siteCreationModel == SiteCreationModel.GroupSiteManagerCreateGroupForSite) + { + apiCall = $"_api/GroupSiteManager/CreateGroupForSite"; + body = JsonSerializer.Serialize(payload, PnPConstants.JsonSerializer_IgnoreNullValues_CamelCase); + } + else + { + throw new ClientException(ErrorType.Unsupported, "The requested site creation model does not exist"); + } + + var result = await (context.Web as Web).RawRequestAsync(new ApiCall(apiCall, ApiType.SPORest, body), HttpMethod.Post).ConfigureAwait(false); + + var responseJson = JsonSerializer.Deserialize(result.Json); + + #region Json Response + /* + Success => SiteStatus = 2 + Provisioning => SiteStatus = 1 + Error => all other values + + { + "d": { + "Create": { + "__metadata": { + "type": "Microsoft.SharePoint.Portal.SPSiteCreationResponse" + }, + "SiteId": "12befc2b-4c17-46a4-985e-530e6745cf35", + "SiteStatus": 2, + "SiteUrl": "https://bertonline.sharepoint.com/sites/pnpcoresdktestcommsite1" + } + } + } + + */ + #endregion + + int siteStatus = responseJson.GetProperty("SiteStatus").GetInt32(); + + PnPContext responseContext; + if (siteStatus == 2) + { + // Site creation succeeded + responseContext = await context.CloneAsync(new Uri(responseJson.GetProperty("SiteUrl").ToString())).ConfigureAwait(false); + } + else if (siteStatus == 1) + { + Guid groupId = Guid.Empty; + if (siteCreationModel != SiteCreationModel.SPSiteManagerCreate) + { + groupId = responseJson.GetProperty("GroupId").GetGuid(); + } + + // Site creation in progress, let's wait for it to finish + responseContext = await VerifySiteStatusAsync(context, siteCreationModel != SiteCreationModel.SPSiteManagerCreate ? groupId.ToString() : payload["Url"].ToString(), + siteCreationModel, creationOptions.MaxStatusChecks.Value, creationOptions.WaitAfterStatusCheck.Value).ConfigureAwait(false); + } + else + { + // Something went wrong + throw new ClientException(ErrorType.SharePointRestServiceError, string.Format(PnPCoreAdminResources.Exception_SiteCreation, payload["Url"].ToString(), siteStatus)); + } + + // Apply our "wait" strategy + if (creationOptions.WaitAfterCreation.HasValue && creationOptions.WaitAfterCreation.Value > 0) + { + await responseContext.WaitAsync(TimeSpan.FromSeconds(creationOptions.WaitAfterCreation.Value)).ConfigureAwait(false); + } + else + { + if (creationOptions.WaitForAsyncProvisioning.HasValue && creationOptions.WaitForAsyncProvisioning.Value) + { + // Let's wait for the async provisioning of features, site scripts and content types to be done before we allow API's to further update the created site + await WaitForProvisioningToCompleteAsync(responseContext, creationOptions).ConfigureAwait(false); + } + } + + return responseContext; + } + + private static async Task WaitForProvisioningToCompleteAsync(PnPContext context, SiteCreationOptions creationOptions) + { + context.Logger.LogInformation($"Started waiting for the async provisioning of site {context.Uri} to be complete"); + + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + bool isProvisioningComplete = false; + bool validatePendingWebTemplateExtensionCalled = false; + var retryAttempt = 1; + do + { + context.Logger.LogDebug($"Elapsed: {stopwatch.Elapsed:mm\\:ss\\.fff} | Attempt {retryAttempt}/{creationOptions.MaxAsyncProvisioningStatusChecks}"); + + if (retryAttempt > 1) + { + context.Logger.LogDebug($"Elapsed: {stopwatch.Elapsed:mm\\:ss\\.fff} | Waiting {creationOptions.WaitAfterAsyncProvisioningStatusCheck.Value} seconds"); + + await context.WaitAsync(TimeSpan.FromSeconds(creationOptions.WaitAfterAsyncProvisioningStatusCheck.Value)).ConfigureAwait(false); + } + + var web = await context.Web.GetAsync(p => p.IsProvisioningComplete).ConfigureAwait(false); + if (web.IsProvisioningComplete) + { + isProvisioningComplete = true; + } + + // We waited for more than 90 seconds + if (!isProvisioningComplete && !validatePendingWebTemplateExtensionCalled && retryAttempt * creationOptions.WaitAfterAsyncProvisioningStatusCheck.Value > 90) + { + context.Logger.LogDebug($"Calling ValidatePendingWebTemplateExtension for site {context.Uri}"); + + // Try "push" the process + await (context.Web as Web).RawRequestAsync( + new ApiCall("_api/Microsoft.Sharepoint.Utilities.WebTemplateExtensions.SiteScriptUtility.ValidatePendingWebTemplateExtension", ApiType.SPORest), + HttpMethod.Post).ConfigureAwait(false); + validatePendingWebTemplateExtensionCalled = true; + + context.Logger.LogDebug($"Calling ValidatePendingWebTemplateExtension for site {context.Uri} done"); + } + + retryAttempt++; + + } + while (!isProvisioningComplete && retryAttempt <= creationOptions.MaxAsyncProvisioningStatusChecks); + + stopwatch.Stop(); + + context.Logger.LogDebug($"Elapsed: {stopwatch.Elapsed:mm\\:ss\\.fff} | Finished"); + + if (!isProvisioningComplete) + { + // Bummer, sites seems to be still not ready...log a warning but let's not fail + context.Logger.LogWarning($"Async provisioning of site {context.Uri} did not complete in {stopwatch.Elapsed:mm\\:ss\\.fff}"); + } + else + { + context.Logger.LogInformation($"Async provisioning of site {context.Uri} is complete"); + } + } + + private static async Task VerifySiteStatusAsync(PnPContext context, string urlOrGroupToCheck, SiteCreationModel siteCreationModel, int maxStatusChecks, int waitAfterStatusCheck) + { + var siteCreated = false; + var siteUrl = string.Empty; + var statusCheckAttempt = 1; + int lastSiteStatus = -1; + + string apiCall; + + if (siteCreationModel == SiteCreationModel.SPSiteManagerCreate) + { + apiCall = $"_api/SPSiteManager/status?url='{HttpUtility.UrlEncode(urlOrGroupToCheck)}'"; + } + else + { + apiCall = $"_api/groupsitemanager/GetSiteStatus('{urlOrGroupToCheck}')"; + } + + do + { + if (statusCheckAttempt > 1) + { + await context.WaitAsync(TimeSpan.FromSeconds(statusCheckAttempt * waitAfterStatusCheck)).ConfigureAwait(false); + } + + try + { + var result = await (context.Web as Web).RawRequestAsync(new ApiCall(apiCall, ApiType.SPORest), HttpMethod.Get).ConfigureAwait(false); + var responseJson = JsonSerializer.Deserialize(result.Json); + + #region Json response + /* + { + "d": { + "Status": { + "__metadata": { + "type": "Microsoft.SharePoint.Portal.SPSiteCreationResponse" + }, + "SiteId": "b1ec46e2-c26a-423f-ab01-3aeb951c1c82", + "SiteStatus": 2, + "SiteUrl": "https://bertonline.sharepoint.com/sites/pnpcoresdktestcommsite1" + } + } + } + */ + #endregion + + int siteStatus = responseJson.GetProperty("SiteStatus").GetInt32(); + lastSiteStatus = siteStatus; + if (siteStatus == 2) + { + siteCreated = true; + siteUrl = responseJson.GetProperty("SiteUrl").GetString(); + } + } + catch (Exception ex) + { + // Log and eat exception here + context.Logger.LogWarning(PnPCoreAdminResources.Log_Warning_ExceptionWhileGettingSiteStatus, urlOrGroupToCheck, ex.ToString()); + } + + statusCheckAttempt++; + } + while (!siteCreated && statusCheckAttempt <= maxStatusChecks); + + if (siteCreated) + { + return await context.CloneAsync(new Uri(siteUrl)).ConfigureAwait(false); + } + else + { + throw new ClientException(ErrorType.SharePointRestServiceError, string.Format(PnPCoreAdminResources.Exception_SiteCreationStatusCheck, siteUrl, lastSiteStatus)); + } + } + + private static Dictionary BuildBaseCommonNoGroupSiteRequestPayload(CommonNoGroupSiteOptions siteCollectionCreationInformation) + { + return new Dictionary + { + { "Title", siteCollectionCreationInformation.Title }, + { "Lcid", (int)siteCollectionCreationInformation.Language }, + { "ShareByEmailEnabled", siteCollectionCreationInformation.ShareByEmailEnabled }, + { "Url", siteCollectionCreationInformation.Url }, + { "Classification", siteCollectionCreationInformation.Classification ?? "" }, + { "Description", siteCollectionCreationInformation.Description ?? "" }, + { "WebTemplate", siteCollectionCreationInformation.WebTemplate }, + { "WebTemplateExtensionId", Guid.Empty }, + { "Owner", siteCollectionCreationInformation.Owner } + }; + } + + private static Guid GetSiteDesignId(CommonNoGroupSiteOptions siteCollectionCreationInformation) + { + if (siteCollectionCreationInformation.SiteDesignId != Guid.Empty) + { + return siteCollectionCreationInformation.SiteDesignId; + } + else if (siteCollectionCreationInformation is CommunicationSiteOptions communicationSiteOptions) + { + switch (communicationSiteOptions.SiteDesign) + { + case CommunicationSiteDesign.Topic: + { + return Guid.Empty; + } + case CommunicationSiteDesign.Showcase: + { + return Guid.Parse("6142d2a0-63a5-4ba0-aede-d9fefca2c767"); + } + case CommunicationSiteDesign.Blank: + { + return Guid.Parse("f6cc5403-0d63-442e-96c0-285923709ffc"); + } + } + } + + return Guid.Empty; + } + + private static string NormalizeSiteAlias(string alias) + { + alias = NormalizeInput.RemoveUnallowedCharacters(alias); + alias = NormalizeInput.ReplaceAccentedCharactersWithLatin(alias); + return alias; + } + + + } +}