protected override void ExecuteCmdlet()
        {
            SelectedWeb.EnsureProperty(w => w.Url);

            if (!System.IO.Path.IsPathRooted(Path))
            {
                Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
            }
            if (!string.IsNullOrEmpty(ResourceFolder))
            {
                if (!System.IO.Path.IsPathRooted(ResourceFolder))
                {
                    ResourceFolder = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, ResourceFolder);
                }
            }

            FileInfo fileInfo = new FileInfo(Path);

            XMLTemplateProvider  provider             = null;
            ProvisioningTemplate provisioningTemplate = null;
            var isOpenOfficeFile = IsOpenOfficeFile(Path);

            if (isOpenOfficeFile)
            {
                var fileSystemconnector = new FileSystemConnector(fileInfo.DirectoryName, "");
                provider = new XMLOpenXMLTemplateProvider(new OpenXMLConnector(fileInfo.Name, fileSystemconnector));
                var fileName = fileInfo.Name.Substring(0, fileInfo.Name.LastIndexOf(".")) + ".xml";
                provisioningTemplate = provider.GetTemplate(fileName);
            }
            else
            {
                provider             = new XMLFileSystemTemplateProvider(fileInfo.DirectoryName, "");
                provisioningTemplate = provider.GetTemplate(fileInfo.Name);
            }

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

                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 (this.MyInvocation.BoundParameters.ContainsKey("Handlers"))
                {
                    applyingInformation.HandlersToProcess = Handlers;
                }
                if (this.MyInvocation.BoundParameters.ContainsKey("ExcludeHandlers"))
                {
                    foreach (var handler in (OfficeDevPnP.Core.Framework.Provisioning.Model.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 <ExtensibilityHandler>();
                }

                applyingInformation.ProgressDelegate = (message, step, total) =>
                {
                    WriteProgress(new ProgressRecord(0, string.Format("Applying template to {0}", SelectedWeb.Url), message)
                    {
                        PercentComplete = (100 / total) * step
                    });
                };

                applyingInformation.MessagesDelegate = (message, type) =>
                {
                    if (type == ProvisioningMessageType.Warning)
                    {
                        WriteWarning(message);
                    }
                };

                applyingInformation.OverwriteSystemPropertyBagValues = OverwriteSystemPropertyBagValues;
                SelectedWeb.ApplyProvisioningTemplate(provisioningTemplate, applyingInformation);
            }
        }
Example #2
0
        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);
                }
                if (!string.IsNullOrEmpty(ResourceFolder))
                {
                    if (!System.IO.Path.IsPathRooted(ResourceFolder))
                    {
                        ResourceFolder = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path,
                                                                ResourceFolder);
                    }
                }
                FileInfo fileInfo = new FileInfo(Path);
                fileConnector = new FileSystemConnector(fileInfo.DirectoryName, "");
            }
            else
            {
                Uri fileUri         = new Uri(Path);
                var webUrl          = Microsoft.SharePoint.Client.Web.WebUrlFromFolderUrlDirect(this.ClientContext, fileUri);
                var templateContext = this.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             = null;
            ProvisioningTemplate provisioningTemplate = null;
            Stream stream           = fileConnector.GetFileStream(templateFileName);
            var    isOpenOfficeFile = IsOpenOfficeFile(stream);

            if (isOpenOfficeFile)
            {
                provider         = new XMLOpenXMLTemplateProvider(new OpenXMLConnector(templateFileName, fileConnector));
                templateFileName = templateFileName.Substring(0, templateFileName.LastIndexOf(".")) + ".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;
            }

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

            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 (this.MyInvocation.BoundParameters.ContainsKey("Handlers"))
            {
                applyingInformation.HandlersToProcess = Handlers;
            }
            if (this.MyInvocation.BoundParameters.ContainsKey("ExcludeHandlers"))
            {
                foreach (var handler in (OfficeDevPnP.Core.Framework.Provisioning.Model.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 <ExtensibilityHandler>();
            }

            applyingInformation.ProgressDelegate = (message, step, total) =>
            {
                WriteProgress(new ProgressRecord(0, string.Format("Applying template to {0}", SelectedWeb.Url), message)
                {
                    PercentComplete = (100 / total) * step
                });
            };

            applyingInformation.MessagesDelegate = (message, type) =>
            {
                if (type == ProvisioningMessageType.Warning)
                {
                    WriteWarning(message);
                }
            };

            applyingInformation.OverwriteSystemPropertyBagValues = OverwriteSystemPropertyBagValues;
            SelectedWeb.ApplyProvisioningTemplate(provisioningTemplate, applyingInformation);
        }
Example #3
0
        protected override void ExecuteCmdlet()
        {
            SelectedWeb.EnsureProperty(w => w.Url);
            ProvisioningTemplate provisioningTemplate;

            FileConnectorBase fileConnector;

            if (MyInvocation.BoundParameters.ContainsKey("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)
                {
                    provider         = new XMLOpenXMLTemplateProvider(new OpenXMLConnector(templateFileName, fileConnector));
                    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)
                {
                    // 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
            {
                if (MyInvocation.BoundParameters.ContainsKey("GalleryTemplateId"))
                {
                    provisioningTemplate = GalleryHelper.GetTemplate(GalleryTemplateId);
                }
                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(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 (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 {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;

            SelectedWeb.ApplyProvisioningTemplate(provisioningTemplate, applyingInformation);

            WriteProgress(new ProgressRecord(0, $"Applying template to {SelectedWeb.Url}", " ")
            {
                RecordType = ProgressRecordType.Completed
            });
        }
Example #4
0
        protected override void ProcessRecord()
        {
            // Determine the output file name and path
            string outFileName = Path.GetFileName(Out);

            if (!Path.IsPathRooted(Out))
            {
                Out = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Out);
            }

            bool proceed = false;

            if (System.IO.File.Exists(Out))
            {
                if (Force || ShouldContinue(string.Format(Properties.Resources.File0ExistsOverwrite, Out),
                                            Properties.Resources.Confirm))
                {
                    proceed = true;
                }
            }
            else
            {
                proceed = true;
            }

            string outPath = new FileInfo(Out).DirectoryName;

            // Determine if it is an .XML or a .PNP file
            var extension = "";

            if (proceed && outFileName != null)
            {
                if (outFileName.IndexOf(".", StringComparison.Ordinal) > -1)
                {
                    extension = outFileName.Substring(outFileName.LastIndexOf(".", StringComparison.Ordinal)).ToLower();
                }
                else
                {
                    extension = ".pnp";
                }
            }

            var fileSystemConnector = new FileSystemConnector(outPath, "");

            ITemplateFormatter formatter = XMLPnPSchemaFormatter.LatestFormatter;

            if (extension == ".pnp")
            {
                IsolatedStorage.InitializeIsolatedStorage();

                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(
                    Out, fileSystemConnector);
                var templateFileName = outFileName.Substring(0, outFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                provider.SaveAs(Template, templateFileName, formatter, TemplateProviderExtensions);
                ProcessFiles(Out, fileSystemConnector, provider.Connector);
            }
            else
            {
                XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(outPath, "");
                provider.SaveAs(Template, Out, formatter, TemplateProviderExtensions);
            }
        }
Example #5
0
        private void ExtractTemplate(XMLPnPSchemaVersion schema, string path, string packageName)
        {
            SelectedWeb.EnsureProperty(w => w.Url);

            var creationInformation = new ProvisioningTemplateCreationInformation(SelectedWeb);

            creationInformation.HandlersToProcess = Handlers.Lists;

            var extension = "";

            if (packageName != null)
            {
                if (packageName.IndexOf(".", StringComparison.Ordinal) > -1)
                {
                    extension = packageName.Substring(packageName.LastIndexOf(".", StringComparison.Ordinal)).ToLower();
                }
                else
                {
                    packageName += ".pnp";
                    extension    = ".pnp";
                }
            }

            var fileSystemConnector = new FileSystemConnector(path, "");

            if (extension == ".pnp")
            {
                creationInformation.FileConnector = new OpenXMLConnector(packageName, fileSystemConnector);
            }
            else
            {
                creationInformation.FileConnector = fileSystemConnector;
            }

            creationInformation.ProgressDelegate = (message, step, total) =>
            {
                var percentage = Convert.ToInt32((100 / Convert.ToDouble(total)) * Convert.ToDouble(step));

                WriteProgress(new ProgressRecord(0, $"Extracting Template from {SelectedWeb.Url}", message)
                {
                    PercentComplete = percentage
                });
            };
            creationInformation.MessagesDelegate = (message, type) =>
            {
                switch (type)
                {
                case ProvisioningMessageType.Warning:
                {
                    WriteWarning(message);
                    break;
                }

                case ProvisioningMessageType.Progress:
                {
                    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          = messageSplitted[0];
                            subProgressRecord.StatusDescription = 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;
                }
                }
            };

            if (List != null && List.Count > 0)
            {
                creationInformation.ListsToExtract.AddRange(List);
            }

            var template = SelectedWeb.GetProvisioningTemplate(creationInformation);



            if (!OutputInstance)
            {
                var formatter = ProvisioningHelper.GetFormatter(schema);

                if (extension == ".pnp")
                {
#if !PNPPSCORE
                    IsolatedStorage.InitializeIsolatedStorage();
#endif
                    XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(
                        creationInformation.FileConnector as OpenXMLConnector);
                    var templateFileName = packageName.Substring(0, packageName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                    provider.SaveAs(template, templateFileName, formatter, null);
                }
                else
                {
                    if (Out != null)
                    {
                        XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(path, "");
                        provider.SaveAs(template, Path.Combine(path, packageName), formatter, null);
                    }
                    else
                    {
                        var outputStream = formatter.ToFormattedTemplate(template);
                        var reader       = new StreamReader(outputStream);

                        WriteObject(reader.ReadToEnd());
                    }
                }
            }
            else
            {
                WriteObject(template);
            }
        }
Example #6
0
        protected override void ProcessRecord()
        {
            if (MyInvocation.InvocationName.ToLower() == "save-pnpprovisioninghierarchy")
            {
                WriteWarning("Save-PnPProvisioningHierarchy has been deprecated. Use Save-PnPTenantTemplate instead.");
            }
            // Determine the output file name and path
            string outFileName = Path.GetFileName(Out);

            if (!Path.IsPathRooted(Out))
            {
                Out = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Out);
            }

            bool proceed = false;

            if (System.IO.File.Exists(Out))
            {
                if (Force || ShouldContinue(string.Format(Properties.Resources.File0ExistsOverwrite, Out),
                                            Properties.Resources.Confirm))
                {
                    System.IO.File.Delete(Out);
                    proceed = true;
                }
            }
            else
            {
                proceed = true;
            }

            string outPath = new FileInfo(Out).DirectoryName;

            // Determine if it is an .XML or a .PNP file
            var extension = "";

            if (proceed && outFileName != null)
            {
                if (outFileName.IndexOf(".", StringComparison.Ordinal) > -1)
                {
                    extension = outFileName.Substring(outFileName.LastIndexOf(".", StringComparison.Ordinal)).ToLower();
                }
                else
                {
                    extension = ".pnp";
                }
            }

            var fileSystemConnector = new FileSystemConnector(outPath, "");

            ITemplateFormatter formatter = XMLPnPSchemaFormatter.LatestFormatter;

            if (extension == ".pnp")
            {
                // var connector = new OpenXMLConnector(Out, fileSystemConnector);
                var templateFileName = outFileName.Substring(0, outFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(
                    Out, fileSystemConnector, templateFileName: templateFileName);
                WriteObject("Processing template");
                provider.SaveAs(Template, templateFileName);
                ProcessFiles(Out, fileSystemConnector, provider.Connector);

                //provider.SaveAs(Hierarchy, templateFileName);
                //connector.Commit();
            }
            else
            {
                XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(outPath, "");
                provider.SaveAs(Template, Out);
            }
        }
Example #7
0
        private void ExtractTemplate(XMLPnPSchemaVersion schema, string path, string packageName, ExtractConfiguration configuration)
        {
            SelectedWeb.EnsureProperty(w => w.Url);
            ProvisioningTemplateCreationInformation creationInformation = null;

            if (configuration != null)
            {
                creationInformation = configuration.ToCreationInformation(SelectedWeb);
            }
            else
            {
                creationInformation = new ProvisioningTemplateCreationInformation(SelectedWeb);
            }

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

            var extension = "";

            if (packageName != null)
            {
                if (packageName.IndexOf(".", StringComparison.Ordinal) > -1)
                {
                    extension = packageName.Substring(packageName.LastIndexOf(".", StringComparison.Ordinal)).ToLower();
                }
                else
                {
                    packageName += ".pnp";
                    extension    = ".pnp";
                }
            }

            var fileSystemConnector = new FileSystemConnector(path, "");

            if (extension == ".pnp")
            {
                creationInformation.FileConnector = new OpenXMLConnector(packageName, fileSystemConnector);
            }
            else
            {
                creationInformation.FileConnector = fileSystemConnector;
            }
#pragma warning disable 618
            if (ParameterSpecified(nameof(PersistBrandingFiles)))
            {
                creationInformation.PersistBrandingFiles = PersistBrandingFiles;
            }
#pragma warning restore 618
            creationInformation.PersistPublishingFiles       = PersistPublishingFiles;
            creationInformation.IncludeNativePublishingFiles = IncludeNativePublishingFiles;
            if (ParameterSpecified(nameof(IncludeSiteGroups)))
            {
                creationInformation.IncludeSiteGroups = IncludeSiteGroups;
            }
            creationInformation.IncludeTermGroupsSecurity  = IncludeTermGroupsSecurity;
            creationInformation.IncludeSearchConfiguration = IncludeSearchConfiguration;
            if (ParameterSpecified(nameof(IncludeHiddenLists)))
            {
                creationInformation.IncludeHiddenLists = IncludeHiddenLists;
            }
            if (ParameterSpecified(nameof(IncludeAllClientSidePages)))
            {
                creationInformation.IncludeAllClientSidePages = IncludeAllClientSidePages;
            }
            creationInformation.SkipVersionCheck = SkipVersionCheck;
            if (ParameterSpecified(nameof(ContentTypeGroups)) && ContentTypeGroups != null)
            {
                creationInformation.ContentTypeGroupsToInclude = ContentTypeGroups.ToList();
            }
            creationInformation.PersistMultiLanguageResources = PersistMultiLanguageResources;
            if (extension == ".pnp")
            {
                // if file is of pnp format, persist all files
                creationInformation.PersistBrandingFiles          = true;
                creationInformation.PersistPublishingFiles        = true;
                creationInformation.PersistMultiLanguageResources = true;
            }
            if (!string.IsNullOrEmpty(ResourceFilePrefix))
            {
                creationInformation.ResourceFilePrefix = ResourceFilePrefix;
            }
            else
            {
                if (Out != null)
                {
                    FileInfo fileInfo = new FileInfo(Out);
                    var      prefix   = fileInfo.Name;
                    // strip extension, if there is any
                    var indexOfLastDot = prefix.LastIndexOf(".", StringComparison.Ordinal);
                    if (indexOfLastDot > -1)
                    {
                        prefix = prefix.Substring(0, indexOfLastDot);
                    }
                    creationInformation.ResourceFilePrefix = prefix;
                }
            }
            if (ExtensibilityHandlers != null)
            {
                creationInformation.ExtensibilityHandlers = ExtensibilityHandlers.ToList();
            }

#pragma warning disable CS0618 // Type or member is obsolete
            if (NoBaseTemplate)
            {
                creationInformation.BaseTemplate = null;
            }
            else
            {
                creationInformation.BaseTemplate = SelectedWeb.GetBaseTemplate();
            }
#pragma warning restore CS0618 // Type or member is obsolete

            creationInformation.ProgressDelegate = (message, step, total) =>
            {
                var percentage = Convert.ToInt32((100 / Convert.ToDouble(total)) * Convert.ToDouble(step));

                WriteProgress(new ProgressRecord(0, $"Extracting Template from {SelectedWeb.Url}", message)
                {
                    PercentComplete = percentage
                });
                WriteProgress(new ProgressRecord(1, " ", " ")
                {
                    RecordType = ProgressRecordType.Completed
                });
            };
            creationInformation.MessagesDelegate = (message, type) =>
            {
                switch (type)
                {
                case ProvisioningMessageType.Warning:
                {
                    WriteWarning(message);
                    break;
                }

                case ProvisioningMessageType.Progress:
                {
                    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          = messageSplitted[0];
                            subProgressRecord.StatusDescription = 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;
                }
                }
            };

            if (IncludeAllTermGroups)
            {
                creationInformation.IncludeAllTermGroups = true;
            }
            else
            {
                if (IncludeSiteCollectionTermGroup)
                {
                    creationInformation.IncludeSiteCollectionTermGroup = true;
                }
            }

            if (ParameterSpecified(nameof(ExcludeContentTypesFromSyndication)))
            {
                creationInformation.IncludeContentTypesFromSyndication = !ExcludeContentTypesFromSyndication.ToBool();
            }

            if (ListsToExtract != null && ListsToExtract.Count > 0)
            {
                creationInformation.ListsToExtract.AddRange(ListsToExtract);
            }
            ProvisioningTemplate template = null;
            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);
                }
            }))
            {
                template = SelectedWeb.GetProvisioningTemplate(creationInformation);
            }
            // Set metadata for template, if any
            SetTemplateMetadata(template, TemplateDisplayName, TemplateImagePreviewUrl, TemplateProperties);

            if (!OutputInstance)
            {
                var formatter = ProvisioningHelper.GetFormatter(schema);

                if (extension == ".pnp")
                {
                    XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(
                        creationInformation.FileConnector as OpenXMLConnector);
                    var templateFileName = packageName.Substring(0, packageName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                    provider.SaveAs(template, templateFileName, formatter, TemplateProviderExtensions);
                }
                else
                {
                    if (Out != null)
                    {
                        XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(path, "");
                        provider.SaveAs(template, Path.Combine(path, packageName), formatter, TemplateProviderExtensions);
                    }
                    else
                    {
                        var outputStream = formatter.ToFormattedTemplate(template);
                        var reader       = new StreamReader(outputStream);

                        WriteObject(reader.ReadToEnd());
                    }
                }
            }
            else
            {
                WriteObject(template);
            }
        }
Example #8
0
        internal static void SaveTemplate(Guid templateId, string path, Func <string, bool> overWriteFileAction = null, Action <string> itemSavedAction = null)
        {
            HttpContentHeaders headers = null;
            // Get the template via HTTP REST
            var templateStream =
                HttpHelper.MakeGetRequestForStreamWithResponseHeaders(
                    $"{BaseTemplateGalleryUrl}/api/DownloadTemplate?templateId={templateId}", "application/octet-stream",
                    out headers);

            // If we have any result
            if (templateStream != null)
            {
                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(new OpenXMLConnector(templateStream));
                var cd = new ContentDisposition(headers.ContentDisposition.ToString());
                var openXMLFileName = cd.FileName;

                if (path != null)
                {
                    if (System.IO.Directory.Exists(path))
                    {
                        var  fileName = System.IO.Path.Combine(path, openXMLFileName);
                        bool doSave   = false;
                        if (System.IO.File.Exists(fileName))
                        {
                            if (overWriteFileAction != null)
                            {
                                doSave = overWriteFileAction(fileName);
                            }
                            else
                            {
                                doSave = true;
                            }
                        }
                        else
                        {
                            doSave = true;
                        }
                        if (doSave)
                        {
                            // Save the template to the path
                            using (var fileStream = System.IO.File.Create(fileName))
                            {
                                templateStream.Seek(0, SeekOrigin.Begin);
                                templateStream.CopyTo(fileStream);
                            }
                            itemSavedAction?.Invoke(fileName);
                        }
                    }
                }
                else
                {
                    // Determine the name of the XML file inside the PNP Open XML file
                    var xmlTemplateFile = openXMLFileName.ToLower().Replace(".pnp", ".xml");

                    // Get the template
                    var result = provider.GetTemplate(xmlTemplateFile);
                    result.Connector = provider.Connector;
                    templateStream.Close();
                }
            }
        }
Example #9
0
        private void ExtractTemplate(XMLPnPSchemaVersion schema, string path, string packageName)
        {
            SelectedWeb.EnsureProperty(w => w.Url);

            var creationInformation = new ProvisioningTemplateCreationInformation(SelectedWeb);

            if (this.MyInvocation.BoundParameters.ContainsKey("Handlers"))
            {
                creationInformation.HandlersToProcess = Handlers;
            }
            if (this.MyInvocation.BoundParameters.ContainsKey("ExcludeHandlers"))
            {
                foreach (var handler in (OfficeDevPnP.Core.Framework.Provisioning.Model.Handlers[])Enum.GetValues(typeof(Handlers)))
                {
                    if (!ExcludeHandlers.Has(handler) && handler != Handlers.All)
                    {
                        Handlers = Handlers | handler;
                    }
                }
                creationInformation.HandlersToProcess = Handlers;
            }

            var extension = "";

            if (packageName != null)
            {
                if (packageName.IndexOf(".") > -1)
                {
                    extension = packageName.Substring(packageName.LastIndexOf(".")).ToLower();
                }
                else
                {
                    packageName += ".pnp";
                    extension    = ".pnp";
                }
            }

            var fileSystemConnector = new FileSystemConnector(path, "");

            if (extension == ".pnp")
            {
                creationInformation.FileConnector = new OpenXMLConnector(packageName, fileSystemConnector);
            }
            else
            {
                creationInformation.FileConnector = fileSystemConnector;
            }
#pragma warning disable 618
            creationInformation.PersistBrandingFiles = PersistBrandingFiles || PersistComposedLookFiles;
#pragma warning restore 618
            creationInformation.PersistPublishingFiles       = PersistPublishingFiles;
            creationInformation.IncludeNativePublishingFiles = IncludeNativePublishingFiles;
            creationInformation.IncludeSiteGroups            = IncludeSiteGroups;
            creationInformation.IncludeTermGroupsSecurity    = IncludeTermGroupsSecurity;
#if !SP2013
            creationInformation.PersistMultiLanguageResources = PersistMultiLanguageResources;
            if (!string.IsNullOrEmpty(ResourceFilePrefix))
            {
                creationInformation.ResourceFilePrefix = ResourceFilePrefix;
            }
            else
            {
                if (Out != null)
                {
                    FileInfo fileInfo = new FileInfo(Out);
                    var      prefix   = fileInfo.Name.Substring(0, fileInfo.Name.LastIndexOf("."));
                    creationInformation.ResourceFilePrefix = prefix;
                }
            }
#endif
            if (ExtensibilityHandlers != null)
            {
                creationInformation.ExtensibilityHandlers = ExtensibilityHandlers.ToList <ExtensibilityHandler>();
            }

#pragma warning disable CS0618 // Type or member is obsolete
            if (NoBaseTemplate)
            {
                creationInformation.BaseTemplate = null;
            }
            else
            {
                creationInformation.BaseTemplate = this.SelectedWeb.GetBaseTemplate();
            }
#pragma warning restore CS0618 // Type or member is obsolete

            creationInformation.ProgressDelegate = (message, step, total) =>
            {
                WriteProgress(new ProgressRecord(0, string.Format("Extracting Template from {0}", SelectedWeb.Url), message)
                {
                    PercentComplete = (100 / total) * step
                });
            };
            creationInformation.MessagesDelegate = (message, type) =>
            {
                if (type == ProvisioningMessageType.Warning)
                {
                    WriteWarning(message);
                }
            };

            if (IncludeAllTermGroups)
            {
                creationInformation.IncludeAllTermGroups = true;
            }
            else
            {
                if (IncludeSiteCollectionTermGroup)
                {
                    creationInformation.IncludeSiteCollectionTermGroup = true;
                }
            }

            var template = SelectedWeb.GetProvisioningTemplate(creationInformation);

            // Set metadata for template, if any
            SetTemplateMetadata(template, TemplateDisplayName, TemplateImagePreviewUrl, TemplateProperties);

            ITemplateFormatter formatter = null;
            switch (schema)
            {
            case XMLPnPSchemaVersion.LATEST:
            {
                formatter = XMLPnPSchemaFormatter.LatestFormatter;
                break;
            }

            case XMLPnPSchemaVersion.V201503:
            {
#pragma warning disable CS0618 // Type or member is obsolete
                formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_03);
#pragma warning restore CS0618 // Type or member is obsolete
                break;
            }

            case XMLPnPSchemaVersion.V201505:
            {
#pragma warning disable CS0618 // Type or member is obsolete
                formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_05);
#pragma warning restore CS0618 // Type or member is obsolete
                break;
            }

            case XMLPnPSchemaVersion.V201508:
            {
                formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_08);
                break;
            }

            case XMLPnPSchemaVersion.V201512:
            {
                formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_12);
                break;
            }
            }

            if (extension == ".pnp")
            {
                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(

                    creationInformation.FileConnector as OpenXMLConnector);
                var templateFileName = packageName.Substring(0, packageName.LastIndexOf(".")) + ".xml";

                provider.SaveAs(template, templateFileName, formatter, TemplateProviderExtensions);
            }
            else
            {
                if (Out != null)
                {
                    XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(path, "");
                    provider.SaveAs(template, Path.Combine(path, packageName), formatter, TemplateProviderExtensions);
                }
                else
                {
                    var          _outputStream = formatter.ToFormattedTemplate(template);
                    StreamReader reader        = new StreamReader(_outputStream);

                    WriteObject(reader.ReadToEnd());
                }
            }
        }
Example #10
0
        public static async Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "post")] ApplyTemplateRequest request, TraceWriter log)
        {
            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Start();
            string siteUrl = request.SiteURL;

            RedirectAssembly();
            try
            {
                if (string.IsNullOrWhiteSpace(request.SiteURL))
                {
                    throw new ArgumentException("Parameter cannot be null", "SiteURL");
                }
                if (string.IsNullOrWhiteSpace(request.TemplateURL))
                {
                    throw new ArgumentException("Parameter cannot be null", "TemplateURL");
                }

                string templateUrl   = request.TemplateURL.Trim(); // remove potential spaces/line breaks
                var    clientContext = await ConnectADAL.GetClientContext(siteUrl, log);

                var web = clientContext.Web;
                web.Lists.EnsureSiteAssetsLibrary();
                clientContext.ExecuteQueryRetry();

                Uri templateFileUri = new Uri(templateUrl);
                var webUrl          = Web.WebUrlFromFolderUrlDirect(clientContext, templateFileUri);
                var templateContext = clientContext.Clone(webUrl.ToString());

                var library = templateUrl.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
                var    fileConnector         = new SharePointConnector(templateContext, templateContext.Url, library);
                string templateFileName      = Path.GetFileName(templateUrl);
                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(new OpenXMLConnector(templateFileName, fileConnector));
                templateFileName = templateFileName.Substring(0, templateFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";
                var provisioningTemplate = provider.GetTemplate(templateFileName, new ITemplateProviderExtension[0]);

                if (request.Parameters != null)
                {
                    foreach (var parameter in request.Parameters)
                    {
                        provisioningTemplate.Parameters[parameter.Key] = parameter.Value;
                    }
                }

                provisioningTemplate.Connector = provider.Connector;

                TokenReplaceCustomAction(provisioningTemplate, clientContext.Web);

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

                clientContext.Web.ApplyProvisioningTemplate(provisioningTemplate, applyingInformation);
                stopWatch.Stop();

                var applyTemplateResponse = new ApplyTemplateResponse
                {
                    TemplateApplied     = true,
                    ElapsedMilliseconds = stopWatch.ElapsedMilliseconds
                };
                return(await Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new ObjectContent <ApplyTemplateResponse>(applyTemplateResponse, new JsonMediaTypeFormatter())
                }));
            }
            catch (Exception e)
            {
                stopWatch.Stop();
                log.Error($"Error: {e.Message}\n\n{e.StackTrace}");
                return(await Task.FromResult(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable)
                {
                    Content = new ObjectContent <string>(e.Message, new JsonMediaTypeFormatter())
                }));
            }
        }
Example #11
0
        protected override void ProcessRecord()
        {
            if (!System.IO.Path.IsPathRooted(Path))
            {
                Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
            }
            if (!System.IO.Path.IsPathRooted(Source))
            {
                Source = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Source);
            }
            // Load the template
            var template = LoadProvisioningTemplate
                           .LoadProvisioningTemplateFromFile(Path,
                                                             TemplateProviderExtensions);

            if (template == null)
            {
                throw new ApplicationException("Invalid template file!");
            }

            // Load the file and add it to the .PNP file
            using (var fs = new FileStream(Source, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                Folder = Folder.Replace("\\", "/");

                var fileName  = Source.IndexOf("\\") > 0 ? Source.Substring(Source.LastIndexOf("\\") + 1) : Source;
                var container = !string.IsNullOrEmpty(Container) ? Container : string.Empty;
                var source    = !string.IsNullOrEmpty(container) ? (container + "/" + fileName) : fileName;

                template.Connector.SaveFileStream(fileName, container, fs);

                if (template.Connector is ICommitableFileConnector)
                {
                    ((ICommitableFileConnector)template.Connector).Commit();
                }

                template.Files.Add(new OfficeDevPnP.Core.Framework.Provisioning.Model.File
                {
                    Src       = source,
                    Folder    = Folder,
                    Level     = FileLevel,
                    Overwrite = FileOverwrite,
                });

                // Determine the output file name and path
                var outFileName = System.IO.Path.GetFileName(Path);
                var outPath     = new FileInfo(Path).DirectoryName;

                var fileSystemConnector = new FileSystemConnector(outPath, "");
                var formatter           = XMLPnPSchemaFormatter.LatestFormatter;
                var extension           = new FileInfo(Path).Extension.ToLowerInvariant();
                if (extension == ".pnp")
                {
                    var provider         = new XMLOpenXMLTemplateProvider(template.Connector as OpenXMLConnector);
                    var templateFileName = outFileName.Substring(0, outFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                    provider.SaveAs(template, templateFileName, formatter, TemplateProviderExtensions);
                }
                else
                {
                    XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(Path, "");
                    provider.SaveAs(template, Path, formatter, TemplateProviderExtensions);
                }
            }
        }
Example #12
0
        private void SaveProvisioningTemplateInternal(ClientContext context, GetProvisioningTemplateJob job, Boolean globalRepository = true)
        {
            // Fix the job filename if it is missing the .pnp extension
            if (!job.FileName.ToLower().EndsWith(".pnp"))
            {
                job.FileName += ".pnp";
            }

            // Get the Access Token from the current context
            //var accessToken = "Bearer " + context.GetAccessToken();
            var accessToken = context.GetAccessToken();

            Console.WriteLine("Bearer " + accessToken);

            // Get a reference to the target web site
            Web web = context.Web;

            context.Load(web, w => w.Url, w => w.ServerRelativeUrl);
            context.ExecuteQueryRetry();

            // Prepare the support variables
            ClientContext repositoryContext = null;
            Web           repositoryWeb     = null;

            // Define whether we need to use the global infrastructural repository or the local one
            if (globalRepository)
            {
                // Get a reference to the global repository web site and context
                repositoryContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext(
                    PnPPartnerPackSettings.InfrastructureSiteUrl);
            }
            else
            {
                // Get a reference to the local repository web site and context
                repositoryContext = web.Context.GetSiteCollectionContext();
            }

            using (repositoryContext)
            {
                repositoryWeb = repositoryContext.Site.RootWeb;
                repositoryContext.Load(repositoryWeb, w => w.Url);
                repositoryContext.ExecuteQueryRetry();

                // Configure the XML SharePoint provider for the Infrastructural Site Collection
                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(job.FileName,
                                                                              new SharePointConnector(repositoryContext, repositoryWeb.Url,
                                                                                                      PnPPartnerPackConstants.PnPProvisioningTemplates));

                ProvisioningTemplateCreationInformation ptci =
                    new ProvisioningTemplateCreationInformation(web);
                ptci.FileConnector                  = provider.Connector;
                ptci.IncludeAllTermGroups           = job.IncludeAllTermGroups;
                ptci.IncludeSearchConfiguration     = job.IncludeSearchConfiguration;
                ptci.IncludeSiteCollectionTermGroup = job.IncludeSiteCollectionTermGroup;
                ptci.IncludeSiteGroups              = job.IncludeSiteGroups;
                ptci.PersistBrandingFiles           = job.PersistComposedLookFiles;

                // We do intentionally remove taxonomies and search, which are not supported
                // in the AppOnly Authorization model
                // For further details, see the PnP Partner Pack documentation
                ptci.HandlersToProcess ^= Handlers.TermGroups;
                ptci.HandlersToProcess ^= Handlers.SearchSettings;

                // Extract the current template
                ProvisioningTemplate templateToSave = web.GetProvisioningTemplate(ptci);

                templateToSave.Description = job.Description;
                templateToSave.DisplayName = job.Title;

                if (job.PersistComposedLookFiles)
                {
                    // Create Theme Entity object
                    ThemeEntity themeEntity = web.GetCurrentComposedLook();

                    foreach (var p in themeEntity.GetType().GetProperties().Where(p => p.GetGetMethod().GetParameters().Count() == 0))
                    {
                        string propName  = p.Name;
                        string propValue = Convert.ToString(p.GetValue(themeEntity, null));

                        if (propName == "Theme")
                        {
                            propName = "ColorFile";
                        }
                        else if (propName == "Font")
                        {
                            propName = "FontFile";
                        }
                        else if (propName == "BackgroundImage")
                        {
                            propValue = "PlaceHolderValue";
                        }
                        else if (propName == "Name" && String.IsNullOrEmpty(propValue))
                        {
                            propValue = "CustomTheme";
                        }

                        string fileName    = propValue.Substring(propValue.LastIndexOf("/") + 1);
                        string relativeURL = propValue.Substring(0, propValue.LastIndexOf("/") + 1);

                        // Update template Files
                        if (propName != "Name" && propName != "IsCustomComposedLook" && !String.IsNullOrEmpty(propValue))
                        {
                            var property = templateToSave.ComposedLook.GetType().GetProperty(propName);

                            try
                            {
                                string folderPath = "";
                                Stream fileStream = null;

                                if (propName == "BackgroundImage")
                                {
                                    if (job.templateBackgroundImgFile != null)
                                    {
                                        folderPath = "{site}/SiteAssets";
                                        fileName   = job.FileName.ToLower().Replace(".pnp", ".png");
                                        fileStream = job.templateBackgroundImgFile.ToStream();
                                        Console.WriteLine("fileName: " + fileName);
                                        Console.WriteLine("fileStream: " + fileStream);
                                        templateToSave.ComposedLook.BackgroundFile = String.Format("{{sitecollection}}/SiteAssets/{0}", fileName);
                                    }
                                }
                                else if (propName.Contains("MasterPage"))
                                {
                                    folderPath = "{masterpagecatalog}";
                                    var strUrl = String.Format("{0}/_api/web/getfilebyserverrelativeurl('{1}{2}')/$value", web.Url, web.ServerRelativeUrl, propValue);
                                    fileStream = HttpHelper.MakeGetRequestForStream(strUrl, "application/octet-stream", accessToken);
                                    property.SetValue(templateToSave.ComposedLook, String.Format("{{masterpagecatalog}}/{0}", fileName), new object[] { });
                                }
                                else
                                {
                                    folderPath = "{themecatalog}/15";
                                    var strUrl = String.Format("{0}/_api/web/getfilebyserverrelativeurl('{1}{2}')/$value", web.Url, web.ServerRelativeUrl, propValue);
                                    fileStream = HttpHelper.MakeGetRequestForStream(strUrl, "application/octet-stream", accessToken);
                                    property.SetValue(templateToSave.ComposedLook, String.Format("{{themecatalog}}/15/{0}", fileName), new object[] { });
                                }

                                Console.WriteLine("Saving files: {0}, {1}", fileName, fileStream);
                                provider.Connector.SaveFileStream(fileName, fileStream);

                                Console.WriteLine("File Paths: {0}, {1}", fileName, folderPath);
                                templateToSave.Files.Add(new OfficeDevPnP.Core.Framework.Provisioning.Model.File
                                {
                                    Src       = fileName,
                                    Folder    = folderPath,
                                    Overwrite = true,
                                });

                                Console.WriteLine("Files saved: {0}, {1}", fileName, folderPath);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex);
                            }
                        }
                        else if (propName == "Name")
                        {
                            var property = templateToSave.ComposedLook.GetType().GetProperty(propName);

                            property.SetValue(templateToSave.ComposedLook, fileName, new object[] { });
                        }
                    }

                    if (job.templateAltCSSFile != null)
                    {
                        //TODO: Add handling for native Alternate CSS
                        //web.AlternateCssUrl;
                        string folderPath = "{site}/SiteAssets";
                        string fileName   = job.FileName.ToLower().Replace(".pnp", ".css");
                        Stream fileStream = job.templateAltCSSFile.ToStream();

                        provider.Connector.SaveFileStream(fileName, fileStream);

                        templateToSave.WebSettings = new WebSettings
                        {
                            AlternateCSS = String.Format("{{sitecollection}}/SiteAssets/{0}", fileName),
                        };

                        Console.WriteLine("File Paths: {0}, {1}", fileName, folderPath);
                        templateToSave.Files.Add(new OfficeDevPnP.Core.Framework.Provisioning.Model.File
                        {
                            Src       = fileName,
                            Folder    = folderPath,
                            Overwrite = true,
                        });
                    }
                }

                // Save template image preview in folder
                Microsoft.SharePoint.Client.Folder templatesFolder = repositoryWeb.GetFolderByServerRelativeUrl(PnPPartnerPackConstants.PnPProvisioningTemplates);
                repositoryContext.Load(templatesFolder, f => f.ServerRelativeUrl, f => f.Name);
                repositoryContext.ExecuteQueryRetry();

                // If there is a preview image
                if (job.TemplateImageFile != null)
                {
                    // Determine the preview image file name
                    String previewImageFileName = job.FileName.ToLower().Replace(".pnp", "_preview.png");

                    // Save the preview image inside the Open XML package
                    provider.Connector.SaveFileStream(previewImageFileName, job.TemplateImageFile.ToStream());

                    // And store URL in the XML file
                    templateToSave.ImagePreviewUrl = String.Format("{0}{1}/{2}/{3}/{4}",
                                                                   repositoryWeb.Url.ToLower().StartsWith("https") ? "pnps" : "pnp",
                                                                   repositoryWeb.Url.Substring(repositoryWeb.Url.IndexOf("://")),
                                                                   templatesFolder.Name, job.FileName, previewImageFileName);
                }

                // And save it on the file system
                provider.SaveAs(templateToSave, job.FileName.ToLower().Replace(".pnp", ".xml"));

                Microsoft.SharePoint.Client.File templateFile = templatesFolder.GetFile(job.FileName);
                ListItem item = templateFile.ListItemAllFields;

                item[PnPPartnerPackConstants.ContentTypeIdField]               = PnPPartnerPackConstants.PnPProvisioningTemplateContentTypeId;
                item[PnPPartnerPackConstants.TitleField]                       = job.Title;
                item[PnPPartnerPackConstants.PnPProvisioningTemplateScope]     = job.Scope.ToString();
                item[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl] = job.SourceSiteUrl;

                item.Update();

                repositoryContext.ExecuteQueryRetry();
            }
        }
        private void ExtractTemplate(XMLPnPSchemaVersion schema, string path, string packageName)
        {
            SelectedWeb.EnsureProperty(w => w.Url);

            var creationInformation = new ProvisioningTemplateCreationInformation(SelectedWeb);

            creationInformation.HandlersToProcess = Handlers.Lists;

            var extension = "";

            if (packageName != null)
            {
                if (packageName.IndexOf(".", StringComparison.Ordinal) > -1)
                {
                    extension = packageName.Substring(packageName.LastIndexOf(".", StringComparison.Ordinal)).ToLower();
                }
                else
                {
                    packageName += ".pnp";
                    extension    = ".pnp";
                }
            }

            var fileSystemConnector = new FileSystemConnector(path, "");

            if (extension == ".pnp")
            {
                creationInformation.FileConnector = new OpenXMLConnector(packageName, fileSystemConnector);
            }
            else
            {
                creationInformation.FileConnector = fileSystemConnector;
            }

            creationInformation.ProgressDelegate = (message, step, total) =>
            {
                var percentage = Convert.ToInt32((100 / Convert.ToDouble(total)) * Convert.ToDouble(step));

                WriteProgress(new ProgressRecord(0, $"Extracting Template from {SelectedWeb.Url}", message)
                {
                    PercentComplete = percentage
                });
            };
            creationInformation.MessagesDelegate = (message, type) =>
            {
                switch (type)
                {
                case ProvisioningMessageType.Warning:
                {
                    WriteWarning(message);
                    break;
                }

                case ProvisioningMessageType.Progress:
                {
                    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          = messageSplitted[0];
                            subProgressRecord.StatusDescription = 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;
                }
                }
            };

            if (List != null && List.Count > 0)
            {
                creationInformation.ListsToExtract.AddRange(List);
            }

            var template = SelectedWeb.GetProvisioningTemplate(creationInformation);



            if (!OutputInstance)
            {
                ITemplateFormatter formatter = null;
                switch (schema)
                {
                case XMLPnPSchemaVersion.LATEST:
                {
                    formatter = XMLPnPSchemaFormatter.LatestFormatter;
                    break;
                }

                case XMLPnPSchemaVersion.V201503:
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_03);
#pragma warning restore CS0618 // Type or member is obsolete
                    break;
                }

                case XMLPnPSchemaVersion.V201505:
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_05);
#pragma warning restore CS0618 // Type or member is obsolete
                    break;
                }

                case XMLPnPSchemaVersion.V201508:
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_08);
#pragma warning restore CS0618 // Type or member is obsolete
                    break;
                }

                case XMLPnPSchemaVersion.V201512:
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_12);
#pragma warning restore CS0618 // Type or member is obsolete
                    break;
                }

                case XMLPnPSchemaVersion.V201605:
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2016_05);
#pragma warning restore CS0618 // Type or member is obsolete
                    break;
                }

                case XMLPnPSchemaVersion.V201705:
                {
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2017_05);
                    break;
                }

                case XMLPnPSchemaVersion.V201801:
                {
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2018_01);
                    break;
                }

                case XMLPnPSchemaVersion.V201805:
                {
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2018_05);
                    break;
                }

                case XMLPnPSchemaVersion.V201807:
                {
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2018_07);
                    break;
                }

                case XMLPnPSchemaVersion.V201903:
                {
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2019_03);
                    break;
                }

                case XMLPnPSchemaVersion.V201909:
                {
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2019_09);
                    break;
                }
                }

                if (extension == ".pnp")
                {
                    IsolatedStorage.InitializeIsolatedStorage();

                    XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(
                        creationInformation.FileConnector as OpenXMLConnector);
                    var templateFileName = packageName.Substring(0, packageName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                    provider.SaveAs(template, templateFileName, formatter, null);
                }
                else
                {
                    if (Out != null)
                    {
                        XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(path, "");
                        provider.SaveAs(template, Path.Combine(path, packageName), formatter, null);
                    }
                    else
                    {
                        var outputStream = formatter.ToFormattedTemplate(template);
                        var reader       = new StreamReader(outputStream);

                        WriteObject(reader.ReadToEnd());
                    }
                }
            }
            else
            {
                WriteObject(template);
            }
        }
Example #14
0
        public string ApplyRambollTemplateOnSite(ApplyRambollTemplateRequest request)
        {
            try
            {
                var pnpPackageName            = "RambollProjectTemplate.pnp";
                ProvisioningTemplate template = null;
                var ptai = new ProvisioningTemplateApplyingInformation();
                ptai.ProgressDelegate = delegate(String message, Int32 progress, Int32 total)
                {
                    Console.WriteLine(@"{0:00}/{1:00} - {2}", progress, total, message);
                };
                if (string.IsNullOrEmpty(request.PnPXML)) //normal pnp file flow
                {
                    var storageFile     = fileStorageManager.GetFile($"{TemplateFolder}\\{pnpPackageName}");
                    var pnpTemplatePath = HostingEnvironment.MapPath($"~/{TemplateFolder}");
                    var tempFile        = $"{pnpTemplatePath}\\{pnpPackageName}";
                    System.IO.File.WriteAllBytes(tempFile, storageFile.Content);
                    using (
                        var context = TokenHelper.GetClientContextWithAccessToken(request.SiteUrl, request.AccessToken))
                    {
                        var fileSystemConnector      = new FileSystemConnector(pnpTemplatePath, "");
                        XMLTemplateProvider provider =
                            new XMLOpenXMLTemplateProvider(new OpenXMLConnector(pnpPackageName, fileSystemConnector));

                        template = provider.GetTemplate(pnpPackageName.Replace(".pnp", ".xml"));

                        template.Connector = provider.Connector;

                        RefineTemplate(context, template, ptai, request);

                        context.Web.ApplyProvisioningTemplate(template, ptai);
                        if (System.IO.File.Exists(tempFile))
                        {
                            System.IO.File.Delete(tempFile);
                        }
                        return("{ \"IsSuccess\": true, \"Message\": \"PnP template has been applied successfully\" }");
                    }
                }
                else
                {
                    //PNP xml flow
                    using (Stream s = GenerateStreamFromString(request.PnPXML))
                    {
                        var t = new XMLPnPSchemaFormatter();
                        template = t.ToProvisioningTemplate(s);
                    }

                    using (var context = TokenHelper.GetClientContextWithAccessToken(request.SiteUrl, request.AccessToken))
                    {
                        RefineTemplate(context, template, ptai, request);
                        context.Web.ApplyProvisioningTemplate(template, ptai);

                        return("{ \"IsSuccess\": true, \"Message\": \"PnP template has been applied successfully\" }");
                    }
                }
            }
            catch (Exception ex)
            {
                return("{ \"IsSuccess\": false, \"Message\": \"PnP template apply failed, Error: " + ex.Message + "\" }");
            }
        }
        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);
        }
        protected override void ProcessRecord()
        {
            if (MyInvocation.InvocationName.ToLower() == "save-pnpprovisioninghierarchy")
            {
                WriteWarning("Save-PnPProvisioningHierarchy has been deprecated. Use Save-PnPTenantTemplate instead.");
            }
            // Determine the output file name and path
            string outFileName = Path.GetFileName(Out);

            if (!Path.IsPathRooted(Out))
            {
                Out = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Out);
            }

            bool proceed = false;

            if (System.IO.File.Exists(Out))
            {
                if (Force || ShouldContinue(string.Format(Properties.Resources.File0ExistsOverwrite, Out),
                                            Properties.Resources.Confirm))
                {
                    System.IO.File.Delete(Out);
                    proceed = true;
                }
            }
            else
            {
                proceed = true;
            }

            string outPath = new FileInfo(Out).DirectoryName;

            // Determine if it is an .XML or a .PNP file
            var extension = "";

            if (proceed && outFileName != null)
            {
                if (outFileName.IndexOf(".", StringComparison.Ordinal) > -1)
                {
                    extension = outFileName.Substring(outFileName.LastIndexOf(".", StringComparison.Ordinal)).ToLower();
                }
                else
                {
                    extension = ".pnp";
                }
            }

            var fileSystemConnector = new FileSystemConnector(outPath, "");

            ITemplateFormatter formatter = XMLPnPSchemaFormatter.LatestFormatter;

            if (extension == ".pnp")
            {
                var useNewEvidence = false;
                try
                {
                    var usfdAttempt1 = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForDomain(); // this will fail when the current AppDomain Evidence is instantiated via COM or in PowerShell
                }
                catch (Exception e)
                {
                    useNewEvidence = true;
                }

                if (useNewEvidence)
                {
                    var replacementEvidence = new System.Security.Policy.Evidence();
                    replacementEvidence.AddHostEvidence(new System.Security.Policy.Zone(System.Security.SecurityZone.MyComputer));

                    var currentAppDomain      = System.Threading.Thread.GetDomain();
                    var securityIdentityField = currentAppDomain.GetType().GetField("_SecurityIdentity", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                    securityIdentityField.SetValue(currentAppDomain, replacementEvidence);
                }

                var templateFileName = outFileName.Substring(0, outFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(
                    Out, fileSystemConnector, templateFileName: templateFileName);
                WriteObject("Processing template");
                provider.SaveAs(Template, templateFileName);
                ProcessFiles(Out, fileSystemConnector, provider.Connector);
            }
            else
            {
                XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(outPath, "");
                provider.SaveAs(Template, Out);
            }
        }
        protected override void ExecuteCmdlet()
        {
            if (!System.IO.Path.IsPathRooted(Path))
            {
                Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
            }
            // Load the template
            var template = ProvisioningHelper.LoadSiteTemplateFromFile(Path, TemplateProviderExtensions, (e) =>
            {
                WriteError(new ErrorRecord(e, "TEMPLATENOTVALID", ErrorCategory.SyntaxError, null));
            });

            if (template == null)
            {
                throw new ApplicationException("Invalid template file.");
            }


            List spList = List.GetList(CurrentWeb);

            ClientContext.Load(spList, l => l.RootFolder, l => l.HasUniqueRoleAssignments);
            ClientContext.ExecuteQueryRetry();

            //We will remove a list if it's found so we can get the list
            ListInstance listInstance = template.Lists.Find(l => l.Title == spList.Title);

            if (listInstance == null)
            {
                throw new ApplicationException("List does not exist in the template file.");
            }


            Microsoft.SharePoint.Client.Folder listFolder = spList.RootFolder;
            ClientContext.Load(listFolder);
            ClientContext.ExecuteQueryRetry();

            IList <PnP.Framework.Provisioning.Model.Folder> folders = GetChildFolders(listFolder);

            template.Lists.Remove(listInstance);
            listInstance.Folders.AddRange(folders);
            template.Lists.Add(listInstance);

            // Determine the output file name and path
            var outFileName = System.IO.Path.GetFileName(Path);
            var outPath     = new FileInfo(Path).DirectoryName;

            var fileSystemConnector = new FileSystemConnector(outPath, "");
            var formatter           = XMLPnPSchemaFormatter.LatestFormatter;
            var extension           = new FileInfo(Path).Extension.ToLowerInvariant();

            if (extension == ".pnp")
            {
                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(new OpenXMLConnector(Path, fileSystemConnector));
                var templateFileName         = outFileName.Substring(0, outFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                provider.SaveAs(template, templateFileName, formatter, TemplateProviderExtensions);
            }
            else
            {
                XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(Path, "");
                provider.SaveAs(template, Path, formatter, TemplateProviderExtensions);
            }
        }
Example #18
0
        public static ProvisioningTemplate PrepareBrandingTemplate(ClientContext repositoryContext, BrandingSettings brandingSettings)
        {
            var repositoryWeb = repositoryContext.Site.RootWeb;

            repositoryContext.Load(repositoryWeb, w => w.Url);
            repositoryContext.ExecuteQueryRetry();

            var refererUri   = new Uri(repositoryWeb.Url);
            var refererValue = $"{refererUri.Scheme}://{refererUri.Host}/";

            var templateId = Guid.NewGuid();

            // Prepare an OpenXML provider
            XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider($"{templateId}.pnp",
                                                                          new SharePointConnector(repositoryContext, repositoryWeb.Url,
                                                                                                  PnPPartnerPackConstants.PnPProvisioningTemplates));

            // Prepare the branding provisioning template
            var template = new ProvisioningTemplate()
            {
                Id          = $"Branding-{Guid.NewGuid()}",
                DisplayName = "Branding Template",
            };

            template.WebSettings = new WebSettings
            {
                AlternateCSS = brandingSettings.CSSOverrideUrl,
                SiteLogo     = brandingSettings.LogoImageUrl,
            };

            template.ComposedLook = new ComposedLook()
            {
                Name = "SharePointBranding",
            };

            if (!String.IsNullOrEmpty(brandingSettings.BackgroundImageUrl))
            {
                var backgroundImageFileName   = brandingSettings.BackgroundImageUrl.Substring(brandingSettings.BackgroundImageUrl.LastIndexOf("/") + 1);
                var backgroundImageFileStream = HttpHelper.MakeGetRequestForStream(brandingSettings.BackgroundImageUrl, "application/octet-stream", referer: refererValue);
                template.ComposedLook.BackgroundFile = String.Format("{{sitecollection}}/SiteAssets/{0}", backgroundImageFileName);
                provider.Connector.SaveFileStream(backgroundImageFileName, backgroundImageFileStream);

                template.Files.Add(new Core.Framework.Provisioning.Model.File
                {
                    Src       = backgroundImageFileName,
                    Folder    = "SiteAssets",
                    Overwrite = true,
                });
            }
            else
            {
                template.ComposedLook.BackgroundFile = String.Empty;
            }

            if (!String.IsNullOrEmpty(brandingSettings.FontFileUrl))
            {
                var fontFileName   = brandingSettings.FontFileUrl.Substring(brandingSettings.FontFileUrl.LastIndexOf("/") + 1);
                var fontFileStream = HttpHelper.MakeGetRequestForStream(brandingSettings.FontFileUrl, "application/octet-stream", referer: refererValue);
                template.ComposedLook.FontFile = String.Format("{{themecatalog}}/15/{0}", fontFileName);
                provider.Connector.SaveFileStream(fontFileName, fontFileStream);

                template.Files.Add(new Core.Framework.Provisioning.Model.File
                {
                    Src       = fontFileName,
                    Folder    = "{themecatalog}/15",
                    Overwrite = true,
                });
            }
            else
            {
                template.ComposedLook.FontFile = String.Empty;
            }

            if (!String.IsNullOrEmpty(brandingSettings.ColorFileUrl))
            {
                var colorFileName   = brandingSettings.ColorFileUrl.Substring(brandingSettings.ColorFileUrl.LastIndexOf("/") + 1);
                var colorFileStream = HttpHelper.MakeGetRequestForStream(brandingSettings.ColorFileUrl, "application/octet-stream", referer: refererValue);
                template.ComposedLook.ColorFile = String.Format("{{themecatalog}}/15/{0}", colorFileName);
                provider.Connector.SaveFileStream(colorFileName, colorFileStream);

                template.Files.Add(new Core.Framework.Provisioning.Model.File
                {
                    Src       = colorFileName,
                    Folder    = "{themecatalog}/15",
                    Overwrite = true,
                });
            }
            else
            {
                template.ComposedLook.ColorFile = String.Empty;
            }

            // Save the template, ready to be applied
            provider.SaveAs(template, $"{templateId}.xml");

            // Re-open the template provider just saved
            provider = new XMLOpenXMLTemplateProvider($"{templateId}.pnp",
                                                      new SharePointConnector(repositoryContext, repositoryWeb.Url,
                                                                              PnPPartnerPackConstants.PnPProvisioningTemplates));

            // Set the connector of the template, in order to being able to retrieve support files
            template.Connector = provider.Connector;

            return(template);
        }
Example #19
0
        internal static ProvisioningHierarchy LoadProvisioningHierarchyFromFile(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
            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);
        }
        public PnPFileInfo GetPnPTemplateFileFromSite(CreatePnPTemplateRequest request)
        {
            var pnpPackageInfo = new PnPFileInfo();

            try
            {
                using (var context = TokenHelper.GetClientContextWithAccessToken(request.SiteUrl, request.AccessToken))
                {
                    var web = context.Web;
                    context.Load(web, w => w.Title, w => w.ServerRelativeUrl, w => w.Url);
                    context.ExecuteQuery();

                    var siteUrl = new Uri(request.SiteUrl);

                    var pnpFileName = "";

                    if (string.IsNullOrEmpty(request.PnpPackageName))
                    {
                        pnpFileName = BuildPnPPackageName(siteUrl);
                    }
                    else
                    {
                        pnpFileName = request.PnpPackageName;
                        if (pnpFileName.ToLower().EndsWith(".pnp"))
                        {
                            pnpFileName = pnpFileName.Substring(0, pnpFileName.Length - 4);
                        }
                    }
                    var pnpTemplatePath = HostingEnvironment.MapPath($"~/{TemplateFolder}");

                    var ptci = new ProvisioningTemplateCreationInformation(context.Web);
                    var fileSystemConnector = new FileSystemConnector(pnpTemplatePath, "");

                    ptci.PersistBrandingFiles          = true;
                    ptci.PersistPublishingFiles        = true;
                    ptci.PersistMultiLanguageResources = true;
                    ptci.FileConnector = new OpenXMLConnector($"{pnpFileName}.pnp", fileSystemConnector);

                    ptci.ProgressDelegate = delegate(String message, Int32 progress, Int32 total)
                    {
                        Console.WriteLine(@"{0:00}/{1:00} - {2}", progress, total, message);
                    };
                    ProvisioningTemplate template = new ProvisioningTemplate();
                    try
                    {
                        template = web.GetProvisioningTemplate(ptci);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("PnP engine failed to extract template. Error: {0}", ex.Message);
                    }

                    try
                    {
                        PageProvisionManager pageProvisionManager = new PageProvisionManager();
                        var pagesTemplate = pageProvisionManager.Extract(context, ptci);
                        foreach (var theFile in pagesTemplate.Files)
                        {
                            var existingFile =
                                template.Files.FirstOrDefault(
                                    f => f.Src.Equals(theFile.Src, StringComparison.InvariantCultureIgnoreCase));
                            if (existingFile == null)
                            {
                                template.Files.Add(theFile);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Failed to extract Pages. Error: {0}", ex.Message);
                    }
                    if (web.IsSubSite())
                    {
                        try
                        {
                            var siteColumnsTemplate = new SiteColumnProvisionManager().Extract(web, ptci);
                            foreach (var col in siteColumnsTemplate.SiteFields)
                            {
                                if (!template.SiteFields.Contains(col))
                                {
                                    template.SiteFields.Add(col);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Failed to extract Site Columns. Error: {0}", ex.Message);
                        }
                        try
                        {
                            var siteCTTemplate = new ContentTypeProvisionManager().Extract(web, ptci);
                            foreach (var ct in siteCTTemplate.ContentTypes)
                            {
                                if (!template.ContentTypes.Contains(ct))
                                {
                                    template.ContentTypes.Add(ct);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Failed to extract Site Content Types. Error: {0}", ex.Message);
                        }
                    }

                    XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider((OpenXMLConnector)ptci.FileConnector);
                    provider.SaveAs(template, $"{pnpFileName}.xml");
                    string fileLocation = $"{pnpTemplatePath}\\{pnpFileName}.pnp";
                    var    file         = new FileInfo(fileLocation);

                    fileStorageManager.SaveFile($"{TemplateFolder}\\{pnpFileName}.pnp", System.IO.File.ReadAllBytes(fileLocation));

                    pnpPackageInfo = new PnPFileInfo()
                    {
                        Name = $"{pnpFileName}.pnp",
                        Size = file.Length / 1024.0m
                    };
                    if (file.Exists)
                    {
                        file.Delete();
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return(pnpPackageInfo);
        }
        protected override void ExecuteCmdlet()
        {
            if (!System.IO.Path.IsPathRooted(Path))
            {
                Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
            }

            var template = ReadProvisioningTemplate
                           .LoadProvisioningTemplateFromFile(Path,
                                                             TemplateProviderExtensions, (e) =>
            {
                WriteError(new ErrorRecord(e, "TEMPLATENOTVALID", ErrorCategory.SyntaxError, null));
            });

            if (template == null)
            {
                throw new ApplicationException("Invalid template file!");
            }
            //We will remove a list if it's found so we can get the list

            ListInstance listInstance = template.Lists.Find(l => l.Title == List.Title);

            if (listInstance == null)
            {
                throw new ApplicationException("List does not exist in the template file!");
            }

            List spList = List.GetList(SelectedWeb);

            ClientContext.Load(spList, l => l.RootFolder, l => l.HasUniqueRoleAssignments);
            ClientContext.ExecuteQueryRetry();

            if (TokenizeUrls.IsPresent)
            {
                ClientContext.Load(ClientContext.Web, w => w.Url, w => w.ServerRelativeUrl, w => w.Id);
                ClientContext.Load(ClientContext.Site, s => s.Url, s => s.ServerRelativeUrl, s => s.Id);
                ClientContext.Load(ClientContext.Web.Lists, lists => lists.Include(l => l.Title, l => l.RootFolder.ServerRelativeUrl));
            }

            CamlQuery query = new CamlQuery();

            var viewFieldsStringBuilder = new StringBuilder();

            if (Fields != null)
            {
                viewFieldsStringBuilder.Append("<ViewFields>");
                foreach (var field in Fields)
                {
                    viewFieldsStringBuilder.AppendFormat("<FieldRef Name='{0}'/>", field);
                }
                viewFieldsStringBuilder.Append("</ViewFields>");
            }

            query.ViewXml = string.Format("<View>{0}{1}</View>", Query, viewFieldsStringBuilder);
            var listItems = spList.GetItems(query);

            ClientContext.Load(listItems, lI => lI.Include(l => l.HasUniqueRoleAssignments, l => l.ContentType.StringId));
            ClientContext.ExecuteQueryRetry();

            Microsoft.SharePoint.Client.FieldCollection fieldCollection = spList.Fields;
            ClientContext.Load(fieldCollection, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind, f => f.ReadOnlyField));
            ClientContext.ExecuteQueryRetry();

            var rows = new DataRowCollection(template);

            foreach (var listItem in listItems)
            {
                //Make sure we don't pull Folders.. Of course this won't work
                if (listItem.ServerObjectIsNull == false)
                {
                    ClientContext.Load(listItem);
                    ClientContext.ExecuteQueryRetry();
                    if (!(listItem.FileSystemObjectType == FileSystemObjectType.Folder))
                    {
                        DataRow row = new DataRow();
                        if (IncludeSecurity && listItem.HasUniqueRoleAssignments)
                        {
                            row.Security.ClearSubscopes      = true;
                            row.Security.CopyRoleAssignments = false;

                            var roleAssignments = listItem.RoleAssignments;
                            ClientContext.Load(roleAssignments);
                            ClientContext.ExecuteQueryRetry();

                            ClientContext.Load(roleAssignments, r => r.Include(a => a.Member.LoginName, a => a.Member, a => a.RoleDefinitionBindings));
                            ClientContext.ExecuteQueryRetry();

                            foreach (var roleAssignment in roleAssignments)
                            {
                                var principalName = roleAssignment.Member.LoginName;
                                var roleBindings  = roleAssignment.RoleDefinitionBindings;
                                foreach (var roleBinding in roleBindings)
                                {
                                    row.Security.RoleAssignments.Add(new OfficeDevPnP.Core.Framework.Provisioning.Model.RoleAssignment()
                                    {
                                        Principal = principalName, RoleDefinition = roleBinding.Name
                                    });
                                }
                            }
                        }
                        if (Fields != null)
                        {
                            foreach (var fieldName in Fields)
                            {
                                Microsoft.SharePoint.Client.Field dataField = fieldCollection.FirstOrDefault(f => f.InternalName == fieldName);

                                if (dataField != null)
                                {
                                    var defaultFieldValue = GetFieldValueAsText(ClientContext.Web, listItem, dataField);
                                    if (TokenizeUrls.IsPresent)
                                    {
                                        defaultFieldValue = Tokenize(defaultFieldValue, ClientContext.Web, ClientContext.Site);
                                    }

                                    row.Values.Add(fieldName, defaultFieldValue);
                                }
                            }
                        }
                        else
                        {
                            //All fields are added except readonly fields and unsupported field type
                            var fieldsToExport = fieldCollection.AsEnumerable()
                                                 .Where(f => !f.ReadOnlyField && !_unsupportedFieldTypes.Contains(f.FieldTypeKind));
                            foreach (var field in fieldsToExport)
                            {
                                var fldKey = (from f in listItem.FieldValues.Keys where f == field.InternalName select f).FirstOrDefault();
                                if (!string.IsNullOrEmpty(fldKey))
                                {
                                    var fieldValue = GetFieldValueAsText(ClientContext.Web, listItem, field);
                                    if (TokenizeUrls.IsPresent)
                                    {
                                        fieldValue = Tokenize(fieldValue, ClientContext.Web, ClientContext.Site);
                                    }
                                    row.Values.Add(field.InternalName, fieldValue);
                                }
                            }
                        }

                        rows.Add(row);
                    }
                }
            }
            template.Lists.Remove(listInstance);
            listInstance.DataRows.AddRange(rows);
            template.Lists.Add(listInstance);

            var outFileName = System.IO.Path.GetFileName(Path);
            var outPath     = new FileInfo(Path).DirectoryName;

            var fileSystemConnector = new FileSystemConnector(outPath, "");
            var formatter           = XMLPnPSchemaFormatter.LatestFormatter;
            var extension           = new FileInfo(Path).Extension.ToLowerInvariant();

            if (extension == ".pnp")
            {
                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(new OpenXMLConnector(Path, fileSystemConnector));
                var templateFileName         = outFileName.Substring(0, outFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                provider.SaveAs(template, templateFileName, formatter, TemplateProviderExtensions);
            }
            else
            {
                XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(Path, "");
                provider.SaveAs(template, Path, formatter, TemplateProviderExtensions);
            }
        }
        private void SaveProvisioningTemplateInternal(ClientContext context, GetProvisioningTemplateJob job, Boolean globalRepository = true)
        {
            // Fix the job filename if it is missing the .pnp extension
            if (!job.FileName.ToLower().EndsWith(".pnp"))
            {
                job.FileName += ".pnp";
            }

            // Get a reference to the target web site
            Web web = context.Web;

            context.Load(web, w => w.Url);
            context.ExecuteQueryRetry();

            // Prepare the support variables
            ClientContext repositoryContext = null;
            Web           repositoryWeb     = null;

            // Define whether we need to use the global infrastructural repository or the local one
            if (globalRepository)
            {
                // Get a reference to the global repository web site and context
                repositoryContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext(
                    PnPPartnerPackSettings.InfrastructureSiteUrl);
            }
            else
            {
                // Get a reference to the local repository web site and context
                repositoryContext = web.Context.GetSiteCollectionContext();
            }

            using (repositoryContext)
            {
                repositoryWeb = repositoryContext.Site.RootWeb;
                repositoryContext.Load(repositoryWeb, w => w.Url);
                repositoryContext.ExecuteQueryRetry();

                // Configure the XML SharePoint provider for the Infrastructural Site Collection
                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(job.FileName,
                                                                              new SharePointConnector(repositoryContext, repositoryWeb.Url,
                                                                                                      PnPPartnerPackConstants.PnPProvisioningTemplates));

                ProvisioningTemplateCreationInformation ptci =
                    new ProvisioningTemplateCreationInformation(web);
                ptci.FileConnector                  = provider.Connector;
                ptci.IncludeAllTermGroups           = job.IncludeAllTermGroups;
                ptci.IncludeSearchConfiguration     = job.IncludeSearchConfiguration;
                ptci.IncludeSiteCollectionTermGroup = job.IncludeSiteCollectionTermGroup;
                ptci.IncludeSiteGroups              = job.IncludeSiteGroups;
                ptci.PersistBrandingFiles           = job.PersistComposedLookFiles;

                // We do intentionally remove taxonomies and search, which are not supported
                // in the AppOnly Authorization model
                // For further details, see the PnP Partner Pack documentation
                ptci.HandlersToProcess ^= Handlers.TermGroups;
                ptci.HandlersToProcess ^= Handlers.SearchSettings;

                // Extract the current template
                ProvisioningTemplate templateToSave = web.GetProvisioningTemplate(ptci);

                templateToSave.Description = job.Description;
                templateToSave.DisplayName = job.Title;

                // Save template image preview in folder
                Microsoft.SharePoint.Client.Folder templatesFolder = repositoryWeb.GetFolderByServerRelativeUrl(PnPPartnerPackConstants.PnPProvisioningTemplates);
                repositoryContext.Load(templatesFolder, f => f.ServerRelativeUrl, f => f.Name);
                repositoryContext.ExecuteQueryRetry();

                // If there is a preview image
                if (job.TemplateImageFile != null)
                {
                    // Determine the preview image file name
                    String previewImageFileName = job.FileName.ToLower().Replace(".pnp", "_preview.png");

                    // Save the preview image inside the Open XML package
                    provider.Connector.SaveFileStream(previewImageFileName, job.TemplateImageFile.ToStream());

                    // And store URL in the XML file
                    templateToSave.ImagePreviewUrl = String.Format("{0}{1}/{2}/{3}/{4}",
                                                                   repositoryWeb.Url.ToLower().StartsWith("https") ? "pnps" : "pnp",
                                                                   repositoryWeb.Url.Substring(repositoryWeb.Url.IndexOf("://")),
                                                                   templatesFolder.Name, job.FileName, previewImageFileName);
                }

                // And save it on the file system
                provider.SaveAs(templateToSave, job.FileName.ToLower().Replace(".pnp", ".xml"));

                Microsoft.SharePoint.Client.File templateFile = templatesFolder.GetFile(job.FileName);
                ListItem item = templateFile.ListItemAllFields;

                item[PnPPartnerPackConstants.ContentTypeIdField]               = PnPPartnerPackConstants.PnPProvisioningTemplateContentTypeId;
                item[PnPPartnerPackConstants.TitleField]                       = job.Title;
                item[PnPPartnerPackConstants.PnPProvisioningTemplateScope]     = job.Scope.ToString();
                item[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl] = job.SourceSiteUrl;

                item.Update();

                repositoryContext.ExecuteQueryRetry();
            }
        }
        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();
                }
            }
        }
        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();
            }
        }
        private List <ProvisioningTemplateInformation> SearchProvisioningTemplatesInternal(string searchText, TargetPlatform platforms, TargetScope scope, String cacheKey)
        {
            List <ProvisioningTemplateInformation> result = new List <ProvisioningTemplateInformation>();

            // Connect to the target Templates Site Collection
            using (var context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(TemplatesSiteUrl))
            {
                // Get a reference to the target library
                Web web = context.Web;

                String platformsCAMLFilter = null;

                // Build the target Platforms filter
                if (platforms != TargetPlatform.None && platforms != TargetPlatform.All)
                {
                    if ((platforms & TargetPlatform.SharePointOnline) == TargetPlatform.SharePointOnline)
                    {
                        platformsCAMLFilter = @"<Eq>
                                                    <FieldRef Name='PnPProvisioningTemplatePlatform' />
                                                    <Value Type='MultiChoice'>SharePoint Online</Value>
                                                </Eq>";
                    }
                    if ((platforms & TargetPlatform.SharePoint2016) == TargetPlatform.SharePoint2016)
                    {
                        if (!String.IsNullOrEmpty(platformsCAMLFilter))
                        {
                            platformsCAMLFilter = @"<Or>" +
                                                  platformsCAMLFilter + @"
                                                        <Eq>
                                                            <FieldRef Name='PnPProvisioningTemplatePlatform' />
                                                            <Value Type='MultiChoice'>SharePoint 2016</Value>
                                                        </Eq>
                                                    </Or>";
                        }
                        else
                        {
                            platformsCAMLFilter = @"<Eq>
                                                    <FieldRef Name='PnPProvisioningTemplatePlatform' />
                                                    <Value Type='MultiChoice'>SharePoint 2016</Value>
                                                </Eq>";
                        }
                    }
                    if ((platforms & TargetPlatform.SharePoint2013) == TargetPlatform.SharePoint2013)
                    {
                        if (!String.IsNullOrEmpty(platformsCAMLFilter))
                        {
                            platformsCAMLFilter = @"<Or>" +
                                                  platformsCAMLFilter + @"
                                                        <Eq>
                                                            <FieldRef Name='PnPProvisioningTemplatePlatform' />
                                                            <Value Type='MultiChoice'>SharePoint 2013</Value>
                                                        </Eq>
                                                    </Or>";
                        }
                        else
                        {
                            platformsCAMLFilter = @"<Eq>
                                                    <FieldRef Name='PnPProvisioningTemplatePlatform' />
                                                    <Value Type='MultiChoice'>SharePoint 2013</Value>
                                                </Eq>";
                        }
                    }

                    try
                    {
                        List list = web.Lists.GetByTitle(PnPPartnerPackConstants.PnPProvisioningTemplates);

                        // Get only Provisioning Templates documents with the specified Scope
                        CamlQuery query = new CamlQuery();
                        query.ViewXml =
                            @"<View>
                        <Query>
                            <Where>" +
                            (!String.IsNullOrEmpty(platformsCAMLFilter) ? " < And>" : String.Empty) + @"
                                    <And>
                                        <Eq>
                                            <FieldRef Name='PnPProvisioningTemplateScope' />
                                            <Value Type='Choice'>" + scope.ToString() + @"</Value>
                                        </Eq>
                                        <Eq>
                                            <FieldRef Name='ContentType' />
                                            <Value Type=''Computed''>PnPProvisioningTemplate</Value>
                                        </Eq>
                                    </And>" + platformsCAMLFilter +
                            (!String.IsNullOrEmpty(platformsCAMLFilter) ? "</And>" : String.Empty) + @"                                
                            </Where>
                        </Query>
                        <ViewFields>
                            <FieldRef Name='Title' />
                            <FieldRef Name='PnPProvisioningTemplateScope' />
                            <FieldRef Name='PnPProvisioningTemplatePlatform' />
                            <FieldRef Name='PnPProvisioningTemplateSourceUrl' />
                        </ViewFields>
                    </View>";

                        ListItemCollection items = list.GetItems(query);
                        context.Load(items,
                                     includes => includes.Include(i => i.File,
                                                                  i => i[PnPPartnerPackConstants.PnPProvisioningTemplateScope],
                                                                  i => i[PnPPartnerPackConstants.PnPProvisioningTemplatePlatform],
                                                                  i => i[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl]));
                        context.ExecuteQueryRetry();

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

                        // Configure the SharePoint Connector
                        var sharepointConnector = new SharePointConnector(context, web.Url,
                                                                          PnPPartnerPackConstants.PnPProvisioningTemplates);

                        foreach (ListItem item in items)
                        {
                            // Get the template file name and server relative URL
                            item.File.EnsureProperties(f => f.Name, f => f.ServerRelativeUrl);

                            TemplateProviderBase provider = null;

                            // If the target is a .PNP Open XML template
                            if (item.File.Name.ToLower().EndsWith(".pnp"))
                            {
                                // Configure the Open XML provider for SharePoint
                                provider =
                                    new XMLOpenXMLTemplateProvider(
                                        new OpenXMLConnector(item.File.Name, sharepointConnector));
                            }
                            else
                            {
                                // Otherwise use the .XML template provider for SharePoint
                                provider =
                                    new XMLSharePointTemplateProvider(context, web.Url,
                                                                      PnPPartnerPackConstants.PnPProvisioningTemplates);
                            }

                            // Determine the name of the XML file inside the PNP Open XML file, if any
                            var xmlTemplateFile = item.File.Name.ToLower().Replace(".pnp", ".xml");

                            // Get the template
                            ProvisioningTemplate template = provider.GetTemplate(xmlTemplateFile);

                            // Prepare the resulting item
                            var templateInformation = new ProvisioningTemplateInformation
                            {
                                // Scope = (TargetScope)Enum.Parse(typeof(TargetScope), (String)item[PnPPartnerPackConstants.PnPProvisioningTemplateScope], true),
                                TemplateSourceUrl = item[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl] != null ? ((FieldUrlValue)item[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl]).Url : null,
                                TemplateFileUri   = String.Format("{0}/{1}/{2}", web.Url, PnPPartnerPackConstants.PnPProvisioningTemplates, item.File.Name),
                                TemplateImageUrl  = template.ImagePreviewUrl,
                                DisplayName       = template.DisplayName,
                                Description       = template.Description,
                            };

                            #region Determine Scope

                            String targetScope;
                            if (template.Properties.TryGetValue(PnPPartnerPackConstants.TEMPLATE_SCOPE, out targetScope))
                            {
                                if (String.Equals(targetScope, PnPPartnerPackConstants.TEMPLATE_SCOPE_PARTIAL, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    templateInformation.Scope = TargetScope.Partial;
                                }
                                else if (String.Equals(targetScope, PnPPartnerPackConstants.TEMPLATE_SCOPE_WEB, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    templateInformation.Scope = TargetScope.Web;
                                }
                                else if (String.Equals(targetScope, PnPPartnerPackConstants.TEMPLATE_SCOPE_SITE, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    templateInformation.Scope = TargetScope.Site;
                                }
                            }

                            #endregion

                            #region Determine target Platforms

                            String spoPlatform, sp2016Platform, sp2013Platform;
                            if (template.Properties.TryGetValue(PnPPartnerPackConstants.PLATFORM_SPO, out spoPlatform))
                            {
                                if (spoPlatform.Equals(PnPPartnerPackConstants.TRUE_VALUE, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    templateInformation.Platforms |= TargetPlatform.SharePointOnline;
                                }
                            }
                            if (template.Properties.TryGetValue(PnPPartnerPackConstants.PLATFORM_SP2016, out sp2016Platform))
                            {
                                if (sp2016Platform.Equals(PnPPartnerPackConstants.TRUE_VALUE, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    templateInformation.Platforms |= TargetPlatform.SharePoint2016;
                                }
                            }
                            if (template.Properties.TryGetValue(PnPPartnerPackConstants.PLATFORM_SP2013, out sp2013Platform))
                            {
                                if (sp2013Platform.Equals(PnPPartnerPackConstants.TRUE_VALUE, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    templateInformation.Platforms |= TargetPlatform.SharePoint2013;
                                }
                            }

                            #endregion

                            // If we don't have a search text
                            // or we have a search text and it is contained either
                            // in the DisplayName or in the Description of the template
                            if ((!String.IsNullOrEmpty(searchText) &&
                                 ((!String.IsNullOrEmpty(template.DisplayName) && template.DisplayName.ToLower().Contains(searchText.ToLower())) ||
                                  (!String.IsNullOrEmpty(template.Description) && template.Description.ToLower().Contains(searchText.ToLower())))) ||
                                String.IsNullOrEmpty(searchText))
                            {
                                // Add the template to the result
                                result.Add(templateInformation);
                            }
                        }
                    }
                    catch (ServerException)
                    {
                        // In case of any issue, ignore the failing templates
                    }
                }
            }

            CacheItemPolicy policy = new CacheItemPolicy
            {
                Priority           = CacheItemPriority.Default,
                AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(30), // Cache results for 30 minutes
                RemovedCallback    = (args) =>
                {
                    if (args.RemovedReason == CacheEntryRemovedReason.Expired)
                    {
                        var removedKey   = args.CacheItem.Key;
                        var searchInputs = JsonConvert.DeserializeObject <SharePointSearchCacheKey>(removedKey);

                        var newItem = SearchProvisioningTemplatesInternal(
                            searchInputs.SearchText,
                            searchInputs.Platforms,
                            searchInputs.Scope,
                            removedKey);
                    }
                },
            };

            Cache.Set(cacheKey, result, policy);

            return(result);
        }
        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);
                }
                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);
            }

            ProvisioningTemplate provisioningTemplate;

            // If we don't have the -InputInstance parameter, we load the template from the source connector
            if (InputInstance == null)
            {
                Stream stream           = fileConnector.GetFileStream(templateFileName);
                var    isOpenOfficeFile = IsOpenOfficeFile(stream);
                XMLTemplateProvider provider;
                if (isOpenOfficeFile)
                {
                    provider         = new XMLOpenXMLTemplateProvider(new OpenXMLConnector(templateFileName, fileConnector));
                    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)
                {
                    // 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;
                    }
                }
            }
            // Otherwise we use the provisioning template instance provided through the -InputInstance parameter
            else
            {
                provisioningTemplate = InputInstance;

                if (ResourceFolder != null)
                {
                    var fileSystemConnector = new FileSystemConnector(ResourceFolder, "");
                    provisioningTemplate.Connector = fileSystemConnector;
                }
                else
                {
                    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 (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) =>
            {
                WriteProgress(new ProgressRecord(0, $"Applying template to {SelectedWeb.Url}", message)
                {
                    PercentComplete = (100 / total) * step
                });
            };

            applyingInformation.MessagesDelegate = (message, type) =>
            {
                if (type == ProvisioningMessageType.Warning)
                {
                    WriteWarning(message);
                }
            };

            applyingInformation.OverwriteSystemPropertyBagValues = OverwriteSystemPropertyBagValues;
            SelectedWeb.ApplyProvisioningTemplate(provisioningTemplate, applyingInformation);
        }
Example #27
0
        private void ExtractTemplate(XMLPnPSchemaVersion schema, string path, string packageName)
        {
            SelectedWeb.EnsureProperty(w => w.Url);

            var creationInformation = new ProvisioningTemplateCreationInformation(SelectedWeb);

            if (MyInvocation.BoundParameters.ContainsKey("Handlers"))
            {
                creationInformation.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;
                    }
                }
                creationInformation.HandlersToProcess = Handlers;
            }

            var extension = "";

            if (packageName != null)
            {
                if (packageName.IndexOf(".", StringComparison.Ordinal) > -1)
                {
                    extension = packageName.Substring(packageName.LastIndexOf(".", StringComparison.Ordinal)).ToLower();
                }
                else
                {
                    packageName += ".pnp";
                    extension    = ".pnp";
                }
            }

            var fileSystemConnector = new FileSystemConnector(path, "");

            if (extension == ".pnp")
            {
                creationInformation.FileConnector = new OpenXMLConnector(packageName, fileSystemConnector);
            }
            else
            {
                creationInformation.FileConnector = fileSystemConnector;
            }
#pragma warning disable 618
            creationInformation.PersistBrandingFiles = PersistBrandingFiles || PersistComposedLookFiles;
#pragma warning restore 618
            creationInformation.PersistPublishingFiles       = PersistPublishingFiles;
            creationInformation.IncludeNativePublishingFiles = IncludeNativePublishingFiles;
            creationInformation.IncludeSiteGroups            = IncludeSiteGroups;
            creationInformation.IncludeTermGroupsSecurity    = IncludeTermGroupsSecurity;
            creationInformation.IncludeSearchConfiguration   = IncludeSearchConfiguration;
            creationInformation.SkipVersionCheck             = SkipVersionCheck;
            if (ContentTypeGroups != null)
            {
                creationInformation.ContentTypeGroupsToInclude = ContentTypeGroups.ToList();
            }
#if !SP2013
            creationInformation.PersistMultiLanguageResources = PersistMultiLanguageResources;
            if (extension == ".pnp")
            {
                // if file is of pnp format, persist all files
                creationInformation.PersistBrandingFiles          = true;
                creationInformation.PersistPublishingFiles        = true;
                creationInformation.PersistMultiLanguageResources = true;
            }
            if (!string.IsNullOrEmpty(ResourceFilePrefix))
            {
                creationInformation.ResourceFilePrefix = ResourceFilePrefix;
            }
            else
            {
                if (Out != null)
                {
                    FileInfo fileInfo = new FileInfo(Out);
                    var      prefix   = fileInfo.Name.Substring(0, fileInfo.Name.LastIndexOf(".", StringComparison.Ordinal));
                    creationInformation.ResourceFilePrefix = prefix;
                }
            }
#endif
            if (ExtensibilityHandlers != null)
            {
                creationInformation.ExtensibilityHandlers = ExtensibilityHandlers.ToList();
            }

#pragma warning disable CS0618 // Type or member is obsolete
            if (NoBaseTemplate)
            {
                creationInformation.BaseTemplate = null;
            }
            else
            {
                creationInformation.BaseTemplate = SelectedWeb.GetBaseTemplate();
            }
#pragma warning restore CS0618 // Type or member is obsolete

            creationInformation.ProgressDelegate = (message, step, total) =>
            {
                var percentage = Convert.ToInt32((100 / Convert.ToDouble(total)) * Convert.ToDouble(step));

                WriteProgress(new ProgressRecord(0, $"Extracting Template from {SelectedWeb.Url}", message)
                {
                    PercentComplete = percentage
                });
            };
            creationInformation.MessagesDelegate = (message, type) =>
            {
                switch (type)
                {
                case ProvisioningMessageType.Warning:
                {
                    WriteWarning(message);
                    break;
                }

                case ProvisioningMessageType.Progress:
                {
                    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          = messageSplitted[0];
                            subProgressRecord.StatusDescription = 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;
                }
                }
            };

            if (IncludeAllTermGroups)
            {
                creationInformation.IncludeAllTermGroups = true;
            }
            else
            {
                if (IncludeSiteCollectionTermGroup)
                {
                    creationInformation.IncludeSiteCollectionTermGroup = true;
                }
            }

            var template = SelectedWeb.GetProvisioningTemplate(creationInformation);

            // Set metadata for template, if any
            SetTemplateMetadata(template, TemplateDisplayName, TemplateImagePreviewUrl, TemplateProperties);

            if (!OutputInstance)
            {
                ITemplateFormatter formatter = null;
                switch (schema)
                {
                case XMLPnPSchemaVersion.LATEST:
                {
                    formatter = XMLPnPSchemaFormatter.LatestFormatter;
                    break;
                }

                case XMLPnPSchemaVersion.V201503:
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_03);
#pragma warning restore CS0618 // Type or member is obsolete
                    break;
                }

                case XMLPnPSchemaVersion.V201505:
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_05);
#pragma warning restore CS0618 // Type or member is obsolete
                    break;
                }

                case XMLPnPSchemaVersion.V201508:
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_08);
#pragma warning restore CS0618 // Type or member is obsolete
                    break;
                }

                case XMLPnPSchemaVersion.V201512:
                {
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2015_12);
                    break;
                }

                case XMLPnPSchemaVersion.V201605:
                {
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2016_05);
                    break;
                }

                case XMLPnPSchemaVersion.V201705:
                {
                    formatter = XMLPnPSchemaFormatter.GetSpecificFormatter(XMLConstants.PROVISIONING_SCHEMA_NAMESPACE_2017_05);
                    break;
                }
                }

                if (extension == ".pnp")
                {
                    XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(

                        creationInformation.FileConnector as OpenXMLConnector);
                    var templateFileName = packageName.Substring(0, packageName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                    provider.SaveAs(template, templateFileName, formatter, TemplateProviderExtensions);
                }
                else
                {
                    if (Out != null)
                    {
                        XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(path, "");
                        provider.SaveAs(template, Path.Combine(path, packageName), formatter, TemplateProviderExtensions);
                    }
                    else
                    {
                        var outputStream = formatter.ToFormattedTemplate(template);
                        var reader       = new StreamReader(outputStream);

                        WriteObject(reader.ReadToEnd());
                    }
                }
            }
            else
            {
                WriteObject(template);
            }
        }
        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(async(resource, scope) =>
            {
                if (resource.ToLower().StartsWith("https://"))
                {
                    var uri = new Uri(resource);
                    resource = uri.Authority;
                }
                // 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(await Task.FromResult(graphAccessToken));
                    }
                }

                if (PnPConnection.CurrentConnection.PSCredential != null)
                {
                    // Using normal credentials
                    return(await 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
            SelectedWeb.ApplyProvisioningTemplate(provisioningTemplate, applyingInformation);
#if !ONPREMISES
        }
#endif

            WriteProgress(new ProgressRecord(0, $"Applying template to {SelectedWeb.Url}", " ")
            {
                RecordType = ProgressRecordType.Completed
            });
        }
        protected override void ProcessRecord()
        {
            var templateObject = Template.GetTemplate(SessionState.Path.CurrentFileSystemLocation.Path, (e) =>
            {
                WriteError(new ErrorRecord(e, "TEMPLATENOTVALID", ErrorCategory.SyntaxError, null));
            });

            // Determine the output file name and path
            string outFileName = Path.GetFileName(Out);

            if (!Path.IsPathRooted(Out))
            {
                Out = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Out);
            }

            bool proceed = false;

            if (System.IO.File.Exists(Out))
            {
                if (Force || ShouldContinue(string.Format(Properties.Resources.File0ExistsOverwrite, Out),
                                            Properties.Resources.Confirm))
                {
                    proceed = true;
                }
            }
            else
            {
                proceed = true;
            }

            string outPath = new FileInfo(Out).DirectoryName;

            // Determine if it is an .XML or a .PNP file
            var extension = "";

            if (proceed && outFileName != null)
            {
                if (outFileName.IndexOf(".", StringComparison.Ordinal) > -1)
                {
                    extension = outFileName.Substring(outFileName.LastIndexOf(".", StringComparison.Ordinal)).ToLower();
                }
                else
                {
                    extension = ".pnp";
                }
            }

            var fileSystemConnector = new FileSystemConnector(outPath, "");

            ITemplateFormatter formatter = ProvisioningHelper.GetFormatter(Schema);

            if (extension == ".pnp")
            {
                XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(
                    Out, fileSystemConnector);
                var templateFileName = outFileName.Substring(0, outFileName.LastIndexOf(".", StringComparison.Ordinal)) + ".xml";

                provider.SaveAs(templateObject, templateFileName, formatter, TemplateProviderExtensions);
                ProcessFiles(templateObject, Out, fileSystemConnector);
            }
            else
            {
                XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(outPath, "");
                provider.SaveAs(templateObject, Out, formatter, TemplateProviderExtensions);
            }
        }
Example #30
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;
            }
        }