public override void ProvisionObjects(Web web, ProvisioningTemplate template) { // if this is a sub site then we're not provisioning content types. Technically this can be done but it's not a recommended practice if (web.IsSubSite()) { return; } var existingCts = web.AvailableContentTypes; web.Context.Load(existingCts, cts => cts.Include(ct => ct.StringId)); web.Context.ExecuteQuery(); //TODO: Upgrade to SharePoint.Client v16.0 so refactoring can be done (uncomment following line when done!) //var existingCtsIds = existingCts.Select(cts => cts.StringId.ToLower()).ToList(); var existingCtsIds = existingCts.AsEnumerable().Select(cts => cts.StringId.ToLower()).ToList(); foreach (var ct in template.ContentTypes) { // find the id of the content type XDocument document = XDocument.Parse(ct.SchemaXml); var contentTypeId = document.Root.Attribute("ID").Value; if (!existingCtsIds.Contains(contentTypeId.ToLower())) { web.CreateContentTypeFromXMLString(ct.SchemaXml); existingCtsIds.Add(contentTypeId); } } }
public override ProvisioningTemplate CreateEntities(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { var context = web.Context as ClientContext; bool isSubSite = web.IsSubSite(); var webCustomActions = web.GetCustomActions(); var siteCustomActions = context.Site.GetCustomActions(); var customActions = new CustomActions(); foreach (var customAction in webCustomActions) { customActions.WebCustomActions.Add(CopyUserCustomAction(customAction)); } // if this is a sub site then we're not creating entities for site collection scoped custom actions if (!isSubSite) { foreach (var customAction in siteCustomActions) { customActions.SiteCustomActions.Add(CopyUserCustomAction(customAction)); } } template.CustomActions = customActions; // If a base template is specified then use that one to "cleanup" the generated template model if (creationInfo.BaseTemplate != null) { template = CleanupEntities(template, creationInfo.BaseTemplate, isSubSite); } return template; }
private ProvisioningTemplate CleanupEntities(ProvisioningTemplate template, ProvisioningTemplate baseTemplate, bool isSubSite) { if (!isSubSite) { foreach (var customAction in baseTemplate.CustomActions.SiteCustomActions) { int index = template.CustomActions.SiteCustomActions.FindIndex(f => f.Name.Equals(customAction.Name)); if (index > -1) { template.CustomActions.SiteCustomActions.RemoveAt(index); } } } foreach (var customAction in baseTemplate.CustomActions.WebCustomActions) { int index = template.CustomActions.WebCustomActions.FindIndex(f => f.Name.Equals(customAction.Name)); if (index > -1) { template.CustomActions.WebCustomActions.RemoveAt(index); } } return template; }
public override void ProvisionObjects(Web web, ProvisioningTemplate template) { // if this is a sub site then we're not provisioning fields. Technically this can be done but it's not a recommended practice if (web.IsSubSite()) { return; } var parser = new TokenParser(web); var existingFields = web.Fields; web.Context.Load(existingFields, fs => fs.Include(f => f.Id)); web.Context.ExecuteQuery(); //TODO: Upgrade to SharePoint.Client v16.0 so refactoring can be done (uncomment following line when done!) //var existingFieldIds = existingFields.Select(l => l.Id).ToList(); var existingFieldIds = existingFields.AsEnumerable().Select(l => l.Id).ToList(); var fields = template.SiteFields; foreach (var field in fields) { XDocument document = XDocument.Parse(field.SchemaXml); var fieldId = document.Root.Attribute("ID").Value; if (!existingFieldIds.Contains(Guid.Parse(fieldId))) { var fieldXml = parser.Parse(field.SchemaXml); web.Fields.AddFieldAsXml(fieldXml, false, AddFieldOptions.DefaultValue); web.Context.ExecuteQuery(); } } }
public override void ProvisionObjects(Web web, ProvisioningTemplate template) { TokenParser parser = new TokenParser(web); var context = web.Context as ClientContext; if (!web.IsPropertyAvailable("ServerRelativeUrl")) { context.Load(web, w => w.ServerRelativeUrl); context.ExecuteQuery(); } foreach (var file in template.Files) { var folderName = parser.Parse(file.Folder); if (folderName.ToLower().StartsWith((web.ServerRelativeUrl.ToLower()))) { folderName = folderName.Substring(web.ServerRelativeUrl.Length); } var folder = web.EnsureFolderPath(folderName); using (var stream = template.Connector.GetFileStream(file.Src)) { folder.UploadFile(file.Src, stream, true); } } }
public override ProvisioningTemplate CreateEntities(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { // if this is a sub site then we're not creating field entities. if (web.IsSubSite()) { return template; } var existingFields = web.Fields; web.Context.Load(existingFields, fs => fs.Include(f => f.Id, f => f.SchemaXml)); web.Context.ExecuteQuery(); foreach (var field in existingFields) { if (!BuiltInFieldId.Contains(field.Id)) { template.SiteFields.Add(new Field() { SchemaXml = field.SchemaXml }); } } // If a base template is specified then use that one to "cleanup" the generated template model if (creationInfo.BaseTemplate != null) { template = CleanupEntities(template, creationInfo.BaseTemplate); } return template; }
public override ProvisioningTemplate CreateEntities(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { // if this is a sub site then we're not creating content type entities. if (web.IsSubSite()) { return template; } var cts = web.ContentTypes; web.Context.Load(cts); web.Context.ExecuteQuery(); foreach (var ct in cts) { if (!BuiltInContentTypeId.Contains(ct.StringId)) { template.ContentTypes.Add(new Birchman.RemoteProvisioning.Domain.Model.ContentType() { SchemaXml = ct.SchemaXml }); } } // If a base template is specified then use that one to "cleanup" the generated template model if (creationInfo.BaseTemplate != null) { template = CleanupEntities(template, creationInfo.BaseTemplate); } return template; }
public override void Save(ProvisioningTemplate template) { if (template == null) { throw new ArgumentNullException("template"); } SaveToConnector(template, this.Identifier); }
public override ProvisioningTemplate CreateEntities(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { // If a base template is specified then use that one to "cleanup" the generated template model if (creationInfo.BaseTemplate != null) { template = CleanupEntities(template, creationInfo.BaseTemplate); } return template; }
public override void ProvisionObjects(Web web, ProvisioningTemplate template) { var context = web.Context as ClientContext; // if this is a sub site then we're not enabling the site collection scoped features if (!web.IsSubSite()) { var siteFeatures = template.Features.SiteFeatures; ProvisionFeaturesImplementation(context.Site, siteFeatures); } var webFeatures = template.Features.WebFeatures; ProvisionFeaturesImplementation(web, webFeatures); }
public override void ProvisionObjects(Web web, ProvisioningTemplate template) { var _ctx = web.Context as ClientContext; foreach(var _provider in template.Providers) { try { _extManager.ExecuteExtensibilityCallOut(_ctx, _provider, template); } catch(Exception ex) { Log.Error(Constants.LOGGING_SOURCE, ex.Message); } } }
public override void ProvisionObjects(Web web, ProvisioningTemplate template) { var context = web.Context as ClientContext; var site = context.Site; // if this is a sub site then we're not enabling the site collection scoped custom actions if (!web.IsSubSite()) { var siteCustomActions = template.CustomActions.SiteCustomActions; ProvisionCustomActionImplementation(site, siteCustomActions); } var webCustomActions = template.CustomActions.WebCustomActions; ProvisionCustomActionImplementation(web, webCustomActions); }
/// <summary> /// Actual implementation of the apply templates /// </summary> /// <param name="web"></param> /// <param name="template"></param> internal void ApplyRemoteTemplate(Web web, ProvisioningTemplate template) { // Site Security new ObjectSiteSecurity().ProvisionObjects(web, template); // Features new ObjectFeatures().ProvisionObjects(web, template); // Site Fields new ObjectField().ProvisionObjects(web, template); // Content Types new ObjectContentType().ProvisionObjects(web, template); // Lists new ObjectListInstance().ProvisionObjects(web, template); // Files new ObjectFiles().ProvisionObjects(web, template); // Custom actions new ObjectCustomActions().ProvisionObjects(web, template); // Composite look (commented) //new ObjectComposedLook().ProvisionObjects(web, template); // Property Bag Entries new ObjectPropertyBagEntry().ProvisionObjects(web, template); // Extensibility Provider CallOut the last thing we do. new ObjectExtensibilityProviders().ProvisionObjects(web, template); web.SetPropertyBagValue("_PnP_ProvisioningTemplateId", template.ID != null ? template.ID : ""); web.AddIndexedPropertyBagKey("_PnP_ProvisioningTemplateId"); ProvisioningTemplateInfo info = new ProvisioningTemplateInfo(); info.TemplateID = template.ID != null ? template.ID : ""; info.TemplateVersion = template.Version; info.TemplateSitePolicy = template.SitePolicy; info.Result = true; info.ProvisioningTime = DateTime.Now; var s = new JavaScriptSerializer(); string jsonInfo = s.Serialize(info); web.SetPropertyBagValue("_PnP_ProvisioningTemplateInfo", jsonInfo); }
private ProvisioningTemplate CleanupEntities(ProvisioningTemplate template, ProvisioningTemplate baseTemplate) { foreach (var ct in baseTemplate.ContentTypes) { XDocument xDoc = XDocument.Parse(ct.SchemaXml); var id = xDoc.Root.Attribute("ID") != null ? xDoc.Root.Attribute("ID").Value : null; if (id != null) { int index = template.ContentTypes.FindIndex(f => f.SchemaXml.IndexOf(id, StringComparison.InvariantCultureIgnoreCase) > -1); if (index > -1) { template.ContentTypes.RemoveAt(index); } } } return template; }
/// <summary> /// Method to Invoke Custom Provisioning Providers. /// Ensure the ClientContext is not dispose in the custom provider. /// </summary> /// <param name="ctx">Authenticated ClientContext that is passed to teh custom provider.</param> /// <param name="provider">A custom Extensibility Provisioning Provider</param> /// <param name="template">ProvisioningTemplate that is passed to the custom provider</param> /// <exception cref="ExtensiblityPipelineException"></exception> /// <exception cref="ArgumentException">Provider.Assembly or Provider.Type is NullOrWhiteSpace></exception> /// <exception cref="ArgumentNullException">ClientContext is Null></exception> public void ExecuteExtensibilityCallOut(ClientContext ctx, Provider provider, ProvisioningTemplate template) { var _loggingSource = "OfficeDevPnP.Core.Framework.Provisioning.Extensibility.ExtensibilityManager.ExecuteCallout"; if (ctx == null) { throw new ArgumentNullException(CoreResources.Provisioning_Extensibility_Pipeline_ClientCtxNull); } if (string.IsNullOrWhiteSpace(provider.Assembly)) { throw new ArgumentException(CoreResources.Provisioning_Extensibility_Pipeline_Missing_AssemblyName); } if(string.IsNullOrWhiteSpace(provider.Type)) { throw new ArgumentException(CoreResources.Provisioning_Extensibility_Pipeline_Missing_TypeName); } try { Log.Info(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_BeforeInvocation, provider.Assembly, provider.Type); var _instance = (IProvisioningExtensibilityProvider)Activator.CreateInstance(provider.Assembly, provider.Type).Unwrap(); _instance.ProcessRequest(ctx, template, provider.Configuration); Log.Info(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_Success, provider.Assembly, provider.Type); } catch(Exception ex) { string _message = string.Format( CoreResources.Provisioning_Extensibility_Pipeline_Exception, provider.Assembly, provider.Type, ex); Log.Error(_loggingSource, _message); throw new ExtensiblityPipelineException(_message, ex); } }
public override ProvisioningTemplate CreateEntities(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { var context = web.Context as ClientContext; bool isSubSite = web.IsSubSite(); var webFeatures = web.Features; var siteFeatures = context.Site.Features; context.Load(webFeatures, fs => fs.Include(f => f.DefinitionId)); if (!isSubSite) { context.Load(siteFeatures, fs => fs.Include(f => f.DefinitionId)); } context.ExecuteQuery(); var features = new Features(); foreach (var feature in webFeatures) { features.WebFeatures.Add(new Feature() { Deactivate = false, ID = feature.DefinitionId }); } // if this is a sub site then we're not creating site collection scoped feature entities if (!isSubSite) { foreach (var feature in siteFeatures) { features.SiteFeatures.Add(new Feature() { Deactivate = false, ID = feature.DefinitionId }); } } template.Features = features; // If a base template is specified then use that one to "cleanup" the generated template model if (creationInfo.BaseTemplate != null) { template = CleanupEntities(template, creationInfo.BaseTemplate, isSubSite); } return template; }
public override bool WillExtract(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { return(creationInfo.IncludeSearchConfiguration); }
/// <summary> /// Retrieves a file as a byte array from the connector. If the file name contains special characters (e.g. "%20") and cannot be retrieved, a workaround will be performed /// </summary> private static byte[] GetFileBytes(ProvisioningTemplate template, string fileName) { var container = String.Empty; if (fileName.Contains(@"\") || fileName.Contains(@"/")) { var tempFileName = fileName.Replace(@"/", @"\"); container = fileName.Substring(0, tempFileName.LastIndexOf(@"\")); fileName = fileName.Substring(tempFileName.LastIndexOf(@"\") + 1); } // add the default provided container (if any) if (!String.IsNullOrEmpty(container)) { if (!String.IsNullOrEmpty(template.Connector.GetContainer())) { if (container.StartsWith("/")) { container = container.TrimStart("/".ToCharArray()); } #if !NETSTANDARD2_0 if (template.Connector.GetType() == typeof(Connectors.AzureStorageConnector)) { if (template.Connector.GetContainer().EndsWith("/")) { container = $@"{template.Connector.GetContainer()}{container}"; } else { container = $@"{template.Connector.GetContainer()}/{container}"; } } else { container = $@"{template.Connector.GetContainer()}\{container}"; } #else container = $@"{template.Connector.GetContainer()}\{container}"; #endif } } else { container = template.Connector.GetContainer(); } var stream = template.Connector.GetFileStream(fileName, container); if (stream == null) { //Decode the URL and try again fileName = WebUtility.UrlDecode(fileName); stream = template.Connector.GetFileStream(fileName, container); } byte[] returnData; using (var memStream = new MemoryStream()) { stream.CopyTo(memStream); memStream.Position = 0; returnData = memStream.ToArray(); } return(returnData); }
public override bool WillExtract(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { // By default we don't extract the packages return(false); }
private static ProvisioningTemplate CleanupEntities(ProvisioningTemplate template, ProvisioningTemplate baseTemplate) { if (template.ComposedLook != null && baseTemplate.ComposedLook != null) { if (template.ComposedLook.Equals(baseTemplate.ComposedLook)) { template.ComposedLook = null; } } return(template); }
private TokenParser ProcessSiteDesigns(Web web, ProvisioningTemplate template, TokenParser parser, PnPMonitoredScope scope) { if (template.Tenant.SiteDesigns != null && template.Tenant.SiteDesigns.Any()) { using (var tenantContext = web.Context.Clone(web.GetTenantAdministrationUrl())) { var tenant = new Tenant(tenantContext); var existingDesigns = tenant.GetSiteDesigns(); tenantContext.Load(existingDesigns); tenantContext.ExecuteQueryRetry(); foreach (var siteDesign in template.Tenant.SiteDesigns) { var designTitle = parser.ParseString(siteDesign.Title); var designDescription = parser.ParseString(siteDesign.Description); var designPreviewImageUrl = parser.ParseString(siteDesign.PreviewImageUrl); var designPreviewImageAltText = parser.ParseString(siteDesign.PreviewImageAltText); var existingSiteDesign = existingDesigns.FirstOrDefault(d => d.Title == designTitle); if (existingSiteDesign == null) { TenantSiteDesignCreationInfo siteDesignCreationInfo = new TenantSiteDesignCreationInfo() { Title = designTitle, Description = designDescription, PreviewImageUrl = designPreviewImageUrl, PreviewImageAltText = designPreviewImageAltText, IsDefault = siteDesign.IsDefault, }; switch (siteDesign.WebTemplate) { case SiteDesignWebTemplate.TeamSite: { siteDesignCreationInfo.WebTemplate = "64"; break; } case SiteDesignWebTemplate.CommunicationSite: { siteDesignCreationInfo.WebTemplate = "68"; break; } } if (siteDesign.SiteScripts != null && siteDesign.SiteScripts.Any()) { List <Guid> ids = new List <Guid>(); foreach (var siteScriptRef in siteDesign.SiteScripts) { ids.Add(Guid.Parse(parser.ParseString(siteScriptRef))); } siteDesignCreationInfo.SiteScriptIds = ids.ToArray(); } var design = tenant.CreateSiteDesign(siteDesignCreationInfo); tenantContext.Load(design); tenantContext.ExecuteQueryRetry(); if (siteDesign.Grants != null && siteDesign.Grants.Any()) { foreach (var grant in siteDesign.Grants) { var rights = (TenantSiteDesignPrincipalRights)Enum.Parse(typeof(TenantSiteDesignPrincipalRights), grant.Right.ToString()); tenant.GrantSiteDesignRights(design.Id, new[] { grant.Principal }, rights); } tenantContext.ExecuteQueryRetry(); } parser.AddToken(new SiteDesignIdToken(web, design.Title, design.Id)); } else { if (siteDesign.Overwrite) { var existingId = existingSiteDesign.Id; existingSiteDesign = Tenant.GetSiteDesign(tenantContext, existingId); tenantContext.ExecuteQueryRetry(); existingSiteDesign.Title = designTitle; existingSiteDesign.Description = designDescription; existingSiteDesign.PreviewImageUrl = designPreviewImageUrl; existingSiteDesign.PreviewImageAltText = designPreviewImageAltText; existingSiteDesign.IsDefault = siteDesign.IsDefault; switch (siteDesign.WebTemplate) { case SiteDesignWebTemplate.TeamSite: { existingSiteDesign.WebTemplate = "64"; break; } case SiteDesignWebTemplate.CommunicationSite: { existingSiteDesign.WebTemplate = "68"; break; } } tenant.UpdateSiteDesign(existingSiteDesign); tenantContext.ExecuteQueryRetry(); var existingToken = parser.Tokens.OfType <SiteDesignIdToken>().FirstOrDefault(t => t.GetReplaceValue() == existingId.ToString()); if (existingToken != null) { parser.Tokens.Remove(existingToken); } parser.AddToken(new SiteScriptIdToken(web, designTitle, existingId)); if (siteDesign.Grants != null && siteDesign.Grants.Any()) { var existingRights = Tenant.GetSiteDesignRights(tenantContext, existingId); tenantContext.Load(existingRights); tenantContext.ExecuteQueryRetry(); foreach (var existingRight in existingRights) { Tenant.RevokeSiteDesignRights(tenantContext, existingId, new[] { existingRight.PrincipalName }); } foreach (var grant in siteDesign.Grants) { var rights = (TenantSiteDesignPrincipalRights)Enum.Parse(typeof(TenantSiteDesignPrincipalRights), grant.Right.ToString()); tenant.GrantSiteDesignRights(existingId, new[] { parser.ParseString(grant.Principal) }, rights); } tenantContext.ExecuteQueryRetry(); } } } } } } return(parser); }
/// <summary> /// Actual implementation of extracting configuration from existing site. /// </summary> /// <param name="web"></param> /// <param name="baseTemplate"></param> /// <returns></returns> internal ProvisioningTemplate GetRemoteTemplate(Web web, ProvisioningTemplateCreationInformation creationInfo) { // Create empty object ProvisioningTemplate template = new ProvisioningTemplate(); // Hookup connector, is handy when the generated template object is used to apply to another site template.Connector = creationInfo.FileConnector; // Get Security template = new ObjectSiteSecurity().CreateEntities(web, template, creationInfo); // Site Fields template = new ObjectField().CreateEntities(web, template, creationInfo); // Content Types template = new ObjectContentType().CreateEntities(web, template, creationInfo); // Get Lists template = new ObjectListInstance().CreateEntities(web, template, creationInfo); // Get custom actions template = new ObjectCustomActions().CreateEntities(web, template, creationInfo); // Get features template = new ObjectFeatures().CreateEntities(web, template, creationInfo); // Get composite look //template = new ObjectComposedLook().CreateEntities(web, template, creationInfo); // Get files template = new ObjectFiles().CreateEntities(web, template, creationInfo); // Get Property Bag Entries template = new ObjectPropertyBagEntry().CreateEntities(web, template, creationInfo); // In future we could just instantiate all objects which are inherited from object handler base dynamically // Set default values for Template ID and Version template.ID = String.Format("TEMPLATE-{0:N}", Guid.NewGuid()).ToUpper(); template.Version = 1; // Retrieve original Template ID and remove it from Property Bag Entries int provisioningTemplateIdIndex = template.PropertyBagEntries.FindIndex(f => f.Key.Equals("_PnP_ProvisioningTemplateId")); if (provisioningTemplateIdIndex > -1) { var templateId = template.PropertyBagEntries[provisioningTemplateIdIndex].Value; if (!String.IsNullOrEmpty(templateId)) { template.ID = templateId; } template.PropertyBagEntries.RemoveAt(provisioningTemplateIdIndex); } // Retrieve original Template Info and remove it from Property Bag Entries int provisioningTemplateInfoIndex = template.PropertyBagEntries.FindIndex(f => f.Key.Equals("_PnP_ProvisioningTemplateInfo")); if (provisioningTemplateInfoIndex > -1) { var jsonInfo = template.PropertyBagEntries[provisioningTemplateInfoIndex].Value; var s = new JavaScriptSerializer(); ProvisioningTemplateInfo info = s.Deserialize<ProvisioningTemplateInfo>(jsonInfo); // Override any previously defined Template ID, Version, and SitePolicy // with the one stored in the Template Info, if any if (!String.IsNullOrEmpty(info.TemplateID)) { template.ID = info.TemplateID; } if (!String.IsNullOrEmpty(info.TemplateSitePolicy)) { template.SitePolicy = info.TemplateSitePolicy; } if (info.TemplateVersion > 0) { template.Version = info.TemplateVersion; } template.PropertyBagEntries.RemoveAt(provisioningTemplateInfoIndex); } return template; }
private ProvisioningTemplate DetectComposedLook(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo, PnPMonitoredScope scope, SharePointConnector spConnector, SharePointConnector spConnectorRoot) { var theme = web.GetCurrentComposedLook(); if (theme != null) { if (creationInfo != null) { // Don't exclude the DesignPreviewThemedCssFolderUrl property bag, if any creationInfo.PropertyBagPropertiesToPreserve.Add("DesignPreviewThemedCssFolderUrl"); } template.ComposedLook.Name = theme.Name != null ? theme.Name : String.Empty; if (theme.IsCustomComposedLook) { // Set the URL pointers to files template.ComposedLook.BackgroundFile = FixFileUrl(Tokenize(theme.BackgroundImage, web.Url)); template.ComposedLook.ColorFile = FixFileUrl(Tokenize(theme.Theme, web.Url)); template.ComposedLook.FontFile = FixFileUrl(Tokenize(theme.Font, web.Url)); // Download files if this is root site, since theme files are only stored there if (!web.IsSubSite() && creationInfo != null && creationInfo.PersistBrandingFiles && creationInfo.FileConnector != null) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Creating_SharePointConnector); // Let's create a SharePoint connector since our files anyhow are in SharePoint at this moment // Download the theme/branding specific files DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, theme.BackgroundImage, scope); DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, theme.Theme, scope); DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, theme.Font, scope); } // Create file entries for the custom theme files, but only if it's a root site // If it's root site we do not extract or set theme files, since those are in the root of the site collection if (!web.IsSubSite()) { if (!string.IsNullOrEmpty(template.ComposedLook.BackgroundFile)) { template.Files.Add(GetComposedLookFile(template.ComposedLook.BackgroundFile)); } if (!string.IsNullOrEmpty(template.ComposedLook.ColorFile)) { template.Files.Add(GetComposedLookFile(template.ComposedLook.ColorFile)); } if (!string.IsNullOrEmpty(template.ComposedLook.FontFile)) { template.Files.Add(GetComposedLookFile(template.ComposedLook.FontFile)); } } // If a base template is specified then use that one to "cleanup" the generated template model if (creationInfo != null && creationInfo.BaseTemplate != null) { template = CleanupEntities(template, creationInfo.BaseTemplate); } } else { template.ComposedLook.BackgroundFile = ""; template.ComposedLook.ColorFile = ""; template.ComposedLook.FontFile = ""; } } else { template.ComposedLook = null; } return(template); }
public override ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { using (var scope = new PnPMonitoredScope(this.Name)) { // Extract the Home Page web.EnsureProperties(w => w.RootFolder.WelcomePage, w => w.ServerRelativeUrl, w => w.Url); var homepageUrl = web.RootFolder.WelcomePage; if (string.IsNullOrEmpty(homepageUrl)) { homepageUrl = "Default.aspx"; } var welcomePageUrl = UrlUtility.Combine(web.ServerRelativeUrl, homepageUrl); var file = web.GetFileByServerRelativeUrl(welcomePageUrl); try { var listItem = file.EnsureProperty(f => f.ListItemAllFields); if (listItem != null) { if (listItem.FieldValues.ContainsKey("WikiField") && listItem.FieldValues["WikiField"] != null) { // Wiki page var fullUri = new Uri(UrlUtility.Combine(web.Url, web.RootFolder.WelcomePage)); //var folderPath = fullUri.Segments.Take(fullUri.Segments.Count() - 1).ToArray().Aggregate((i, x) => i + x).TrimEnd('/'); //var fileName = fullUri.Segments[fullUri.Segments.Count() - 1]; var homeFile = web.GetFileByServerRelativeUrl(welcomePageUrl); var limitedWPManager = homeFile.GetLimitedWebPartManager(PersonalizationScope.Shared); web.Context.Load(limitedWPManager); //var webParts = web.GetWebParts(welcomePageUrl); var page = new Page() { Layout = WikiPageLayout.Custom, Overwrite = true, Url = Tokenize(fullUri.PathAndQuery, web.Url), }; var pageContents = listItem.FieldValues["WikiField"].ToString(); Regex regexClientIds = new Regex(@"id=\""div_(?<ControlId>(\w|\-)+)"); if (regexClientIds.IsMatch(pageContents)) { foreach (Match webPartMatch in regexClientIds.Matches(pageContents)) { String serverSideControlId = webPartMatch.Groups["ControlId"].Value; try { var serverSideControlIdToSearchFor = $"g_{serverSideControlId.Replace("-", "_")}"; var webPart = limitedWPManager.WebParts.GetByControlId(serverSideControlIdToSearchFor); web.Context.Load(webPart, wp => wp.Id, wp => wp.WebPart.Title, wp => wp.WebPart.ZoneIndex ); web.Context.ExecuteQueryRetry(); var webPartxml = TokenizeWebPartXml(web, web.GetWebPartXml(webPart.Id, welcomePageUrl)); page.WebParts.Add(new Model.WebPart() { Title = webPart.WebPart.Title, Contents = webPartxml, Order = (uint)webPart.WebPart.ZoneIndex, Row = 1, // By default we will create a onecolumn layout, add the webpart to it, and later replace the wikifield on the page to position the webparts correctly. Column = 1 // By default we will create a onecolumn layout, add the webpart to it, and later replace the wikifield on the page to position the webparts correctly. }); pageContents = Regex.Replace(pageContents, serverSideControlId, $"{{webpartid:{webPart.WebPart.Title}}}", RegexOptions.IgnoreCase); } catch (ServerException) { scope.LogWarning("Found a WebPart ID which is not available on the server-side. ID: {0}", serverSideControlId); } } } page.Fields.Add("WikiField", pageContents); template.Pages.Add(page); // Set the homepage if (template.WebSettings == null) { template.WebSettings = new WebSettings(); } template.WebSettings.WelcomePage = homepageUrl; } else if (listItem.FieldValues.ContainsKey("ClientSideApplicationId") && listItem.FieldValues["ClientSideApplicationId"] != null && listItem.FieldValues["ClientSideApplicationId"].ToString().ToLower() == "b6917cb1-93a0-4b97-a84d-7cf49975d4ec") { // this is a client side page, so let's skip it since it's handled by the Client Side Page contents handler } else { if (web.Context.HasMinimalServerLibraryVersion(Constants.MINIMUMZONEIDREQUIREDSERVERVERSION) || creationInfo.SkipVersionCheck) { // Not a wikipage template = GetFileContents(web, template, welcomePageUrl, creationInfo, scope); if (template.WebSettings == null) { template.WebSettings = new WebSettings(); } template.WebSettings.WelcomePage = homepageUrl; } else { WriteMessage( $"Page content export requires a server version that is newer than the current server. Server version is {web.Context.ServerLibraryVersion}, minimal required is {Constants.MINIMUMZONEIDREQUIREDSERVERVERSION}. Set SkipVersionCheck to true to override this check.", ProvisioningMessageType.Warning); scope.LogWarning("Page content export requires a server version that is newer than the current server. Server version is {0}, minimal required is {1}", web.Context.ServerLibraryVersion, Constants.MINIMUMZONEIDREQUIREDSERVERVERSION); } } } } catch (ServerException ex) { //ignore this error. The default page is not a page but a list view. if (ex.ServerErrorCode != -2146232832 && ex.HResult != -2146233088) { throw; } else { if (ex.HResult != -2146233088) { if (web.Context.HasMinimalServerLibraryVersion(Constants.MINIMUMZONEIDREQUIREDSERVERVERSION) || creationInfo.SkipVersionCheck) { // Page does not belong to a list, extract the file as is template = GetFileContents(web, template, welcomePageUrl, creationInfo, scope); if (template.WebSettings == null) { template.WebSettings = new WebSettings(); } template.WebSettings.WelcomePage = homepageUrl; } else { WriteMessage( $"Page content export requires a server version that is newer than the current server. Server version is {web.Context.ServerLibraryVersion}, minimal required is {Constants.MINIMUMZONEIDREQUIREDSERVERVERSION}. Set SkipVersionCheck to true to override this check.", ProvisioningMessageType.Warning); scope.LogWarning("Page content export requires a server version that is newer than the current server. Server version is {0}, minimal required is {1}", web.Context.ServerLibraryVersion, Constants.MINIMUMZONEIDREQUIREDSERVERVERSION); } } } } // If a base template is specified then use that one to "cleanup" the generated template model if (creationInfo.BaseTemplate != null) { template = CleanupEntities(template, creationInfo.BaseTemplate); } } return(template); }
private ProvisioningTemplate CleanupEntities(ProvisioningTemplate template, ProvisioningTemplate baseTemplate) { return(template); }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { // This handler only extracts contents and adds them to the Files and Pages collection. return(parser); }
private ProvisioningTemplate GetFileContents(Web web, ProvisioningTemplate template, string welcomePageUrl, ProvisioningTemplateCreationInformation creationInfo, PnPMonitoredScope scope) { var homepageUrl = web.RootFolder.WelcomePage; if (string.IsNullOrEmpty(homepageUrl)) { homepageUrl = "Default.aspx"; } var fullUri = new Uri(UrlUtility.Combine(web.Url, homepageUrl)); var folderPath = fullUri.Segments.Take(fullUri.Segments.Count() - 1).ToArray().Aggregate((i, x) => i + x).TrimEnd('/'); var fileName = fullUri.Segments[fullUri.Segments.Count() - 1]; var webParts = web.GetWebParts(welcomePageUrl); var file = web.GetFileByServerRelativeUrl(welcomePageUrl); file.EnsureProperty(f => f.Level); var containerPath = folderPath.StartsWith(web.ServerRelativeUrl) && web.ServerRelativeUrl != "/" ? folderPath.Substring(web.ServerRelativeUrl.Length) : folderPath; var container = containerPath.Trim('/').Replace("%20", " ").Replace("/", "\\"); var homeFile = new Model.File() { Folder = Tokenize(folderPath, web.Url), Src = !string.IsNullOrEmpty(container) ? $"{container}\\{fileName}" : fileName, Overwrite = true, Level = (Model.FileLevel)Enum.Parse(typeof(Model.FileLevel), file.Level.ToString()) }; // Add field values to file RetrieveFieldValues(web, file, homeFile); // Add WebParts to file foreach (var webPart in webParts) { var webPartxml = TokenizeWebPartXml(web, web.GetWebPartXml(webPart.Id, welcomePageUrl)); Model.WebPart newWp = new Model.WebPart() { Title = webPart.WebPart.Title, Row = (uint)webPart.WebPart.ZoneIndex, Order = (uint)webPart.WebPart.ZoneIndex, Contents = webPartxml }; #if !SP2016 // As long as we've no CSOM library that has the ZoneID we can't use the version check as things don't compile... if (web.Context.HasMinimalServerLibraryVersion(Constants.MINIMUMZONEIDREQUIREDSERVERVERSION)) { newWp.Zone = webPart.ZoneId; } #endif homeFile.WebParts.Add(newWp); } template.Files.Add(homeFile); // Persist file using connector if (creationInfo.PersistBrandingFiles) { PersistFile(web, creationInfo, scope, folderPath, fileName); } return(template); }
/// <summary> /// Method to Invoke Custom Provisioning Token Providers which implement the IProvisioningExtensibilityTokenProvider interface. /// Ensure the ClientContext is not disposed in the custom provider. /// </summary> /// <param name="ctx">Authenticated ClientContext that is passed to the custom provider.</param> /// <param name="provider">A custom Extensibility Provisioning Provider</param> /// <param name="template">ProvisioningTemplate that is passed to the custom provider</param> /// <exception cref="ExtensiblityPipelineException"></exception> /// <exception cref="ArgumentException">Provider.Assembly or Provider.Type is NullOrWhiteSpace></exception> /// <exception cref="ArgumentNullException">ClientContext is Null></exception> public IEnumerable <TokenDefinition> ExecuteTokenProviderCallOut(ClientContext ctx, ExtensibilityHandler provider, ProvisioningTemplate template) { var _loggingSource = "PnP.Framework.Provisioning.Extensibility.ExtensibilityManager.ExecuteTokenProviderCallOut"; if (ctx == null) { throw new ArgumentNullException(nameof(ctx), CoreResources.Provisioning_Extensibility_Pipeline_ClientCtxNull); } if (string.IsNullOrWhiteSpace(provider.Assembly)) { throw new ArgumentException(String.Format("{0}.{1}", nameof(provider), nameof(provider.Assembly)), CoreResources.Provisioning_Extensibility_Pipeline_Missing_AssemblyName); } if (string.IsNullOrWhiteSpace(provider.Type)) { throw new ArgumentException(String.Format("{0}.{1}", nameof(provider), nameof(provider.Type)), CoreResources.Provisioning_Extensibility_Pipeline_Missing_TypeName); } try { var providerInstance = GetProviderInstance(provider); var extensibilityTokenProviderInstance = providerInstance as IProvisioningExtensibilityTokenProvider; if (extensibilityTokenProviderInstance != null) { Log.Info(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_BeforeInvocation, provider.Assembly, provider.Type); var tokens = extensibilityTokenProviderInstance.GetTokens(ctx, template, provider.Configuration); Log.Info(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_Success, provider.Assembly, provider.Type); return(tokens); } else if (providerInstance != null) { throw new ArgumentOutOfRangeException(nameof(provider), string.Format(CoreResources.Provisioning_Extensibility_Invalid_Handler_Implementation, this.GetType().Assembly.GetName().Version.ToString(), provider.Assembly, provider.Type)); } return(new List <TokenDefinition>()); } catch (Exception ex) { Log.Error(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_Exception, provider.Assembly, provider.Type, ex); string _message = string.Format( CoreResources.Provisioning_Extensibility_Pipeline_Exception, provider.Assembly, provider.Type, ex); throw new ExtensiblityPipelineException(_message, ex); } }
/// <summary> /// Method to Invoke Custom Extraction Handlers. /// </summary> /// <remarks> /// Ensure the ClientContext is not disposed in the custom provider. /// </remarks> /// <param name="ctx">Authenticated ClientContext that is passed to the custom provider.</param> /// <param name="handler">A custom Extensibility Provisioning Provider</param> /// <param name="template">ProvisioningTemplate that is passed to the custom provider</param> /// <param name="creationInformation">The Provisioning Template creation information object</param> /// <param name="scope">The PnPMonitoredScope of the current step in the pipeline</param> /// <exception cref="ExtensiblityPipelineException"></exception> /// <exception cref="ArgumentException">Provider.Assembly or Provider.Type is NullOrWhiteSpace></exception> /// <exception cref="ArgumentNullException">ClientContext is Null></exception> public ProvisioningTemplate ExecuteExtensibilityExtractionCallOut(ClientContext ctx, ExtensibilityHandler handler, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInformation, PnPMonitoredScope scope) { var _loggingSource = "PnP.Framework.Provisioning.Extensibility.ExtensibilityManager.ExecuteCallout"; if (ctx == null) { throw new ArgumentNullException(nameof(ctx), CoreResources.Provisioning_Extensibility_Pipeline_ClientCtxNull); } if (string.IsNullOrWhiteSpace(handler.Assembly)) { throw new ArgumentException(String.Format("{0}.{1}", nameof(handler), nameof(handler.Assembly)), CoreResources.Provisioning_Extensibility_Pipeline_Missing_AssemblyName); } if (string.IsNullOrWhiteSpace(handler.Type)) { throw new ArgumentException(String.Format("{0}.{1}", nameof(handler), nameof(handler.Type)), CoreResources.Provisioning_Extensibility_Pipeline_Missing_TypeName); } ProvisioningTemplate parsedTemplate = null; try { var _instance = GetProviderInstance(handler); if (_instance is IProvisioningExtensibilityHandler) { Log.Info(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_BeforeInvocation, handler.Assembly, handler.Type); parsedTemplate = (_instance as IProvisioningExtensibilityHandler).Extract(ctx, template, creationInformation, scope, handler.Configuration); Log.Info(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_Success, handler.Assembly, handler.Type); } else if (_instance != null && !(_instance is IProvisioningExtensibilityTokenProvider)) { throw new ArgumentOutOfRangeException(nameof(handler), string.Format(CoreResources.Provisioning_Extensibility_Invalid_Handler_Implementation, this.GetType().Assembly.GetName().Version.ToString(), handler.Assembly, handler.Type)); } else { parsedTemplate = template; } } catch (Exception ex) { Log.Error(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_Exception, handler.Assembly, handler.Type, ex); string _message = string.Format( CoreResources.Provisioning_Extensibility_Pipeline_Exception, handler.Assembly, handler.Type, ex); throw new ExtensiblityPipelineException(_message, ex); } return(parsedTemplate); }
/// <summary> /// Method to Invoke Custom Provisioning Handlers. /// </summary> /// <remarks> /// Ensure the ClientContext is not disposed in the custom provider. /// </remarks> /// <param name="ctx">Authenticated ClientContext that is passed to the custom provider.</param> /// <param name="handler">A custom Extensibility Provisioning Provider</param> /// <param name="template">ProvisioningTemplate that is passed to the custom provider</param> /// <param name="applyingInformation">The Provisioning Template application information object</param> /// <param name="tokenParser">The Token Parser used by the engine during template provisioning</param> /// <param name="scope">The PnPMonitoredScope of the current step in the pipeline</param> /// <exception cref="ExtensiblityPipelineException"></exception> /// <exception cref="ArgumentException">Provider.Assembly or Provider.Type is NullOrWhiteSpace></exception> /// <exception cref="ArgumentNullException">ClientContext is Null></exception> public void ExecuteExtensibilityProvisionCallOut(ClientContext ctx, ExtensibilityHandler handler, ProvisioningTemplate template, ProvisioningTemplateApplyingInformation applyingInformation, TokenParser tokenParser, PnPMonitoredScope scope) { var _loggingSource = "PnP.Framework.Provisioning.Extensibility.ExtensibilityManager.ExecuteCallout"; if (ctx == null) { throw new ArgumentNullException(nameof(ctx), CoreResources.Provisioning_Extensibility_Pipeline_ClientCtxNull); } if (string.IsNullOrWhiteSpace(handler.Assembly)) { throw new ArgumentException(String.Format("{0}.{1}", nameof(handler), nameof(handler.Type)), CoreResources.Provisioning_Extensibility_Pipeline_Missing_AssemblyName); } if (string.IsNullOrWhiteSpace(handler.Type)) { throw new ArgumentException(String.Format("{0}.{1}", nameof(handler), nameof(handler.Type)), CoreResources.Provisioning_Extensibility_Pipeline_Missing_TypeName); } try { var _instance = GetProviderInstance(handler); #pragma warning disable 618 if (_instance is IProvisioningExtensibilityProvider) #pragma warning restore 618 { Log.Info(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_BeforeInvocation, handler.Assembly, handler.Type); #pragma warning disable 618 (_instance as IProvisioningExtensibilityProvider).ProcessRequest(ctx, template, handler.Configuration); #pragma warning restore 618 Log.Info(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_Success, handler.Assembly, handler.Type); } else if (_instance is IProvisioningExtensibilityHandler) { Log.Info(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_BeforeInvocation, handler.Assembly, handler.Type); (_instance as IProvisioningExtensibilityHandler).Provision(ctx, template, applyingInformation, tokenParser, scope, handler.Configuration); Log.Info(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_Success, handler.Assembly, handler.Type); } else if (_instance != null && !(_instance is IProvisioningExtensibilityTokenProvider)) { throw new ArgumentOutOfRangeException(nameof(handler), string.Format(CoreResources.Provisioning_Extensibility_Invalid_Handler_Implementation, this.GetType().Assembly.GetName().Version.ToString(), handler.Assembly, handler.Type)); } } catch (Exception ex) { Log.Error(_loggingSource, CoreResources.Provisioning_Extensibility_Pipeline_Exception, handler.Assembly, handler.Type, ex); string _message = string.Format( CoreResources.Provisioning_Extensibility_Pipeline_Exception, handler.Assembly, handler.Type, ex); throw new ExtensiblityPipelineException(_message, ex); } }
public override ProvisioningTemplate CreateEntities(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { if (!web.IsPropertyAvailable("ServerRelativeUrl")) { web.Context.Load(web, w => w.ServerRelativeUrl); web.Context.ExecuteQuery(); } var serverRelativeUrl = web.ServerRelativeUrl; // For each list in the site ListCollection lists = web.Lists; web.Context.Load(lists, lc => lc.IncludeWithDefaultProperties(l => l.ContentTypes, l => l.Views, l => l.RootFolder.ServerRelativeUrl, l => l.Fields)); web.Context.ExecuteQuery(); foreach (var item in lists) { // Do not export system lists if (!item.Hidden) { int index = -1; if (creationInfo.BaseTemplate != null) { // Check if we need to skip this list...if so let's do it before we gather all the other information for this list...improves perf index = creationInfo.BaseTemplate.Lists.FindIndex(f => f.Url.Equals(item.RootFolder.ServerRelativeUrl.Substring(serverRelativeUrl.Length)) && f.TemplateType.Equals(item.BaseTemplate)); } if (index == -1) { var contentTypeFields = new List<FieldRef>(); ListInstance list = new ListInstance(); list.Description = item.Description; list.EnableVersioning = item.EnableVersioning; list.TemplateType = item.BaseTemplate; list.Title = item.Title; list.Hidden = item.Hidden; list.DocumentTemplate = Tokenize(item.DocumentTemplateUrl, web.Url); list.ContentTypesEnabled = item.ContentTypesEnabled; list.Url = item.RootFolder.ServerRelativeUrl.Substring(serverRelativeUrl.Length).TrimStart('/'); int count = 0; foreach (var ct in item.ContentTypes) { web.Context.Load(ct, c => c.Parent); web.Context.ExecuteQuery(); if (ct.Parent != null) { // Add the parent to the list of content types if (!BuiltInContentTypeId.Contains(ct.Parent.StringId)) { list.ContentTypeBindings.Add(new ContentTypeBinding() {ContentTypeID = ct.Parent.StringId, Default = count == 0 ? true : false}); } } else { list.ContentTypeBindings.Add(new ContentTypeBinding() {ContentTypeID = ct.StringId, Default = count == 0}); } web.Context.Load(ct.FieldLinks); web.Context.ExecuteQuery(); foreach (var fieldLink in ct.FieldLinks) { if (!fieldLink.Hidden) { contentTypeFields.Add(new FieldRef() { ID = fieldLink.Id }); } } count++; } foreach (var view in item.Views) { if (!view.Hidden) { list.Views.Add(new View() { SchemaXml = view.ListViewXml }); } } var siteColumns = web.Fields; web.Context.Load(siteColumns, scs => scs.Include(sc => sc.Id)); web.Context.ExecuteQuery(); foreach (var field in item.Fields) { if (!field.Hidden) { if (siteColumns.FirstOrDefault(sc => sc.Id == field.Id) != null) { if (contentTypeFields.FirstOrDefault(c => c.ID == field.Id) == null) { list.FieldRefs.Add(new FieldRef() { ID = field.Id }); } } else { list.Fields.Add((new Model.Field() { SchemaXml = field.SchemaXml })); } } } template.Lists.Add(list); } } } return template; }
public override void ProvisionObjects(Web web, ProvisioningTemplate template) { Log.Info(Constants.LOGGING_SOURCE_FRAMEWORK_PROVISIONING, CoreResources.Provisioning_ObjectHandlers_Pages); var context = web.Context as ClientContext; if (!web.IsPropertyAvailable("ServerRelativeUrl")) { context.Load(web, w => w.ServerRelativeUrl); context.ExecuteQueryRetry(); } foreach (var page in template.Pages) { var url = page.Url.ToParsedString(); if (!url.ToLower().StartsWith(web.ServerRelativeUrl.ToLower())) { url = UrlUtility.Combine(web.ServerRelativeUrl, url); } var exists = true; Microsoft.SharePoint.Client.File file = null; try { file = web.GetFileByServerRelativeUrl(url); web.Context.Load(file); web.Context.ExecuteQuery(); } catch (ServerException ex) { if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException") { exists = false; } } if (exists) { if (page.Overwrite) { file.DeleteObject(); web.Context.ExecuteQueryRetry(); web.AddWikiPageByUrl(url); web.AddLayoutToWikiPage(page.Layout, url); } } else { web.AddWikiPageByUrl(url); web.AddLayoutToWikiPage(page.Layout, url); } if (page.WebParts != null & page.WebParts.Any()) { var existingWebParts = web.GetWebParts(url); foreach (var webpart in page.WebParts) { if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == webpart.Title) == null) { WebPartEntity wpEntity = new WebPartEntity(); wpEntity.WebPartTitle = webpart.Title; wpEntity.WebPartXml = webpart.Contents.ToParsedString(); web.AddWebPartToWikiPage(url, wpEntity, (int)webpart.Row, (int)webpart.Column, false); } } } } }
private ProvisioningTemplate CleanupEntities(ProvisioningTemplate template, ProvisioningTemplate baseTemplate) { return template; }
/// <summary> /// Constructor /// </summary> /// <param name="web">A SharePoint site or subsite</param> public ProvisioningTemplateCreationInformation(Web web) { this.baseTemplate = web.GetBaseTemplate(); this.propertyBagPropertiesToPreserve = new List <String>(); this.contentTypeGroupsToInclude = new List <String>(); }
public static bool PersistResourceValue(UserResource userResource, string token, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { bool returnValue = false; foreach (var language in template.SupportedUILanguages) { var culture = new CultureInfo(language.LCID); var value = userResource.GetValueForUICulture(culture.Name); userResource.Context.ExecuteQueryRetry(); if (!string.IsNullOrEmpty(value.Value)) { returnValue = true; ResourceTokens.Add(new Tuple <string, int, string>(token, language.LCID, value.Value)); } } return(returnValue); }
public ProvisioningTemplate PostProcessGetTemplate(ProvisioningTemplate template) { throw new NotImplementedException(); }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { if (template.ComposedLook != null && !template.ComposedLook.IsEmptyOrBlank()) { // Check if this is not a noscript site as themes and composed looks are not supported if (web.IsNoScriptSite()) { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_NoSiteCheck); return(parser); } bool executeQueryNeeded = false; if (executeQueryNeeded) { web.Context.ExecuteQueryRetry(); } if (String.IsNullOrEmpty(template.ComposedLook.ColorFile) && String.IsNullOrEmpty(template.ComposedLook.FontFile) && String.IsNullOrEmpty(template.ComposedLook.BackgroundFile)) { // Apply OOB theme web.SetComposedLookByUrl(template.ComposedLook.Name, "", "", ""); } else { // Apply custom theme string colorFile = null; if (!string.IsNullOrEmpty(template.ComposedLook.ColorFile)) { colorFile = parser.ParseString(template.ComposedLook.ColorFile); } string backgroundFile = null; if (!string.IsNullOrEmpty(template.ComposedLook.BackgroundFile)) { backgroundFile = parser.ParseString(template.ComposedLook.BackgroundFile); } string fontFile = null; if (!string.IsNullOrEmpty(template.ComposedLook.FontFile)) { fontFile = parser.ParseString(template.ComposedLook.FontFile); } string masterUrl = null; if (template.WebSettings != null && !string.IsNullOrEmpty(template.WebSettings.MasterPageUrl)) { masterUrl = parser.ParseString(template.WebSettings.MasterPageUrl); } web.CreateComposedLookByUrl(template.ComposedLook.Name, colorFile, fontFile, backgroundFile, masterUrl); web.SetComposedLookByUrl(template.ComposedLook.Name, colorFile, fontFile, backgroundFile, masterUrl); } // Persist composed look info in property bag var composedLookJson = JsonConvert.SerializeObject(template.ComposedLook); web.SetPropertyBagValue("_PnP_ProvisioningTemplateComposedLookInfo", composedLookJson); } } return(parser); }
private ProvisioningTemplate CleanupEntities(ProvisioningTemplate template, ProvisioningTemplate baseTemplate, bool isSubSite) { List<Guid> featuresToExclude = new List<Guid>(); // Seems to be an feature left over on some older online sites... featuresToExclude.Add(Guid.Parse("d70044a4-9f71-4a3f-9998-e7238c11ce1a")); if (!isSubSite) { foreach (var feature in baseTemplate.Features.SiteFeatures) { int index = template.Features.SiteFeatures.FindIndex(f => f.ID.Equals(feature.ID)); if (index > -1) { template.Features.SiteFeatures.RemoveAt(index); } } foreach(var feature in featuresToExclude) { int index = template.Features.SiteFeatures.FindIndex(f => f.ID.Equals(feature)); if (index > -1) { template.Features.SiteFeatures.RemoveAt(index); } } } foreach (var feature in baseTemplate.Features.WebFeatures) { int index = template.Features.WebFeatures.FindIndex(f => f.ID.Equals(feature.ID)); if (index > -1) { template.Features.WebFeatures.RemoveAt(index); } } foreach (var feature in featuresToExclude) { int index = template.Features.WebFeatures.FindIndex(f => f.ID.Equals(feature)); if (index > -1) { template.Features.WebFeatures.RemoveAt(index); } } return template; }
public override ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { using (var scope = new PnPMonitoredScope(this.Name)) { scope.LogInfo(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Retrieving_current_composed_look); // Ensure that we have URL property loaded for web and site web.EnsureProperty(w => w.Url); Site site = (web.Context as ClientContext).Site; site.EnsureProperty(s => s.Url); SharePointConnector spConnector = new SharePointConnector(web.Context, web.Url, "dummy"); // to get files from theme catalog we need a connector linked to the root site SharePointConnector spConnectorRoot; if (!site.Url.Equals(web.Url, StringComparison.InvariantCultureIgnoreCase)) { spConnectorRoot = new SharePointConnector(web.Context.Clone(site.Url), site.Url, "dummy"); } else { spConnectorRoot = spConnector; } // Check if we have composed look info in the property bag, if so, use that, otherwise try to detect the current composed look if (web.PropertyBagContainsKey("_PnP_ProvisioningTemplateComposedLookInfo")) { scope.LogInfo(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Using_ComposedLookInfoFromPropertyBag); try { var composedLook = JsonConvert.DeserializeObject <ComposedLook>(web.GetPropertyBagValueString("_PnP_ProvisioningTemplateComposedLookInfo", "")); if (composedLook.Name == null) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_ComposedLookInfoFailedToDeserialize); throw new JsonSerializationException(); } composedLook.BackgroundFile = Tokenize(composedLook.BackgroundFile, web.Url); composedLook.FontFile = Tokenize(composedLook.FontFile, web.Url); composedLook.ColorFile = Tokenize(composedLook.ColorFile, web.Url); template.ComposedLook = composedLook; if (!web.IsSubSite() && creationInfo != null && creationInfo.PersistBrandingFiles && creationInfo.FileConnector != null) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Creating_SharePointConnector); // Let's create a SharePoint connector since our files anyhow are in SharePoint at this moment TokenParser parser = new TokenParser(web, template); DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.BackgroundFile), scope); DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.ColorFile), scope); DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.FontFile), scope); } // Create file entries for the custom theme files if (!string.IsNullOrEmpty(template.ComposedLook.BackgroundFile)) { var f = GetComposedLookFile(template.ComposedLook.BackgroundFile); f.Folder = Tokenize(f.Folder, web.Url); template.Files.Add(f); } if (!string.IsNullOrEmpty(template.ComposedLook.ColorFile)) { var f = GetComposedLookFile(template.ComposedLook.ColorFile); f.Folder = Tokenize(f.Folder, web.Url); template.Files.Add(f); } if (!string.IsNullOrEmpty(template.ComposedLook.FontFile)) { var f = GetComposedLookFile(template.ComposedLook.FontFile); f.Folder = Tokenize(f.Folder, web.Url); template.Files.Add(f); } } catch (JsonSerializationException) { // cannot deserialize the object, fall back to composed look detection template = DetectComposedLook(web, template, creationInfo, scope, spConnector, spConnectorRoot); } } else { template = DetectComposedLook(web, template, creationInfo, scope, spConnector, spConnectorRoot); } if (creationInfo != null && creationInfo.BaseTemplate != null) { template = CleanupEntities(template, creationInfo.BaseTemplate); } } return(template); }
public ProvisioningTemplateCreationInformation(Web web) { this.baseTemplate = web.GetBaseTemplate(); }
public override ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { return(template); }
public abstract void SaveAs(ProvisioningTemplate template, string identifier);
private void ProcessApps(Web web, ProvisioningTemplate template, TokenParser parser, PnPMonitoredScope scope) { if (template.Tenant.AppCatalog != null && template.Tenant.AppCatalog.Packages.Count > 0) { var manager = new AppManager(web.Context as ClientContext); var appCatalogUri = web.GetAppCatalog(); if (appCatalogUri != null) { foreach (var app in template.Tenant.AppCatalog.Packages) { AppMetadata appMetadata = null; if (app.Action == PackageAction.Upload || app.Action == PackageAction.UploadAndPublish) { var appBytes = GetFileBytes(template, app.Src); var appFilename = app.Src.Substring(app.Src.LastIndexOf('\\') + 1); appMetadata = manager.Add(appBytes, appFilename, app.Overwrite, timeoutSeconds: 300); parser.Tokens.Add(new AppPackageIdToken(web, appFilename, appMetadata.Id)); } if (app.Action == PackageAction.Publish || app.Action == PackageAction.UploadAndPublish) { if (appMetadata == null) { appMetadata = manager.GetAvailable() .FirstOrDefault(a => a.Id == Guid.Parse(parser.ParseString(app.PackageId))); } if (appMetadata != null) { manager.Deploy(appMetadata, app.SkipFeatureDeployment); } else { scope.LogError("Referenced App Package {0} not available", app.PackageId); throw new Exception($"Referenced App Package {app.PackageId} not available"); } } if (app.Action == PackageAction.Remove) { var appId = Guid.Parse(parser.ParseString(app.PackageId)); // Get the apps already installed in the site var appExists = manager.GetAvailable()?.Any(a => a.Id == appId); if (appExists.HasValue && appExists.Value) { manager.Remove(appId); } else { WriteMessage($"App Package with ID {appId} does not exist in the AppCatalog and cannot be removed!", ProvisioningMessageType.Warning); } } } } else { WriteMessage($"Tenant app catalog doesn't exist. ALM step will be skipped!", ProvisioningMessageType.Warning); } } }
public static ProvisioningTemplate ToProvisioningTemplate(this SharePointProvisioningTemplate template) { if (template == null) { throw new ArgumentNullException("template"); } // Check the provided template against the XML schema if (!template.IsValidSharePointProvisioningTemplate()) { // TODO: Use resource file throw new ApplicationException("The provided template is not valid!"); } ProvisioningTemplate result = new ProvisioningTemplate(); // Translate basic properties result.ID = template.ID; result.Version = Double.Parse(!String.IsNullOrEmpty(template.Version) ? template.Version : "0", new CultureInfo("en-US")); result.SitePolicy = template.SitePolicy; // Translate PropertyBagEntries, if any if (template.PropertyBagEntries != null) { result.PropertyBagEntries.AddRange( from bag in template.PropertyBagEntries select new Model.PropertyBagEntry { Key = bag.Key, Value = bag.Value, }); } // Translate Security configuration, if any if (template.Security != null) { if (template.Security.AdditionalAdministrators != null) { result.Security.AdditionalAdministrators.AddRange( from user in template.Security.AdditionalAdministrators select new Model.User { Name = user.Name, }); } if (template.Security.AdditionalOwners != null) { result.Security.AdditionalOwners.AddRange( from user in template.Security.AdditionalOwners select new Model.User { Name = user.Name, }); } if (template.Security.AdditionalMembers != null) { result.Security.AdditionalMembers.AddRange( from user in template.Security.AdditionalMembers select new Model.User { Name = user.Name, }); } if (template.Security.AdditionalVisitors != null) { result.Security.AdditionalVisitors.AddRange( from user in template.Security.AdditionalVisitors select new Model.User { Name = user.Name, }); } } // Translate Site Columns (Fields), if any if ((template.SiteFields != null) && (template.SiteFields.Any != null)) { result.SiteFields.AddRange( from field in template.SiteFields.Any select new Field { SchemaXml = field.OuterXml, }); } // Translate ContentTypes, if any if ((template.ContentTypes != null) && (template.ContentTypes.Any != null)) { result.ContentTypes.AddRange( from contentType in template.ContentTypes.Any select new ContentType { SchemaXml = contentType.OuterXml, }); } // Translate Lists Instances, if any if (template.Lists != null) { result.Lists.AddRange( from list in template.Lists select new Model.ListInstance( (list.ContentTypeBindings != null ? (from contentTypeBinding in list.ContentTypeBindings select new Model.ContentTypeBinding { ContentTypeID = contentTypeBinding.ContentTypeID, Default = contentTypeBinding.Default, }) : null), (list.Views != null ? (from view in list.Views.Any select new View { SchemaXml = view.OuterXml, }) : null), (list.Fields != null ? (from field in list.Fields.Any select new Field { SchemaXml = field.OuterXml, }) : null), (list.FieldRefs != null ? (from fieldRef in list.FieldRefs select new Model.FieldRef { ID = Guid.Parse(fieldRef.ID) }) : null) ) { ContentTypesEnabled = list.ContentTypesEnabled, Description = list.Description, DocumentTemplate = list.DocumentTemplate, EnableVersioning = list.EnableVersioning, Hidden = list.Hidden, MinorVersionLimit = list.MinorVersionLimit, MaxVersionLimit = list.MaxVersionLimit, OnQuickLaunch = list.OnQuickLaunch, RemoveDefaultContentType = list.RemoveDefaultContentType, TemplateType = list.TemplateType, Title = list.Title, Url = list.Url, }); } // Translate Features, if any if (template.Features != null) { if (result.Features.SiteFeatures != null && template.Features.SiteFeatures != null) { result.Features.SiteFeatures.AddRange( from feature in template.Features.SiteFeatures select new Model.Feature { ID = new Guid(feature.ID), Deactivate = feature.Deactivate, }); } if (result.Features.WebFeatures != null && template.Features.WebFeatures != null) { result.Features.WebFeatures.AddRange( from feature in template.Features.WebFeatures select new Model.Feature { ID = new Guid(feature.ID), Deactivate = feature.Deactivate, }); } } // Translate CustomActions, if any if (template.CustomActions != null) { if (result.CustomActions.SiteCustomActions != null && template.CustomActions.SiteCustomActions != null) { result.CustomActions.SiteCustomActions.AddRange( from customAction in template.CustomActions.SiteCustomActions select new Model.CustomAction { Description = customAction.Description, Enabled = customAction.Enabled, Group = customAction.Group, ImageUrl = customAction.ImageUrl, Location = customAction.Location, Name = customAction.Name, RightsValue = customAction.RightsSpecified ? customAction.Rights : 0, ScriptBlock = customAction.ScriptBlock, ScriptSrc = customAction.ScriptSrc, Sequence = customAction.SequenceSpecified ? customAction.Sequence : 100, Title = customAction.Title, Url = customAction.Url, }); } if (result.CustomActions.WebCustomActions != null && template.CustomActions.WebCustomActions != null) { result.CustomActions.WebCustomActions.AddRange( from customAction in template.CustomActions.WebCustomActions select new Model.CustomAction { Description = customAction.Description, Enabled = customAction.Enabled, Group = customAction.Group, ImageUrl = customAction.ImageUrl, Location = customAction.Location, Name = customAction.Name, RightsValue = customAction.RightsSpecified ? customAction.Rights : 0, ScriptBlock = customAction.ScriptBlock, ScriptSrc = customAction.ScriptSrc, Sequence = customAction.SequenceSpecified ? customAction.Sequence : 100, Title = customAction.Title, Url = customAction.Url, }); } } // Translate Files, if any if (template.Files != null) { result.Files.AddRange( from file in template.Files select new Model.File { Overwrite = file.Overwrite, Src = file.Src, Folder = file.Folder, }); } // Translate ComposedLook, if any if (template.ComposedLook != null) { result.ComposedLook.AlternateCSS = template.ComposedLook.AlternateCSS; result.ComposedLook.BackgroundFile = template.ComposedLook.BackgroundFile; result.ComposedLook.ColorFile = template.ComposedLook.ColorFile; result.ComposedLook.FontFile = template.ComposedLook.FontFile; result.ComposedLook.MasterPage = template.ComposedLook.MasterPage; result.ComposedLook.Name = template.ComposedLook.Name; result.ComposedLook.SiteLogo = template.ComposedLook.SiteLogo; result.ComposedLook.Version = template.ComposedLook.Version; } // Translate Providers, if any if (template.Providers != null) { result.Providers.AddRange( from provider in template.Providers select new Model.Provider { Assembly = provider.Assembly, Configuration = provider.Configuration != null ? provider.Configuration.ToProviderConfiguration() : null, Enabled = provider.Enabled, Type = provider.Type, }); } return (result); }
public abstract void ProvisionObjects(Web web, ProvisioningTemplate template);
private static void ApplyProvisioningTemplate(ConsoleColor defaultForeground, string webUrl, string userName, SecureString pwd, ProvisioningTemplate template) { using (var ctx = new ClientContext(webUrl)) { ctx.Credentials = new NetworkCredential(userName, pwd); //ctx.Credentials = new SharePointOnlineCredentials(userName, pwd); ctx.RequestTimeout = Timeout.Infinite; // Just to output the site details Web web = ctx.Web; ctx.Load(web, w => w.Title); ctx.ExecuteQueryRetry(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("Your site title is:" + ctx.Web.Title); Console.ForegroundColor = defaultForeground; // We could potentially also upload the template from file system, but we at least need this for branding file XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(@"c:\temp\pnpprovisioning", ""); template = provider.GetTemplate("PnPProvisioning.xml"); ProvisioningTemplateApplyingInformation ptai = new ProvisioningTemplateApplyingInformation(); ptai.ProgressDelegate = delegate(String message, Int32 progress, Int32 total) { Console.WriteLine("{0:00}/{1:00} - {2}", progress, total, message); }; // Associate file connector for assets FileSystemConnector connector = new FileSystemConnector(@"c:\temp\pnpprovisioning", ""); template.Connector = connector; // Since template is actual object, we can modify this using code as needed template.Lists.Add(new ListInstance() { Title = "PnP Sample Contacts", Url = "lists/PnPContacts", TemplateType = (Int32)ListTemplateType.Contacts, EnableAttachments = true }); web.ApplyProvisioningTemplate(template, ptai); } }
public abstract void Save(ProvisioningTemplate template);
public abstract TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation);
public override void ProvisionObjects(Web web, ProvisioningTemplate template) { var parser = new TokenParser(web); if (!web.IsPropertyAvailable("ServerRelativeUrl")) { web.Context.Load(web, w => w.ServerRelativeUrl); web.Context.ExecuteQuery(); } web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl)); web.Context.ExecuteQuery(); //TODO: Upgrade to SharePoint.Client v16.0 so refactoring can be done (uncomment following line when done!) //var existingLists = web.Lists.Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList(); var existingLists = web.Lists.AsEnumerable().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList(); var serverRelativeUrl = web.ServerRelativeUrl; foreach (var list in template.Lists) { if (!existingLists.Contains(UrlUtility.Combine(serverRelativeUrl, list.Url))) { var listCreate = new ListCreationInformation(); listCreate.Description = list.Description; listCreate.TemplateType = list.TemplateType; listCreate.Title = list.Title; listCreate.QuickLaunchOption = list.OnQuickLaunch ? QuickLaunchOptions.On : QuickLaunchOptions.Off; listCreate.Url = parser.Parse(list.Url); var createdList = web.Lists.Add(listCreate); createdList.EnableVersioning = list.EnableVersioning; if (!String.IsNullOrEmpty(list.DocumentTemplate)) { createdList.DocumentTemplateUrl = parser.Parse(list.DocumentTemplate); } createdList.Hidden = list.Hidden; createdList.ContentTypesEnabled = list.ContentTypesEnabled; createdList.Update(); web.Context.ExecuteQuery(); // TODO: handle 'removedefaultcontenttype' foreach (var ctBinding in list.ContentTypeBindings) { createdList.AddContentTypeToListById(ctBinding.ContentTypeID); if (ctBinding.Default) { createdList.SetDefaultContentTypeToList(ctBinding.ContentTypeID); } } if (list.Fields.Any()) { foreach (var field in list.Fields) { // Double check that the content type did not include the field before adding it in if (!createdList.FieldExistsById(field.SchemaXml.Substring(field.SchemaXml.IndexOf("ID=\"{") + 5, 36))) { var fieldXml = parser.Parse(field.SchemaXml); createdList.Fields.AddFieldAsXml(fieldXml, false, AddFieldOptions.DefaultValue); } } createdList.Update(); web.Context.ExecuteQuery(); } if (list.FieldRefs.Any()) { foreach (var fieldRef in list.FieldRefs) { var field = web.GetFieldById<Field>(fieldRef.ID); if (!createdList.FieldExistsById(fieldRef.ID)) { createdList.Fields.Add(field); } } createdList.Update(); web.Context.ExecuteQuery(); } foreach (var view in list.Views) { var viewDoc = XDocument.Parse(view.SchemaXml); var displayNameXml = viewDoc.Root.Attribute("DisplayName"); if (displayNameXml == null) { throw new ApplicationException("Invalid View element, missing a valid value for the attribute DisplayName."); } var viewTitle = displayNameXml.Value; // Type var viewTypeString = viewDoc.Root.Attribute("Type") != null ? viewDoc.Root.Attribute("Type").Value : "None"; viewTypeString = viewTypeString[0].ToString().ToUpper() + viewTypeString.Substring(1).ToLower(); var viewType = (ViewType)Enum.Parse(typeof(ViewType), viewTypeString); // Fields string[] viewFields = null; var viewFieldsElement = viewDoc.Descendants("ViewFields").FirstOrDefault(); if (viewFieldsElement != null) { viewFields = (from field in viewDoc.Descendants("ViewFields").Descendants("FieldRef") select field.Attribute("Name").Value).ToArray(); } // Default view var viewDefault = viewDoc.Root.Attribute("DefaultView") != null && Boolean.Parse(viewDoc.Root.Attribute("DefaultView").Value); // Row limit bool viewPaged = true; uint viewRowLimit = 30; var rowLimitElement = viewDoc.Descendants("RowLimit").FirstOrDefault(); if (rowLimitElement != null) { if (rowLimitElement.Attribute("Paged") != null) { viewPaged = bool.Parse(rowLimitElement.Attribute("Paged").Value); } viewRowLimit = uint.Parse(rowLimitElement.Value); } // Query var viewQuery = new StringBuilder(); foreach (var queryElement in viewDoc.Descendants("Query").Elements()) { viewQuery.Append(queryElement.ToString()); } var viewCI = new ViewCreationInformation { ViewFields = viewFields, RowLimit = viewRowLimit, Paged = viewPaged, Title = viewTitle, Query = viewQuery.ToString(), ViewTypeKind = viewType, PersonalView = false, SetAsDefaultView = viewDefault }; createdList.Views.Add(viewCI); createdList.Update(); web.Context.ExecuteQuery(); } } } }
public abstract ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo);
public override void SaveAs(ProvisioningTemplate template, string identifier) { if (template == null) { throw new ArgumentNullException("template"); } if (String.IsNullOrEmpty(identifier)) { throw new ArgumentException("identifier"); } SaveToConnector(template, identifier); }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { // Changed by Paolo Pialorsi to embrace the new sub-site attributes for break role inheritance and copy role assignments // if this is a sub site then we're not provisioning security as by default security is inherited from the root site //if (web.IsSubSite() && !template.Security.BreakRoleInheritance) //{ // scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_SiteSecurity_Context_web_is_subweb__skipping_site_security_provisioning); // return parser; //} if (web.IsSubSite() && template.Security.BreakRoleInheritance) { web.BreakRoleInheritance(template.Security.CopyRoleAssignments, template.Security.ClearSubscopes); web.Update(); web.Context.ExecuteQueryRetry(); } var siteSecurity = template.Security; var ownerGroup = web.AssociatedOwnerGroup; var memberGroup = web.AssociatedMemberGroup; var visitorGroup = web.AssociatedVisitorGroup; web.Context.Load(ownerGroup, o => o.Title, o => o.Users); web.Context.Load(memberGroup, o => o.Title, o => o.Users); web.Context.Load(visitorGroup, o => o.Title, o => o.Users); web.Context.ExecuteQueryRetry(); if (!ownerGroup.ServerObjectIsNull.Value) { AddUserToGroup(web, ownerGroup, siteSecurity.AdditionalOwners, scope, parser); } if (!memberGroup.ServerObjectIsNull.Value) { AddUserToGroup(web, memberGroup, siteSecurity.AdditionalMembers, scope, parser); } if (!visitorGroup.ServerObjectIsNull.Value) { AddUserToGroup(web, visitorGroup, siteSecurity.AdditionalVisitors, scope, parser); } foreach (var siteGroup in siteSecurity.SiteGroups) { Group group; var allGroups = web.Context.LoadQuery(web.SiteGroups.Include(gr => gr.LoginName)); web.Context.ExecuteQueryRetry(); string parsedGroupTitle = parser.ParseString(siteGroup.Title); string parsedGroupOwner = parser.ParseString(siteGroup.Owner); string parsedGroupDescription = parser.ParseString(siteGroup.Description); if (!web.GroupExists(parsedGroupTitle)) { scope.LogDebug("Creating group {0}", parsedGroupTitle); group = web.AddGroup( parsedGroupTitle, parsedGroupDescription, parsedGroupTitle == parsedGroupOwner); group.AllowMembersEditMembership = siteGroup.AllowMembersEditMembership; group.AllowRequestToJoinLeave = siteGroup.AllowRequestToJoinLeave; group.AutoAcceptRequestToJoinLeave = siteGroup.AutoAcceptRequestToJoinLeave; if (parsedGroupTitle != parsedGroupOwner) { Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName == parsedGroupOwner); if (ownerPrincipal == null) { ownerPrincipal = web.EnsureUser(parsedGroupOwner); } group.Owner = ownerPrincipal; } group.Update(); web.Context.Load(group, g => g.Id, g => g.Title); web.Context.ExecuteQueryRetry(); parser.AddToken(new GroupIdToken(web, group.Title, group.Id)); } else { group = web.SiteGroups.GetByName(parsedGroupTitle); web.Context.Load(group, g => g.Title, g => g.Description, g => g.AllowMembersEditMembership, g => g.AllowRequestToJoinLeave, g => g.AutoAcceptRequestToJoinLeave, g => g.Owner.LoginName); web.Context.ExecuteQueryRetry(); var isDirty = false; if (!String.IsNullOrEmpty(group.Description) && group.Description != parsedGroupDescription) { group.Description = parsedGroupDescription; isDirty = true; } if (group.AllowMembersEditMembership != siteGroup.AllowMembersEditMembership) { group.AllowMembersEditMembership = siteGroup.AllowMembersEditMembership; isDirty = true; } if (group.AllowRequestToJoinLeave != siteGroup.AllowRequestToJoinLeave) { group.AllowRequestToJoinLeave = siteGroup.AllowRequestToJoinLeave; isDirty = true; } if (group.AutoAcceptRequestToJoinLeave != siteGroup.AutoAcceptRequestToJoinLeave) { group.AutoAcceptRequestToJoinLeave = siteGroup.AutoAcceptRequestToJoinLeave; isDirty = true; } if (group.Owner.LoginName != parsedGroupOwner) { if (parsedGroupTitle != parsedGroupOwner) { Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName == parsedGroupOwner); if (ownerPrincipal == null) { ownerPrincipal = web.EnsureUser(parsedGroupOwner); } group.Owner = ownerPrincipal; } else { group.Owner = group; } isDirty = true; } if (isDirty) { scope.LogDebug("Updating existing group {0}", group.Title); group.Update(); web.Context.ExecuteQueryRetry(); } } if (group != null && siteGroup.Members.Any()) { AddUserToGroup(web, group, siteGroup.Members, scope, parser); } } foreach (var admin in siteSecurity.AdditionalAdministrators) { var parsedAdminName = parser.ParseString(admin.Name); var user = web.EnsureUser(parsedAdminName); user.IsSiteAdmin = true; user.Update(); web.Context.ExecuteQueryRetry(); } if (!web.IsSubSite() && siteSecurity.SiteSecurityPermissions != null) // Only manage permissions levels on sitecol level { var existingRoleDefinitions = web.Context.LoadQuery(web.RoleDefinitions.Include(wr => wr.Name, wr => wr.BasePermissions, wr => wr.Description)); web.Context.ExecuteQueryRetry(); if (siteSecurity.SiteSecurityPermissions.RoleDefinitions.Any()) { foreach (var templateRoleDefinition in siteSecurity.SiteSecurityPermissions.RoleDefinitions) { var roleDefinitions = existingRoleDefinitions as RoleDefinition[] ?? existingRoleDefinitions.ToArray(); var siteRoleDefinition = roleDefinitions.FirstOrDefault(erd => erd.Name == parser.ParseString(templateRoleDefinition.Name)); if (siteRoleDefinition == null) { scope.LogDebug("Creation role definition {0}", parser.ParseString(templateRoleDefinition.Name)); var roleDefinitionCI = new RoleDefinitionCreationInformation(); roleDefinitionCI.Name = parser.ParseString(templateRoleDefinition.Name); roleDefinitionCI.Description = parser.ParseString(templateRoleDefinition.Description); BasePermissions basePermissions = new BasePermissions(); foreach (var permission in templateRoleDefinition.Permissions) { basePermissions.Set(permission); } roleDefinitionCI.BasePermissions = basePermissions; web.RoleDefinitions.Add(roleDefinitionCI); web.Context.ExecuteQueryRetry(); } else { var isDirty = false; if (siteRoleDefinition.Description != parser.ParseString(templateRoleDefinition.Description)) { siteRoleDefinition.Description = parser.ParseString(templateRoleDefinition.Description); isDirty = true; } var templateBasePermissions = new BasePermissions(); templateRoleDefinition.Permissions.ForEach(p => templateBasePermissions.Set(p)); if (siteRoleDefinition.BasePermissions != templateBasePermissions) { isDirty = true; foreach (var permission in templateRoleDefinition.Permissions) { siteRoleDefinition.BasePermissions.Set(permission); } } if (isDirty) { scope.LogDebug("Updating role definition {0}", parser.ParseString(templateRoleDefinition.Name)); siteRoleDefinition.Update(); web.Context.ExecuteQueryRetry(); } } } } var webRoleDefinitions = web.Context.LoadQuery(web.RoleDefinitions); var groups = web.Context.LoadQuery(web.SiteGroups.Include(g => g.LoginName)); web.Context.ExecuteQueryRetry(); if (siteSecurity.SiteSecurityPermissions.RoleAssignments.Any()) { foreach (var roleAssignment in siteSecurity.SiteSecurityPermissions.RoleAssignments) { Principal principal = groups.FirstOrDefault(g => g.LoginName == parser.ParseString(roleAssignment.Principal)); if (principal == null) { principal = web.EnsureUser(parser.ParseString(roleAssignment.Principal)); } var roleDefinitionBindingCollection = new RoleDefinitionBindingCollection(web.Context); var roleDefinition = webRoleDefinitions.FirstOrDefault(r => r.Name == parser.ParseString(roleAssignment.RoleDefinition)); if (roleDefinition != null) { roleDefinitionBindingCollection.Add(roleDefinition); } web.RoleAssignments.Add(principal, roleDefinitionBindingCollection); web.Context.ExecuteQueryRetry(); } } } } return(parser); }
private void SaveToConnector(ProvisioningTemplate template, string identifier) { if (String.IsNullOrEmpty(template.ID)) { template.ID = Path.GetFileNameWithoutExtension(identifier); } using (var stream = template.ToXmlStream()) { this.Connector.SaveFileStream(identifier, stream); } }
public override ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo) { using (var scope = new PnPMonitoredScope(this.Name)) { web.EnsureProperties(w => w.HasUniqueRoleAssignments, w => w.Title); // Changed by Paolo Pialorsi to embrace the new sub-site attributes for break role inheritance and copy role assignments // if this is a sub site then we're not creating security entities as by default security is inherited from the root site if (web.IsSubSite() && !web.HasUniqueRoleAssignments) { return(template); } var ownerGroup = web.AssociatedOwnerGroup; var memberGroup = web.AssociatedMemberGroup; var visitorGroup = web.AssociatedVisitorGroup; web.Context.ExecuteQueryRetry(); if (!ownerGroup.ServerObjectIsNull.Value) { web.Context.Load(ownerGroup, o => o.Id, o => o.Users, o => o.Title); } if (!memberGroup.ServerObjectIsNull.Value) { web.Context.Load(memberGroup, o => o.Id, o => o.Users, o => o.Title); } if (!visitorGroup.ServerObjectIsNull.Value) { web.Context.Load(visitorGroup, o => o.Id, o => o.Users, o => o.Title); } web.Context.ExecuteQueryRetry(); List <int> associatedGroupIds = new List <int>(); var owners = new List <User>(); var members = new List <User>(); var visitors = new List <User>(); if (!ownerGroup.ServerObjectIsNull.Value) { associatedGroupIds.Add(ownerGroup.Id); foreach (var member in ownerGroup.Users) { owners.Add(new User() { Name = member.LoginName }); } } if (!memberGroup.ServerObjectIsNull.Value) { associatedGroupIds.Add(memberGroup.Id); foreach (var member in memberGroup.Users) { members.Add(new User() { Name = member.LoginName }); } } if (!visitorGroup.ServerObjectIsNull.Value) { associatedGroupIds.Add(visitorGroup.Id); foreach (var member in visitorGroup.Users) { visitors.Add(new User() { Name = member.LoginName }); } } var siteSecurity = new SiteSecurity(); siteSecurity.AdditionalOwners.AddRange(owners); siteSecurity.AdditionalMembers.AddRange(members); siteSecurity.AdditionalVisitors.AddRange(visitors); var query = from user in web.SiteUsers where user.IsSiteAdmin select user; var allUsers = web.Context.LoadQuery(query); web.Context.ExecuteQueryRetry(); var admins = new List <User>(); foreach (var member in allUsers) { admins.Add(new User() { Name = member.LoginName }); } siteSecurity.AdditionalAdministrators.AddRange(admins); if (creationInfo.IncludeSiteGroups) { web.Context.Load(web.SiteGroups, o => o.IncludeWithDefaultProperties( gr => gr.Title, gr => gr.AllowMembersEditMembership, gr => gr.AutoAcceptRequestToJoinLeave, gr => gr.AllowRequestToJoinLeave, gr => gr.Description, gr => gr.Users.Include(u => u.LoginName), gr => gr.OnlyAllowMembersViewMembership, gr => gr.Owner.LoginName, gr => gr.RequestToJoinLeaveEmailSetting )); web.Context.ExecuteQueryRetry(); if (web.IsSubSite()) { WriteWarning("You are requesting to export sitegroups from a subweb. Notice that ALL sitegroups from the site collection are included in the result.", ProvisioningMessageType.Warning); } foreach (var group in web.SiteGroups.AsEnumerable().Where(o => !associatedGroupIds.Contains(o.Id))) { scope.LogDebug("Processing group {0}", group.Title); var siteGroup = new SiteGroup() { Title = group.Title.Replace(web.Title, "{sitename}"), AllowMembersEditMembership = group.AllowMembersEditMembership, AutoAcceptRequestToJoinLeave = group.AutoAcceptRequestToJoinLeave, AllowRequestToJoinLeave = group.AllowRequestToJoinLeave, Description = group.Description, OnlyAllowMembersViewMembership = group.OnlyAllowMembersViewMembership, Owner = ReplaceGroupTokens(web, group.Owner.LoginName), RequestToJoinLeaveEmailSetting = group.RequestToJoinLeaveEmailSetting }; foreach (var member in group.Users) { siteGroup.Members.Add(new User() { Name = member.LoginName }); } siteSecurity.SiteGroups.Add(siteGroup); } } var webRoleDefinitions = web.Context.LoadQuery(web.RoleDefinitions.Include(r => r.Name, r => r.Description, r => r.BasePermissions, r => r.RoleTypeKind)); web.Context.ExecuteQueryRetry(); if (web.HasUniqueRoleAssignments) { var permissionKeys = Enum.GetNames(typeof(PermissionKind)); if (!web.IsSubSite()) { foreach (var webRoleDefinition in webRoleDefinitions) { if (webRoleDefinition.RoleTypeKind == RoleType.None) { scope.LogDebug("Processing custom role definition {0}", webRoleDefinition.Name); var modelRoleDefinitions = new Model.RoleDefinition(); modelRoleDefinitions.Description = webRoleDefinition.Description; modelRoleDefinitions.Name = webRoleDefinition.Name; foreach (var permissionKey in permissionKeys) { var permissionKind = (PermissionKind)Enum.Parse(typeof(PermissionKind), permissionKey); if (webRoleDefinition.BasePermissions.Has(permissionKind)) { modelRoleDefinitions.Permissions.Add(permissionKind); } } siteSecurity.SiteSecurityPermissions.RoleDefinitions.Add(modelRoleDefinitions); } else { scope.LogDebug("Skipping OOTB role definition {0}", webRoleDefinition.Name); } } } var webRoleAssignments = web.Context.LoadQuery(web.RoleAssignments.Include( r => r.RoleDefinitionBindings.Include( rd => rd.Name, rd => rd.RoleTypeKind), r => r.Member.LoginName, r => r.Member.PrincipalType)); web.Context.ExecuteQueryRetry(); foreach (var webRoleAssignment in webRoleAssignments) { if (webRoleAssignment.Member.PrincipalType == PrincipalType.SharePointGroup && !creationInfo.IncludeSiteGroups) { continue; } if (webRoleAssignment.Member.LoginName != "Excel Services Viewers") { foreach (var roleDefinition in webRoleAssignment.RoleDefinitionBindings) { if (roleDefinition.RoleTypeKind != RoleType.Guest) { var modelRoleAssignment = new Model.RoleAssignment(); var roleDefinitionValue = roleDefinition.Name; if (roleDefinition.RoleTypeKind != RoleType.None) { // Replace with token roleDefinitionValue = string.Format("{{roledefinition:{0}}}", roleDefinition.RoleTypeKind); } modelRoleAssignment.RoleDefinition = roleDefinitionValue; if (webRoleAssignment.Member.PrincipalType == PrincipalType.SharePointGroup) { modelRoleAssignment.Principal = ReplaceGroupTokens(web, webRoleAssignment.Member.LoginName); } else { modelRoleAssignment.Principal = webRoleAssignment.Member.LoginName; } siteSecurity.SiteSecurityPermissions.RoleAssignments.Add(modelRoleAssignment); } } } } } template.Security = siteSecurity; // If a base template is specified then use that one to "cleanup" the generated template model if (creationInfo.BaseTemplate != null) { template = CleanupEntities(template, creationInfo.BaseTemplate); } } return(template); }
public ProvisioningTemplate PreProcessSaveTemplate(ProvisioningTemplate template) { throw new NotImplementedException(); }
private ProvisioningTemplate CleanupEntities(ProvisioningTemplate template, ProvisioningTemplate baseTemplate) { foreach (var user in baseTemplate.Security.AdditionalAdministrators) { int index = template.Security.AdditionalAdministrators.FindIndex(f => f.Name.Equals(user.Name)); if (index > -1) { template.Security.AdditionalAdministrators.RemoveAt(index); } } foreach (var user in baseTemplate.Security.AdditionalMembers) { int index = template.Security.AdditionalMembers.FindIndex(f => f.Name.Equals(user.Name)); if (index > -1) { template.Security.AdditionalMembers.RemoveAt(index); } } foreach (var user in baseTemplate.Security.AdditionalOwners) { int index = template.Security.AdditionalOwners.FindIndex(f => f.Name.Equals(user.Name)); if (index > -1) { template.Security.AdditionalOwners.RemoveAt(index); } } foreach (var user in baseTemplate.Security.AdditionalVisitors) { int index = template.Security.AdditionalVisitors.FindIndex(f => f.Name.Equals(user.Name)); if (index > -1) { template.Security.AdditionalVisitors.RemoveAt(index); } } foreach (var baseSiteGroup in baseTemplate.Security.SiteGroups) { var templateSiteGroup = template.Security.SiteGroups.FirstOrDefault(sg => sg.Title == baseSiteGroup.Title); if (templateSiteGroup != null) { if (templateSiteGroup.Equals(baseSiteGroup)) { template.Security.SiteGroups.Remove(templateSiteGroup); } } } foreach (var baseRoleDef in baseTemplate.Security.SiteSecurityPermissions.RoleDefinitions) { var templateRoleDef = template.Security.SiteSecurityPermissions.RoleDefinitions.FirstOrDefault(rd => rd.Name == baseRoleDef.Name); if (templateRoleDef != null) { if (templateRoleDef.Equals(baseRoleDef)) { template.Security.SiteSecurityPermissions.RoleDefinitions.Remove(templateRoleDef); } } } foreach (var baseRoleAssignment in baseTemplate.Security.SiteSecurityPermissions.RoleAssignments) { var templateRoleAssignments = template.Security.SiteSecurityPermissions.RoleAssignments.Where(ra => ra.Principal == baseRoleAssignment.Principal).ToList(); foreach (var templateRoleAssignment in templateRoleAssignments) { if (templateRoleAssignment.Equals(baseRoleAssignment)) { template.Security.SiteSecurityPermissions.RoleAssignments.Remove(templateRoleAssignment); } } } return(template); }
public abstract bool WillProvision(Web web, ProvisioningTemplate template);
public abstract bool WillExtract(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo);
/// <summary> /// Can be used to apply custom remote provisioning template on top of existing site. /// </summary> /// <param name="web"></param> /// <param name="template">ProvisioningTemplate with the settings to be applied</param> public static void ApplyProvisioningTemplate(this Web web, ProvisioningTemplate template) { // Call actual handler new SiteToTemplateConversion().ApplyRemoteTemplate(web, template); }
public abstract ProvisioningTemplate CreateEntities(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo);