/// <summary> /// Gets a list of the available site policies /// </summary> /// <param name="web">Web to operate on</param> /// <returns>A list of <see cref="SitePolicyEntity"/> objects</returns> public static List <SitePolicyEntity> GetSitePolicies(this Web web) { ClientObjectList <ProjectPolicy> sitePolicies = ProjectPolicy.GetProjectPolicies(web.Context, web); web.Context.Load(sitePolicies); web.Context.ExecuteQueryRetry(); List <SitePolicyEntity> policies = new List <SitePolicyEntity>(); if (sitePolicies != null && sitePolicies.Count > 0) { foreach (var policy in sitePolicies) { policies.Add(new SitePolicyEntity { Name = policy.Name, Description = policy.Description, EmailBody = policy.EmailBody, EmailBodyWithTeamMailbox = policy.EmailBodyWithTeamMailbox, EmailSubject = policy.EmailSubject }); } } return(policies); }
/// <summary> /// Apply a policy to a site /// </summary> /// <param name="web">Web to operate on</param> /// <param name="sitePolicy">Policy to apply</param> /// <returns>True if applied, false otherwise</returns> public static bool ApplySitePolicy(this Web web, string sitePolicy) { bool result = false; ClientObjectList <ProjectPolicy> sitePolicies = ProjectPolicy.GetProjectPolicies(web.Context, web); web.Context.Load(sitePolicies); web.Context.ExecuteQueryRetry(); if (sitePolicies != null && sitePolicies.Count > 0) { ProjectPolicy policyToApply = sitePolicies.FirstOrDefault(p => p.Name == sitePolicy); if (policyToApply != null) { ProjectPolicy.ApplyProjectPolicy(web.Context, web, policyToApply); web.Context.ExecuteQueryRetry(); result = true; } } return(result); }
public override TokenParser ProvisionObjects(Tenant tenant, Model.ProvisioningHierarchy hierarchy, string sequenceId, TokenParser tokenParser, ApplyConfiguration configuration) { using (var scope = new PnPMonitoredScope(CoreResources.Provisioning_ObjectHandlers_Provisioning)) { bool nowait = false; if (configuration != null) { nowait = configuration.Tenant.DoNotWaitForSitesToBeFullyCreated; } var sequence = hierarchy.Sequences.FirstOrDefault(s => s.ID == sequenceId); if (sequence != null) { var siteUrls = new Dictionary <Guid, string>(); TokenParser siteTokenParser = null; // CHANGED: To avoid issues with low privilege users ClientObjectList <Microsoft.Online.SharePoint.TenantManagement.ThemeProperties> tenantThemes = null; if (TenantExtensions.IsCurrentUserTenantAdmin((ClientContext)tenant.Context)) { tenantThemes = tenant.GetAllTenantThemes(); tenant.Context.Load(tenantThemes); tenant.Context.ExecuteQueryRetry(); } foreach (var sitecollection in sequence.SiteCollections) { var rootSiteUrl = tenant.Context.Url.Replace("-admin", ""); ClientContext rootSiteContext = tenant.Context.Clone(rootSiteUrl, configuration.AccessTokens); ClientContext siteContext = null; switch (sitecollection) { case TeamSiteCollection t: { TeamSiteCollectionCreationInformation siteInfo = new TeamSiteCollectionCreationInformation() { Alias = tokenParser.ParseString(t.Alias), DisplayName = tokenParser.ParseString(t.Title), Description = tokenParser.ParseString(t.Description), Classification = tokenParser.ParseString(t.Classification), IsPublic = t.IsPublic, Lcid = (uint)t.Language }; if (Guid.TryParse(t.SiteDesign, out Guid siteDesignId)) { siteInfo.SiteDesignId = siteDesignId; } var groupSiteInfo = Sites.SiteCollection.GetGroupInfoAsync(rootSiteContext, siteInfo.Alias).GetAwaiter().GetResult(); string graphAccessToken = null; if (groupSiteInfo == null) { if (PnPProvisioningContext.Current != null) { try { graphAccessToken = PnPProvisioningContext.Current.AcquireCookie(PnP.Framework.Utilities.Graph.GraphHelper.MicrosoftGraphBaseURI); } catch { graphAccessToken = PnPProvisioningContext.Current.AcquireToken(new Uri(PnP.Framework.Utilities.Graph.GraphHelper.MicrosoftGraphBaseURI).Authority, null); } } WriteMessage($"Creating Team Site {siteInfo.Alias}", ProvisioningMessageType.Progress); #pragma warning disable CS0618 siteContext = Sites.SiteCollection.Create(rootSiteContext, siteInfo, configuration.Tenant.DelayAfterModernSiteCreation, noWait: nowait, graphAccessToken: graphAccessToken); #pragma warning restore CS0618 } else { if (groupSiteInfo.ContainsKey("siteUrl")) { WriteMessage($"Using existing Team Site {siteInfo.Alias}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(groupSiteInfo["siteUrl"], configuration.AccessTokens); } } if (t.IsHubSite) { siteContext.Load(siteContext.Site, s => s.Id); siteContext.ExecuteQueryRetry(); RegisterAsHubSite(tenant, siteContext.Url, siteContext.Site.Id, t.HubSiteLogoUrl, t.HubSiteTitle, tokenParser); } if (!string.IsNullOrEmpty(t.Theme) && tenantThemes != null) { var parsedTheme = tokenParser.ParseString(t.Theme); if (tenantThemes.FirstOrDefault(th => th.Name == parsedTheme) != null) { tenant.SetWebTheme(parsedTheme, siteContext.Url); tenant.Context.ExecuteQueryRetry(); } else { WriteMessage($"Theme {parsedTheme} doesn't exist in the tenant, will not be applied", ProvisioningMessageType.Warning); } } if (siteContext.IsAppOnly() && string.IsNullOrEmpty(graphAccessToken) && (t.Teamify || t.HideTeamify)) { WriteMessage("Teamify and HideTeamify operation is not supported in App-only context", ProvisioningMessageType.Warning); } else if (siteContext.IsAppOnly() && !string.IsNullOrEmpty(graphAccessToken) && (t.Teamify || t.HideTeamify)) { try { if (t.Teamify) { siteContext.Site.EnsureProperty(s => s.GroupId); Graph.UnifiedGroupsUtility.CreateTeam(siteContext.Site.GroupId.ToString(), graphAccessToken).GetAwaiter().GetResult(); WriteMessage($"Teamifying the O365 group connected site at URL - {siteContext.Url}", ProvisioningMessageType.Progress); } } catch (Exception ex) { WriteMessage($"Teamifying site at URL - {siteContext.Url} failed due to an exception:- {ex.Message}", ProvisioningMessageType.Warning); } if (t.HideTeamify) { WriteMessage($"Teamifying prompt couldn't be hidden at site at URL - {siteContext.Url} in App-only context", ProvisioningMessageType.Warning); } } else { if (t.Teamify) { try { siteContext.TeamifyAsync().GetAwaiter().GetResult(); WriteMessage($"Teamifying the O365 group connected site at URL - {siteContext.Url}", ProvisioningMessageType.Progress); } catch (Exception ex) { WriteMessage($"Teamifying site at URL - {siteContext.Url} failed due to an exception:- {ex.Message}", ProvisioningMessageType.Warning); } } if (t.HideTeamify) { try { siteContext.HideTeamifyPromptAsync().GetAwaiter().GetResult(); WriteMessage($"Teamify prompt is now hidden for site at URL - {siteContext.Url}", ProvisioningMessageType.Progress); } catch (Exception ex) { WriteMessage($"Teamify prompt couldn't be hidden for site at URL - {siteContext.Url} due to an exception:- {ex.Message}", ProvisioningMessageType.Warning); } } } siteUrls.Add(t.Id, siteContext.Url); if (!string.IsNullOrEmpty(t.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, t.ProvisioningId, siteContext.Url)); siteContext.Web.EnsureProperty(w => w.Id); _additionalTokens.Add(new SequenceSiteIdToken(null, t.ProvisioningId, siteContext.Web.Id)); siteContext.Site.EnsureProperties(s => s.Id, s => s.GroupId); _additionalTokens.Add(new SequenceSiteCollectionIdToken(null, t.ProvisioningId, siteContext.Site.Id)); _additionalTokens.Add(new SequenceSiteGroupIdToken(null, t.ProvisioningId, siteContext.Site.GroupId)); } break; } case CommunicationSiteCollection c: { var siteUrl = tokenParser.ParseString(c.Url); if (!siteUrl.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase)) { // CHANGED: Modified to support low privilege users siteUrl = UrlUtility.Combine(rootSiteUrl, siteUrl); } CommunicationSiteCollectionCreationInformation siteInfo = new CommunicationSiteCollectionCreationInformation() { ShareByEmailEnabled = c.AllowFileSharingForGuestUsers, Classification = tokenParser.ParseString(c.Classification), Description = tokenParser.ParseString(c.Description), Lcid = (uint)c.Language, Owner = tokenParser.ParseString(c.Owner), Title = tokenParser.ParseString(c.Title), Url = siteUrl }; Guid siteDesignId; if (Guid.TryParse(c.SiteDesign, out siteDesignId)) { siteInfo.SiteDesignId = siteDesignId; } else if (Guid.TryParse(tokenParser.ParseString(c.SiteDesign), out siteDesignId)) { siteInfo.SiteDesignId = siteDesignId; } else { if (!string.IsNullOrEmpty(c.SiteDesign)) { siteInfo.SiteDesign = (CommunicationSiteDesign)Enum.Parse(typeof(CommunicationSiteDesign), c.SiteDesign); } else { siteInfo.SiteDesign = CommunicationSiteDesign.Showcase; } } // check if site exists var siteExistence = tenant.SiteExistsAnywhere(siteInfo.Url); if (siteExistence == SiteExistence.Yes) { WriteMessage($"Using existing Communications Site at {siteInfo.Url}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(siteInfo.Url, configuration.AccessTokens); } else if (siteExistence == SiteExistence.Recycled) { var errorMessage = $"The requested Communications Site at {siteInfo.Url} is in the Recycle Bin and cannot be created"; WriteMessage(errorMessage, ProvisioningMessageType.Error); throw new RecycledSiteException(errorMessage); } else { WriteMessage($"Creating Communications Site at {siteInfo.Url}", ProvisioningMessageType.Progress); #pragma warning disable CS0618 siteContext = Sites.SiteCollection.Create(rootSiteContext, siteInfo, configuration.Tenant.DelayAfterModernSiteCreation, noWait: nowait); #pragma warning restore CS0618 } if (c.IsHubSite) { siteContext.Load(siteContext.Site, s => s.Id); siteContext.ExecuteQueryRetry(); RegisterAsHubSite(tenant, siteInfo.Url, siteContext.Site.Id, c.HubSiteLogoUrl, c.HubSiteTitle, tokenParser); } if (!string.IsNullOrEmpty(c.Theme) && tenantThemes != null) { var parsedTheme = tokenParser.ParseString(c.Theme); if (tenantThemes.FirstOrDefault(th => th.Name == parsedTheme) != null) { tenant.SetWebTheme(parsedTheme, siteInfo.Url); tenant.Context.ExecuteQueryRetry(); } else { WriteMessage($"Theme {parsedTheme} doesn't exist in the tenant, will not be applied", ProvisioningMessageType.Warning); } } siteUrls.Add(c.Id, siteInfo.Url); if (!string.IsNullOrEmpty(c.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, c.ProvisioningId, siteInfo.Url)); siteContext.Web.EnsureProperty(w => w.Id); _additionalTokens.Add(new SequenceSiteIdToken(null, c.ProvisioningId, siteContext.Web.Id)); siteContext.Site.EnsureProperties(s => s.Id, s => s.GroupId); _additionalTokens.Add(new SequenceSiteCollectionIdToken(null, c.ProvisioningId, siteContext.Site.Id)); _additionalTokens.Add(new SequenceSiteGroupIdToken(null, c.ProvisioningId, siteContext.Site.GroupId)); } break; } case TeamNoGroupSiteCollection t: { var siteUrl = tokenParser.ParseString(t.Url); TeamNoGroupSiteCollectionCreationInformation siteInfo = new TeamNoGroupSiteCollectionCreationInformation() { Lcid = (uint)t.Language, Url = siteUrl, Title = tokenParser.ParseString(t.Title), Description = tokenParser.ParseString(t.Description), Owner = tokenParser.ParseString(t.Owner) }; // check if site exists var siteExistence = tenant.SiteExistsAnywhere(siteUrl); if (siteExistence == SiteExistence.Yes) { WriteMessage($"Using existing Team Site at {siteUrl}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(siteUrl, configuration.AccessTokens); } else if (siteExistence == SiteExistence.Recycled) { var errorMessage = $"The requested Team Site at {siteUrl} is in the Recycle Bin and cannot be created"; WriteMessage(errorMessage, ProvisioningMessageType.Error); throw new RecycledSiteException(errorMessage); } else { WriteMessage($"Creating Team Site with no Office 365 group at {siteUrl}", ProvisioningMessageType.Progress); #pragma warning disable CS0618 siteContext = Sites.SiteCollection.Create(rootSiteContext, siteInfo, configuration.Tenant.DelayAfterModernSiteCreation, noWait: nowait); #pragma warning restore CS0618 } if (t.Groupify) { if (string.IsNullOrEmpty(t.Alias)) { // We generate the alias, if it is missing t.Alias = t.Title.Replace(" ", string.Empty).ToLower(); } // In case we need to groupify the just created site var groupifyInformation = new TeamSiteCollectionGroupifyInformation { Alias = t.Alias, // Mandatory Classification = t.Classification, // Optional Description = t.Description, DisplayName = t.Title, HubSiteId = Guid.Empty, // Optional, so far we skip it IsPublic = t.IsPublic, // Mandatory KeepOldHomePage = t.KeepOldHomePage, // Optional, but we provide it Lcid = (uint)t.Language, Owners = new string[] { t.Owner }, }; tenant.GroupifySite(siteUrl, groupifyInformation); } if (t.IsHubSite) { siteContext.Load(siteContext.Site, s => s.Id); siteContext.ExecuteQueryRetry(); RegisterAsHubSite(tenant, siteContext.Url, siteContext.Site.Id, t.HubSiteLogoUrl, t.HubSiteTitle, tokenParser); } if (!string.IsNullOrEmpty(t.Theme) && tenantThemes != null) { var parsedTheme = tokenParser.ParseString(t.Theme); if (tenantThemes.FirstOrDefault(th => th.Name == parsedTheme) != null) { tenant.SetWebTheme(parsedTheme, siteContext.Url); tenant.Context.ExecuteQueryRetry(); } else { WriteMessage($"Theme {parsedTheme} doesn't exist in the tenant, will not be applied", ProvisioningMessageType.Warning); } } siteUrls.Add(t.Id, siteContext.Url); if (!string.IsNullOrEmpty(t.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, t.ProvisioningId, siteContext.Url)); siteContext.Web.EnsureProperty(w => w.Id); _additionalTokens.Add(new SequenceSiteIdToken(null, t.ProvisioningId, siteContext.Web.Id)); siteContext.Site.EnsureProperties(s => s.Id, s => s.GroupId); _additionalTokens.Add(new SequenceSiteCollectionIdToken(null, t.ProvisioningId, siteContext.Site.Id)); _additionalTokens.Add(new SequenceSiteGroupIdToken(null, t.ProvisioningId, siteContext.Site.GroupId)); } break; } } var web = siteContext.Web; if (siteTokenParser == null) { siteTokenParser = new TokenParser(tenant, hierarchy, configuration.ToApplyingInformation()); foreach (var token in _additionalTokens) { siteTokenParser.AddToken(token); // Add the token to the global token parser, too tokenParser.AddToken(token); } } foreach (var subsite in sitecollection.Sites) { var subSiteObject = (TeamNoGroupSubSite)subsite; web.EnsureProperties(w => w.Webs.IncludeWithDefaultProperties(), w => w.ServerRelativeUrl); siteTokenParser = CreateSubSites(hierarchy, siteTokenParser, sitecollection, siteContext, web, subSiteObject); } siteTokenParser = null; } // System.Threading.Thread.Sleep(TimeSpan.FromMinutes(10)); WriteMessage("Applying templates", ProvisioningMessageType.Progress); var currentSite = ""; var provisioningTemplateApplyingInformation = configuration.ToApplyingInformation(); provisioningTemplateApplyingInformation.ProgressDelegate = (string message, int step, int total) => { configuration.ProgressDelegate?.Invoke($"{currentSite} : {message}", step, total); }; foreach (var sitecollection in sequence.SiteCollections) { currentSite = sitecollection.ProvisioningId != null ? sitecollection.ProvisioningId : sitecollection.Title; siteUrls.TryGetValue(sitecollection.Id, out string siteUrl); if (siteUrl != null) { using (var clonedContext = tenant.Context.Clone(siteUrl, configuration.AccessTokens)) { var web = clonedContext.Web; foreach (var templateRef in sitecollection.Templates) { var provisioningTemplate = hierarchy.Templates.FirstOrDefault(t => t.Id == templateRef); if (provisioningTemplate != null) { provisioningTemplate.Connector = hierarchy.Connector; //if (siteTokenParser == null) //{ siteTokenParser = new TokenParser(web, provisioningTemplate, configuration.ToApplyingInformation()); foreach (var token in _additionalTokens) { siteTokenParser.AddToken(token); } //} //else //{ // siteTokenParser.Rebase(web, provisioningTemplate); //} WriteMessage($"Applying Template", ProvisioningMessageType.Progress); new SiteToTemplateConversion().ApplyRemoteTemplate(web, provisioningTemplate, provisioningTemplateApplyingInformation, true, siteTokenParser); } else { WriteMessage($"Referenced template ID {templateRef} not found", ProvisioningMessageType.Error); } } if (siteTokenParser == null) { siteTokenParser = new TokenParser(tenant, hierarchy, configuration.ToApplyingInformation()); foreach (var token in _additionalTokens) { siteTokenParser.AddToken(token); } } foreach (var subsite in sitecollection.Sites) { var subSiteObject = (TeamNoGroupSubSite)subsite; web.EnsureProperties(w => w.Webs.IncludeWithDefaultProperties(), w => w.ServerRelativeUrl); siteTokenParser = ApplySubSiteTemplates(hierarchy, siteTokenParser, sitecollection, clonedContext, web, subSiteObject, provisioningTemplateApplyingInformation); } if (sitecollection.IsHubSite) { RESTUtilities.ExecuteGetAsync(web, "/_api/web/hubsitedata(true)").GetAwaiter().GetResult(); } } } } } return(tokenParser); } }