public void OpenXMLFileDuplicationTest()
        {
            var fileSystemConnector = new FileSystemConnector(
                String.Format(@"{0}\..\..\Resources",
                              AppDomain.CurrentDomain.BaseDirectory),
                "Templates");

            int retries = 3;

            while (retries-- > 0)
            {
                var openXMLConnector = new OpenXMLConnector(packageFileName,
                                                            fileSystemConnector,
                                                            "OfficeDevPnP Automated Test");

                SaveFileInPackage(fileSystemConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + @"\garagelogo.png", "Images\\OpenXMLFileDuplicationTest", openXMLConnector);
                SaveFileInPackage(fileSystemConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + @"\garagebg.jpg", "Images/OpenXMLFileDuplicationTest", openXMLConnector);

                var files = openXMLConnector.GetFiles("Images\\OpenXMLFileDuplicationTest");
                Assert.IsTrue(files.Count == 2);

                files = openXMLConnector.GetFiles("Images/OpenXMLFileDuplicationTest");
                Assert.IsTrue(files.Count == 2);

                if (openXMLConnector is ICommitableFileConnector)
                {
                    ((ICommitableFileConnector)openXMLConnector).Commit();
                }
            }
        }
Example #2
0
        // ===========================================================================================================
        /// <summary>
        /// Applies the current template as an open XML ".pnp" package on the specified web
        /// </summary>
        /// <param name="web">The <b>Web</b> on which to apply the template</param>
        /// <param name="templateProvider">The <b>XMLTemplateProvider</b> that is mapped to the client's working directory</param>
        // ===========================================================================================================
        private void ApplyOpenXML(Web web, XMLTemplateProvider templateProvider)
        {
            logger.Info("Applying open XML package '{0}' from file '{1}'", this.Name, this.Path);

            // --------------------------------------------------
            // Formats the template's execution rendering
            // --------------------------------------------------
            ProvisioningTemplateApplyingInformation ptai = GetTemplateApplyInfo();

            // --------------------------------------------------
            // Replaces the regular provider by an OpenXml one
            // --------------------------------------------------
            string workingDirectory = templateProvider.Connector.Parameters[PARAMETER_CONNECTION_STRING].ToString();
            FileSystemConnector fileSystemConnector     = new FileSystemConnector(workingDirectory, "");
            OpenXMLConnector    openXmlConnector        = new OpenXMLConnector(this.Path, fileSystemConnector);
            XMLTemplateProvider openXmlTemplateProvider = new XMLOpenXMLTemplateProvider(openXmlConnector);

            // --------------------------------------------------
            // Loops through all templates within the .pnp package
            // --------------------------------------------------
            List <ProvisioningTemplate> templates = openXmlTemplateProvider.GetTemplates();

            foreach (ProvisioningTemplate template in templates)
            {
                logger.Info("Applying template '{0}' from file '{1}'", template.Id, this.Path);

                // --------------------------------------------------
                // Applies the template
                // --------------------------------------------------
                template.Connector = openXmlTemplateProvider.Connector;
                web.ApplyProvisioningTemplate(template, ptai);
            }
        }
Example #3
0
        public void OpenXMLLoadTemplate()
        {
            var fileSystemConnector = new FileSystemConnector(
                String.Format(@"{0}\..\..\Resources",
                              AppDomain.CurrentDomain.BaseDirectory),
                "Templates");

            var openXMLConnector = new OpenXMLConnector(packageFileName,
                                                        fileSystemConnector);

            var templateFile = openXMLConnector.GetFileStream("ProvisioningSchema-2015-12-FullSample-02.xml");

            XMLPnPSchemaV201512Formatter formatter = new XMLPnPSchemaV201512Formatter();
            Boolean checkTemplate = formatter.IsValid(templateFile);

            Assert.IsTrue(checkTemplate);

            var image1 = openXMLConnector.GetFileStream("garagelogo.png", "Images");

            Assert.IsNotNull(image1);

            var image2 = openXMLConnector.GetFileStream("garagelogo.png", "Images");

            Assert.IsNotNull(image2);
        }
Example #4
0
        internal static ProvisioningTemplate LoadProvisioningTemplateFromFile(string templatePath, ITemplateProviderExtension[] templateProviderExtensions, Action <Exception> exceptionHandler)
        {
            // Prepare the File Connector
            string templateFileName = System.IO.Path.GetFileName(templatePath);

            // Prepare the template path
            var fileInfo = new FileInfo(templatePath);
            FileConnectorBase fileConnector = new FileSystemConnector(fileInfo.DirectoryName, "");

            // Load the provisioning template file
            Stream stream = fileConnector.GetFileStream(templateFileName);

            if (stream == null)
            {
                throw new FileNotFoundException($"File {templatePath} does not exist.", templatePath);
            }

            var isOpenOfficeFile = FileUtilities.IsOpenOfficeFile(stream);

            XMLTemplateProvider provider;

            if (isOpenOfficeFile)
            {
                var openXmlConnector = new OpenXMLConnector(templateFileName, fileConnector);
                provider = new XMLOpenXMLTemplateProvider(openXmlConnector);
                if (!String.IsNullOrEmpty(openXmlConnector.Info?.Properties?.TemplateFileName))
                {
                    templateFileName = openXmlConnector.Info.Properties.TemplateFileName;
                }
                else
                {
                    templateFileName = templateFileName.Substring(0, templateFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";
                }
            }
            else
            {
                provider = new XMLFileSystemTemplateProvider(fileConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + "", "");
            }
            try
            {
                ProvisioningTemplate provisioningTemplate = provider.GetTemplate(templateFileName, templateProviderExtensions);
                provisioningTemplate.Connector = provider.Connector;
                return(provisioningTemplate);
            }
            catch (ApplicationException ex)
            {
                if (ex.InnerException is AggregateException)
                {
                    if (exceptionHandler != null)
                    {
                        foreach (var exception in ((AggregateException)ex.InnerException).InnerExceptions)
                        {
                            exceptionHandler(exception);
                        }
                    }
                }
            }
            return(null);
        }
Example #5
0
        private ProvisioningTemplate GetProvisioningTemplate()
        {
            var connector        = new OpenXMLConnector(stream);
            var templateProvider = new XMLOpenXMLTemplateProvider(connector);

            var templates = templateProvider.GetTemplates();
            var template  = templates.Single();

            template.Connector = connector;

            return(template);
        }
        public ProvisioningHierarchy GetTenantTemplate(string templateUri)
        {
            // Get the URL of the Templates repository Site Collection
            var targetSiteUrl = SPOUtilities.GetSiteCollectionRootUrl(templateUri);

            // Connect to the Templates repository Site Collection
            using (var context = SPOContextProvider.BuildAppOnlyClientContext(targetSiteUrl))
            {
                // Get a reference to the target library
                Web web = context.Web;

                web.EnsureProperty(w => w.Url);

                var packageFileName = templateUri.Substring(templateUri.LastIndexOf("/") + 1);

                // Configure the SharePoint Connector
                var sharepointConnector = new SharePointConnector(context, web.Url,
                                                                  Environment.GetEnvironmentVariable("TemplatesLibrary"));

                TemplateProviderBase provider = null;

                // Configure the initial template file name
                String xmlTemplateFileName = packageFileName;

                // If the target is a .PNP Open XML template
                if (packageFileName.ToLower().EndsWith(".pnp", StringComparison.InvariantCultureIgnoreCase))
                {
                    // Configure the Open XML provider for SharePoint
                    OpenXMLConnector openXmlConnector = new OpenXMLConnector(packageFileName, sharepointConnector);
                    provider = new XMLOpenXMLTemplateProvider(openXmlConnector);

                    // Get the .xml provisioning template file name
                    xmlTemplateFileName = !String.IsNullOrEmpty(openXmlConnector.Info?.Properties?.TemplateFileName) ?
                                          openXmlConnector.Info?.Properties?.TemplateFileName :
                                          packageFileName.Substring(packageFileName.LastIndexOf('/') + 1)
                                          .Replace(".pnp", ".xml");
                }
                else
                {
                    // Otherwise use the .XML template provider for SharePoint
                    provider =
                        new XMLSharePointTemplateProvider(context, web.Url,
                                                          Environment.GetEnvironmentVariable("TemplatesLibrary"));
                }

                // Get the template
                ProvisioningHierarchy tenantTemplate = provider.GetHierarchy(xmlTemplateFileName);
                tenantTemplate.Connector = provider.Connector;

                return(tenantTemplate);
            }
        }
Example #7
0
        private static ProvisioningHierarchy GetHierarchyFromStorage(String packageLocalFolder, String packageFileName)
        {
            // Prepare the resulting value
            ProvisioningHierarchy hierarchy = null;

            // Create the template provider instance targeting the Blob Storage
            var provider = new XMLAzureStorageTemplateProvider(
                ConfigurationManager.AppSettings["BlobTemplatesProvider:ConnectionString"],
                packageLocalFolder);

            using (Stream stream = provider.Connector.GetFileStream(packageFileName))
            {
                // Crate a copy of the source stream
                MemoryStream mem = new MemoryStream();
                stream.CopyTo(mem);
                mem.Position = 0;

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

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

                    var formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(xml.Root.Name.NamespaceName);
                    formatter.Initialize(provider);

                    hierarchy = ((IProvisioningHierarchyFormatter)formatter).ToProvisioningHierarchy(mem);
                }
                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 openXmlProvider  = 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 = openXmlProvider.GetHierarchy(xmlTemplateFileName);
                }
            }

            return(hierarchy);
        }
Example #8
0
        internal static ProvisioningHierarchy LoadProvisioningHierarchyFromFile(string templatePath, ITemplateProviderExtension[] templateProviderExtensions)
        {
            // Prepare the File Connector
            string templateFileName = System.IO.Path.GetFileName(templatePath);

            // Prepare the template path
            var fileInfo = new FileInfo(templatePath);
            FileConnectorBase fileConnector = new FileSystemConnector(fileInfo.DirectoryName, "");

            // Load the provisioning template file
            var isOpenOfficeFile = false;

            using (var stream = fileConnector.GetFileStream(templateFileName))
            {
                isOpenOfficeFile = FileUtilities.IsOpenOfficeFile(stream);
            }

            XMLTemplateProvider provider;

            if (isOpenOfficeFile)
            {
                var openXmlConnector = new OpenXMLConnector(templateFileName, fileConnector);
                provider = new XMLOpenXMLTemplateProvider(openXmlConnector);
                if (!String.IsNullOrEmpty(openXmlConnector.Info?.Properties?.TemplateFileName))
                {
                    templateFileName = openXmlConnector.Info.Properties.TemplateFileName;
                }
                else
                {
                    templateFileName = templateFileName.Substring(0, templateFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";
                }

                var hierarchy = (provider as XMLOpenXMLTemplateProvider).GetHierarchy();
                if (hierarchy != null)
                {
                    hierarchy.Connector = provider.Connector;
                    return(hierarchy);
                }
            }
            else
            {
                provider = new XMLFileSystemTemplateProvider(fileConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + "", "");
            }

            ProvisioningHierarchy provisioningHierarchy = provider.GetHierarchy(templateFileName);

            provisioningHierarchy.Connector = provider.Connector;
            // Return the result
            return(provisioningHierarchy);
        }
        public void OpenXMLGetFileFromTemplate()
        {
            var fileSystemConnector = new FileSystemConnector(String.Format(@"{0}\..\..\Resources", AppDomain.CurrentDomain.BaseDirectory), "Templates");
            var openXMLConnector    = new OpenXMLConnector(packageFileName, fileSystemConnector);
            var file = openXMLConnector.GetFile("garagebg.jpg");

            Assert.IsNull(file);
            file = openXMLConnector.GetFile("garagebg.jpg", "Images");
            Assert.IsNotNull(file);
            Stream stream = openXMLConnector.GetFileStream("garagebg.jpg");

            Assert.IsNull(stream);
            stream = openXMLConnector.GetFileStream("garagebg.jpg", "Images");
            Assert.IsNotNull(stream.Length > 0);
        }
        public void OpenXMLDeleteFileFromTemplate()
        {
            var fileSystemConnector = new FileSystemConnector(
                String.Format(@"{0}\..\..\Resources",
                              AppDomain.CurrentDomain.BaseDirectory),
                "Templates");

            var openXMLConnector = new OpenXMLConnector(packageFileName,
                                                        fileSystemConnector);

            openXMLConnector.DeleteFile("garagelogo.png", "Images");

            var image1 = openXMLConnector.GetFileStream("garagelogo.png", "Images");

            Assert.IsNull(image1);
        }
        private static void OpenXMLSaveTemplateInternal()
        {
            var fileSystemConnector = new FileSystemConnector(
                String.Format(@"{0}\..\..\Resources",
                              AppDomain.CurrentDomain.BaseDirectory),
                "Templates");

            var openXMLConnector = new OpenXMLConnector(packageFileName,
                                                        fileSystemConnector,
                                                        "OfficeDevPnP Automated Test");

            SaveFileInPackage(fileSystemConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + @"\Templates\ProvisioningSchema-2015-12-FullSample-02.xml", "", openXMLConnector);
            SaveFileInPackage(fileSystemConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + @"\garagelogo.png", "Images", openXMLConnector);
            SaveFileInPackage(fileSystemConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + @"\garagebg.jpg", "Images", openXMLConnector);

            if (openXMLConnector is ICommitableFileConnector)
            {
                ((ICommitableFileConnector)openXMLConnector).Commit();
            }
        }
        public void OpenXMLGetFilesFromFolder()
        {
            var fileSystemConnector = new FileSystemConnector(
                String.Format(@"{0}\..\..\Resources",
                              AppDomain.CurrentDomain.BaseDirectory),
                "Templates");

            var openXMLConnector = new OpenXMLConnector(packageFileName,
                                                        fileSystemConnector,
                                                        "OfficeDevPnP Automated Test");

            SaveFileInPackage(fileSystemConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + @"\garagelogo.png", "Images", openXMLConnector);
            SaveFileInPackage(fileSystemConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + @"\garagelogo.png", "Images\\Test", openXMLConnector);
            SaveFileInPackage(fileSystemConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + @"\garagebg.jpg", "Images/Test", openXMLConnector);

            if (openXMLConnector is ICommitableFileConnector)
            {
                ((ICommitableFileConnector)openXMLConnector).Commit();
            }

            openXMLConnector = new OpenXMLConnector(packageFileName,
                                                    fileSystemConnector,
                                                    "OfficeDevPnP Automated Test");


            var folders = openXMLConnector.GetFolders();

            Assert.IsTrue(folders.Count > 0);
            Assert.IsTrue(folders.Exists(s => string.Equals(s, "Images", StringComparison.OrdinalIgnoreCase)));
            var files = openXMLConnector.GetFiles("Images");

            Assert.IsTrue(files.Count > 0);

            files = openXMLConnector.GetFiles("Images\\Test");
            Assert.IsTrue(files.Count == 2);

            files = openXMLConnector.GetFiles("Images/Test");
            Assert.IsTrue(files.Count == 2);
        }
        public void OpenXMLLoadTemplateOriginal()
        {
            var fileSystemConnector = new FileSystemConnector(
                String.Format(@"{0}\..\..\..\Resources",
                              AppDomain.CurrentDomain.BaseDirectory),
                "Templates");

            var openXMLConnector = new OpenXMLConnector(packageFileNameBackwardsCompatibility, fileSystemConnector);
            var templateFile     = openXMLConnector.GetFileStream("ProvisioningSchema-2019-03-FullSample-01.xml");

            XMLPnPSchemaV201903Serializer formatter = new XMLPnPSchemaV201903Serializer();
            var checkTemplate = formatter.IsValid(templateFile);

            Assert.IsTrue(checkTemplate);

            var image1 = openXMLConnector.GetFileStream("garagelogo.png", "Images");

            Assert.IsNotNull(image1);

            var image2 = openXMLConnector.GetFileStream("garagebg.jpg", "Images");

            Assert.IsNotNull(image2);
        }
 public MarkdownOpenXMLTemplateProvider(OpenXMLConnector openXMLConnector) :
     base(openXMLConnector)
 {
 }
        public static async Task RunAsync([QueueTrigger("actions")] ProvisioningActionModel action, TextWriter log)
        {
            var startProvisioning = DateTime.Now;

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

            log.WriteLine($"Processing queue trigger function for tenant {action.TenantId}");
            log.WriteLine($"PnP Correlation ID: {action.CorrelationId.ToString()}");

            // Instantiate and use the telemetry model
            TelemetryUtility telemetry = new TelemetryUtility((s) => {
                log.WriteLine(s);
            });
            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"]);

                log.WriteLine($"Retrieved target Microsoft Graph Access Token.");

                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;

                    log.WriteLine($"Target SharePoint Online Tenant: {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"]);

                    log.WriteLine($"Retrieved target SharePoint Online Access Token.");

                    #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);

                        log.WriteLine($"SharePoint Online Root Site Collection title: {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"]);

                                log.WriteLine($"Retrieved target SharePoint Online Admin Center Access Token.");

                                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)
                                        {
                                            log.WriteLine($"{messageType} - {message}");
                                        };
                                        ptai.ProgressDelegate += delegate(string message, int step, int total)
                                        {
                                            log.WriteLine($"{step:00}/{total:00} - {message}");
                                        };
                                        ptai.SiteProvisionedDelegate += delegate(string title, string url)
                                        {
                                            log.WriteLine($"Fully provisioned site '{title}' with URL: {url}");
                                            var provisionedSite = new Tuple <string, string>(title, url);
                                            if (!provisionedSites.Contains(provisionedSite))
                                            {
                                                provisionedSites.Add(provisionedSite);
                                            }
                                        };

//#if !DEBUG
//                                        // Set the default delay for sites creations to 5 mins
//                                        ptai.DelayAfterModernSiteCreation = 60 * 5;
//#endif

                                        // 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);
                                                }
                                            }

                                            // Apply the hierarchy
                                            log.WriteLine($"Hierarchy Provisioning Started: {DateTime.Now:hh.mm.ss}");
                                            tenant.ApplyProvisionHierarchy(hierarchy,
                                                                           (hierarchy.Sequences != null && hierarchy.Sequences.Count > 0) ?
                                                                           hierarchy.Sequences[0].ID : null,
                                                                           ptai);
                                            log.WriteLine($"Hierarchy Provisioning Completed: {DateTime.Now:hh.mm.ss}");
                                        }

                                        if (action.ApplyTheme && action.ApplyCustomTheme)
                                        {
                                            if (!String.IsNullOrEmpty(action.ThemePrimaryColor) &&
                                                !String.IsNullOrEmpty(action.ThemeBodyTextColor) &&
                                                !String.IsNullOrEmpty(action.ThemeBodyBackgroundColor))
                                            {
                                                log.WriteLine($"Applying custom Theme to provisioned sites");

                                                #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))
                                                        {
                                                            log.WriteLine($"Custom Theme applied on site '{ps.Item1}' with URL: {ps.Item2}");
                                                        }
                                                        else
                                                        {
                                                            log.WriteLine($"Failed to apply custom Theme on site '{ps.Item1}' with URL: {ps.Item2}");
                                                        }
                                                    }
                                                }
                                            }
                                        }

                                        // 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);
                                    }
                                }
                            }
                            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

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

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

                    // Log reporting event (4 = ConcurrentProvisioningException)
                    LogReporting(action, provisioningEnvironment, startProvisioning, null, 4, ex.ToDetailedString());
                }
                else
                {
                    // Log telemetry event
                    telemetry?.LogException(ex, "ProvisioningFunction.RunAsync", telemetryProperties);

                    // Log reporting event (2 = Failed)
                    LogReporting(action, provisioningEnvironment, startProvisioning, null, 2, ex.ToDetailedString());
                }

                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();
            }
        }
 public XMLOpenXMLTemplateProvider(OpenXMLConnector openXMLConnector) :
     base(openXMLConnector)
 {
 }
        protected override void ExecuteCmdlet()
        {
            SelectedWeb.EnsureProperty(w => w.Url);
            bool templateFromFileSystem = !Path.ToLower().StartsWith("http");
            FileConnectorBase fileConnector;
            string            templateFileName = System.IO.Path.GetFileName(Path);

            if (templateFromFileSystem)
            {
                if (!System.IO.Path.IsPathRooted(Path))
                {
                    Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
                }
                FileInfo fileInfo = new FileInfo(Path);
                fileConnector = new FileSystemConnector(fileInfo.DirectoryName, "");
            }
            else
            {
                Uri fileUri         = new Uri(Path);
                var webUrl          = Microsoft.SharePoint.Client.Web.WebUrlFromFolderUrlDirect(ClientContext, fileUri);
                var templateContext = ClientContext.Clone(webUrl.ToString());

                string library = Path.ToLower().Replace(templateContext.Url.ToLower(), "").TrimStart('/');
                int    idx     = library.IndexOf("/");
                library       = library.Substring(0, idx);
                fileConnector = new SharePointConnector(templateContext, templateContext.Url, library);
            }
            XMLTemplateProvider  provider;
            ProvisioningTemplate provisioningTemplate;
            Stream stream           = fileConnector.GetFileStream(templateFileName);
            var    isOpenOfficeFile = FileUtilities.IsOpenOfficeFile(stream);

            if (isOpenOfficeFile)
            {
                var openXmlConnector = new OpenXMLConnector(templateFileName, fileConnector);
                provider = new XMLOpenXMLTemplateProvider(openXmlConnector);
                if (!String.IsNullOrEmpty(openXmlConnector.Info?.Properties?.TemplateFileName))
                {
                    templateFileName = openXmlConnector.Info.Properties.TemplateFileName;
                }
                else
                {
                    templateFileName = templateFileName.Substring(0, templateFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";
                }
            }
            else
            {
                if (templateFromFileSystem)
                {
                    provider = new XMLFileSystemTemplateProvider(fileConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + "", "");
                }
                else
                {
                    throw new NotSupportedException("Only .pnp package files are supported from a SharePoint library");
                }
            }
            provisioningTemplate = provider.GetTemplate(templateFileName, TemplateProviderExtensions);

            if (provisioningTemplate == null)
            {
                return;
            }

            GetSiteTemplate.SetTemplateMetadata(provisioningTemplate, TemplateDisplayName, TemplateImagePreviewUrl, TemplateProperties);

            provider.SaveAs(provisioningTemplate, templateFileName, TemplateProviderExtensions);
        }
Example #18
0
        private bool BuildPackage(ITaskItem item)
        {
            var res = true;

            try
            {
                var idenity            = item.GetMetadata("Identity");
                var filename           = Path.GetFileName(idenity);
                var packageName        = ProjectName + ".pnp";
                var packedTemplateName = Path.GetFileNameWithoutExtension(filename) + ".xml";

                LogMessage($"Packing template={filename}, package={packageName}");

                XMLFileSystemTemplateProvider provider = new XMLFileSystemTemplateProvider(ProjectDir, "");
                var fsConnector = provider.Connector;
                var template    = provider.GetTemplate(idenity);

                var configManager = new ConfigurationManager();
                var config        = configManager.GetProjectConfiguration(ProjectDir);

                var outFile = Path.Combine(ProjectDir, OutDir, packageName);
                OpenXMLConnector openXml = new OpenXMLConnector(outFile, fsConnector, config.Author);

                //write files
                var files = template.Files != null?template.Files.Select(f => f.Src.ToLower()).ToList() : new List <string>();

                if (TemplateFiles?.Length > 0)
                {
                    files = files.Union(TemplateFiles.Select(t => t.GetMetadata("Identity")?.ToLower())).ToList();
                }

                foreach (var file in files)
                {
                    LogMessage($"Packing file={file}, package={packageName}");
                    var fileName  = Path.GetFileName(file);
                    var container = Path.GetDirectoryName(file);
                    using (var stream = fsConnector.GetFileStream(fileName, container))
                    {
                        if (stream != null)
                        {
                            openXml.SaveFileStream(fileName, container, stream);
                        }
                        else
                        {
                            throw new FileNotFoundException($"Not found: {Path.Combine(ProjectDir, file)}");
                        }
                    }
                }

                var xml = template.ToXML();
                using (var stream = GetStream(xml))
                {
                    openXml.SaveFileStream(packedTemplateName, stream);
                }

                openXml.Commit();
                LogMessage($"Packed successfully.");
            }
            catch (Exception e)
            {
                LogError(e);
                res = false;
            }
            return(res);
        }
Example #19
0
        private static ProvisioningHierarchy LoadProvisioningHierarchyFromFile(string templatePath, Action <Exception> exceptionHandler)
        {
            // Prepare the File Connector
            string templateFileName = System.IO.Path.GetFileName(templatePath);

            // Prepare the template path
            var fileInfo = new FileInfo(templatePath);
            FileConnectorBase fileConnector = new FileSystemConnector(fileInfo.DirectoryName, "");

            // Load the provisioning template file
            var isOpenOfficeFile = false;

            using (var stream = fileConnector.GetFileStream(templateFileName))
            {
                isOpenOfficeFile = FileUtilities.IsOpenOfficeFile(stream);
            }

            XMLTemplateProvider provider;

            if (isOpenOfficeFile)
            {
                var openXmlConnector = new OpenXMLConnector(templateFileName, fileConnector);
                provider = new XMLOpenXMLTemplateProvider(openXmlConnector);
                if (!String.IsNullOrEmpty(openXmlConnector.Info?.Properties?.TemplateFileName))
                {
                    templateFileName = openXmlConnector.Info.Properties.TemplateFileName;
                }
                else
                {
                    templateFileName = templateFileName.Substring(0, templateFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";
                }

                var hierarchy = (provider as XMLOpenXMLTemplateProvider).GetHierarchy();
                if (hierarchy != null)
                {
                    hierarchy.Connector = provider.Connector;
                    return(hierarchy);
                }
            }
            else
            {
                provider = new XMLFileSystemTemplateProvider(fileConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + "", "");
            }

            try
            {
                ProvisioningHierarchy provisioningHierarchy = provider.GetHierarchy(templateFileName);
                provisioningHierarchy.Connector = provider.Connector;
                return(provisioningHierarchy);
            }
            catch (ApplicationException ex)
            {
                if (ex.InnerException is AggregateException)
                {
                    if (exceptionHandler != null)
                    {
                        foreach (var exception in ((AggregateException)ex.InnerException).InnerExceptions)
                        {
                            exceptionHandler(exception);
                        }
                    }
                }
            }
            return(null);
        }
        protected override void ExecuteCmdlet()
        {
            SelectedWeb.EnsureProperty(w => w.Url);
            ProvisioningTemplate provisioningTemplate;

            FileConnectorBase fileConnector;

            if (ParameterSpecified(nameof(Path)))
            {
                bool   templateFromFileSystem = !Path.ToLower().StartsWith("http");
                string templateFileName       = System.IO.Path.GetFileName(Path);
                if (templateFromFileSystem)
                {
                    if (!System.IO.Path.IsPathRooted(Path))
                    {
                        Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
                    }
                    if (!System.IO.File.Exists(Path))
                    {
                        throw new FileNotFoundException($"File not found");
                    }
                    if (!string.IsNullOrEmpty(ResourceFolder))
                    {
                        if (!System.IO.Path.IsPathRooted(ResourceFolder))
                        {
                            ResourceFolder = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path,
                                                                    ResourceFolder);
                        }
                    }
                    var fileInfo = new FileInfo(Path);
                    fileConnector = new FileSystemConnector(fileInfo.DirectoryName, "");
                }
                else
                {
                    Uri fileUri         = new Uri(Path);
                    var webUrl          = Microsoft.SharePoint.Client.Web.WebUrlFromFolderUrlDirect(ClientContext, fileUri);
                    var templateContext = ClientContext.Clone(webUrl.ToString());

                    var library = Path.ToLower().Replace(templateContext.Url.ToLower(), "").TrimStart('/');
                    var idx     = library.IndexOf("/", StringComparison.Ordinal);
                    library = library.Substring(0, idx);

                    // This syntax creates a SharePoint connector regardless we have the -InputInstance argument or not
                    fileConnector = new SharePointConnector(templateContext, templateContext.Url, library);
                }

                // If we don't have the -InputInstance parameter, we load the template from the source connector

                Stream stream           = fileConnector.GetFileStream(templateFileName);
                var    isOpenOfficeFile = FileUtilities.IsOpenOfficeFile(stream);
                XMLTemplateProvider provider;
                if (isOpenOfficeFile)
                {
                    var openXmlConnector = new OpenXMLConnector(templateFileName, fileConnector);
                    provider = new XMLOpenXMLTemplateProvider(openXmlConnector);
                    if (!String.IsNullOrEmpty(openXmlConnector.Info?.Properties?.TemplateFileName))
                    {
                        templateFileName = openXmlConnector.Info.Properties.TemplateFileName;
                    }
                    else
                    {
                        templateFileName = templateFileName.Substring(0, templateFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";
                    }
                }
                else
                {
                    if (templateFromFileSystem)
                    {
                        provider = new XMLFileSystemTemplateProvider(fileConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + "", "");
                    }
                    else
                    {
                        throw new NotSupportedException("Only .pnp package files are supported from a SharePoint library");
                    }
                }

                if (ParameterSpecified(nameof(TemplateId)))
                {
                    provisioningTemplate = provider.GetTemplate(templateFileName, TemplateId, null, TemplateProviderExtensions);
                }
                else
                {
                    provisioningTemplate = provider.GetTemplate(templateFileName, TemplateProviderExtensions);
                }

                if (provisioningTemplate == null)
                {
                    // If we don't have the template, raise an error and exit
                    WriteError(new ErrorRecord(new Exception("The -Path parameter targets an invalid repository or template object."), "WRONG_PATH", ErrorCategory.SyntaxError, null));
                    return;
                }

                if (isOpenOfficeFile)
                {
                    provisioningTemplate.Connector = provider.Connector;
                }
                else
                {
                    if (ResourceFolder != null)
                    {
                        var fileSystemConnector = new FileSystemConnector(ResourceFolder, "");
                        provisioningTemplate.Connector = fileSystemConnector;
                    }
                    else
                    {
                        provisioningTemplate.Connector = provider.Connector;
                    }
                }
            }

            else
            {
                provisioningTemplate = InputInstance;

                if (ResourceFolder != null)
                {
                    var fileSystemConnector = new FileSystemConnector(ResourceFolder, "");
                    provisioningTemplate.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);
                    fileConnector = new FileSystemConnector(System.IO.Path.IsPathRooted(fileInfo.FullName) ? fileInfo.FullName : fileInfo.DirectoryName, "");
                    provisioningTemplate.Connector = fileConnector;
                }
            }

            if (Parameters != null)
            {
                foreach (var parameter in Parameters.Keys)
                {
                    if (provisioningTemplate.Parameters.ContainsKey(parameter.ToString()))
                    {
                        provisioningTemplate.Parameters[parameter.ToString()] = Parameters[parameter].ToString();
                    }
                    else
                    {
                        provisioningTemplate.Parameters.Add(parameter.ToString(), Parameters[parameter].ToString());
                    }
                }
            }

            var applyingInformation = new ProvisioningTemplateApplyingInformation();

            if (ParameterSpecified(nameof(Handlers)))
            {
                applyingInformation.HandlersToProcess = Handlers;
            }
            if (ParameterSpecified(nameof(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 {SelectedWeb.Url}";
                    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;

#if !ONPREMISES
            using (var provisioningContext = new PnPProvisioningContext((resource, scope) =>
            {
                // Get Azure AD Token
                if (PnPConnection.CurrentConnection != null)
                {
                    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...
                    return(null);
                }
            }))
            {
#endif
            SelectedWeb.ApplyProvisioningTemplate(provisioningTemplate, applyingInformation);
#if !ONPREMISES
        }
#endif

            WriteProgress(new ProgressRecord(0, $"Applying template to {SelectedWeb.Url}", " ")
            {
                RecordType = ProgressRecordType.Completed
            });
        }
Example #21
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)
                {
                    // We se the DisplayName to the DisplayName of the hierarchy if we don't have a siteTitle in the settings.json file
                    if (string.IsNullOrEmpty(package.DisplayName))
                    {
                        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 #22
0
        public static async Task <IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, ExecutionContext context)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            try
            {
                string siteUrl  = "";
                string userName = "";
                string password = "";

                var securePassword = new SecureString();
                foreach (char c in password)
                {
                    securePassword.AppendChar(c);
                }
                securePassword.MakeReadOnly();

                var authManager = new AuthenticationManager(userName, securePassword);
                using (ClientContext clientContext = authManager.GetContext(siteUrl))
                {
                    var web = clientContext.Web;

                    var templateFileName            = "SitePagesTemplate.pnp";
                    FileConnectorBase fileConnector = new FileSystemConnector(context.FunctionAppDirectory, "");
                    var openXmlConnector            = new OpenXMLConnector(templateFileName, fileConnector);
                    var provider = new XMLOpenXMLTemplateProvider(openXmlConnector);
                    templateFileName = templateFileName.Substring(0, templateFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";
                    ProvisioningTemplate provisioningTemplate = provider.GetTemplate(templateFileName);
                    provisioningTemplate.Connector = provider.Connector;

                    var applyingInformation = new ProvisioningTemplateApplyingInformation()
                    {
                        ProgressDelegate = (message, progress, total) =>
                        {
                            log.LogInformation(string.Format("{0:00}/{1:00} - {2}", progress, total, message));
                        },
                        MessagesDelegate = (message, messageType) =>
                        {
                            log.LogInformation(string.Format("{0} - {1}", messageType, message));
                        },
                        IgnoreDuplicateDataRowErrors = true
                    };

                    web.ApplyProvisioningTemplate(provisioningTemplate, applyingInformation);

                    return(new OkObjectResult("Done"));
                }
            }
            catch (ServerException e)
            {
                log.LogError($"Message: {e.Message}");
                log.LogError($"ServerErrorCode: {e.ServerErrorCode}");
                log.LogError($"ServerErrorDetails: {e.ServerErrorDetails}");
                log.LogError($"ServerErrorTraceCorrelationId: {e.ServerErrorTraceCorrelationId}");
                log.LogError($"ServerErrorTypeName: {e.ServerErrorTypeName}");
                log.LogError($"ServerErrorValue: {e.ServerErrorValue}");
                log.LogError($"ServerStackTrace: {e.ServerStackTrace}");
                log.LogError($"Source: {e.Source}");
                log.LogError($"StackTrace: {e.StackTrace}");

                throw;
            }
            catch (Exception e)
            {
                log.LogError($"Error while processing dossier: {e.Message}\n\n{e.StackTrace}");
                throw;
            }
        }