/// <summary>
        /// Applies a Provisioning Template Hierarchy to a target tenant
        /// </summary>
        /// <param name="targetSiteUrl">The URL of the target Site Collection</param>
        /// <param name="tenantTemplate">The Provisioning Template Hierarchy to apply</param>
        /// <param name="log">The TraceWriter to log activities</param>
        public static void ApplyTenantTemplate(String targetSiteUrl, ProvisioningHierarchy tenantTemplate, ILogger log)
        {
            ProvisioningTemplateApplyingInformation ptai =
                new ProvisioningTemplateApplyingInformation();

            // We exclude Term Groups because they are not supported in AppOnly
            ptai.HandlersToProcess  = Handlers.All;
            ptai.HandlersToProcess ^= Handlers.TermGroups;

            ptai.MessagesDelegate += delegate(string message, ProvisioningMessageType messageType)
            {
                log.LogDebug($"{messageType} - {message}");
            };
            ptai.ProgressDelegate += delegate(string message, int step, int total)
            {
                log.LogInformation($"{step:00}/{total:00} - {message}");
            };

            var tenantUrl = SPOUtilities.GetTenantAdministrationUrl(targetSiteUrl);

            using (var tenantContext = SPOContextProvider.BuildAppOnlyClientContext(tenantUrl))
            {
                using (var pnpTenantContext = PnPClientContext.ConvertFrom(tenantContext))
                {
                    var tenant = new Microsoft.Online.SharePoint.TenantAdministration.Tenant(pnpTenantContext);

                    // Prepare a dictionary to hold the access tokens
                    var accessTokens = new Dictionary <String, String>();

                    // Get the Microsoft Graph Access Token
                    var clientApplication = ConfidentialClientApplicationBuilder
                                            .Create(Environment.GetEnvironmentVariable("ClientId"))
                                            .WithTenantId(Environment.GetEnvironmentVariable("Tenant"))
                                            .WithClientSecret(Environment.GetEnvironmentVariable("ClientSecret")).Build();

                    try
                    {
                        string[] graphScopes          = new string[] { "https://graph.microsoft.com/.default" };
                        var      authenticationResult = clientApplication.AcquireTokenForClient(graphScopes).ExecuteAsync().GetAwaiter().GetResult();
                        var      graphAccessToken     = authenticationResult.AccessToken;
                        accessTokens.Add(new Uri("https://graph.microsoft.com/").Authority, graphAccessToken);
                    }
                    catch (Exception ex)
                    {
                        log.LogError(ex.Message);
                        throw;
                    }

                    // Configure the OAuth Access Tokens for the PnPClientContext, too
                    pnpTenantContext.PropertyBag["AccessTokens"] = accessTokens;
                    ptai.AccessTokens = accessTokens;

                    // Define a PnPProvisioningContext scope to share the security context across calls
                    using (var pnpProvisioningContext = new PnPProvisioningContext(async(r, s) =>
                    {
                        if (accessTokens.Any(i => i.Key.Equals(r, StringComparison.InvariantCultureIgnoreCase) ||
                                             r.ToLower().Contains(i.Key)))
                        {
                            // In this scenario we just use the dictionary of access tokens
                            // in fact the overall operation for sure will take less than 1 hour
                            var item = accessTokens.FirstOrDefault(i =>
                                                                   i.Key.Equals(r, StringComparison.InvariantCultureIgnoreCase) ||
                                                                   r.ToLower().Contains(i.Key));

                            return(await Task.FromResult(item.Value));
                        }
                        else
                        {
                            return(null);
                        }
                    }))
                    {
                        log.LogInformation($"Hierarchy Provisioning Started: {DateTime.Now:hh.mm.ss}");
                        tenant.ApplyProvisionHierarchy(tenantTemplate, null, ptai);
                        log.LogInformation($"Hierarchy Provisioning Completed: {DateTime.Now:hh.mm.ss}");
                    }
                }
            }
        }
Example #2
0
        private async Task <CanProvisionResult> CanProvisionInternal(CanProvisionModel model)
        {
            var canProvisionResult = new CanProvisionResult();

            String provisioningScope       = ConfigurationManager.AppSettings["SPPA:ProvisioningScope"];
            String provisioningEnvironment = ConfigurationManager.AppSettings["SPPA:ProvisioningEnvironment"];

            var tokenId          = $"{model.TenantId}-{model.UserPrincipalName.GetHashCode()}-{provisioningScope}-{provisioningEnvironment}";
            var graphAccessToken = await ProvisioningAppManager.AccessTokenProvider.GetAccessTokenAsync(
                tokenId, "https://graph.microsoft.com/");

            // Retrieve the provisioning package from the database and from the Blob Storage
            var context = dbContext;

            DomainModel.Package package = null;

            // Get the package
            if (ProvisioningAppManager.IsTestingEnvironment)
            {
                // Process all packages in the test environment
                package = context.Packages.FirstOrDefault(p => p.Id == new Guid(model.PackageId));
            }
            else
            {
                // Process not-preview packages in the production environment
                package = context.Packages.FirstOrDefault(p => p.Id == new Guid(model.PackageId) && p.Preview == false);
            }

            if (package != null)
            {
                // Retrieve parameters from the package/template definition
                var packageFileUrl     = new Uri(package.PackageUrl);
                var packageLocalFolder = packageFileUrl.AbsolutePath.Substring(1,
                                                                               packageFileUrl.AbsolutePath.LastIndexOf('/') - 1);
                var packageFileName = packageFileUrl.AbsolutePath.Substring(packageLocalFolder.Length + 2);

                ProvisioningHierarchy hierarchy = GetHierarchyFromStorage(packageLocalFolder, packageFileName);

                // If we have the hierarchy
                if (hierarchy != null)
                {
                    var accessTokens = new Dictionary <String, String>();

                    AuthenticationManager authManager = new AuthenticationManager();
                    var ptai = new ProvisioningTemplateApplyingInformation();

                    // Retrieve the SPO URL for the Admin Site
                    var rootSiteUrl = model.SPORootSiteUrl;

                    // Retrieve the SPO Access Token for SPO
                    var spoAccessToken = await ProvisioningAppManager.AccessTokenProvider.GetAccessTokenAsync(
                        tokenId, rootSiteUrl,
                        ConfigurationManager.AppSettings["ida:ClientId"],
                        ConfigurationManager.AppSettings["ida:ClientSecret"],
                        ConfigurationManager.AppSettings["ida:AppUrl"]);

                    // Store the SPO Access Token for any further context cloning
                    accessTokens.Add(new Uri(rootSiteUrl).Authority, spoAccessToken);

                    // Define a PnPProvisioningContext scope to share the security context across calls
                    using (var pnpProvisioningContext = new PnPProvisioningContext(async(r, s) =>
                    {
                        if (accessTokens.ContainsKey(r))
                        {
                            // In this scenario we just use the dictionary of access tokens
                            // in fact the overall operation for sure will take less than 1 hour
                            // (in fact, it's a matter of few seconds)
                            return(await Task.FromResult(accessTokens[r]));
                        }
                        else
                        {
                            // Try to get a fresh new Access Token
                            var token = await ProvisioningAppManager.AccessTokenProvider.GetAccessTokenAsync(
                                tokenId, $"https://{r}",
                                ConfigurationManager.AppSettings["ida:ClientId"],
                                ConfigurationManager.AppSettings["ida:ClientSecret"],
                                ConfigurationManager.AppSettings["ida:AppUrl"]);

                            accessTokens.Add(r, token);

                            return(token);
                        }
                    }))
                    {
                        // If the user is an admin (SPO or Tenant) we run the Tenant level CanProvision rules
                        if (model.UserIsSPOAdmin || model.UserIsTenantAdmin)
                        {
                            // Retrieve the SPO URL for the Admin Site
                            var adminSiteUrl = model.SPORootSiteUrl.Replace(".sharepoint.com", "-admin.sharepoint.com");

                            // Retrieve the SPO Access Token for the Admin Site
                            var spoAdminAccessToken = await ProvisioningAppManager.AccessTokenProvider.GetAccessTokenAsync(
                                tokenId, adminSiteUrl,
                                ConfigurationManager.AppSettings["ida:ClientId"],
                                ConfigurationManager.AppSettings["ida:ClientSecret"],
                                ConfigurationManager.AppSettings["ida:AppUrl"]);

                            // Store the SPO Admin Access Token for any further context cloning
                            accessTokens.Add(new Uri(adminSiteUrl).Authority, spoAdminAccessToken);

                            // Connect to SPO Admin Site and evaluate the CanProvision rules for the hierarchy
                            using (var tenantContext = authManager.GetAzureADAccessTokenAuthenticatedContext(adminSiteUrl, spoAdminAccessToken))
                            {
                                using (var pnpTenantContext = PnPClientContext.ConvertFrom(tenantContext))
                                {
                                    // Creat the Tenant object for the current SPO Admin Site context
                                    TenantAdmin.Tenant tenant = new TenantAdmin.Tenant(pnpTenantContext);

                                    // Run the CanProvision rules against the current tenant
                                    canProvisionResult = CanProvisionRulesManager.CanProvision(tenant, hierarchy, null, ptai);
                                }
                            }
                        }
                        else
                        {
                            // Otherwise we run the Site level CanProvision rules

                            // Connect to SPO Root Site and evaluate the CanProvision rules for the hierarchy
                            using (var clientContext = authManager.GetAzureADAccessTokenAuthenticatedContext(rootSiteUrl, spoAccessToken))
                            {
                                using (var pnpContext = PnPClientContext.ConvertFrom(clientContext))
                                {
                                    // Run the CanProvision rules against the root site
                                    canProvisionResult = CanProvisionRulesManager.CanProvision(pnpContext.Web, hierarchy.Templates[0], ptai);
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                throw new ApplicationException("Invalid request, the requested package/template is not available!");
            }

            return(canProvisionResult);
        }
        internal static void ProcessFiles(ProvisioningHierarchy tenantTemplate, string templateFileName, FileConnectorBase fileSystemConnector, FileConnectorBase connector, Action <string> progress)
        {
            var templateFile = ReadTenantTemplate.LoadProvisioningHierarchyFromFile(templateFileName, null, null);

            if (tenantTemplate.Tenant?.AppCatalog != null)
            {
                foreach (var app in tenantTemplate.Tenant.AppCatalog.Packages)
                {
                    progress($"Processing {app.Src}");
                    AddFile(app.Src, templateFile, fileSystemConnector, connector);
                }
            }
            if (tenantTemplate.Tenant?.SiteScripts != null)
            {
                foreach (var siteScript in tenantTemplate.Tenant.SiteScripts)
                {
                    progress($"Processing {siteScript.JsonFilePath}");
                    AddFile(siteScript.JsonFilePath, templateFile, fileSystemConnector, connector);
                }
            }
            if (tenantTemplate.Localizations != null && tenantTemplate.Localizations.Any())
            {
                foreach (var location in tenantTemplate.Localizations)
                {
                    progress($"Processing {location.ResourceFile}");
                    AddFile(location.ResourceFile, templateFile, fileSystemConnector, connector);
                }
            }
            foreach (var template in tenantTemplate.Templates)
            {
                if (template.WebSettings != null && !String.IsNullOrEmpty(template.WebSettings.SiteLogo))
                {
                    // is it a file?
                    var isFile = false;
                    try
                    {
                        using (var fileStream = fileSystemConnector.GetFileStream(template.WebSettings.SiteLogo))
                        {
                            isFile = fileStream != null;
                        }
                    }
                    catch { }
                    if (isFile)
                    {
                        progress($"Processing {template.WebSettings.SiteLogo}");
                        AddFile(template.WebSettings.SiteLogo, templateFile, fileSystemConnector, connector);
                    }
                }
                if (template.Files.Any())
                {
                    foreach (var file in template.Files)
                    {
                        progress($"Processing {file.Src}");
                        AddFile(file.Src, templateFile, fileSystemConnector, connector);
                    }
                }
                if (template.Lists.Any())
                {
                    foreach (var list in template.Lists)
                    {
                        if (list.DataRows.Any())
                        {
                            foreach (var dataRow in list.DataRows)
                            {
                                if (dataRow.Attachments.Any())
                                {
                                    progress("List attachments");
                                    foreach (var attachment in dataRow.Attachments)
                                    {
                                        AddFile(attachment.Src, templateFile, fileSystemConnector, connector);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (templateFile.Connector is ICommitableFileConnector)
            {
                ((ICommitableFileConnector)templateFile.Connector).Commit();
            }
        }
 public override ProvisioningHierarchy ExtractObjects(Tenant tenant, ProvisioningHierarchy hierarchy, ProvisioningTemplateCreationInformation creationInfo)
 {
     // So far, no extraction
     return(hierarchy);
 }
Example #5
0
 public override ProvisioningHierarchy ExtractObjects(Tenant tenant, ProvisioningHierarchy hierarchy, ExtractConfiguration configuration)
 {
     throw new NotImplementedException();
 }
Example #6
0
        public ProvisioningHierarchy ToProvisioningHierarchy(Stream hierarchy)
        {
            // Create a copy of the source stream
            MemoryStream sourceStream = new MemoryStream();

            hierarchy.Position = 0;
            hierarchy.CopyTo(sourceStream);
            sourceStream.Position = 0;

            // Check the provided template against the XML schema
            if (!this.IsValid(sourceStream))
            {
                // TODO: Use resource file
                throw new ApplicationException("The provided provisioning file is not valid!");
            }

            // Prepare the output variable
            ProvisioningHierarchy resultHierarchy = new ProvisioningHierarchy();

            // Determine if the file is a provisioning hierarchy
            sourceStream.Position = 0;
            XDocument xml = XDocument.Load(sourceStream);

            if (xml.Root.Name.LocalName != "Provisioning")
            {
                throw new ApplicationException("The provided provisioning file is not a Hierarchy!");
            }

            // Determine the specific formatter needed for the current provisioning file
            var innerFormatter = XMLPnPSchemaFormatter.GetSpecificFormatter(
                xml.Root.Name.NamespaceName);

            // Process all the provisioning templates included in the hierarchy, if any
            XmlNamespaceManager nsManager = new XmlNamespaceManager(new System.Xml.NameTable());

            nsManager.AddNamespace("pnp", xml.Root.Name.NamespaceName);

            // Start with templates embedded in the provisioning file
            var templates = xml.XPathSelectElements("/pnp:Provisioning/pnp:Templates/pnp:ProvisioningTemplate", nsManager).ToList();

            foreach (var template in templates)
            {
                // Save the single template into a MemoryStream
                MemoryStream templateStream = new MemoryStream();
                template.Save(templateStream);
                templateStream.Position = 0;

                // Process the single template with the classic technique
                var provisioningTemplate = innerFormatter.ToProvisioningTemplate(templateStream);

                // Add the generated template to the resulting hierarchy
                resultHierarchy.Templates.Add(provisioningTemplate);
            }

            // Then process any external file reference
            var templateFiles = xml.XPathSelectElements("/pnp:Provisioning/pnp:Templates/pnp:ProvisioningTemplateFile", nsManager).ToList();

            foreach (var template in templateFiles)
            {
                var templateID   = template.Attribute("ID")?.Value;
                var templateFile = template.Attribute("File")?.Value;
                if (!String.IsNullOrEmpty(templateFile) && !String.IsNullOrEmpty(templateID))
                {
                    // Process the single template file with the classic technique
                    var provisioningTemplate = this._provider.GetTemplate(templateFile);
                    provisioningTemplate.Id = templateID;

                    // Add the generated template to the resulting hierarchy
                    resultHierarchy.Templates.Add(provisioningTemplate);
                }
            }

            // And now process the top level children elements
            // using schema specific serializers

            using (var scope = new PnPSerializationScope(typeof(TSchemaTemplate)))
            {
                // We prepare a dummy template to leverage the existing serialization infrastructure
                var dummyTemplate = new ProvisioningTemplate();
                dummyTemplate.Id = $"DUMMY-{Guid.NewGuid()}";
                resultHierarchy.Templates.Add(dummyTemplate);

                // Deserialize the whole wrapper
                Object        wrapper       = null;
                var           wrapperType   = Type.GetType($"{PnPSerializationScope.Current?.BaseSchemaNamespace}.Provisioning, {PnPSerializationScope.Current?.BaseSchemaAssemblyName}", true);
                XmlSerializer xmlSerializer = new XmlSerializer(wrapperType);
                using (var reader = xml.Root.CreateReader())
                {
                    wrapper = xmlSerializer.Deserialize(reader);
                }

                // Handle the Parameters of the schema wrapper, if any
                var tps = new TemplateParametersSerializer();
                tps.Deserialize(wrapper, dummyTemplate);

                // Handle the Localizations of the schema wrapper, if any
                var ls = new LocalizationsSerializer();
                ls.Deserialize(wrapper, dummyTemplate);

                // Handle the Tenant-wide settings of the schema wrapper, if any
                var ts = new TenantSerializer();
                ts.Deserialize(wrapper, dummyTemplate);

                // Handle the Sequences
                var ss = new SequenceSerializer();
                ss.Deserialize(wrapper, dummyTemplate);

                // Handle the Provisioning Hierarchy properties
                var phs = new ProvisioningHierarchySerializer();
                phs.Deserialize(wrapper, dummyTemplate);

                // Remove the dummy template from the hierarchy
                resultHierarchy.Templates.Remove(dummyTemplate);
            }

            return(resultHierarchy);
        }
Example #7
0
 public override CanProvisionResult CanProvision(Tenant tenant, ProvisioningHierarchy hierarchy, string sequenceId, ProvisioningTemplateApplyingInformation applyingInformation)
 {
     // Rely on the corresponding Site level CanProvision rule
     return(this.EvaluateSiteRule <CanProvisionTermStoreRuleSite>(tenant, hierarchy, sequenceId, applyingInformation));
 }
        public override ProvisioningHierarchy ExtractObjects(Tenant tenant, ProvisioningHierarchy hierarchy, ExtractConfiguration configuration)
        {
            ProvisioningHierarchy tenantTemplate     = new ProvisioningHierarchy();
            List <string>         siteCollectionUrls = configuration.Tenant.Sequence.SiteUrls;

            List <string> connectedSiteUrls = new List <string>();

            foreach (var siteCollectionUrl in siteCollectionUrls)
            {
                using (var siteContext = tenant.Context.Clone(siteCollectionUrl))
                {
                    if (configuration.Tenant.Sequence.IncludeJoinedSites && siteContext.Site.EnsureProperty(s => s.IsHubSite))
                    {
                        foreach (var hubsiteChildUrl in tenant.GetHubSiteChildUrls(siteContext.Site.EnsureProperty(s => s.Id)))
                        {
                            if (!connectedSiteUrls.Contains(hubsiteChildUrl) && !siteCollectionUrl.Contains(hubsiteChildUrl))
                            {
                                connectedSiteUrls.Add(hubsiteChildUrl);
                            }
                        }
                    }
                }
            }
            siteCollectionUrls.AddRange(connectedSiteUrls);

            ProvisioningSequence provisioningSequence = new ProvisioningSequence();

            provisioningSequence.ID = "TENANTSEQUENCE";
            foreach (var siteCollectionUrl in siteCollectionUrls)
            {
                var siteProperties = tenant.GetSitePropertiesByUrl(siteCollectionUrl, true);

                tenant.Context.Load(siteProperties);
                tenant.Context.ExecuteQueryRetry();
                Model.SiteCollection siteCollection = null;
                using (var siteContext = tenant.Context.Clone(siteCollectionUrl))
                {
                    siteContext.Site.EnsureProperties(s => s.Id, s => s.ShareByEmailEnabled);
                    var templateGuid = siteContext.Site.Id.ToString("N");
                    switch (siteProperties.Template)
                    {
                    case "SITEPAGEPUBLISHING#0":
                    {
                        siteCollection = new CommunicationSiteCollection();

                        siteCollection.IsHubSite = siteProperties.IsHubSite;
                        if (siteProperties.IsHubSite)
                        {
                            var hubsiteProperties = tenant.GetHubSitePropertiesByUrl(siteCollectionUrl);
                            tenant.Context.Load(hubsiteProperties);
                            tenant.Context.ExecuteQueryRetry();
                            siteCollection.HubSiteLogoUrl = hubsiteProperties.LogoUrl;
                            siteCollection.HubSiteTitle   = hubsiteProperties.Title;
                        }
                        siteCollection.Description = siteProperties.Description;
                        ((CommunicationSiteCollection)siteCollection).Language = (int)siteProperties.Lcid;
                        ((CommunicationSiteCollection)siteCollection).Owner    = siteProperties.OwnerEmail;
                        ((CommunicationSiteCollection)siteCollection).AllowFileSharingForGuestUsers = siteContext.Site.ShareByEmailEnabled;
                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_URL", siteProperties.Url);
                        ((CommunicationSiteCollection)siteCollection).Url = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_URL}}";
                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE", siteProperties.Title);
                        siteCollection.Title = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE}}";
                        break;
                    }

                    case "GROUP#0":
                    {
                        siteCollection           = new TeamSiteCollection();
                        siteCollection.IsHubSite = siteProperties.IsHubSite;
                        if (siteProperties.IsHubSite)
                        {
                            var hubsiteProperties = tenant.GetHubSitePropertiesByUrl(siteCollectionUrl);
                            tenant.Context.Load(hubsiteProperties);
                            tenant.Context.ExecuteQueryRetry();
                            siteCollection.HubSiteLogoUrl = hubsiteProperties.LogoUrl;
                            siteCollection.HubSiteTitle   = hubsiteProperties.Title;
                        }
                        siteCollection.Description = siteProperties.Description;

                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_ALIAS", siteProperties.Url.Substring(siteProperties.Url.LastIndexOf("/")));
                        ((TeamSiteCollection)siteCollection).Alias       = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_ALIAS}}";
                        ((TeamSiteCollection)siteCollection).DisplayName = siteProperties.Title;
                        ((TeamSiteCollection)siteCollection).HideTeamify = Core.Sites.SiteCollection.IsTeamifyPromptHiddenAsync(siteContext).GetAwaiter().GetResult();

                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE", siteProperties.Title);
                        siteCollection.Title = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE}}";
                        break;
                    }

                    case "STS#3":
                    {
                        siteCollection           = new TeamNoGroupSiteCollection();
                        siteCollection.IsHubSite = siteProperties.IsHubSite;
                        if (siteProperties.IsHubSite)
                        {
                            var hubsiteProperties = tenant.GetHubSitePropertiesByUrl(siteCollectionUrl);
                            tenant.Context.Load(hubsiteProperties);
                            tenant.Context.ExecuteQueryRetry();
                            siteCollection.HubSiteLogoUrl = hubsiteProperties.LogoUrl;
                            siteCollection.HubSiteTitle   = hubsiteProperties.Title;
                        }
                        siteCollection.Description = siteProperties.Description;
                        ((TeamNoGroupSiteCollection)siteCollection).Language   = (int)siteProperties.Lcid;
                        ((TeamNoGroupSiteCollection)siteCollection).Owner      = siteProperties.OwnerEmail;
                        ((TeamNoGroupSiteCollection)siteCollection).TimeZoneId = siteProperties.TimeZoneId;
                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_URL", siteProperties.Url);
                        ((TeamNoGroupSiteCollection)siteCollection).Url = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_URL}}";
                        tenantTemplate.Parameters.Add($"SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE", siteProperties.Title);
                        siteCollection.Title = $"{{parameter:SITECOLLECTION_{siteContext.Site.Id.ToString("N")}_TITLE}}";
                        break;
                    }
                    }
                    var siteTemplateCreationInfo = new ProvisioningTemplateCreationInformation(siteContext.Web);

                    // Retrieve the template for the site
                    if (configuration != null)
                    {
                        siteTemplateCreationInfo = configuration.ToCreationInformation(siteContext.Web);
                    }
                    var siteTemplate = siteContext.Web.GetProvisioningTemplate(siteTemplateCreationInfo);
                    siteTemplate.Id = $"TEMPLATE-{templateGuid}";
                    if (siteProperties.HubSiteId != null && siteProperties.HubSiteId != Guid.Empty && siteProperties.HubSiteId != siteContext.Site.Id && siteTemplate.WebSettings != null)
                    {
                        siteTemplate.WebSettings.HubSiteUrl = $"{{parameter:SITECOLLECTION_{siteProperties.HubSiteId.ToString("N")}_URL}}";
                    }
                    tenantTemplate.Templates.Add(siteTemplate);

                    siteCollection.Templates.Add(siteTemplate.Id);

                    if (siteProperties.WebsCount > 1 && configuration.Tenant.Sequence.IncludeSubsites)
                    {
                        var webs         = siteContext.Web.EnsureProperty(w => w.Webs);
                        int currentDepth = 1;
                        foreach (var subweb in webs)
                        {
                            siteCollection.Sites.Add(ParseSubsiteSequences(subweb, ref tenantTemplate, configuration, currentDepth, configuration.Tenant.Sequence.MaxSubsiteDepth));
                        }
                    }
                    provisioningSequence.SiteCollections.Add(siteCollection);
                }
            }

            tenantTemplate.Sequences.Add(provisioningSequence);

            PnPProvisioningContext.Current.ParsedSiteUrls.Clear();
            PnPProvisioningContext.Current.ParsedSiteUrls.AddRange(siteCollectionUrls);

            return(tenantTemplate);
        }
Example #9
0
 public override void Save(ProvisioningHierarchy hierarchy)
 {
     throw new NotImplementedException();
 }
Example #10
0
 public override void SaveAs(ProvisioningHierarchy hierarchy, string uri, ITemplateFormatter formatter = null)
 {
     throw new NotImplementedException();
 }
        public void ProvisionTenantTemplate()
        {
            if (TestCommon.AppOnlyTesting())
            {
                Assert.Inconclusive("This test does not yet work with app-only due to group connected site creation");
            }

            string tenantNameParamValue    = new Uri(TestCommon.DevSiteUrl).DnsSafeHost.Split('.')[0];
            string accountDomainParamValue = TestCommon.O365AccountDomain;

            if (string.IsNullOrEmpty(accountDomainParamValue))
            {
                accountDomainParamValue = "contoso.com";
            }

            var resourceFolder           = string.Format(@"{0}\..\..\..\Resources\Templates", AppDomain.CurrentDomain.BaseDirectory);
            XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(resourceFolder, "");

            var existingTemplate = provider.GetTemplate("ProvisioningSchema-2018-07-FullSample-01.xml");

            Guid siteGuid = Guid.NewGuid();
            int  siteId   = siteGuid.GetHashCode();
            var  template = new ProvisioningTemplate
            {
                Id = "TestTemplate"
            };

            template.Lists.Add(new ListInstance()
            {
                Title        = "Testlist",
                TemplateType = 100,
                Url          = "lists/testlist"
            });

            template.TermGroups.AddRange(existingTemplate.TermGroups);

            ProvisioningHierarchy hierarchy = new ProvisioningHierarchy();

            hierarchy.Templates.Add(template);

            hierarchy.Parameters.Add("CompanyName", "Contoso");

            if (!string.IsNullOrEmpty(tenantNameParamValue))
            {
                hierarchy.Parameters.Add("O365TenantName", tenantNameParamValue);
            }

            if (!string.IsNullOrEmpty(accountDomainParamValue))
            {
                hierarchy.Parameters.Add("O365AccountDomain", accountDomainParamValue);
            }

            var sequence = new ProvisioningSequence
            {
                ID = Guid.NewGuid().ToString(),

                TermStore = new ProvisioningTermStore()
            };

            var termGroup = new TermGroup()
            {
                Name = "Contoso TermGroup"
            };
            var termSet = new TermSet()
            {
                Name = "Projects", Id = Guid.NewGuid(), IsAvailableForTagging = true, Language = 1033
            };
            var term = new Term()
            {
                Name = "Contoso Term"
            };

            termSet.Terms.Add(term);
            // termGroup.TermSets.Add(termSet);

            var existingTermSet = existingTemplate.TermGroups[0].TermSets[0];

            termGroup.TermSets.Add(existingTermSet);

            // sequence.TermStore.TermGroups.Add(termGroup);

            var teamSite1 = new TeamSiteCollection()
            {
                //  Alias = $"prov-1-{siteId}",
                Alias       = "prov-1",
                Description = "prov-1",
                DisplayName = "prov-1",
                IsHubSite   = false,
                IsPublic    = false,
                Title       = "prov-1",
            };

            teamSite1.Templates.Add("TestTemplate");

            var subsite = new TeamNoGroupSubSite()
            {
                Description = "Test Sub",
                Url         = "testsub1",
                Language    = 1033,
                TimeZoneId  = 4,
                Title       = "Test Sub",
                UseSamePermissionsAsParentSite = true
            };

            subsite.Templates.Add("TestTemplate");
            teamSite1.Sites.Add(subsite);

            sequence.SiteCollections.Add(teamSite1);

            var teamSite2 = new TeamSiteCollection()
            {
                Alias       = $"prov-2-{siteId}",
                Description = "prov-2",
                DisplayName = "prov-2",
                IsHubSite   = false,
                IsPublic    = false,
                Title       = "prov-2"
            };

            teamSite2.Templates.Add("TestTemplate");

            sequence.SiteCollections.Add(teamSite2);

            hierarchy.Sequences.Add(sequence);


            using (var tenantContext = TestCommon.CreateTenantClientContext())
            {
                var applyConfiguration = new ApplyConfiguration
                {
                    ProgressDelegate = (message, step, total) =>
                    {
                        if (message != null)
                        {
                        }
                    }
                };

                var tenant = new Tenant(tenantContext);

                tenant.ApplyTenantTemplate(hierarchy, sequence.ID, applyConfiguration);
            }
        }
Example #12
0
        public static async Task RunAsync([ServiceBusTrigger("actions", IsSessionsEnabled = false)] ProvisioningActionModel action, ILogger logger)
        {
            var startProvisioning = DateTime.Now;

            String provisioningEnvironment = ConfigurationManager.AppSettings["SPPA:ProvisioningEnvironment"];

            logger.LogInformationWithPnPCorrelation("Processing queue trigger function for tenant {TenantId}", action.CorrelationId, action.TenantId);

            // Instantiate and use the telemetry model
            TelemetryUtility telemetry = new TelemetryUtility((s) => {
                logger.LogInformationWithPnPCorrelation(s, action.CorrelationId);
            });
            Dictionary <string, string> telemetryProperties = new Dictionary <string, string>();

            // Configure telemetry properties
            // telemetryProperties.Add("UserPrincipalName", action.UserPrincipalName);
            telemetryProperties.Add("TenantId", action.TenantId);
            telemetryProperties.Add("PnPCorrelationId", action.CorrelationId.ToString());
            telemetryProperties.Add("TargetSiteAlreadyExists", action.TargetSiteAlreadyExists.ToString());
            telemetryProperties.Add("TargetSiteBaseTemplateId", action.TargetSiteBaseTemplateId);

            // Get a reference to the data context
            ProvisioningAppDBContext dbContext = new ProvisioningAppDBContext();

            try
            {
                // Log telemetry event
                telemetry?.LogEvent("ProvisioningFunction.Start");

                if (CheckIfActionIsAlreadyRunning(action, dbContext))
                {
                    throw new ConcurrentProvisioningException("The requested package is currently provisioning in the selected target tenant and cannot be applied in parallel. Please wait for the previous provisioning action to complete.");
                }

                var tokenId = $"{action.TenantId}-{action.UserPrincipalName.ToLower().GetHashCode()}-{action.ActionType.ToString().ToLower()}-{provisioningEnvironment}";

                // Retrieve the SPO target tenant via Microsoft Graph
                var graphAccessToken = await ProvisioningAppManager.AccessTokenProvider.GetAccessTokenAsync(
                    tokenId, "https://graph.microsoft.com/",
                    ConfigurationManager.AppSettings[$"{action.ActionType}:ClientId"],
                    ConfigurationManager.AppSettings[$"{action.ActionType}:ClientSecret"],
                    ConfigurationManager.AppSettings[$"{action.ActionType}:AppUrl"]);

                logger.LogInformationWithPnPCorrelation("Retrieved target Microsoft Graph Access Token.", action.CorrelationId);

                if (!String.IsNullOrEmpty(graphAccessToken))
                {
                    #region Get current context data (User, SPO Tenant, SPO Access Token)

                    // Get the currently connected user name and email (UPN)
                    var jwtAccessToken = new System.IdentityModel.Tokens.Jwt.JwtSecurityToken(graphAccessToken);

                    String delegatedUPN = String.Empty;
                    var    upnClaim     = jwtAccessToken.Claims.FirstOrDefault(c => c.Type == "upn");
                    if (upnClaim != null && !String.IsNullOrEmpty(upnClaim.Value))
                    {
                        delegatedUPN = upnClaim.Value;
                    }

                    String delegatedUserName = String.Empty;
                    var    nameClaim         = jwtAccessToken.Claims.FirstOrDefault(c => c.Type == "name");
                    if (nameClaim != null && !String.IsNullOrEmpty(nameClaim.Value))
                    {
                        delegatedUserName = nameClaim.Value;
                    }

                    // Determine the URL of the root SPO site for the current tenant
                    var            rootSiteJson = HttpHelper.MakeGetRequestForString("https://graph.microsoft.com/v1.0/sites/root", graphAccessToken);
                    SharePointSite rootSite     = JsonConvert.DeserializeObject <SharePointSite>(rootSiteJson);

                    String spoTenant = rootSite.WebUrl;

                    logger.LogInformationWithPnPCorrelation("Target SharePoint Online Tenant: {SPOTenant}", action.CorrelationId, spoTenant);

                    // Configure telemetry properties
                    telemetryProperties.Add("SPOTenant", spoTenant);

                    // Retrieve the SPO Access Token
                    var spoAccessToken = await ProvisioningAppManager.AccessTokenProvider.GetAccessTokenAsync(
                        tokenId, rootSite.WebUrl,
                        ConfigurationManager.AppSettings[$"{action.ActionType}:ClientId"],
                        ConfigurationManager.AppSettings[$"{action.ActionType}:ClientSecret"],
                        ConfigurationManager.AppSettings[$"{action.ActionType}:AppUrl"]);

                    logger.LogInformationWithPnPCorrelation("Retrieved target SharePoint Online Access Token.", action.CorrelationId);

                    #endregion

                    // Connect to SPO, create and provision site
                    AuthenticationManager authManager = new AuthenticationManager();
                    using (ClientContext context = authManager.GetAzureADAccessTokenAuthenticatedContext(spoTenant, spoAccessToken))
                    {
                        // Telemetry and startup
                        var web = context.Web;
                        context.ClientTag = $"SPDev:ProvisioningPortal-{provisioningEnvironment}";
                        context.Load(web, w => w.Title, w => w.Id);
                        await context.ExecuteQueryAsync();

                        // Save the current SPO Correlation ID
                        telemetryProperties.Add("SPOCorrelationId", context.TraceCorrelationId);

                        logger.LogInformationWithPnPCorrelation("SharePoint Online Root Site Collection title: {WebTitle}", action.CorrelationId, web.Title);

                        #region Store the main site URL in KeyVault

                        // Store the main site URL in the Vault
                        var vault = ProvisioningAppManager.SecurityTokensServiceProvider;

                        // Read any existing properties for the current tenantId
                        var properties = await vault.GetAsync(tokenId);

                        if (properties == null)
                        {
                            // If there are no properties, create a new dictionary
                            properties = new Dictionary <String, String>();
                        }

                        // Set/Update the RefreshToken value
                        properties["SPORootSite"] = spoTenant;

                        // Add or Update the Key Vault accordingly
                        await vault.AddOrUpdateAsync(tokenId, properties);

                        #endregion

                        #region Provision the package

                        var package = dbContext.Packages.FirstOrDefault(p => p.Id == new Guid(action.PackageId));

                        if (package != null)
                        {
                            // Update the Popularity of the package
                            package.TimesApplied++;
                            dbContext.SaveChanges();

                            #region Get the Provisioning Hierarchy file

                            // Determine reference path variables
                            var blobConnectionString = ConfigurationManager.AppSettings["BlobTemplatesProvider:ConnectionString"];
                            var blobContainerName    = ConfigurationManager.AppSettings["BlobTemplatesProvider:ContainerName"];

                            var packageFileName           = package.PackageUrl.Substring(package.PackageUrl.LastIndexOf('/') + 1);
                            var packageFileUri            = new Uri(package.PackageUrl);
                            var packageFileRelativePath   = packageFileUri.AbsolutePath.Substring(2 + blobContainerName.Length);
                            var packageFileRelativeFolder = packageFileRelativePath.Substring(0, packageFileRelativePath.LastIndexOf('/'));

                            // Configure telemetry properties
                            telemetryProperties.Add("PackageFileName", packageFileName);
                            telemetryProperties.Add("PackageFileUri", packageFileUri.ToString());

                            // Read the main provisioning file from the Blob Storage
                            CloudStorageAccount csa;
                            if (!CloudStorageAccount.TryParse(blobConnectionString, out csa))
                            {
                                throw new ArgumentException("Cannot create cloud storage account from given connection string.");
                            }

                            CloudBlobClient    blobClient    = csa.CreateCloudBlobClient();
                            CloudBlobContainer blobContainer = blobClient.GetContainerReference(blobContainerName);

                            var blockBlob = blobContainer.GetBlockBlobReference(packageFileRelativePath);

                            // Crate an in-memory copy of the source stream
                            MemoryStream mem = new MemoryStream();
                            await blockBlob.DownloadToStreamAsync(mem);

                            mem.Position = 0;

                            // Prepare the output hierarchy
                            ProvisioningHierarchy hierarchy = null;

                            if (packageFileName.EndsWith(".xml", StringComparison.InvariantCultureIgnoreCase))
                            {
                                // That's an XML Provisioning Template file

                                XDocument xml = XDocument.Load(mem);
                                mem.Position = 0;

                                // Deserialize the stream into a provisioning hierarchy reading any
                                // dependecy with the Azure Blob Storage connector
                                var formatter           = XMLPnPSchemaFormatter.GetSpecificFormatter(xml.Root.Name.NamespaceName);
                                var templateLocalFolder = $"{blobContainerName}/{packageFileRelativeFolder}";

                                var provider = new XMLAzureStorageTemplateProvider(
                                    blobConnectionString,
                                    templateLocalFolder);
                                formatter.Initialize(provider);

                                // Get the full hierarchy
                                hierarchy           = ((IProvisioningHierarchyFormatter)formatter).ToProvisioningHierarchy(mem);
                                hierarchy.Connector = provider.Connector;
                            }
                            else if (packageFileName.EndsWith(".pnp", StringComparison.InvariantCultureIgnoreCase))
                            {
                                // That's a PnP Package file

                                // Get a provider based on the in-memory .PNP Open XML file
                                OpenXMLConnector    openXmlConnector = new OpenXMLConnector(mem);
                                XMLTemplateProvider provider         = new XMLOpenXMLTemplateProvider(
                                    openXmlConnector);

                                // Get the .xml provisioning template file name
                                var xmlTemplateFileName = openXmlConnector.Info?.Properties?.TemplateFileName ??
                                                          packageFileName.Substring(packageFileName.LastIndexOf('/') + 1)
                                                          .ToLower().Replace(".pnp", ".xml");

                                // Get the full hierarchy
                                hierarchy           = provider.GetHierarchy(xmlTemplateFileName);
                                hierarchy.Connector = provider.Connector;
                            }

                            #endregion

                            #region Apply the template

                            // Prepare variable to collect provisioned sites
                            var provisionedSites = new List <Tuple <String, String> >();

                            // If we have a hierarchy with at least one Sequence
                            if (hierarchy != null) // && hierarchy.Sequences != null && hierarchy.Sequences.Count > 0)
                            {
                                Console.WriteLine($"Provisioning hierarchy \"{hierarchy.DisplayName}\"");

                                var tenantUrl = UrlUtilities.GetTenantAdministrationUrl(context.Url);

                                // Retrieve the SPO Access Token
                                var spoAdminAccessToken = await ProvisioningAppManager.AccessTokenProvider.GetAccessTokenAsync(
                                    tokenId, tenantUrl,
                                    ConfigurationManager.AppSettings[$"{action.ActionType}:ClientId"],
                                    ConfigurationManager.AppSettings[$"{action.ActionType}:ClientSecret"],
                                    ConfigurationManager.AppSettings[$"{action.ActionType}:AppUrl"]);

                                logger.LogInformationWithPnPCorrelation("Retrieved target SharePoint Online Admin Center Access Token.", action.CorrelationId);

                                using (var tenantContext = authManager.GetAzureADAccessTokenAuthenticatedContext(tenantUrl, spoAdminAccessToken))
                                {
                                    using (var pnpTenantContext = PnPClientContext.ConvertFrom(tenantContext))
                                    {
                                        var tenant = new Microsoft.Online.SharePoint.TenantAdministration.Tenant(pnpTenantContext);

                                        // Prepare a dictionary to hold the access tokens
                                        var accessTokens = new Dictionary <String, String>();

                                        // Prepare logging for hierarchy application
                                        var ptai = new ProvisioningTemplateApplyingInformation();
                                        ptai.MessagesDelegate += delegate(string message, ProvisioningMessageType messageType)
                                        {
                                            logger.LogInformationWithPnPCorrelation($"{messageType} - {message.Replace("{", "{{").Replace("}", "}}")}", action.CorrelationId);
                                        };
                                        ptai.ProgressDelegate += delegate(string message, int step, int total)
                                        {
                                            logger.LogInformationWithPnPCorrelation($"{step:00}/{total:00} - {message.Replace("{", "{{").Replace("}", "}}")}", action.CorrelationId);
                                        };
                                        ptai.SiteProvisionedDelegate += delegate(string title, string url)
                                        {
                                            logger.LogInformationWithPnPCorrelation("Fully provisioned site '{SiteTitle}' with URL: {SiteUrl}", action.CorrelationId, title, url);
                                            var provisionedSite = new Tuple <string, string>(title, url);
                                            if (!provisionedSites.Contains(provisionedSite))
                                            {
                                                provisionedSites.Add(provisionedSite);
                                            }
                                        };

                                        // Configure the OAuth Access Tokens for the client context
                                        accessTokens.Add(new Uri(tenantUrl).Authority, spoAdminAccessToken);
                                        accessTokens.Add(new Uri(spoTenant).Authority, spoAccessToken);

                                        // Configure the OAuth Access Tokens for the PnPClientContext, too
                                        pnpTenantContext.PropertyBag["AccessTokens"] = accessTokens;
                                        ptai.AccessTokens = accessTokens;

                                        #region Theme handling

                                        // Process the graphical Theme
                                        if (action.ApplyTheme)
                                        {
                                            // If we don't have any custom Theme
                                            if (!action.ApplyCustomTheme)
                                            {
                                                // Associate the selected already existing Theme to all the sites of the hierarchy
                                                foreach (var sc in hierarchy.Sequences[0].SiteCollections)
                                                {
                                                    sc.Theme = action.SelectedTheme;
                                                    foreach (var s in sc.Sites)
                                                    {
                                                        UpdateChildrenSitesTheme(s, action.SelectedTheme);
                                                    }
                                                }
                                            }
                                        }

                                        #endregion

                                        // Configure provisioning parameters
                                        if (action.PackageProperties != null)
                                        {
                                            foreach (var key in action.PackageProperties.Keys)
                                            {
                                                if (hierarchy.Parameters.ContainsKey(key.ToString()))
                                                {
                                                    hierarchy.Parameters[key.ToString()] = action.PackageProperties[key].ToString();
                                                }
                                                else
                                                {
                                                    hierarchy.Parameters.Add(key.ToString(), action.PackageProperties[key].ToString());
                                                }

                                                // Configure telemetry properties
                                                telemetryProperties.Add($"PackageProperty.{key}", action.PackageProperties[key].ToString());
                                            }
                                        }

                                        // Log telemetry event
                                        telemetry?.LogEvent("ProvisioningFunction.BeginProvisioning", telemetryProperties);

                                        // Define a PnPProvisioningContext scope to share the security context across calls
                                        using (var pnpProvisioningContext = new PnPProvisioningContext(async(r, s) =>
                                        {
                                            if (accessTokens.ContainsKey(r))
                                            {
                                                // In this scenario we just use the dictionary of access tokens
                                                // in fact the overall operation for sure will take less than 1 hour
                                                return(await Task.FromResult(accessTokens[r]));
                                            }
                                            else
                                            {
                                                // Try to get a fresh new Access Token
                                                var token = await ProvisioningAppManager.AccessTokenProvider.GetAccessTokenAsync(
                                                    tokenId, $"https://{r}",
                                                    ConfigurationManager.AppSettings[$"{action.ActionType}:ClientId"],
                                                    ConfigurationManager.AppSettings[$"{action.ActionType}:ClientSecret"],
                                                    ConfigurationManager.AppSettings[$"{action.ActionType}:AppUrl"]);

                                                accessTokens.Add(r, token);

                                                return(token);
                                            }
                                        }))
                                        {
                                            // Configure the webhooks, if any
                                            if (action.Webhooks != null && action.Webhooks.Count > 0)
                                            {
                                                foreach (var t in hierarchy.Templates)
                                                {
                                                    foreach (var wh in action.Webhooks)
                                                    {
                                                        AddProvisioningTemplateWebhook(t, wh, ProvisioningTemplateWebhookKind.ProvisioningTemplateStarted);
                                                        AddProvisioningTemplateWebhook(t, wh, ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted);
                                                        AddProvisioningTemplateWebhook(t, wh, ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted);
                                                        AddProvisioningTemplateWebhook(t, wh, ProvisioningTemplateWebhookKind.ProvisioningTemplateCompleted);
                                                        AddProvisioningTemplateWebhook(t, wh, ProvisioningTemplateWebhookKind.ExceptionOccurred);
                                                    }
                                                }

                                                foreach (var wh in action.Webhooks)
                                                {
                                                    AddProvisioningWebhook(hierarchy, wh, ProvisioningTemplateWebhookKind.ProvisioningStarted);
                                                    AddProvisioningWebhook(hierarchy, wh, ProvisioningTemplateWebhookKind.ProvisioningCompleted);
                                                    AddProvisioningWebhook(hierarchy, wh, ProvisioningTemplateWebhookKind.ProvisioningExceptionOccurred);
                                                }
                                            }

                                            // Disable the WebSettings handler for non-admin users
                                            if (!TenantExtensions.IsCurrentUserTenantAdmin(tenantContext))
                                            {
                                                ptai.HandlersToProcess &= ~Handlers.WebSettings;
                                            }

                                            // Apply the hierarchy
                                            logger.LogInformationWithPnPCorrelation("Hierarchy Provisioning Started: {ProvisioningStartDateTime}", action.CorrelationId, DateTime.Now.ToString("hh.mm.ss"));
                                            tenant.ApplyProvisionHierarchy(hierarchy,
                                                                           (hierarchy.Sequences != null && hierarchy.Sequences.Count > 0) ?
                                                                           hierarchy.Sequences[0].ID : null,
                                                                           ptai);
                                            logger.LogInformationWithPnPCorrelation("Hierarchy Provisioning Completed: {ProvisioningEndDateTime}", action.CorrelationId, DateTime.Now.ToString("hh.mm.ss"));
                                        }

                                        if (action.ApplyTheme && action.ApplyCustomTheme)
                                        {
                                            if (!String.IsNullOrEmpty(action.ThemePrimaryColor) &&
                                                !String.IsNullOrEmpty(action.ThemeBodyTextColor) &&
                                                !String.IsNullOrEmpty(action.ThemeBodyBackgroundColor))
                                            {
                                                logger.LogInformationWithPnPCorrelation("Applying custom Theme to provisioned sites", action.CorrelationId);

                                                #region Palette generation for Theme

                                                var jsonPalette = ThemeUtility.GetThemeAsJSON(
                                                    action.ThemePrimaryColor,
                                                    action.ThemeBodyTextColor,
                                                    action.ThemeBodyBackgroundColor);

                                                #endregion

                                                // Apply the custom theme to all of the provisioned sites
                                                foreach (var ps in provisionedSites)
                                                {
                                                    using (var provisionedSiteContext = authManager.GetAzureADAccessTokenAuthenticatedContext(ps.Item2, spoAccessToken))
                                                    {
                                                        if (provisionedSiteContext.Web.ApplyTheme(jsonPalette))
                                                        {
                                                            logger.LogInformationWithPnPCorrelation($"Custom Theme applied on site '{ps.Item1}' with URL: {ps.Item2}", action.CorrelationId);
                                                        }
                                                        else
                                                        {
                                                            logger.LogInformationWithPnPCorrelation($"Failed to apply custom Theme on site '{ps.Item1}' with URL: {ps.Item2}", action.CorrelationId);
                                                        }
                                                    }
                                                }
                                            }
                                        }

                                        // Log telemetry event
                                        telemetry?.LogEvent("ProvisioningFunction.EndProvisioning", telemetryProperties);

                                        // Notify user about the provisioning outcome
                                        if (!String.IsNullOrEmpty(action.NotificationEmail))
                                        {
                                            var appOnlyAccessToken = await ProvisioningAppManager.AccessTokenProvider.GetAppOnlyAccessTokenAsync(
                                                "https://graph.microsoft.com/",
                                                ConfigurationManager.AppSettings["OfficeDevPnP:TenantId"],
                                                ConfigurationManager.AppSettings["OfficeDevPnP:ClientId"],
                                                ConfigurationManager.AppSettings["OfficeDevPnP:ClientSecret"],
                                                ConfigurationManager.AppSettings["OfficeDevPnP:AppUrl"]);

                                            MailHandler.SendMailNotification(
                                                "ProvisioningCompleted",
                                                action.NotificationEmail,
                                                null,
                                                new
                                            {
                                                TemplateName     = action.DisplayName,
                                                ProvisionedSites = provisionedSites,
                                            },
                                                appOnlyAccessToken);
                                        }

                                        // Log reporting event (1 = Success)
                                        LogReporting(action, provisioningEnvironment, startProvisioning, package, 1);

                                        // Log source tracking for provisioned sites
                                        LogSourceTrackingProvisionedSites(action, spoAccessToken, authManager, provisionedSites);
                                    }
                                }
                            }
                            else
                            {
                                throw new ApplicationException($"The requested package does not contain a valid PnP Hierarchy!");
                            }

                            #endregion
                        }
                        else
                        {
                            throw new ApplicationException($"Cannot find the package with ID: {action.PackageId}");
                        }

                        #endregion

                        #region Process any children items

                        // If there are children items
                        if (action.ChildrenItems != null && action.ChildrenItems.Count > 0)
                        {
                            // Prepare any further child provisioning request
                            action.PackageId         = action.ChildrenItems[0].PackageId;
                            action.PackageProperties = action.ChildrenItems[0].Parameters;
                            action.ChildrenItems.RemoveAt(0);

                            // Enqueue any further child provisioning request
                            await ProvisioningAppManager.EnqueueProvisioningRequest(action);
                        }

                        #endregion

                        logger.LogInformationWithPnPCorrelation("Function successfully executed!", action.CorrelationId);
                        // Log telemetry event
                        telemetry?.LogEvent("ProvisioningFunction.End", telemetryProperties);
                    }
                }
                else
                {
                    var noTokensErrorMessage = $"Cannot retrieve Refresh Token or Access Token for action {action.CorrelationId} in tenant {action.TenantId}!";
                    logger.LogInformationWithPnPCorrelation(noTokensErrorMessage, action.CorrelationId);
                    throw new ApplicationException(noTokensErrorMessage);
                }
            }
            catch (Exception ex)
            {
                // Skip logging exception for Recycled Site
                if (ex is RecycledSiteException)
                {
                    // Log reporting event (3 = RecycledSite)
                    LogReporting(action, provisioningEnvironment, startProvisioning, null, 3, ex.ToDetailedString());

                    // rather log an event
                    telemetry?.LogEvent("ProvisioningFunction.RecycledSite", telemetryProperties);
                }
                // Skip logging exception for Concurrent Provisioning
                else if (ex is ConcurrentProvisioningException)
                {
                    // Log reporting event (4 = ConcurrentProvisioningException)
                    LogReporting(action, provisioningEnvironment, startProvisioning, null, 4, ex.ToDetailedString());

                    // rather log an event
                    telemetry?.LogEvent("ProvisioningFunction.ConcurrentProvisioning", telemetryProperties);
                }
                else
                {
                    // Log reporting event (2 = Failed)
                    LogReporting(action, provisioningEnvironment, startProvisioning, null, 2, ex.ToDetailedString());

                    // Log telemetry event
                    telemetry?.LogException(ex, "ProvisioningFunction.RunAsync", telemetryProperties);
                }

                if (!String.IsNullOrEmpty(action.NotificationEmail))
                {
                    var appOnlyAccessToken = await ProvisioningAppManager.AccessTokenProvider.GetAppOnlyAccessTokenAsync(
                        "https://graph.microsoft.com/",
                        ConfigurationManager.AppSettings["OfficeDevPnP:TenantId"],
                        ConfigurationManager.AppSettings["OfficeDevPnP:ClientId"],
                        ConfigurationManager.AppSettings["OfficeDevPnP:ClientSecret"],
                        ConfigurationManager.AppSettings["OfficeDevPnP:AppUrl"]);

                    // Notify user about the provisioning outcome
                    MailHandler.SendMailNotification(
                        "ProvisioningFailed",
                        action.NotificationEmail,
                        null,
                        new
                    {
                        TemplateName     = action.DisplayName,
                        ExceptionDetails = SimplifyException(ex),
                        PnPCorrelationId = action.CorrelationId.ToString(),
                    },
                        appOnlyAccessToken);
                }

                ProcessWebhooksExceptionNotification(action, ex);

                // Track the failure in the local action log
                MarkCurrentActionItemAsFailed(action, dbContext);

                throw ex;
            }
            finally
            {
                // Try to cleanup the pending action item, if any
                CleanupCurrentActionItem(action, dbContext);

                telemetry?.Flush();
            }
        }
 /// <summary>
 /// Constructor for ProvisioningSequenceCollection class
 /// </summary>
 /// <param name="parentProvisioning">Parent Provisioning object</param>
 public ProvisioningSequenceCollection(ProvisioningHierarchy parentProvisioning) :
     base(parentProvisioning)
 {
 }
Example #14
0
        private async Task FillPackageAsync(DomainModel.Package package, ITemplateFile packageFile)
        {
            using (Stream stream = await packageFile.DownloadAsync())
            {
                // Crate a copy of the source stream
                MemoryStream mem = new MemoryStream();
                await stream.CopyToAsync(mem);

                mem.Position = 0;

                // Prepare the output hierarchy
                ProvisioningHierarchy hierarchy = null;

                if (packageFile.Path.EndsWith(".xml", StringComparison.InvariantCultureIgnoreCase))
                {
                    // That's an XML Provisioning Template file

                    XDocument xml = XDocument.Load(mem);
                    mem.Position = 0;

                    // Deserialize the stream into a provisioning hierarchy reading any
                    // dependecy with the Azure Blob Storage connector
                    var formatter           = XMLPnPSchemaFormatter.GetSpecificFormatter(xml.Root.Name.NamespaceName);
                    var templateLocalFolder = $"{ConfigurationManager.AppSettings["BlobTemplatesProvider:ContainerName"]}/{packageFile.Path.Substring(0, packageFile.Path.LastIndexOf('/'))}";

                    var provider = new XMLAzureStorageTemplateProvider(
                        ConfigurationManager.AppSettings["BlobTemplatesProvider:ConnectionString"],
                        templateLocalFolder);
                    formatter.Initialize(provider);

                    // Get the full hierarchy
                    hierarchy = ((IProvisioningHierarchyFormatter)formatter).ToProvisioningHierarchy(mem);
                }
                else if (packageFile.Path.EndsWith(".pnp", StringComparison.InvariantCultureIgnoreCase))
                {
                    // That's a PnP Package file

                    // Get a provider based on the in-memory .PNP Open XML file
                    OpenXMLConnector    openXmlConnector = new OpenXMLConnector(mem);
                    XMLTemplateProvider provider         = new XMLOpenXMLTemplateProvider(
                        openXmlConnector);

                    // Get the .xml provisioning template file name
                    var xmlTemplateFileName = openXmlConnector.Info?.Properties?.TemplateFileName ??
                                              packageFile.Path.Substring(packageFile.Path.LastIndexOf('/') + 1)
                                              .ToLower().Replace(".pnp", ".xml");

                    // Get the full hierarchy
                    hierarchy = provider.GetHierarchy(xmlTemplateFileName);
                }

                if (hierarchy != null)
                {
                    package.DisplayName     = hierarchy.DisplayName;
                    package.ImagePreviewUrl = ChangeUri(packageFile.DownloadUri, hierarchy?.ImagePreviewUrl ?? String.Empty);
                    package.Description     = await GetDescriptionAsync(packageFile.GetDirectoryPath()) ?? hierarchy?.Description ?? "";

                    package.Version           = hierarchy?.Version.ToString();
                    package.PackageProperties = JsonConvert.SerializeObject(hierarchy.Parameters);
                }
            }
        }
Example #15
0
 public override ProvisioningHierarchy ExtractObjects(Tenant tenant, ProvisioningHierarchy hierarchy, ProvisioningTemplateCreationInformation creationInfo)
 {
     throw new NotImplementedException();
 }
        protected override void ExecuteCmdlet()
        {
            var sitesProvisioned = new List <ProvisionedSite>();
            var configuration    = new ApplyConfiguration();

            if (ParameterSpecified(nameof(Configuration)))
            {
                configuration = Configuration.GetConfiguration(SessionState.Path.CurrentFileSystemLocation.Path);
            }


            configuration.SiteProvisionedDelegate = (title, url) =>
            {
                if (sitesProvisioned.FirstOrDefault(s => s.Url == url) == null)
                {
                    sitesProvisioned.Add(new ProvisionedSite()
                    {
                        Title = title, Url = url
                    });
                }
            };

            if (ParameterSpecified(nameof(Handlers)))
            {
                if (!Handlers.Has(Handlers.All))
                {
                    foreach (var enumValue in (Handlers[])Enum.GetValues(typeof(Handlers)))
                    {
                        if (Handlers.Has(enumValue))
                        {
                            if (enumValue == Handlers.TermGroups)
                            {
                                configuration.Handlers.Add(ConfigurationHandler.Taxonomy);
                            }
                            else if (enumValue == Handlers.PageContents)
                            {
                                configuration.Handlers.Add(ConfigurationHandler.Pages);
                            }
                            else if (Enum.TryParse <ConfigurationHandler>(enumValue.ToString(), out ConfigurationHandler configHandler))
                            {
                                configuration.Handlers.Add(configHandler);
                            }
                        }
                    }
                }
            }
            if (ParameterSpecified(nameof(ExcludeHandlers)))
            {
                foreach (var handler in (Handlers[])Enum.GetValues(typeof(Handlers)))
                {
                    if (!ExcludeHandlers.Has(handler) && handler != Handlers.All)
                    {
                        if (handler == Handlers.TermGroups)
                        {
                            if (configuration.Handlers.Contains(ConfigurationHandler.Taxonomy))
                            {
                                configuration.Handlers.Remove(ConfigurationHandler.Taxonomy);
                            }
                            else if (Enum.TryParse <ConfigurationHandler>(handler.ToString(), out ConfigurationHandler configHandler))
                            {
                                if (configuration.Handlers.Contains(configHandler))
                                {
                                    configuration.Handlers.Remove(configHandler);
                                }
                            }
                        }
                    }
                }
            }

            if (ExtensibilityHandlers != null)
            {
                configuration.Extensibility.Handlers = ExtensibilityHandlers.ToList();
            }

            configuration.ProgressDelegate = (message, step, total) =>
            {
                if (message != null)
                {
                    var percentage = Convert.ToInt32((100 / Convert.ToDouble(total)) * Convert.ToDouble(step));
                    progressRecord.Activity          = $"Applying template to tenant";
                    progressRecord.StatusDescription = message;
                    progressRecord.PercentComplete   = percentage;
                    progressRecord.RecordType        = ProgressRecordType.Processing;
                    WriteProgress(progressRecord);
                }
            };

            var warningsShown = new List <string>();

            configuration.MessagesDelegate = (message, type) =>
            {
                switch (type)
                {
                case ProvisioningMessageType.Warning:
                {
                    if (!warningsShown.Contains(message))
                    {
                        WriteWarning(message);
                        warningsShown.Add(message);
                    }
                    break;
                }

                case ProvisioningMessageType.Progress:
                {
                    if (message != null)
                    {
                        var activity = message;
                        if (message.IndexOf("|") > -1)
                        {
                            var messageSplitted = message.Split('|');
                            if (messageSplitted.Length == 4)
                            {
                                var current = double.Parse(messageSplitted[2]);
                                var total   = double.Parse(messageSplitted[3]);
                                subProgressRecord.RecordType        = ProgressRecordType.Processing;
                                subProgressRecord.Activity          = string.IsNullOrEmpty(messageSplitted[0]) ? "-" : messageSplitted[0];
                                subProgressRecord.StatusDescription = string.IsNullOrEmpty(messageSplitted[1]) ? "-" : messageSplitted[1];
                                subProgressRecord.PercentComplete   = Convert.ToInt32((100 / total) * current);
                                WriteProgress(subProgressRecord);
                            }
                            else
                            {
                                subProgressRecord.Activity          = "Processing";
                                subProgressRecord.RecordType        = ProgressRecordType.Processing;
                                subProgressRecord.StatusDescription = activity;
                                subProgressRecord.PercentComplete   = 0;
                                WriteProgress(subProgressRecord);
                            }
                        }
                        else
                        {
                            subProgressRecord.Activity          = "Processing";
                            subProgressRecord.RecordType        = ProgressRecordType.Processing;
                            subProgressRecord.StatusDescription = activity;
                            subProgressRecord.PercentComplete   = 0;
                            WriteProgress(subProgressRecord);
                        }
                    }
                    break;
                }

                case ProvisioningMessageType.Completed:
                {
                    WriteProgress(new ProgressRecord(1, message, " ")
                        {
                            RecordType = ProgressRecordType.Completed
                        });
                    break;
                }
                }
            };

            configuration.PropertyBag.OverwriteSystemValues           = OverwriteSystemPropertyBagValues;
            configuration.Lists.IgnoreDuplicateDataRowErrors          = IgnoreDuplicateDataRowErrors;
            configuration.Navigation.ClearNavigation                  = ClearNavigation;
            configuration.ContentTypes.ProvisionContentTypesToSubWebs = ProvisionContentTypesToSubWebs;
            configuration.Fields.ProvisionFieldsToSubWebs             = ProvisionFieldsToSubWebs;

            ProvisioningHierarchy hierarchyToApply = null;

            switch (ParameterSetName)
            {
            case ParameterSet_PATH:
            {
                hierarchyToApply = GetHierarchy();
                break;
            }

            case ParameterSet_OBJECT:
            {
                hierarchyToApply = Template;
                if (ResourceFolder != null)
                {
                    var fileSystemConnector = new FileSystemConnector(ResourceFolder, "");
                    hierarchyToApply.Connector = fileSystemConnector;
                }
                else
                {
                    if (Path != null)
                    {
                        if (!System.IO.Path.IsPathRooted(Path))
                        {
                            Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
                        }
                    }
                    else
                    {
                        Path = SessionState.Path.CurrentFileSystemLocation.Path;
                    }
                    var fileInfo      = new FileInfo(Path);
                    var fileConnector = new FileSystemConnector(fileInfo.DirectoryName, "");
                    hierarchyToApply.Connector = fileConnector;
                }
                break;
            }
            }
            if (Parameters != null)
            {
                foreach (var parameter in Parameters.Keys)
                {
                    if (hierarchyToApply.Parameters.ContainsKey(parameter.ToString()))
                    {
                        hierarchyToApply.Parameters[parameter.ToString()] = Parameters[parameter].ToString();
                    }
                    else
                    {
                        hierarchyToApply.Parameters.Add(parameter.ToString(), Parameters[parameter].ToString());
                    }
                }
            }
#if !ONPREMISES
            // check if consent is needed and in place
            var consentRequired = false;
            if (hierarchyToApply.Teams != null)
            {
                consentRequired = true;
            }
            if (hierarchyToApply.AzureActiveDirectory != null)
            {
                consentRequired = true;
            }
            if (consentRequired)
            {
                // try to retrieve an access token for the Microsoft Graph:

                var accessToken = PnPConnection.CurrentConnection.TryGetAccessToken(Enums.TokenAudience.MicrosoftGraph);
                if (accessToken == null)
                {
                    if (PnPConnection.CurrentConnection.PSCredential != null)
                    {
                        // Using normal credentials
                        accessToken = TokenHandler.AcquireToken("graph.microsoft.com", null);
                    }
                    if (accessToken == null)
                    {
                        throw new PSInvalidOperationException("Your template contains artifacts that require an access token. Please provide consent to the PnP Management Shell application first by executing: Register-PnPManagementShellAccess");
                    }
                }
            }

            using (var provisioningContext = new PnPProvisioningContext((resource, scope) =>
            {
                if (resource.ToLower().StartsWith("https://"))
                {
                    var uri = new Uri(resource);
                    resource = uri.Authority;
                }
                // Get Azure AD Token
                if (PnPConnection.CurrentConnection != null)
                {
                    if (resource.Equals("graph.microsoft.com", StringComparison.OrdinalIgnoreCase))
                    {
                        var graphAccessToken = PnPConnection.CurrentConnection.TryGetAccessToken(Enums.TokenAudience.MicrosoftGraph);
                        if (graphAccessToken != null)
                        {
                            // Authenticated using -Graph or using another way to retrieve the accesstoken with Connect-PnPOnline
                            return(Task.FromResult(graphAccessToken));
                        }
                    }
                }

                if (PnPConnection.CurrentConnection.PSCredential != null)
                {
                    // Using normal credentials
                    return(Task.FromResult(TokenHandler.AcquireToken(resource, null)));
                }
                else
                {
                    // No token...
                    throw new PSInvalidOperationException("Your template contains artifacts that require an access token. Please provide consent to the PnP Management Shell application first by executing: Register-PnPManagementShellAccess");
                }
            }))
            {
#endif
            if (!string.IsNullOrEmpty(SequenceId))
            {
                Tenant.ApplyTenantTemplate(hierarchyToApply, SequenceId, configuration);
            }
            else
            {
                if (hierarchyToApply.Sequences.Count > 0)
                {
                    foreach (var sequence in hierarchyToApply.Sequences)
                    {
                        Tenant.ApplyTenantTemplate(hierarchyToApply, sequence.ID, configuration);
                    }
                }
                else
                {
                    Tenant.ApplyTenantTemplate(hierarchyToApply, null, configuration);
                }
            }
#if !ONPREMISES
        }
#endif
            WriteObject(sitesProvisioned, true);
        }
Example #17
0
        public Stream ToFormattedHierarchy(ProvisioningHierarchy hierarchy)
        {
            if (hierarchy == null)
            {
                throw new ArgumentNullException(nameof(hierarchy));
            }

            using (var scope = new PnPSerializationScope(typeof(TSchemaTemplate)))
            {
                // We prepare a dummy template to leverage the existing deserialization infrastructure
                var dummyTemplate = new ProvisioningTemplate();
                dummyTemplate.Id = $"DUMMY-{Guid.NewGuid()}";
                hierarchy.Templates.Add(dummyTemplate);

                // Prepare the output wrapper
                Type   wrapperType;
                object wrapper, templatesItem;
                Array  templates;

                ProcessOutputHierarchy(dummyTemplate, out wrapperType, out wrapper, out templates, out templatesItem);

                // Handle the Sequences, if any
                var ts = new SequenceSerializer();
                ts.Serialize(dummyTemplate, wrapper);

                // Remove the dummy template
                hierarchy.Templates.Remove(dummyTemplate);

                // Add every single template to the output
                var provisioningTemplates = Array.CreateInstance(typeof(TSchemaTemplate), hierarchy.Templates.Count);
                for (int c = 0; c < hierarchy.Templates.Count; c++)
                {
                    // Prepare variable to hold the output template
                    var outputTemplate = new TSchemaTemplate();

                    // Serialize the real templates
                    SerializeTemplate(hierarchy.Templates[c], outputTemplate);

                    // Add the serialized template to the output
                    provisioningTemplates.SetValue(outputTemplate, c);
                }

                templatesItem.GetType().GetProperty("ProvisioningTemplate",
                                                    System.Reflection.BindingFlags.Instance |
                                                    System.Reflection.BindingFlags.Public |
                                                    System.Reflection.BindingFlags.IgnoreCase).SetValue(templatesItem, provisioningTemplates);

                templates.SetValue(templatesItem, 0);

                wrapperType.GetProperty("Templates",
                                        System.Reflection.BindingFlags.Instance |
                                        System.Reflection.BindingFlags.Public |
                                        System.Reflection.BindingFlags.IgnoreCase).SetValue(wrapper, templates);

                XmlSerializerNamespaces ns =
                    new XmlSerializerNamespaces();
                ns.Add(((IXMLSchemaFormatter)this).NamespacePrefix,
                       ((IXMLSchemaFormatter)this).NamespaceUri);

                MemoryStream  output        = new MemoryStream();
                XmlSerializer xmlSerializer = new XmlSerializer(wrapperType);
                if (ns != null)
                {
                    xmlSerializer.Serialize(output, wrapper, ns);
                }
                else
                {
                    xmlSerializer.Serialize(output, wrapper);
                }

                output.Position = 0;
                return(output);
            }
        }
        protected override void ExecuteCmdlet()
        {
            var applyingInformation = new ProvisioningTemplateApplyingInformation();

            if (MyInvocation.BoundParameters.ContainsKey("Handlers"))
            {
                applyingInformation.HandlersToProcess = Handlers;
            }
            if (MyInvocation.BoundParameters.ContainsKey("ExcludeHandlers"))
            {
                foreach (var handler in (Handlers[])Enum.GetValues(typeof(Handlers)))
                {
                    if (!ExcludeHandlers.Has(handler) && handler != Handlers.All)
                    {
                        Handlers = Handlers | handler;
                    }
                }
                applyingInformation.HandlersToProcess = Handlers;
            }

            if (ExtensibilityHandlers != null)
            {
                applyingInformation.ExtensibilityHandlers = ExtensibilityHandlers.ToList();
            }

            applyingInformation.ProgressDelegate = (message, step, total) =>
            {
                if (message != null)
                {
                    var percentage = Convert.ToInt32((100 / Convert.ToDouble(total)) * Convert.ToDouble(step));
                    progressRecord.Activity          = $"Applying template to tenant";
                    progressRecord.StatusDescription = message;
                    progressRecord.PercentComplete   = percentage;
                    progressRecord.RecordType        = ProgressRecordType.Processing;
                    WriteProgress(progressRecord);
                }
            };

            var warningsShown = new List <string>();

            applyingInformation.MessagesDelegate = (message, type) =>
            {
                switch (type)
                {
                case ProvisioningMessageType.Warning:
                {
                    if (!warningsShown.Contains(message))
                    {
                        WriteWarning(message);
                        warningsShown.Add(message);
                    }
                    break;
                }

                case ProvisioningMessageType.Progress:
                {
                    if (message != null)
                    {
                        var activity = message;
                        if (message.IndexOf("|") > -1)
                        {
                            var messageSplitted = message.Split('|');
                            if (messageSplitted.Length == 4)
                            {
                                var current = double.Parse(messageSplitted[2]);
                                var total   = double.Parse(messageSplitted[3]);
                                subProgressRecord.RecordType        = ProgressRecordType.Processing;
                                subProgressRecord.Activity          = string.IsNullOrEmpty(messageSplitted[0]) ? "-" : messageSplitted[0];
                                subProgressRecord.StatusDescription = string.IsNullOrEmpty(messageSplitted[1]) ? "-" : messageSplitted[1];
                                subProgressRecord.PercentComplete   = Convert.ToInt32((100 / total) * current);
                                WriteProgress(subProgressRecord);
                            }
                            else
                            {
                                subProgressRecord.Activity          = "Processing";
                                subProgressRecord.RecordType        = ProgressRecordType.Processing;
                                subProgressRecord.StatusDescription = activity;
                                subProgressRecord.PercentComplete   = 0;
                                WriteProgress(subProgressRecord);
                            }
                        }
                        else
                        {
                            subProgressRecord.Activity          = "Processing";
                            subProgressRecord.RecordType        = ProgressRecordType.Processing;
                            subProgressRecord.StatusDescription = activity;
                            subProgressRecord.PercentComplete   = 0;
                            WriteProgress(subProgressRecord);
                        }
                    }
                    break;
                }

                case ProvisioningMessageType.Completed:
                {
                    WriteProgress(new ProgressRecord(1, message, " ")
                        {
                            RecordType = ProgressRecordType.Completed
                        });
                    break;
                }
                }
            };

            applyingInformation.OverwriteSystemPropertyBagValues = OverwriteSystemPropertyBagValues;
            applyingInformation.IgnoreDuplicateDataRowErrors     = IgnoreDuplicateDataRowErrors;
            applyingInformation.ClearNavigation = ClearNavigation;
            applyingInformation.ProvisionContentTypesToSubWebs = ProvisionContentTypesToSubWebs;
            applyingInformation.ProvisionFieldsToSubWebs       = ProvisionFieldsToSubWebs;

            ProvisioningHierarchy hierarchyToApply = null;

            switch (ParameterSetName)
            {
            case ParameterSet_PATH:
            {
                hierarchyToApply = GetHierarchy();
                break;
            }

            case ParameterSet_OBJECT:
            {
                hierarchyToApply = Hierarchy;
                if (ResourceFolder != null)
                {
                    var fileSystemConnector = new FileSystemConnector(ResourceFolder, "");
                    hierarchyToApply.Connector = fileSystemConnector;
                }
                else
                {
                    if (Path != null)
                    {
                        if (!System.IO.Path.IsPathRooted(Path))
                        {
                            Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
                        }
                    }
                    else
                    {
                        Path = SessionState.Path.CurrentFileSystemLocation.Path;
                    }
                    var fileInfo      = new FileInfo(Path);
                    var fileConnector = new FileSystemConnector(fileInfo.DirectoryName, "");
                    hierarchyToApply.Connector = fileConnector;
                }
                break;
            }
            }
            if (Parameters != null)
            {
                foreach (var parameter in Parameters.Keys)
                {
                    if (hierarchyToApply.Parameters.ContainsKey(parameter.ToString()))
                    {
                        hierarchyToApply.Parameters[parameter.ToString()] = Parameters[parameter].ToString();
                    }
                    else
                    {
                        hierarchyToApply.Parameters.Add(parameter.ToString(), Parameters[parameter].ToString());
                    }
                }
            }
            if (!string.IsNullOrEmpty(SequenceId))
            {
                Tenant.ApplyProvisionHierarchy(hierarchyToApply, SequenceId, applyingInformation);
            }
            else
            {
                foreach (var sequence in hierarchyToApply.Sequences)
                {
                    Tenant.ApplyProvisionHierarchy(hierarchyToApply, sequence.ID, applyingInformation);
                }
            }
        }
Example #19
0
 /// <summary>
 /// Constructor for SiteCollectionCollection class
 /// </summary>
 /// <param name="parentHierarchy">Parent Provisioning object</param>
 public SiteCollectionCollection(ProvisioningHierarchy parentHierarchy) :
     base(parentHierarchy)
 {
 }