Пример #1
0
        public override ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateCreationInformation creationInfo)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                var lists = this.GetListsWithPages(template);
                template.Pages = new PageCollection(template);

                var homePageUrl = web.GetHomePageRelativeUrl();
                foreach (var list in lists)
                {
                    try
                    {
                        List splist = web.Lists.GetById(list.ID);
                        web.Context.Load(splist);
                        web.Context.ExecuteQueryRetry();
                        if (!creationInfo.ExecutePreProvisionEvent<ListInstance, List>(Handlers.Pages, template, list, null))
                        {
                            continue;
                        }

                        var listItems = GetListPages(web, splist);
                        var fileItems = listItems.AsEnumerable().Where(x => x.IsFile());
                        foreach (ListItem item in fileItems)
                        {
                            try
                            {
                                IPageModelProvider provider = GetProvider(item, homePageUrl, web, parser);
                                if (null != provider)
                                {
                                    provider.AddPage(item, template);
                                }
                            }
                            catch (Exception ex)
                            {
                                var message = string.Format("Error in export page for list: {0}", list.ServerRelativeUrl);
                                scope.LogError(ex, message);
                            }
                        }

                        creationInfo.ExecutePostProvisionEvent<ListInstance, List>(Handlers.Pages, template, list, splist);
                    }
                    catch (Exception exception)
                    {
                        var message = string.Format("Error in export publishing page for list: {0}", list.ServerRelativeUrl);
                        scope.LogError(exception, message);
                    }
                }
                // Impossible to return all files in the site currently

                // If a base template is specified then use that one to "cleanup" the generated template model
                if (creationInfo.BaseTemplate != null)
                {
                    template = CleanupEntities(template, creationInfo.BaseTemplate);
                }
            }
            return template;
        }
Пример #2
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                // if this is a sub site then we're not provisioning fields. Technically this can be done but it's not a recommended practice
                if (web.IsSubSite())
                {
                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Fields_Context_web_is_subweb__skipping_site_columns);
                    return parser;
                }

                var existingFields = web.Fields;

                web.Context.Load(existingFields, fs => fs.Include(f => f.Id));
                web.Context.ExecuteQueryRetry();
                var existingFieldIds = existingFields.AsEnumerable<SPField>().Select(l => l.Id).ToList();
                var fields = template.SiteFields;

                foreach (var field in fields)
                {
                    XElement templateFieldElement = XElement.Parse(parser.ParseString(field.SchemaXml, "~sitecollection", "~site"));
                    var fieldId = templateFieldElement.Attribute("ID").Value;

                    if (!existingFieldIds.Contains(Guid.Parse(fieldId)))
                    {
                        try
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Fields_Adding_field__0__to_site, fieldId);
                            CreateField(web, templateFieldElement, scope, parser, field.SchemaXml);
                        }
                        catch (Exception ex)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_Fields_Adding_field__0__failed___1_____2_, fieldId, ex.Message, ex.StackTrace);
                            throw;
                        }
                    }
                    else
                        try
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Fields_Updating_field__0__in_site, fieldId);
                            UpdateField(web, fieldId, templateFieldElement, scope, parser, field.SchemaXml);
                        }
                        catch (Exception ex)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_Fields_Updating_field__0__failed___1_____2_, fieldId, ex.Message, ex.StackTrace);
                            throw;
                        }
                }
            }
            return parser;
        }
 public TokenParser AddExtendedTokens(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
 {
     using (var scope = new PnPMonitoredScope(this.Name))
     {
         var context = web.Context as ClientContext;
         foreach (var provider in template.Providers)
         {
             if (provider.Enabled)
             {
                 try
                 {
                     if (!string.IsNullOrEmpty(provider.Configuration))
                     {
                         provider.Configuration = parser.ParseString(provider.Configuration);
                     }
                     scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ExtensibilityProviders_Calling_tokenprovider_extensibility_callout__0_, provider.Assembly);
                     var _providedTokens = _extManager.ExecuteTokenProviderCallOut(context, provider, template);
                     if (_providedTokens != null)
                     {
                         foreach (var token in _providedTokens)
                         {
                             parser.AddToken(token);
                         }
                     }
                 }
                 catch (Exception ex)
                 {
                     scope.LogError(CoreResources.Provisioning_ObjectHandlers_ExtensibilityProviders_tokenprovider_callout_failed___0_____1_, ex.Message, ex.StackTrace);
                     throw;
                 }
             }
         }
         return parser;
     }
 }
        internal void PersistFile(Web web, ProvisioningTemplateCreationInformation creationInfo, PnPMonitoredScope scope, string folderPath, string fileName, Boolean decodeFileName = false)
        {
            if (creationInfo.FileConnector != null)
            {
                SharePointConnector connector = new SharePointConnector(web.Context, web.Url, "dummy");

                Uri u = new Uri(web.Url);
                if (folderPath.IndexOf(u.PathAndQuery, StringComparison.InvariantCultureIgnoreCase) > -1)
                {
                    folderPath = folderPath.Replace(u.PathAndQuery, "");
                }

                using (Stream s = connector.GetFileStream(fileName, folderPath))
                {
                    if (s != null)
                    {
                        creationInfo.FileConnector.SaveFileStream(decodeFileName ? HttpUtility.UrlDecode(fileName) : fileName, s);
                    }
                }
            }
            else
            {
                WriteWarning("No connector present to persist homepage.", ProvisioningMessageType.Error);
                scope.LogError("No connector present to persist homepage");
            }
        }
Пример #5
0
        // This function will be triggered based on the schedule you have set for this WebJob
        public static void VerifyDocLib()
        {
            var url = ConfigurationManager.AppSettings["SpUrl"].ToString();
            var user = ConfigurationManager.AppSettings["SpUserName"].ToString();
            var pw = ConfigurationManager.AppSettings["SpPassword"].ToString();
            using (PnPMonitoredScope p = new PnPMonitoredScope())
            {
                p.LogInfo("Gathering connect info from web.config");
                p.LogInfo("SharePoint url is " + url);
                p.LogInfo("SharePoint user is " + user);
                try
                {
                    ClientContext cc = new ClientContext(url);
                    cc.AuthenticationMode = ClientAuthenticationMode.Default;
                    cc.Credentials = new SharePointOnlineCredentials(user, GetPassword(pw));
                    using (cc)
                    {
                        if (cc != null)
                        {
                            string listName = "Site Pages";
                            p.LogInfo("This is what a Monitored Scope log entry looks like in PNP, more to come as we try to validate a lists existence.");
                            p.LogInfo("Connect to Sharepoint");
                            ListCollection lists = cc.Web.Lists;
                            IEnumerable<List> results = cc.LoadQuery<List>(lists.Where(lst => lst.Title == listName));
                            p.LogInfo("Executing query to find the Site Pages library");
                            cc.ExecuteQuery();
                            p.LogInfo("Query Executed successfully.");
                            List list = results.FirstOrDefault();
                            if (list == null)
                            {
                                p.LogError("Site Pages library not found.");
                            }
                            else
                            {
                                p.LogInfo("Site Pages library found.");

                                ListItemCollection items = list.GetItems(new CamlQuery());
                                cc.Load(items, itms => itms.Include(item => item.DisplayName));
                                cc.ExecuteQueryRetry();
                                string pgs = "These pages were found, " + string.Join(", ", items.Select(x => x.DisplayName));
                                p.LogInfo(pgs);
                            }
                        }
                    }

                }
                catch (System.Exception ex)
                {
                    p.LogInfo("We had a problem: " + ex.Message);
                }
            }
        }
Пример #6
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                try
                {
                    parser = ProcessLookupFields(web, template, parser, scope);
                }
                catch (Exception ex)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_LookupFields_Processing_lookup_fields_failed___0_____1_, ex.Message, ex.StackTrace);
                    //throw;
                }

            }

            return parser;
        }
 public override ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo)
 {
     using (var scope = new PnPMonitoredScope(this.Name))
     {
         var context = web.Context as ClientContext;
         foreach (var handler in creationInfo.ExtensibilityHandlers)
         {
             if (handler.Enabled)
             {
                 try
                 {
                     scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ExtensibilityProviders_Calling_extensibility_callout__0_, handler.Assembly);
                     template = _extManager.ExecuteExtensibilityExtractionCallOut(context, handler, template, creationInfo, scope);
                 }
                 catch (Exception ex)
                 {
                     scope.LogError(CoreResources.Provisioning_ObjectHandlers_ExtensibilityProviders_callout_failed___0_____1_, ex.Message, ex.StackTrace);
                     throw;
                 }
             }
         }
     }
     return template;
 }
        internal void PersistFile(Web web, ProvisioningTemplateCreationInformation creationInfo, PnPMonitoredScope scope, string folderPath, string fileName, Boolean decodeFileName = false)
        {
            if (creationInfo.FileConnector != null)
            {
                SharePointConnector connector = new SharePointConnector(web.Context, web.Url, "dummy");

                if (folderPath.StartsWith( web.ServerRelativeUrl, StringComparison.OrdinalIgnoreCase ) )
                {
                    folderPath = folderPath.Substring(web.ServerRelativeUrl.Length);
                }
                using (Stream s = connector.GetFileStream(fileName, folderPath))
                {
                    if (s != null)
                    {
                        creationInfo.FileConnector.SaveFileStream(decodeFileName ? HttpUtility.UrlDecode(fileName) : fileName, s);
                    }
                }
            }
            else
            {
                WriteWarning("No connector present to persist homepage.", ProvisioningMessageType.Error);
                scope.LogError("No connector present to persist homepage");
            }
        }
Пример #9
0
        private static void UpdateContentType(Web web, Microsoft.SharePoint.Client.ContentType existingContentType, ContentType templateContentType, TokenParser parser, PnPMonitoredScope scope, bool isNoScriptSite = false)
        {
            var isDirty       = false;
            var reOrderFields = false;

            if (existingContentType.Hidden != templateContentType.Hidden)
            {
                scope.LogPropertyUpdate("Hidden");
                existingContentType.Hidden = templateContentType.Hidden;
                isDirty = true;
            }
            if (existingContentType.ReadOnly != templateContentType.ReadOnly)
            {
                scope.LogPropertyUpdate("ReadOnly");
                existingContentType.ReadOnly = templateContentType.ReadOnly;
                isDirty = true;
            }
            if (existingContentType.Sealed != templateContentType.Sealed)
            {
                scope.LogPropertyUpdate("Sealed");
                existingContentType.Sealed = templateContentType.Sealed;
                isDirty = true;
            }
            if (templateContentType.Description != null && existingContentType.Description != parser.ParseString(templateContentType.Description))
            {
                scope.LogPropertyUpdate("Description");
                existingContentType.Description = parser.ParseString(templateContentType.Description);
                isDirty = true;
            }
            if (templateContentType.DocumentTemplate != null && existingContentType.DocumentTemplate != parser.ParseString(templateContentType.DocumentTemplate))
            {
                scope.LogPropertyUpdate("DocumentTemplate");
                existingContentType.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate);
                isDirty = true;
            }
            if (existingContentType.Name != parser.ParseString(templateContentType.Name))
            {
                scope.LogPropertyUpdate("Name");
                existingContentType.Name = parser.ParseString(templateContentType.Name);
                isDirty = true;
                // CT is being renamed, add an extra token to the tokenparser
                parser.AddToken(new ContentTypeIdToken(web, existingContentType.Name, existingContentType.StringId));
            }
            if (templateContentType.Group != null && existingContentType.Group != parser.ParseString(templateContentType.Group))
            {
                scope.LogPropertyUpdate("Group");
                existingContentType.Group = parser.ParseString(templateContentType.Group);
                isDirty = true;
            }


            if (!isNoScriptSite)
            {
                if (templateContentType.DisplayFormUrl != null && existingContentType.DisplayFormUrl != parser.ParseString(templateContentType.DisplayFormUrl))
                {
                    scope.LogPropertyUpdate("DisplayFormUrl");
                    existingContentType.DisplayFormUrl = parser.ParseString(templateContentType.DisplayFormUrl);
                    isDirty = true;
                }
                if (templateContentType.EditFormUrl != null && existingContentType.EditFormUrl != parser.ParseString(templateContentType.EditFormUrl))
                {
                    scope.LogPropertyUpdate("EditFormUrl");
                    existingContentType.EditFormUrl = parser.ParseString(templateContentType.EditFormUrl);
                    isDirty = true;
                }
                if (templateContentType.NewFormUrl != null && existingContentType.NewFormUrl != parser.ParseString(templateContentType.NewFormUrl))
                {
                    scope.LogPropertyUpdate("NewFormUrl");
                    existingContentType.NewFormUrl = parser.ParseString(templateContentType.NewFormUrl);
                    isDirty = true;
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl)) ||
                    !string.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl)) ||
                    !string.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl)))
                {
                    // log message
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipCustomFormUrls, existingContentType.Name);
                }
            }

#if !SP2013
            if (templateContentType.Name.ContainsResourceToken())
            {
                existingContentType.NameResource.SetUserResourceValue(templateContentType.Name, parser);
                isDirty = true;
            }
            if (templateContentType.Description.ContainsResourceToken())
            {
                existingContentType.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser);
                isDirty = true;
            }
#endif
            if (isDirty)
            {
                existingContentType.Update(true);
                web.Context.ExecuteQueryRetry();
            }

            // Set flag to reorder fields CT fields are not equal to template fields
            var existingFieldNames = existingContentType.FieldLinks.AsEnumerable().Select(fld => fld.Name).ToArray();
            var ctFieldNames       = templateContentType.FieldRefs.Select(fld => parser.ParseString(fld.Name)).ToArray();
            reOrderFields = !existingFieldNames.SequenceEqual(ctFieldNames);

            // Delta handling
            existingContentType.EnsureProperty(c => c.FieldLinks);
            var targetIds = existingContentType.FieldLinks.AsEnumerable().Select(c1 => c1.Id).ToList();
            var sourceIds = templateContentType.FieldRefs.Select(c1 => c1.Id).ToList();

            var fieldsNotPresentInTarget = sourceIds.Except(targetIds).ToArray();

            if (fieldsNotPresentInTarget.Any())
            {
                // Set flag to reorder fields when new fields are added.
                reOrderFields = true;

                foreach (var fieldId in fieldsNotPresentInTarget)
                {
                    var fieldRef = templateContentType.FieldRefs.Find(fr => fr.Id == fieldId);
                    var field    = web.AvailableFields.GetById(fieldRef.Id);
                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Adding_field__0__to_content_type, fieldId);
                    web.AddFieldToContentType(existingContentType, field, fieldRef.Required, fieldRef.Hidden);
                }
            }

            // Reorder fields
            if (reOrderFields)
            {
                existingContentType.FieldLinks.Reorder(ctFieldNames);
                isDirty = true;
            }

            foreach (var fieldId in targetIds.Intersect(sourceIds))
            {
                var fieldLink = existingContentType.FieldLinks.FirstOrDefault(fl => fl.Id == fieldId);
                var fieldRef  = templateContentType.FieldRefs.Find(fr => fr.Id == fieldId);
                if (fieldRef != null)
                {
                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Field__0__exists_in_content_type, fieldId);
                    if (fieldLink.Required != fieldRef.Required)
                    {
                        scope.LogPropertyUpdate("Required");
                        fieldLink.Required = fieldRef.Required;
                        isDirty            = true;
                    }
                    if (fieldLink.Hidden != fieldRef.Hidden)
                    {
                        scope.LogPropertyUpdate("Hidden");
                        fieldLink.Hidden = fieldRef.Hidden;
                        isDirty          = true;
                    }
                }
            }

            // The new CT is a DocumentSet, and the target should be, as well
            if (templateContentType.DocumentSetTemplate != null)
            {
                if (!Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.IsChildOfDocumentSetContentType(web.Context, existingContentType).Value)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ContentTypes_InvalidDocumentSet_Update_Request, existingContentType.Id, existingContentType.Name);
                }
                else
                {
                    Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate templateToUpdate =
                        Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, existingContentType);

                    // TODO: Implement Delta Handling
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_DocumentSet_DeltaHandling_OnHold, existingContentType.Id, existingContentType.Name);
                }
            }

            if (isDirty)
            {
                existingContentType.Update(true);
                web.Context.ExecuteQueryRetry();
            }
        }
Пример #10
0
        public void UpdateLookups(Func<Guid, ListItemsProvider> fnGetLookupDependentProvider, PnPMonitoredScope scope)
        {
            if (null != m_lookups)
            {
                bool valueUpdated = false;
                foreach (KeyValuePair<string, LookupDataRef> pair in m_lookups)
                {
                    LookupDataRef lookupData = pair.Value;
                    if (0 < lookupData.ItemLookupValues.Count)
                    {
                        Guid sourceListId = Guid.Empty;
                        try
                        {
                            sourceListId = new Guid(lookupData.Field.LookupList);
                        }
                        catch (Exception ex)
                        {
                            scope.LogError(ex, "Failed to get source list for lookup field. Field Name: {0}, Source List: {1}.",
                                lookupData.Field.InternalName, lookupData.Field.LookupList);
                        }
                        if (!Guid.Empty.Equals(sourceListId))
                        {
                            ListItemsProvider sourceProvider = fnGetLookupDependentProvider(sourceListId);
                            if ((null != sourceProvider) && (null != sourceProvider.m_mappingIDs))
                            {
                                foreach (KeyValuePair<ListItem, object> lookupPair in lookupData.ItemLookupValues)
                                {
                                    ListItem item = lookupPair.Key;
                                    object newItemValue = null;
                                    object oldItemValue = lookupPair.Value;
                                    FieldLookupValue oldLookupValue = oldItemValue as FieldLookupValue;
                                    if (null != oldLookupValue)
                                    {
                                        int lookupId = oldLookupValue.LookupId;
                                        int newId;
                                        if (sourceProvider.m_mappingIDs.TryGetValue(lookupId, out newId) && (0 < newId))
                                        {
                                            newItemValue = new FieldLookupValue()
                                            {
                                                LookupId = newId
                                            };
                                        }
                                    }
                                    else
                                    {
                                        List<FieldLookupValue> newLookupValues = new List<FieldLookupValue>();
                                        FieldLookupValue[] oldLookupValues = oldItemValue as FieldLookupValue[];
                                        if ((null != oldLookupValues) && (0 < oldLookupValues.Length))
                                        {
                                            foreach (FieldLookupValue val in oldLookupValues)
                                            {
                                                int newId;
                                                if (sourceProvider.m_mappingIDs.TryGetValue(val.LookupId, out newId) && (0 < newId))
                                                {
                                                    newLookupValues.Add(new FieldLookupValue()
                                                    {
                                                        LookupId = newId
                                                    });
                                                }
                                            }
                                        }
                                        if (0 < newLookupValues.Count)
                                        {
                                            newItemValue = newLookupValues.ToArray();
                                        }
                                    }
                                    if (null != newItemValue)
                                    {
                                        item[lookupData.Field.InternalName] = newItemValue;
                                        item.Update();

                                        valueUpdated = true;
                                    }
                                }
                            }
                        }
                    }
                }
                if (valueUpdated)
                {
                    try
                    {
                        this.Context.ExecuteQueryRetry();
                    }
                    catch (Exception ex)
                    {
                        string lookupFieldNames = string.Join(", ", m_lookups.Select(pair => pair.Value.Field.InternalName).ToArray());
                        scope.LogError(ex, "Failed to set lookup values. List: '{0}', Lookup Fields: {1}.", this.List.Title, lookupFieldNames);
                    }
                }
            }
        }
Пример #11
0
        private TokenParser ProcessLookupFields(Web web, ProvisioningTemplate template, TokenParser parser, PnPMonitoredScope scope)
        {
            var rootWeb = (web.Context as ClientContext).Site.RootWeb;
            rootWeb.Context.Load(rootWeb.Lists, lists => lists.Include(l => l.Id, l => l.RootFolder.ServerRelativeUrl, l => l.Fields).Where(l => l.Hidden == false));
            rootWeb.Context.ExecuteQueryRetry();

            foreach (var siteField in template.SiteFields)
            {
                var fieldElement = XElement.Parse(siteField.SchemaXml);

                if (fieldElement.Attribute("List") != null)
                {
                    var fieldId = Guid.Parse(fieldElement.Attribute("ID").Value);
                    var listIdentifier = parser.ParseString(fieldElement.Attribute("List").Value);
                    var relationshipDeleteBehavior = fieldElement.Attribute("RelationshipDeleteBehavior") != null ? fieldElement.Attribute("RelationshipDeleteBehavior").Value : string.Empty;
                    var webId = string.Empty;

                    var field = rootWeb.Fields.GetById(fieldId);
                    rootWeb.Context.Load(field, f => f.SchemaXmlWithResourceTokens);
                    rootWeb.Context.ExecuteQueryRetry();

                    List sourceList = FindSourceList(listIdentifier, web, rootWeb);

                    if (sourceList != null)
                    {
                        rootWeb.Context.Load(sourceList.ParentWeb);
                        rootWeb.Context.ExecuteQueryRetry();

                        webId = sourceList.ParentWeb.Id.ToString();

                        ProcessField(field, sourceList.Id, webId, relationshipDeleteBehavior);
                    }
                }
            }

            web.Context.Load(web.Lists, lists => lists.Include(l => l.Id, l => l.RootFolder.ServerRelativeUrl, l => l.Fields).Where(l => l.Hidden == false));
            web.Context.ExecuteQueryRetry();

            foreach (var listInstance in template.Lists)
            {
                foreach (var listField in listInstance.Fields)
                {
                    var fieldElement = XElement.Parse(listField.SchemaXml);
                    if (fieldElement.Attribute("List") == null) continue;

                    var fieldId = Guid.Parse(fieldElement.Attribute("ID").Value);
                    var listIdentifier = parser.ParseString(fieldElement.Attribute("List").Value);
                    var relationshipDeleteBehavior = fieldElement.Attribute("RelationshipDeleteBehavior") != null ? fieldElement.Attribute("RelationshipDeleteBehavior").Value : string.Empty;
                    var webId = string.Empty;

                    var listUrl = UrlUtility.Combine(web.ServerRelativeUrl, parser.ParseString(listInstance.Url));

                    var createdList = web.Lists.FirstOrDefault(l => l.RootFolder.ServerRelativeUrl.Equals(listUrl, StringComparison.OrdinalIgnoreCase));
                    if (createdList != null)
                    {
                        try
                        {
                            var field = createdList.Fields.GetById(fieldId);
                            web.Context.Load(field, f => f.SchemaXmlWithResourceTokens);
                            web.Context.ExecuteQueryRetry();

                            List sourceList = FindSourceList(listIdentifier, web, rootWeb);

                            if (sourceList != null)
                            {
                                web.Context.Load(sourceList.ParentWeb);
                                web.Context.ExecuteQueryRetry();

                                webId = sourceList.ParentWeb.Id.ToString();
                                ProcessField(field, sourceList.Id, webId, relationshipDeleteBehavior);
                            }
                        }
                        catch (ArgumentException ex)
                        {
                            // We skip and log any issues related to not existing lookup fields
                            scope.LogError(String.Format("Exception searching for field! {0}", ex.Message));
                        }
                    }
                }
            }

            return parser;
        }
Пример #12
0
        private Field UpdateField(ClientObject web, ListInfo listInfo, Guid fieldId, XElement templateFieldElement, Field existingField, PnPMonitoredScope scope, TokenParser parser, string originalFieldXml)
        {
            Field field = null;
            web.Context.Load(existingField, f => f.SchemaXmlWithResourceTokens);
            web.Context.ExecuteQueryRetry();

            var existingFieldElement = XElement.Parse(existingField.SchemaXmlWithResourceTokens);

            var equalityComparer = new XNodeEqualityComparer();

            // Is field different in template?
            if (equalityComparer.GetHashCode(existingFieldElement) != equalityComparer.GetHashCode(templateFieldElement))
            {
                // Is existing field of the same type?
                if (existingFieldElement.Attribute("Type").Value == templateFieldElement.Attribute("Type").Value)
                {
                    templateFieldElement = PrepareField(templateFieldElement);
                    if (IsFieldXmlValid(parser.ParseString(templateFieldElement.ToString()), parser, web.Context))
                    {
                        foreach (var attribute in templateFieldElement.Attributes())
                        {
                            if (existingFieldElement.Attribute(attribute.Name) != null)
                            {
                                existingFieldElement.Attribute(attribute.Name).Value = attribute.Value;
                            }
                            else
                            {
                                existingFieldElement.Add(attribute);
                            }
                        }
                        foreach (var element in templateFieldElement.Elements())
                        {
                            if (existingFieldElement.Element(element.Name) != null)
                            {
                                existingFieldElement.Element(element.Name).Remove();
                            }
                            existingFieldElement.Add(element);
                        }

                        if (existingFieldElement.Attribute("Version") != null)
                        {
                            existingFieldElement.Attributes("Version").Remove();
                        }
                        existingField.SchemaXml = parser.ParseString(existingFieldElement.ToString(), "~sitecollection", "~site");
                        existingField.UpdateAndPushChanges(true);
                        web.Context.ExecuteQueryRetry();
                        bool isDirty = false;
            #if !SP2013
                        if (originalFieldXml.ContainsResourceToken())
                        {
                            var originalFieldElement = XElement.Parse(originalFieldXml);
                            var nameAttributeValue = originalFieldElement.Attribute("DisplayName") != null ? originalFieldElement.Attribute("DisplayName").Value : "";
                            if (nameAttributeValue.ContainsResourceToken())
                            {
                                if (existingField.TitleResource.SetUserResourceValue(nameAttributeValue, parser))
                                {
                                    isDirty = true;
                                }
                            }
                            var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null ? originalFieldElement.Attribute("Description").Value : "";
                            if (descriptionAttributeValue.ContainsResourceToken())
                            {
                                if (existingField.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser))
                                {
                                    isDirty = true;
                                }
                            }
                        }
            #endif
                        if (isDirty)
                        {
                            existingField.Update();
                            web.Context.ExecuteQueryRetry();
                            field = existingField;
                        }
                    }
                    else
                    {
                        // The field Xml was found invalid
                        var tokenString = parser.GetLeftOverTokens(originalFieldXml).Aggregate(String.Empty, (acc, i) => acc + " " + i);
                        scope.LogError("The field was found invalid: {0}", tokenString);
                        throw new Exception(string.Format("The field was found invalid: {0}", tokenString));
                    }
                }
                else
                {
                    var fieldName = existingFieldElement.Attribute("Name") != null ? existingFieldElement.Attribute("Name").Value : existingFieldElement.Attribute("StaticName").Value;
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field__0____1___exists_in_list__2____3___but_is_of_different_type__Skipping_field_, fieldName, fieldId, listInfo.TemplateList.Title, listInfo.SiteList.Id);
                    WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field__0____1___exists_in_list__2____3___but_is_of_different_type__Skipping_field_, fieldName, fieldId, listInfo.TemplateList.Title, listInfo.SiteList.Id), ProvisioningMessageType.Warning);
                }
            }
            return field;
        }
Пример #13
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                var context = web.Context as ClientContext;

                web.EnsureProperties(w => w.ServerRelativeUrl, w => w.RootFolder.WelcomePage);

                foreach (var page in template.Pages)
                {
                    var url = parser.ParseString(page.Url);

                    if (!url.ToLower().StartsWith(web.ServerRelativeUrl.ToLower()))
                    {
                        url = UrlUtility.Combine(web.ServerRelativeUrl, url);
                    }

                    var exists = true;
                    Microsoft.SharePoint.Client.File file = null;
                    try
                    {
                        file = web.GetFileByServerRelativeUrl(url);
                        web.Context.Load(file);
                        web.Context.ExecuteQuery();
                    }
                    catch (ServerException ex)
                    {
                        if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException")
                        {
                            exists = false;
                        }
                    }
                    if (exists)
                    {
                        if (page.Overwrite)
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0_, url);

                                if (page.WelcomePage && url.Contains(web.RootFolder.WelcomePage))
                                    web.SetHomePage(string.Empty);

                                file.DeleteObject();
                                web.Context.ExecuteQueryRetry();
                                web.AddWikiPageByUrl(url);
                                if (page.Layout == WikiPageLayout.Custom)
                                {
                                    web.AddLayoutToWikiPage(WikiPageLayout.OneColumn, url);
                                }
                                else {
                                    web.AddLayoutToWikiPage(page.Layout, url);
                                }
                            }
                            catch (Exception ex)
                            {
                                scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace);
                            }
                        }
                    }
                    else
                    {
                        try
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0_, url);

                            web.AddWikiPageByUrl(url);
                            web.AddLayoutToWikiPage(page.Layout, url);
                        }
                        catch (Exception ex)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace);
                        }
                    }

                    if (page.WelcomePage)
                    {
                        web.RootFolder.EnsureProperty(p => p.ServerRelativeUrl);
                        var rootFolderRelativeUrl = url.Substring(web.RootFolder.ServerRelativeUrl.Length);
                        web.SetHomePage(rootFolderRelativeUrl);
                    }

                    if (page.WebParts != null & page.WebParts.Any())
                    {
                        var existingWebParts = web.GetWebParts(url);

                        foreach (var webpart in page.WebParts)
                        {
                            if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == webpart.Title) == null)
                            {
                                WebPartEntity wpEntity = new WebPartEntity();
                                wpEntity.WebPartTitle = webpart.Title;
                                wpEntity.WebPartXml = parser.ParseString(webpart.Contents.Trim(new[] { '\n', ' ' }));
                                web.AddWebPartToWikiPage(url, wpEntity, (int)webpart.Row, (int)webpart.Column, false);
                            }
                        }
                        var allWebParts = web.GetWebParts(url);
                        foreach (var webpart in allWebParts)
                        {
                            parser.AddToken(new WebPartIdToken(web, webpart.WebPart.Title, webpart.Id));
                        }
                    }

                    file = web.GetFileByServerRelativeUrl(url);
                    file.EnsureProperty(f => f.ListItemAllFields);

                    if (page.Fields.Any())
                    {
                        var item = file.ListItemAllFields;
                        foreach (var fieldValue in page.Fields)
                        {
                            item[fieldValue.Key] = parser.ParseString(fieldValue.Value);
                        }
                        item.Update();
                        web.Context.ExecuteQueryRetry();
                    }
                    if (page.Security != null && page.Security.RoleAssignments.Count != 0)
                    {
                        web.Context.Load(file.ListItemAllFields);
                        web.Context.ExecuteQuery();
                        file.ListItemAllFields.SetSecurity(parser, page.Security);
                    }
                }
            }
            return parser;
        }
Пример #14
0
        private void UpdateField(Web web, string fieldId, XElement templateFieldElement, PnPMonitoredScope scope, TokenParser parser, string originalFieldXml)
        {
            var existingField = web.Fields.GetById(Guid.Parse(fieldId));
            web.Context.Load(existingField, f => f.SchemaXml);
            web.Context.ExecuteQueryRetry();

            XElement existingFieldElement = XElement.Parse(existingField.SchemaXml);

            XNodeEqualityComparer equalityComparer = new XNodeEqualityComparer();

            if (equalityComparer.GetHashCode(existingFieldElement) != equalityComparer.GetHashCode(templateFieldElement)) // Is field different in template?
            {
                if (existingFieldElement.Attribute("Type").Value == templateFieldElement.Attribute("Type").Value) // Is existing field of the same type?
                {
                    if (IsFieldXmlValid(parser.ParseString(originalFieldXml), parser, web.Context))
                    {
                        var listIdentifier = templateFieldElement.Attribute("List") != null ? templateFieldElement.Attribute("List").Value : null;

                        if (listIdentifier != null)
                        {
                            // Temporary remove list attribute from list
                            templateFieldElement.Attribute("List").Remove();
                        }

                        foreach (var attribute in templateFieldElement.Attributes())
                        {
                            if (existingFieldElement.Attribute(attribute.Name) != null)
                            {
                                existingFieldElement.Attribute(attribute.Name).Value = attribute.Value;
                            }
                            else
                            {
                                existingFieldElement.Add(attribute);
                            }
                        }
                        foreach (var element in templateFieldElement.Elements())
                        {
                            if (existingFieldElement.Element(element.Name) != null)
                            {
                                existingFieldElement.Element(element.Name).Remove();
                            }
                            existingFieldElement.Add(element);
                        }

                        if (existingFieldElement.Attribute("Version") != null)
                        {
                            existingFieldElement.Attributes("Version").Remove();
                        }
                        existingField.SchemaXml = parser.ParseString(existingFieldElement.ToString(), "~sitecollection", "~site");
                        existingField.UpdateAndPushChanges(true);
                        web.Context.Load(existingField, f => f.TypeAsString, f => f.DefaultValue);
                        web.Context.ExecuteQueryRetry();

                        bool isDirty = false;
            #if !CLIENTSDKV15
                        if (originalFieldXml.ContainsResourceToken())
                        {
                            var originalFieldElement = XElement.Parse(originalFieldXml);
                            var nameAttributeValue = originalFieldElement.Attribute("Title") != null ? originalFieldElement.Attribute("Title").Value : "";
                            if (nameAttributeValue.ContainsResourceToken())
                            {
                                existingField.TitleResource.SetUserResourceValue(nameAttributeValue, parser);
                                isDirty = true;
                            }
                            var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null ? originalFieldElement.Attribute("Description").Value : "";
                            if (descriptionAttributeValue.ContainsResourceToken())
                            {
                                existingField.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser);
                                isDirty = true;
                            }
                        }
            #endif
                        if (isDirty)
                        {
                            existingField.Update();
                            web.Context.ExecuteQuery();
                        }
                        if ((existingField.TypeAsString == "TaxonomyFieldType" || existingField.TypeAsString == "TaxonomyFieldTypeMulti") && !string.IsNullOrEmpty(existingField.DefaultValue))
                        {
                            var taxField = web.Context.CastTo<TaxonomyField>(existingField);
                            ValidateTaxonomyFieldDefaultValue(taxField);
                        }
                    }
                    else
                    {
                        // The field Xml was found invalid
                        var tokenString = parser.GetLeftOverTokens(originalFieldXml).Aggregate(String.Empty, (acc, i) => acc + " " + i);
                        scope.LogError("The field was found invalid: {0}", tokenString);
                        throw new Exception(string.Format("The field was found invalid: {0}", tokenString));
                    }
                }
                else
                {
                    var fieldName = existingFieldElement.Attribute("Name") != null ? existingFieldElement.Attribute("Name").Value : existingFieldElement.Attribute("StaticName").Value;
                    WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_Fields_Field__0____1___exists_but_is_of_different_type__Skipping_field_, fieldName, fieldId), ProvisioningMessageType.Warning);
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_Fields_Field__0____1___exists_but_is_of_different_type__Skipping_field_, fieldName, fieldId);

                }
            }
        }
Пример #15
0
        public override ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                web.EnsureProperties(w => w.HasUniqueRoleAssignments, w => w.Title);

                // Changed by Paolo Pialorsi to embrace the new sub-site attributes for break role inheritance and copy role assignments
                // if this is a sub site then we're not creating security entities as by default security is inherited from the root site
                if (web.IsSubSite() && !web.HasUniqueRoleAssignments)
                {
                    return(template);
                }

                var ownerGroup   = web.AssociatedOwnerGroup;
                var memberGroup  = web.AssociatedMemberGroup;
                var visitorGroup = web.AssociatedVisitorGroup;
                web.Context.ExecuteQueryRetry();

                if (!ownerGroup.ServerObjectIsNull.Value)
                {
                    web.Context.Load(ownerGroup, o => o.Id, o => o.Users, o => o.Title);
                }
                if (!memberGroup.ServerObjectIsNull.Value)
                {
                    web.Context.Load(memberGroup, o => o.Id, o => o.Users, o => o.Title);
                }
                if (!visitorGroup.ServerObjectIsNull.Value)
                {
                    web.Context.Load(visitorGroup, o => o.Id, o => o.Users, o => o.Title);
                }
                web.Context.ExecuteQueryRetry();

                List <int> associatedGroupIds = new List <int>();
                var        owners             = new List <User>();
                var        members            = new List <User>();
                var        visitors           = new List <User>();
                var        siteSecurity       = new SiteSecurity();

                if (!ownerGroup.ServerObjectIsNull.Value)
                {
                    siteSecurity.AssociatedOwnerGroup = ownerGroup.Title;
                    associatedGroupIds.Add(ownerGroup.Id);
                    foreach (var member in ownerGroup.Users)
                    {
                        owners.Add(new User()
                        {
                            Name = member.LoginName
                        });
                    }
                }
                if (!memberGroup.ServerObjectIsNull.Value)
                {
                    siteSecurity.AssociatedMemberGroup = memberGroup.Title;
                    associatedGroupIds.Add(memberGroup.Id);
                    foreach (var member in memberGroup.Users)
                    {
                        members.Add(new User()
                        {
                            Name = member.LoginName
                        });
                    }
                }
                if (!visitorGroup.ServerObjectIsNull.Value)
                {
                    siteSecurity.AssociatedVisitorGroup = visitorGroup.Title;
                    associatedGroupIds.Add(visitorGroup.Id);
                    foreach (var member in visitorGroup.Users)
                    {
                        visitors.Add(new User()
                        {
                            Name = member.LoginName
                        });
                    }
                }
                siteSecurity.AdditionalOwners.AddRange(owners);
                siteSecurity.AdditionalMembers.AddRange(members);
                siteSecurity.AdditionalVisitors.AddRange(visitors);

                var query = from user in web.SiteUsers
                            where user.IsSiteAdmin
                            select user;
                var allUsers = web.Context.LoadQuery(query);

                web.Context.ExecuteQueryRetry();

                var admins = new List <User>();
                foreach (var member in allUsers)
                {
                    admins.Add(new User()
                    {
                        Name = member.LoginName
                    });
                }
                siteSecurity.AdditionalAdministrators.AddRange(admins);

                if (creationInfo.IncludeSiteGroups)
                {
                    web.Context.Load(web.SiteGroups,
                                     o => o.IncludeWithDefaultProperties(
                                         gr => gr.Id,
                                         gr => gr.Title,
                                         gr => gr.AllowMembersEditMembership,
                                         gr => gr.AutoAcceptRequestToJoinLeave,
                                         gr => gr.AllowRequestToJoinLeave,
                                         gr => gr.Description,
                                         gr => gr.Users.Include(u => u.LoginName),
                                         gr => gr.OnlyAllowMembersViewMembership,
                                         gr => gr.Owner.LoginName,
                                         gr => gr.RequestToJoinLeaveEmailSetting
                                         ));

                    web.Context.ExecuteQueryRetry();

                    if (web.IsSubSite())
                    {
                        WriteMessage("You are requesting to export sitegroups from a subweb. Notice that ALL sitegroups from the site collection are included in the result.", ProvisioningMessageType.Warning);
                    }
                    foreach (var group in web.SiteGroups.AsEnumerable().Where(o => !associatedGroupIds.Contains(o.Id)))
                    {
                        try
                        {
                            scope.LogDebug("Processing group {0}", group.Title);
                            var siteGroup = new SiteGroup()
                            {
                                Title = !string.IsNullOrEmpty(web.Title) ? group.Title.Replace(web.Title, "{sitename}") : group.Title,
                                AllowMembersEditMembership   = group.AllowMembersEditMembership,
                                AutoAcceptRequestToJoinLeave = group.AutoAcceptRequestToJoinLeave,
                                AllowRequestToJoinLeave      = group.AllowRequestToJoinLeave,
                                Description = group.Description,
                                OnlyAllowMembersViewMembership = group.OnlyAllowMembersViewMembership,
                                Owner = ReplaceGroupTokens(web, group.Owner.LoginName),
                                RequestToJoinLeaveEmailSetting = group.RequestToJoinLeaveEmailSetting
                            };

                            if (String.IsNullOrEmpty(siteGroup.Description))
                            {
                                var groupItem = web.SiteUserInfoList.GetItemById(group.Id);
                                web.Context.Load(groupItem);
                                web.Context.ExecuteQueryRetry();

                                var groupNotes = (String)groupItem["Notes"];
                                if (!String.IsNullOrEmpty(groupNotes))
                                {
                                    siteGroup.Description = groupNotes;
                                }
                            }

                            foreach (var member in group.Users)
                            {
                                scope.LogDebug("Processing member {0} of group {0}", member.LoginName, group.Title);
                                siteGroup.Members.Add(new User()
                                {
                                    Name = member.LoginName
                                });
                            }
                            siteSecurity.SiteGroups.Add(siteGroup);
                        }
                        catch (Exception ee)
                        {
                            scope.LogError(ee.StackTrace);
                            scope.LogError(ee.Message);
                            scope.LogError(ee.InnerException.StackTrace);
                        }
                    }
                }

                var webRoleDefinitions = web.Context.LoadQuery(web.RoleDefinitions.Include(r => r.Name, r => r.Description, r => r.BasePermissions, r => r.RoleTypeKind));
                web.Context.ExecuteQueryRetry();

                if (web.HasUniqueRoleAssignments)
                {
                    var permissionKeys = Enum.GetNames(typeof(PermissionKind));
                    if (!web.IsSubSite())
                    {
                        foreach (var webRoleDefinition in webRoleDefinitions)
                        {
                            if (webRoleDefinition.RoleTypeKind == RoleType.None)
                            {
                                scope.LogDebug("Processing custom role definition {0}", webRoleDefinition.Name);
                                var modelRoleDefinitions = new Model.RoleDefinition();

                                modelRoleDefinitions.Description = webRoleDefinition.Description;
                                modelRoleDefinitions.Name        = webRoleDefinition.Name;

                                foreach (var permissionKey in permissionKeys)
                                {
                                    scope.LogDebug("Processing custom permissionKey definition {0}", permissionKey);
                                    var permissionKind =
                                        (PermissionKind)Enum.Parse(typeof(PermissionKind), permissionKey);
                                    if (webRoleDefinition.BasePermissions.Has(permissionKind))
                                    {
                                        modelRoleDefinitions.Permissions.Add(permissionKind);
                                    }
                                }
                                siteSecurity.SiteSecurityPermissions.RoleDefinitions.Add(modelRoleDefinitions);
                            }
                            else
                            {
                                scope.LogDebug("Skipping OOTB role definition {0}", webRoleDefinition.Name);
                            }
                        }
                    }
                    var webRoleAssignments = web.Context.LoadQuery(web.RoleAssignments.Include(
                                                                       r => r.RoleDefinitionBindings.Include(
                                                                           rd => rd.Name,
                                                                           rd => rd.RoleTypeKind),
                                                                       r => r.Member.LoginName,
                                                                       r => r.Member.PrincipalType));

                    web.Context.ExecuteQueryRetry();

                    foreach (var webRoleAssignment in webRoleAssignments)
                    {
                        scope.LogDebug("Processing Role Assignment {0}", webRoleAssignment.ToString());
                        if (webRoleAssignment.Member.PrincipalType == PrincipalType.SharePointGroup &&
                            !creationInfo.IncludeSiteGroups)
                        {
                            continue;
                        }

                        if (webRoleAssignment.Member.LoginName != "Excel Services Viewers")
                        {
                            foreach (var roleDefinition in webRoleAssignment.RoleDefinitionBindings)
                            {
                                if (roleDefinition.RoleTypeKind != RoleType.Guest)
                                {
                                    var modelRoleAssignment = new Model.RoleAssignment();
                                    var roleDefinitionValue = roleDefinition.Name;
                                    if (roleDefinition.RoleTypeKind != RoleType.None)
                                    {
                                        // Replace with token
                                        roleDefinitionValue = $"{{roledefinition:{roleDefinition.RoleTypeKind}}}";
                                    }
                                    modelRoleAssignment.RoleDefinition = roleDefinitionValue;
                                    if (webRoleAssignment.Member.PrincipalType == PrincipalType.SharePointGroup)
                                    {
                                        modelRoleAssignment.Principal = ReplaceGroupTokens(web, webRoleAssignment.Member.LoginName);
                                    }
                                    else
                                    {
                                        modelRoleAssignment.Principal = webRoleAssignment.Member.LoginName;
                                    }
                                    siteSecurity.SiteSecurityPermissions.RoleAssignments.Add(modelRoleAssignment);
                                }
                            }
                        }
                    }
                }

                template.Security = siteSecurity;

                // If a base template is specified then use that one to "cleanup" the generated template model
                if (creationInfo.BaseTemplate != null)
                {
                    template = CleanupEntities(template, creationInfo.BaseTemplate);
                }
            }
            return(template);
        }
Пример #16
0
        /// <summary>
        /// Public method to send a Webhook notification
        /// </summary>
        /// <param name="webhook">The reference webhook to notify</param>
        /// <param name="httpClient">The HttpClient instance to use to send the notification</param>
        /// <param name="kind">The Kind of webhook</param>
        /// <param name="parser">The parser to use for parsing parameters, optional</param>
        /// <param name="objectHandler">The objectHandler name, optional</param>
        /// <param name="exception">The exception, optional</param>
        /// <param name="scope">The PnP Provisioning Scope, if any, optional</param>
        public static void InvokeWebhook(ProvisioningWebhookBase webhook,
                                         HttpClient httpClient,
                                         ProvisioningTemplateWebhookKind kind, TokenParser parser = null,
                                         string objectHandler    = null, Exception exception = null,
                                         PnPMonitoredScope scope = null)
        {
            var requestParameters = new Dictionary <String, String>();

            if (exception != null)
            {
                // For GET requests we limit the size of the exception to avoid issues
                requestParameters["__exception"] =
                    webhook.Method == ProvisioningTemplateWebhookMethod.GET ?
                    exception.Message : exception.ToString();
            }

            SimpleTokenParser internalParser = new SimpleTokenParser();

            if (webhook.Parameters != null)
            {
                foreach (var webhookparam in webhook.Parameters)
                {
                    requestParameters.Add(webhookparam.Key, parser != null ? parser.ParseString(webhookparam.Value) : webhookparam.Value);
                    internalParser.AddToken(new WebhookParameter(webhookparam.Key, requestParameters[webhookparam.Key]));
                }
            }
            var url = parser != null?parser.ParseString(webhook.Url) : webhook.Url; // parse for template scoped parameters

            url = internalParser.ParseString(url);                                  // parse for webhook scoped parameters

            // Fix URL if it does not contain ?
            if (!url.Contains("?"))
            {
                url += "?";
            }

            switch (webhook.Method)
            {
            case ProvisioningTemplateWebhookMethod.GET:
            {
                url += $"&__webhookKind={kind.ToString()}";         // add the webhook kind to the REST request URL

                foreach (var k in requestParameters.Keys)
                {
                    url += $"&{HttpUtility.UrlEncode(k)}={HttpUtility.UrlEncode(requestParameters[k])}";
                }

                if ((kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted ||
                     kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted ||
                     kind == ProvisioningTemplateWebhookKind.ExceptionOccurred) && objectHandler != null)
                {
                    url += $"&__handler={HttpUtility.UrlEncode(objectHandler)}";         // add the handler name to the REST request URL
                }
                try
                {
                    if (webhook.Async)
                    {
                        Task.Factory.StartNew(async() =>
                            {
                                await httpClient.GetAsync(url);
                            });
                    }
                    else
                    {
                        httpClient.GetAsync(url).GetAwaiter().GetResult();
                    }
                }
                catch (HttpRequestException ex)
                {
                    scope?.LogError(ex, "Error calling provisioning template webhook");
                }
                break;
            }

            case ProvisioningTemplateWebhookMethod.POST:
            {
                requestParameters.Add("__webhookKind", kind.ToString());         // add the webhook kind to the parameters of the request body

                if ((kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted ||
                     kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted ||
                     kind == ProvisioningTemplateWebhookKind.ExceptionOccurred) && objectHandler != null)
                {
                    requestParameters.Add("__handler", objectHandler);         // add the handler name to the parameters of the request body
                }
                try
                {
                    if (webhook.Async)
                    {
                        Task.Factory.StartNew(async() =>
                            {
                                switch (webhook.BodyFormat)
                                {
                                case ProvisioningTemplateWebhookBodyFormat.Json:
                                    using (var stringContent = new StringContent(JsonConvert.SerializeObject(requestParameters), Encoding.UTF8, "application/json"))
                                    {
                                        await httpClient.PostAsync(url, stringContent);
                                    }
                                    break;

                                case ProvisioningTemplateWebhookBodyFormat.Xml:
                                    using (var stringContent = new StringContent(SerializeXml(requestParameters), Encoding.UTF8, "application/xml"))
                                    {
                                        await httpClient.PostAsync(url, stringContent);
                                    }
                                    break;

                                case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                    using (var content = new FormUrlEncodedContent(requestParameters))
                                    {
                                        await httpClient.PostAsync(url, content);
                                    }
                                    break;
                                }
                            });
                    }
                    else
                    {
                        switch (webhook.BodyFormat)
                        {
                        case ProvisioningTemplateWebhookBodyFormat.Json:
                            using (var stringContent = new StringContent(JsonConvert.SerializeObject(requestParameters), Encoding.UTF8, "application/json"))
                            {
                                httpClient.PostAsync(url, stringContent).GetAwaiter().GetResult();
                            }
                            break;

                        case ProvisioningTemplateWebhookBodyFormat.Xml:
                            using (var stringContent = new StringContent(SerializeXml(requestParameters), Encoding.UTF8, "application/xml"))
                            {
                                httpClient.PostAsync(url, stringContent);
                            }
                            break;

                        case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                            using (var content = new FormUrlEncodedContent(requestParameters))
                            {
                                httpClient.PostAsync(url, content).GetAwaiter().GetResult();
                            }
                            break;
                        }
                    }
                }
                catch (HttpRequestException ex)
                {
                    scope?.LogError(ex, "Error calling provisioning template webhook");
                }
                break;
            }
            }
        }
        public override ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                scope.LogInfo(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Retrieving_current_composed_look);

                // Ensure that we have URL property loaded for web and site
                web.EnsureProperty(w => w.Url);
                Site site = (web.Context as ClientContext).Site;
                site.EnsureProperty(s => s.Url);

                SharePointConnector spConnector = new SharePointConnector(web.Context, web.Url, "dummy");
                // to get files from theme catalog we need a connector linked to the root site
                SharePointConnector spConnectorRoot;
                if (!site.Url.Equals(web.Url, StringComparison.InvariantCultureIgnoreCase))
                {
                    spConnectorRoot = new SharePointConnector(web.Context.Clone(site.Url), site.Url, "dummy");
                }
                else
                {
                    spConnectorRoot = spConnector;
                }

                // Check if we have composed look info in the property bag, if so, use that, otherwise try to detect the current composed look
                if (web.PropertyBagContainsKey("_PnP_ProvisioningTemplateComposedLookInfo"))
                {
                    scope.LogInfo(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Using_ComposedLookInfoFromPropertyBag);

                    try
                    {
                        var composedLook = JsonConvert.DeserializeObject<ComposedLook>(web.GetPropertyBagValueString("_PnP_ProvisioningTemplateComposedLookInfo", ""));
                        if (composedLook.Name == null || composedLook.BackgroundFile == null || composedLook.FontFile == null)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_ComposedLookInfoFailedToDeserialize);
                            throw new JsonSerializationException();
                        }

                        composedLook.BackgroundFile = Tokenize(composedLook.BackgroundFile, web.Url);
                        composedLook.FontFile = Tokenize(composedLook.FontFile, web.Url);
                        composedLook.ColorFile = Tokenize(composedLook.ColorFile, web.Url);
                        template.ComposedLook = composedLook;

                        if (!web.IsSubSite() && creationInfo != null &&
                                creationInfo.PersistBrandingFiles && creationInfo.FileConnector != null)
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Creating_SharePointConnector);
                            // Let's create a SharePoint connector since our files anyhow are in SharePoint at this moment
                            TokenParser parser = new TokenParser(web, template);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.BackgroundFile), scope);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.ColorFile), scope);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.FontFile), scope);
                        }
                        // Create file entries for the custom theme files
                        if (!string.IsNullOrEmpty(template.ComposedLook.BackgroundFile))
                        {
                            var f = GetComposedLookFile(template.ComposedLook.BackgroundFile);
                            f.Folder = Tokenize(f.Folder, web.Url);
                            template.Files.Add(f);
                        }
                        if (!string.IsNullOrEmpty(template.ComposedLook.ColorFile))
                        {
                            var f = GetComposedLookFile(template.ComposedLook.ColorFile);
                            f.Folder = Tokenize(f.Folder, web.Url);
                            template.Files.Add(f);
                        }
                        if (!string.IsNullOrEmpty(template.ComposedLook.FontFile))
                        {
                            var f = GetComposedLookFile(template.ComposedLook.FontFile);
                            f.Folder = Tokenize(f.Folder, web.Url);
                            template.Files.Add(f);
                        }

                    }
                    catch (JsonSerializationException)
                    {
                        // cannot deserialize the object, fall back to composed look detection
                        template = DetectComposedLook(web, template, creationInfo, scope, spConnector, spConnectorRoot);
                    }

                }
                else
                {
                    template = DetectComposedLook(web, template, creationInfo, scope, spConnector, spConnectorRoot);
                }

                if (creationInfo != null && creationInfo.BaseTemplate != null)
                {
                    template = CleanupEntities(template, creationInfo.BaseTemplate);
                }
            }
            return template;
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (!template.Lists.Any())
                {
                    return(parser);
                }

                web.EnsureProperties(w => w.ServerRelativeUrl);

                web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                web.Context.ExecuteQueryRetry();

                #region DataRows
                foreach (var listInstance in template.Lists)
                {
                    if (listInstance.DataRows == null || !listInstance.DataRows.Any())
                    {
                        continue;
                    }

                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Processing_data_rows_for__0_, listInstance.Title);
                    // Retrieve the target list
                    var list = web.Lists.GetByTitle(parser.ParseString(listInstance.Title));
                    web.Context.Load(list);

                    // Retrieve the fields' types from the list
                    Microsoft.SharePoint.Client.FieldCollection fields = list.Fields;
                    web.Context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind, f => f.TypeAsString, f => f.ReadOnlyField, f => f.Title));
                    web.Context.ExecuteQueryRetry();

                    var keyColumnType   = "Text";
                    var parsedKeyColumn = parser.ParseString(listInstance.DataRows.KeyColumn);
                    if (!string.IsNullOrEmpty(parsedKeyColumn))
                    {
                        var keyColumn = fields.FirstOrDefault(f => f.InternalName.Equals(parsedKeyColumn, StringComparison.InvariantCultureIgnoreCase));
                        if (keyColumn != null)
                        {
                            switch (keyColumn.FieldTypeKind)
                            {
                            case FieldType.User:
                            case FieldType.Lookup:
                                keyColumnType = "Lookup";
                                break;

                            case FieldType.URL:
                                keyColumnType = "Url";
                                break;

                            case FieldType.DateTime:
                                keyColumnType = "DateTime";
                                break;

                            case FieldType.Number:
                            case FieldType.Counter:
                                keyColumnType = "Number";
                                break;
                            }
                        }
                    }

                    foreach (var dataRow in listInstance.DataRows)
                    {
                        try
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, listInstance.DataRows.IndexOf(dataRow) + 1);


                            bool     processItem  = true;
                            ListItem listitem     = null;
                            var      updateValues = new List <FieldUpdateValue>();

                            if (!string.IsNullOrEmpty(listInstance.DataRows.KeyColumn))
                            {
                                // Get value from key column
                                var dataRowValues = dataRow.Values.Where(v => v.Key == listInstance.DataRows.KeyColumn).ToList();

                                // if it is empty, skip the check
                                if (dataRowValues.Any())
                                {
                                    var query     = $@"<View><Query><Where><Eq><FieldRef Name=""{parsedKeyColumn}""/><Value Type=""{keyColumnType}"">{parser.ParseString(dataRowValues.FirstOrDefault().Value)}</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>";
                                    var camlQuery = new CamlQuery()
                                    {
                                        ViewXml = query
                                    };
                                    var existingItems = list.GetItems(camlQuery);
                                    list.Context.Load(existingItems);
                                    list.Context.ExecuteQueryRetry();
                                    if (existingItems.Count > 0)
                                    {
                                        if (listInstance.DataRows.UpdateBehavior == UpdateBehavior.Skip)
                                        {
                                            processItem = false;
                                        }
                                        else
                                        {
                                            listitem    = existingItems[0];
                                            processItem = true;
                                        }
                                    }
                                }
                            }

                            if (!processItem)
                            {
                                continue;
                            }

                            if (listitem == null)
                            {
                                var listitemCI = new ListItemCreationInformation();
                                listitem = list.AddItem(listitemCI);
                            }

                            foreach (var dataValue in dataRow.Values)
                            {
                                Field dataField = fields.FirstOrDefault(
                                    f => f.InternalName == parser.ParseString(dataValue.Key));

                                if (dataField != null && dataField.ReadOnlyField &&
                                    !dataField.InternalName.Equals("ContentTypeId", StringComparison.OrdinalIgnoreCase))
                                {
                                    // skip read only fields, except ContentTypeId
                                    continue;
                                }

                                if (dataField == null)
                                {
                                    continue;
                                }

                                if (dataValue.Value == null)
                                {
                                    updateValues.Add(dataField.FieldTypeKind == FieldType.Invalid
                                        ? new FieldUpdateValue(dataValue.Key, null, dataField.TypeAsString)
                                        : new FieldUpdateValue(dataValue.Key, null));
                                }
                                else
                                {
                                    String fieldValue = parser.ParseString(dataValue.Value);

                                    switch (dataField.FieldTypeKind)
                                    {
                                    case FieldType.Geolocation:
                                        // FieldGeolocationValue - Expected format: Altitude,Latitude,Longitude,Measure
                                        var geolocationArray = fieldValue.Split(',');
                                        if (geolocationArray.Length == 4)
                                        {
                                            var geolocationValue = new FieldGeolocationValue
                                            {
                                                Altitude  = Double.Parse(geolocationArray[0]),
                                                Latitude  = Double.Parse(geolocationArray[1]),
                                                Longitude = Double.Parse(geolocationArray[2]),
                                                Measure   = Double.Parse(geolocationArray[3]),
                                            };
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, geolocationValue));
                                        }
                                        else
                                        {
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, fieldValue));
                                        }
                                        break;

                                    case FieldType.Lookup:
                                        // FieldLookupValue - Expected format: LookupID or LookupID,LookupID,LookupID...
                                        if (fieldValue.Contains(","))
                                        {
                                            var lookupValues = new List <FieldLookupValue>();
                                            fieldValue.Split(',').All(value =>
                                            {
                                                lookupValues.Add(new FieldLookupValue
                                                {
                                                    LookupId = int.Parse(value),
                                                });
                                                return(true);
                                            });
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, lookupValues.ToArray()));
                                        }
                                        else
                                        {
                                            var lookupValue = new FieldLookupValue
                                            {
                                                LookupId = int.Parse(fieldValue),
                                            };
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, lookupValue));
                                        }
                                        break;

                                    case FieldType.URL:
                                        // FieldUrlValue - Expected format: URL,Description
                                        var urlArray  = fieldValue.Split(',');
                                        var linkValue = new FieldUrlValue();
                                        if (urlArray.Length == 2)
                                        {
                                            linkValue.Url         = urlArray[0];
                                            linkValue.Description = urlArray[1];
                                        }
                                        else
                                        {
                                            linkValue.Url         = urlArray[0];
                                            linkValue.Description = urlArray[0];
                                        }
                                        updateValues.Add(new FieldUpdateValue(dataValue.Key, linkValue));
                                        break;

                                    case FieldType.User:
                                        // FieldUserValue - Expected format: loginName or loginName,loginName,loginName...
                                        if (fieldValue.Contains(","))
                                        {
                                            var userValues = new List <FieldUserValue>();
                                            fieldValue.Split(',').All(value =>
                                            {
                                                var user = web.EnsureUser(value);
                                                web.Context.Load(user);
                                                web.Context.ExecuteQueryRetry();
                                                if (user != null)
                                                {
                                                    userValues.Add(new FieldUserValue
                                                    {
                                                        LookupId = user.Id,
                                                    });;
                                                }
                                                return(true);
                                            });
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, userValues.ToArray()));
                                        }
                                        else
                                        {
                                            var user = web.EnsureUser(fieldValue);
                                            web.Context.Load(user);
                                            web.Context.ExecuteQueryRetry();
                                            if (user != null)
                                            {
                                                var userValue = new FieldUserValue
                                                {
                                                    LookupId = user.Id,
                                                };
                                                updateValues.Add(new FieldUpdateValue(dataValue.Key, userValue));
                                            }
                                            else
                                            {
                                                updateValues.Add(new FieldUpdateValue(dataValue.Key, fieldValue));
                                            }
                                        }
                                        break;

                                    case FieldType.DateTime:
                                        var dateTime = DateTime.MinValue;
                                        if (DateTime.TryParse(fieldValue, out dateTime))
                                        {
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, dateTime));
                                        }
                                        break;

                                    case FieldType.Invalid:
                                        switch (dataField.TypeAsString)
                                        {
                                        case "TaxonomyFieldType":
                                        // Single value field - Expected format: term label|term GUID
                                        case "TaxonomyFieldTypeMulti":
                                            // Multi value field - Expected format: term label|term GUID;term label|term GUID;term label|term GUID;...
                                        {
                                            if (fieldValue != null)
                                            {
                                                var termStrings = new List <string>();

                                                var termsArray = fieldValue.Split(new char[] { ';' });
                                                foreach (var term in termsArray)
                                                {
                                                    termStrings.Add($"-1;#{term}");
                                                }
                                                updateValues.Add(new FieldUpdateValue(dataValue.Key, termStrings, dataField.TypeAsString));
                                            }
                                            break;
                                        }

                                        default:
                                        {
                                            //Publishing image case, but can be others too
                                            updateValues.Add(new FieldUpdateValue(dataValue.Key, fieldValue));
                                            break;
                                        }
                                        }
                                        break;

                                    default:
                                        updateValues.Add(new FieldUpdateValue(dataValue.Key, fieldValue));
                                        break;
                                    }
                                }
                            }

                            foreach (var itemValue in updateValues.Where(u => u.FieldTypeString != "TaxonomyFieldTypeMulti" && u.FieldTypeString != "TaxonomyFieldType"))
                            {
                                if (string.IsNullOrEmpty(itemValue.FieldTypeString))
                                {
                                    listitem[itemValue.Key] = itemValue.Value;
                                }
                            }
                            listitem.Update();
                            web.Context.Load(listitem);
                            web.Context.ExecuteQueryRetry();
                            foreach (var itemValue in updateValues.Where(u => u.FieldTypeString == "TaxonomyFieldTypeMulti" || u.FieldTypeString == "TaxonomyFieldType"))
                            {
                                switch (itemValue.FieldTypeString)
                                {
                                case "TaxonomyFieldTypeMulti":
                                {
                                    var field    = fields.FirstOrDefault(f => f.InternalName == itemValue.Key as string || f.Title == itemValue.Key as string);
                                    var taxField = web.Context.CastTo <TaxonomyField>(field);
                                    if (itemValue.Value != null)
                                    {
                                        var valueCollection = new TaxonomyFieldValueCollection(web.Context, string.Join(";#", itemValue.Value as List <string>), taxField);
                                        taxField.SetFieldValueByValueCollection(listitem, valueCollection);
                                    }
                                    else
                                    {
                                        var valueCollection = new TaxonomyFieldValueCollection(web.Context, null, taxField);
                                        taxField.SetFieldValueByValueCollection(listitem, valueCollection);
                                    }
                                    listitem.Update();
                                    web.Context.Load(listitem);
                                    web.Context.ExecuteQueryRetry();
                                    break;
                                }

                                case "TaxonomyFieldType":
                                {
                                    var field    = fields.FirstOrDefault(f => f.InternalName == itemValue.Key as string || f.Title == itemValue.Key as string);
                                    var taxField = web.Context.CastTo <TaxonomyField>(field);
                                    taxField.EnsureProperty(f => f.TextField);
                                    var taxValue = new TaxonomyFieldValue();
                                    if (itemValue.Value != null)
                                    {
                                        var termString = (itemValue.Value as List <string>).First();
                                        taxValue.Label    = termString.Split(new string[] { ";#" }, StringSplitOptions.None)[1].Split(new char[] { '|' })[0];
                                        taxValue.TermGuid = termString.Split(new string[] { ";#" }, StringSplitOptions.None)[1].Split(new char[] { '|' })[1];
                                        taxValue.WssId    = -1;
                                        taxField.SetFieldValueByValue(listitem, taxValue);
                                    }
                                    else
                                    {
                                        taxValue.Label    = string.Empty;
                                        taxValue.TermGuid = "11111111-1111-1111-1111-111111111111";
                                        taxValue.WssId    = -1;
                                        Field hiddenField = list.Fields.GetById(taxField.TextField);
                                        listitem.Context.Load(hiddenField, tf => tf.InternalName);
                                        listitem.Context.ExecuteQueryRetry();
                                        taxField.SetFieldValueByValue(listitem, taxValue);     // this order of updates is important.
                                        listitem[hiddenField.InternalName] = string.Empty;     // this order of updates is important.
                                    }
                                    listitem.Update();
                                    web.Context.Load(listitem);
                                    web.Context.ExecuteQueryRetry();
                                    break;
                                }
                                }
                            }
                            if (dataRow.Security != null && (dataRow.Security.ClearSubscopes == true || dataRow.Security.CopyRoleAssignments == true || dataRow.Security.RoleAssignments.Count > 0))
                            {
                                listitem.SetSecurity(parser, dataRow.Security);
                            }
                        }
                        catch (Exception ex)
                        {
                            if (ex.GetType().Equals(typeof(ServerException)) &&
                                (ex as ServerException).ServerErrorTypeName.Equals("Microsoft.SharePoint.SPDuplicateValuesFoundException", StringComparison.InvariantCultureIgnoreCase) &&
                                applyingInformation.IgnoreDuplicateDataRowErrors)
                            {
                                scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_duplicate);
                                continue;
                            }
                            else
                            {
                                scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, ex.Message, ex.StackTrace);
                                throw;
                            }
                        }
                    }
                }

                #endregion
            }

            return(parser);
        }
Пример #19
0
        private bool PersistFile(Web web, ProvisioningTemplateCreationInformation creationInfo, PnPMonitoredScope scope, string serverRelativeUrl)
        {
            var success = false;

            if (creationInfo.PersistBrandingFiles)
            {
                if (creationInfo.FileConnector != null)
                {
                    if (UrlUtility.IsIisVirtualDirectory(serverRelativeUrl))
                    {
                        scope.LogWarning("File is not located in the content database. Not retrieving {0}", serverRelativeUrl);
                        return(success);
                    }

                    try
                    {
                        var    file     = web.GetFileByServerRelativeUrl(serverRelativeUrl);
                        string fileName = string.Empty;
                        if (serverRelativeUrl.IndexOf("/") > -1)
                        {
                            fileName = serverRelativeUrl.Substring(serverRelativeUrl.LastIndexOf("/") + 1);
                        }
                        else
                        {
                            fileName = serverRelativeUrl;
                        }
                        web.Context.Load(file);
                        web.Context.ExecuteQueryRetry();
                        ClientResult <Stream> stream = file.OpenBinaryStream();
                        web.Context.ExecuteQueryRetry();

                        using (Stream memStream = new MemoryStream())
                        {
                            CopyStream(stream.Value, memStream);
                            memStream.Position = 0;
                            creationInfo.FileConnector.SaveFileStream(fileName, memStream);
                        }
                        success = true;
                    }
                    catch (ServerException ex1)
                    {
                        // If we are referring a file from a location outside of the current web or at a location where we cannot retrieve the file an exception is thrown. We swallow this exception.
                        if (ex1.ServerErrorCode != -2147024809)
                        {
                            throw;
                        }
                        else
                        {
                            scope.LogWarning("File is not necessarily located in the current web. Not retrieving {0}", serverRelativeUrl);
                        }
                    }
                }
                else
                {
                    WriteMessage("No connector present to persist homepage.", ProvisioningMessageType.Error);
                    scope.LogError("No connector present to persist homepage");
                }
            }
            else
            {
                success = true;
            }
            return(success);
        }
Пример #20
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.Lists.Any())
                {
                    var rootWeb = (web.Context as ClientContext).Site.RootWeb;

                    web.EnsureProperties(w => w.ServerRelativeUrl);

                    web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                    web.Context.ExecuteQueryRetry();
                    var existingLists     = web.Lists.AsEnumerable <List>().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList();
                    var serverRelativeUrl = web.ServerRelativeUrl;

                    #region DataRows

                    foreach (var listInstance in template.Lists)
                    {
                        if (listInstance.DataRows != null && listInstance.DataRows.Any())
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Processing_data_rows_for__0_, listInstance.Title);
                            // Retrieve the target list
                            var list = web.Lists.GetByTitle(parser.ParseString(listInstance.Title));
                            web.Context.Load(list);

                            // Retrieve the fields' types from the list
                            Microsoft.SharePoint.Client.FieldCollection fields = list.Fields;
                            web.Context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind, f => f.TypeAsString));
                            web.Context.ExecuteQueryRetry();

                            var keyColumnType   = "Text";
                            var parsedKeyColumn = parser.ParseString(listInstance.DataRows.KeyColumn);
                            if (!string.IsNullOrEmpty(parsedKeyColumn))
                            {
                                var keyColumn = fields.FirstOrDefault(f => f.InternalName.Equals(parsedKeyColumn, StringComparison.InvariantCultureIgnoreCase));
                                if (keyColumn != null)
                                {
                                    switch (keyColumn.FieldTypeKind)
                                    {
                                    case FieldType.User:
                                    case FieldType.Lookup:
                                        keyColumnType = "Lookup";
                                        break;

                                    case FieldType.URL:
                                        keyColumnType = "Url";
                                        break;

                                    case FieldType.DateTime:
                                        keyColumnType = "DateTime";
                                        break;

                                    case FieldType.Number:
                                    case FieldType.Counter:
                                        keyColumnType = "Number";
                                        break;
                                    }
                                }
                            }

                            foreach (var dataRow in listInstance.DataRows)
                            {
                                try
                                {
                                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, listInstance.DataRows.IndexOf(dataRow) + 1);


                                    bool     create   = true;
                                    ListItem listitem = null;
                                    if (!string.IsNullOrEmpty(listInstance.DataRows.KeyColumn))
                                    {
                                        // if it is empty, skip the check
                                        if (!string.IsNullOrEmpty(dataRow.Key))
                                        {
                                            var query     = $@"<View><Query><Where><Eq><FieldRef Name=""{parsedKeyColumn}""/><Value Type=""{keyColumnType}"">{parser.ParseString(dataRow.Key)}</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>";
                                            var camlQuery = new CamlQuery()
                                            {
                                                ViewXml = query
                                            };
                                            var existingItems = list.GetItems(camlQuery);
                                            list.Context.Load(existingItems);
                                            list.Context.ExecuteQueryRetry();
                                            if (existingItems.Count > 0)
                                            {
                                                if (listInstance.DataRows.UpdateBehavior == UpdateBehavior.Skip)
                                                {
                                                    create = false;
                                                }
                                                else
                                                {
                                                    listitem = existingItems[0];
                                                    create   = true;
                                                }
                                            }
                                        }
                                    }

                                    if (create)
                                    {
                                        if (listitem == null)
                                        {
                                            var listitemCI = new ListItemCreationInformation();
                                            listitem = list.AddItem(listitemCI);
                                        }

                                        foreach (var dataValue in dataRow.Values)
                                        {
                                            Field dataField = fields.FirstOrDefault(
                                                f => f.InternalName == parser.ParseString(dataValue.Key));

                                            if (dataField != null)
                                            {
                                                String fieldValue = parser.ParseString(dataValue.Value);

                                                switch (dataField.FieldTypeKind)
                                                {
                                                case FieldType.Geolocation:
                                                    // FieldGeolocationValue - Expected format: Altitude,Latitude,Longitude,Measure
                                                    var geolocationArray = fieldValue.Split(',');
                                                    if (geolocationArray.Length == 4)
                                                    {
                                                        var geolocationValue = new FieldGeolocationValue
                                                        {
                                                            Altitude  = Double.Parse(geolocationArray[0]),
                                                            Latitude  = Double.Parse(geolocationArray[1]),
                                                            Longitude = Double.Parse(geolocationArray[2]),
                                                            Measure   = Double.Parse(geolocationArray[3]),
                                                        };
                                                        listitem[parser.ParseString(dataValue.Key)] = geolocationValue;
                                                    }
                                                    else
                                                    {
                                                        listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    }
                                                    break;

                                                case FieldType.Lookup:
                                                    // FieldLookupValue - Expected format: LookupID or LookupID,LookupID,LookupID...
                                                    if (fieldValue.Contains(","))
                                                    {
                                                        var lookupValues = new List <FieldLookupValue>();
                                                        fieldValue.Split(',').All(value =>
                                                        {
                                                            lookupValues.Add(new FieldLookupValue
                                                            {
                                                                LookupId = int.Parse(value),
                                                            });
                                                            return(true);
                                                        });
                                                        listitem[parser.ParseString(dataValue.Key)] = lookupValues.ToArray();
                                                    }
                                                    else
                                                    {
                                                        var lookupValue = new FieldLookupValue
                                                        {
                                                            LookupId = int.Parse(fieldValue),
                                                        };
                                                        listitem[parser.ParseString(dataValue.Key)] = lookupValue;
                                                    }
                                                    break;

                                                case FieldType.URL:
                                                    // FieldUrlValue - Expected format: URL,Description
                                                    var urlArray  = fieldValue.Split(',');
                                                    var linkValue = new FieldUrlValue();
                                                    if (urlArray.Length == 2)
                                                    {
                                                        linkValue.Url         = urlArray[0];
                                                        linkValue.Description = urlArray[1];
                                                    }
                                                    else
                                                    {
                                                        linkValue.Url         = urlArray[0];
                                                        linkValue.Description = urlArray[0];
                                                    }
                                                    listitem[parser.ParseString(dataValue.Key)] = linkValue;
                                                    break;

                                                case FieldType.User:
                                                    // FieldUserValue - Expected format: loginName or loginName,loginName,loginName...
                                                    if (fieldValue.Contains(","))
                                                    {
                                                        var userValues = new List <FieldUserValue>();
                                                        fieldValue.Split(',').All(value =>
                                                        {
                                                            var user = web.EnsureUser(value);
                                                            web.Context.Load(user);
                                                            web.Context.ExecuteQueryRetry();
                                                            if (user != null)
                                                            {
                                                                userValues.Add(new FieldUserValue
                                                                {
                                                                    LookupId = user.Id,
                                                                });;
                                                            }
                                                            return(true);
                                                        });
                                                        listitem[parser.ParseString(dataValue.Key)] = userValues.ToArray();
                                                    }
                                                    else
                                                    {
                                                        var user = web.EnsureUser(fieldValue);
                                                        web.Context.Load(user);
                                                        web.Context.ExecuteQueryRetry();
                                                        if (user != null)
                                                        {
                                                            var userValue = new FieldUserValue
                                                            {
                                                                LookupId = user.Id,
                                                            };
                                                            listitem[parser.ParseString(dataValue.Key)] = userValue;
                                                        }
                                                        else
                                                        {
                                                            listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                        }
                                                    }
                                                    break;

                                                case FieldType.DateTime:
                                                    var dateTime = DateTime.MinValue;
                                                    if (DateTime.TryParse(fieldValue, out dateTime))
                                                    {
                                                        listitem[parser.ParseString(dataValue.Key)] = dateTime;
                                                    }
                                                    break;

                                                default:
                                                    listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    break;
                                                }
                                            }
                                        }
                                        listitem.Update();
                                        web.Context.ExecuteQueryRetry(); // TODO: Run in batches?

                                        if (dataRow.Security != null && (dataRow.Security.ClearSubscopes == true || dataRow.Security.CopyRoleAssignments == true || dataRow.Security.RoleAssignments.Count > 0))
                                        {
                                            listitem.SetSecurity(parser, dataRow.Security);
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    if (ex.GetType().Equals(typeof(ServerException)) &&
                                        (ex as ServerException).ServerErrorTypeName.Equals("Microsoft.SharePoint.SPDuplicateValuesFoundException", StringComparison.InvariantCultureIgnoreCase) &&
                                        applyingInformation.IgnoreDuplicateDataRowErrors)
                                    {
                                        scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_duplicate);
                                        continue;
                                    }
                                    else
                                    {
                                        scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, ex.Message, ex.StackTrace);
                                        throw;
                                    }
                                }
                            }
                        }
                    }

                    #endregion
                }
            }

            return(parser);
        }
Пример #21
0
        private static void UpdateContentType(Web web, Microsoft.SharePoint.Client.ContentType existingContentType, ContentType templateContentType, TokenParser parser, PnPMonitoredScope scope, bool isNoScriptSite = false)
        {
            var isDirty = false;
            if (existingContentType.Hidden != templateContentType.Hidden)
            {
                scope.LogPropertyUpdate("Hidden");
                existingContentType.Hidden = templateContentType.Hidden;
                isDirty = true;
            }
            if (existingContentType.ReadOnly != templateContentType.ReadOnly)
            {
                scope.LogPropertyUpdate("ReadOnly");
                existingContentType.ReadOnly = templateContentType.ReadOnly;
                isDirty = true;
            }
            if (existingContentType.Sealed != templateContentType.Sealed)
            {
                scope.LogPropertyUpdate("Sealed");
                existingContentType.Sealed = templateContentType.Sealed;
                isDirty = true;
            }
            if (templateContentType.Description != null && existingContentType.Description != parser.ParseString(templateContentType.Description))
            {
                scope.LogPropertyUpdate("Description");
                existingContentType.Description = parser.ParseString(templateContentType.Description);
                isDirty = true;
            }
            if (templateContentType.DocumentTemplate != null && existingContentType.DocumentTemplate != parser.ParseString(templateContentType.DocumentTemplate))
            {
                scope.LogPropertyUpdate("DocumentTemplate");
                existingContentType.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate);
                isDirty = true;
            }
            if (existingContentType.Name != parser.ParseString(templateContentType.Name))
            {
                scope.LogPropertyUpdate("Name");
                existingContentType.Name = parser.ParseString(templateContentType.Name);
                isDirty = true;
                // CT is being renamed, add an extra token to the tokenparser
                parser.AddToken(new ContentTypeIdToken(web, existingContentType.Name, existingContentType.StringId));
            }
            if (templateContentType.Group != null && existingContentType.Group != parser.ParseString(templateContentType.Group))
            {
                scope.LogPropertyUpdate("Group");
                existingContentType.Group = parser.ParseString(templateContentType.Group);
                isDirty = true;
            }
            if (!isNoScriptSite)
            {
                if (templateContentType.DisplayFormUrl != null && existingContentType.DisplayFormUrl != parser.ParseString(templateContentType.DisplayFormUrl))
                {
                    scope.LogPropertyUpdate("DisplayFormUrl");
                    existingContentType.DisplayFormUrl = parser.ParseString(templateContentType.DisplayFormUrl);
                    isDirty = true;
                }
                if (templateContentType.EditFormUrl != null && existingContentType.EditFormUrl != parser.ParseString(templateContentType.EditFormUrl))
                {
                    scope.LogPropertyUpdate("EditFormUrl");
                    existingContentType.EditFormUrl = parser.ParseString(templateContentType.EditFormUrl);
                    isDirty = true;
                }
                if (templateContentType.NewFormUrl != null && existingContentType.NewFormUrl != parser.ParseString(templateContentType.NewFormUrl))
                {
                    scope.LogPropertyUpdate("NewFormUrl");
                    existingContentType.NewFormUrl = parser.ParseString(templateContentType.NewFormUrl);
                    isDirty = true;
                }
            }
            else
            {
                if (!String.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl)) ||
                    !String.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl)) ||
                    !String.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl)))
                {
                    // log message
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipCustomFormUrls, existingContentType.Name);
                }
            }

            #if !SP2013
            if (templateContentType.Name.ContainsResourceToken())
            {
                existingContentType.NameResource.SetUserResourceValue(templateContentType.Name, parser);
                isDirty = true;
            }
            if (templateContentType.Description.ContainsResourceToken())
            {
                existingContentType.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser);
                isDirty = true;
            }
            #endif
            if (isDirty)
            {
                existingContentType.Update(true);
                web.Context.ExecuteQueryRetry();
            }
            // Delta handling
            existingContentType.EnsureProperty(c => c.FieldLinks);
            List<Guid> targetIds = existingContentType.FieldLinks.AsEnumerable().Select(c1 => c1.Id).ToList();
            List<Guid> sourceIds = templateContentType.FieldRefs.Select(c1 => c1.Id).ToList();

            var fieldsNotPresentInTarget = sourceIds.Except(targetIds).ToArray();

            if (fieldsNotPresentInTarget.Any())
            {
                foreach (var fieldId in fieldsNotPresentInTarget)
                {
                    var fieldRef = templateContentType.FieldRefs.Find(fr => fr.Id == fieldId);
                    var field = web.Fields.GetById(fieldId);
                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Adding_field__0__to_content_type, fieldId);
                    web.AddFieldToContentType(existingContentType, field, fieldRef.Required, fieldRef.Hidden);
                }
            }

            isDirty = false;
            foreach (var fieldId in targetIds.Intersect(sourceIds))
            {
                var fieldLink = existingContentType.FieldLinks.FirstOrDefault(fl => fl.Id == fieldId);
                var fieldRef = templateContentType.FieldRefs.Find(fr => fr.Id == fieldId);
                if (fieldRef != null)
                {
                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Field__0__exists_in_content_type, fieldId);
                    if (fieldLink.Required != fieldRef.Required)
                    {
                        scope.LogPropertyUpdate("Required");
                        fieldLink.Required = fieldRef.Required;
                        isDirty = true;
                    }
                    if (fieldLink.Hidden != fieldRef.Hidden)
                    {
                        scope.LogPropertyUpdate("Hidden");
                        fieldLink.Hidden = fieldRef.Hidden;
                        isDirty = true;
                    }
                }
            }

            // The new CT is a DocumentSet, and the target should be, as well
            if (templateContentType.DocumentSetTemplate != null)
            {
                if (!Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.IsChildOfDocumentSetContentType(web.Context, existingContentType).Value)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ContentTypes_InvalidDocumentSet_Update_Request, existingContentType.Id, existingContentType.Name);
                }
                else
                {
                    Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate templateToUpdate =
                        Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, existingContentType);

                    // TODO: Implement Delta Handling
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_DocumentSet_DeltaHandling_OnHold, existingContentType.Id, existingContentType.Name);
                }
            }

            if (isDirty)
            {
                existingContentType.Update(true);
                web.Context.ExecuteQueryRetry();
            }
        }
        private bool PersistFile(Web web, ProvisioningTemplateCreationInformation creationInfo, PnPMonitoredScope scope, string serverRelativeUrl)
        {
            var success = false;

            if (creationInfo.PersistBrandingFiles)
            {
                if (creationInfo.FileConnector != null)
                {
                    if (UrlUtility.IsIisVirtualDirectory(serverRelativeUrl))
                    {
                        scope.LogWarning("File is not located in the content database. Not retrieving {0}", serverRelativeUrl);
                        return(success);
                    }

                    try
                    {
                        var    file     = web.GetFileByServerRelativeUrl(serverRelativeUrl);
                        string fileName = string.Empty;
                        if (serverRelativeUrl.IndexOf("/") > -1)
                        {
                            fileName = serverRelativeUrl.Substring(serverRelativeUrl.LastIndexOf("/") + 1);
                        }
                        else
                        {
                            fileName = serverRelativeUrl;
                        }
                        web.Context.Load(file);
                        web.Context.ExecuteQueryRetry();
                        ClientResult <Stream> stream = file.OpenBinaryStream();
                        web.Context.ExecuteQueryRetry();

                        var baseUri    = new Uri(web.Url);
                        var fullUri    = new Uri(baseUri, file.ServerRelativeUrl);
                        var folderPath = HttpUtility.UrlDecode(fullUri.Segments.Take(fullUri.Segments.Count() - 1).ToArray().Aggregate((i, x) => i + x).TrimEnd('/'));

                        // Configure the filename to use
                        fileName = HttpUtility.UrlDecode(fullUri.Segments[fullUri.Segments.Count() - 1]);

                        // Build up a site relative container URL...might end up empty as well
                        String container = HttpUtility.UrlDecode(folderPath.Replace(web.ServerRelativeUrl, "")).Trim('/').Replace("/", "\\");

                        using (Stream memStream = new MemoryStream())
                        {
                            CopyStream(stream.Value, memStream);
                            memStream.Position = 0;
                            if (!string.IsNullOrEmpty(container))
                            {
                                creationInfo.FileConnector.SaveFileStream(fileName, container, memStream);
                            }
                            else
                            {
                                creationInfo.FileConnector.SaveFileStream(fileName, memStream);
                            }
                        }
                        success = true;
                    }
                    catch (ServerException ex1)
                    {
                        // If we are referring a file from a location outside of the current web or at a location where we cannot retrieve the file an exception is thrown. We swallow this exception.
                        if (ex1.ServerErrorCode != -2147024809)
                        {
                            throw;
                        }
                        else
                        {
                            scope.LogWarning("File is not necessarily located in the current web. Not retrieving {0}", serverRelativeUrl);
                        }
                    }
                }
                else
                {
                    WriteMessage("No connector present to persist footer logo.", ProvisioningMessageType.Error);
                    scope.LogError("No connector present to persist footer logo.");
                }
            }
            else
            {
                success = true;
            }
            return(success);
        }
Пример #23
0
        private void UpdateField(Web web, string fieldId, XElement templateFieldElement, PnPMonitoredScope scope, TokenParser parser, string originalFieldXml)
        {
            var existingField = web.Fields.GetById(Guid.Parse(fieldId));

            web.Context.Load(existingField, f => f.SchemaXml);
            web.Context.ExecuteQueryRetry();

            XElement existingFieldElement = XElement.Parse(existingField.SchemaXml);

            XNodeEqualityComparer equalityComparer = new XNodeEqualityComparer();

            if (equalityComparer.GetHashCode(existingFieldElement) != equalityComparer.GetHashCode(templateFieldElement)) // Is field different in template?
            {
                if (existingFieldElement.Attribute("Type").Value == templateFieldElement.Attribute("Type").Value)         // Is existing field of the same type?
                {
                    if (IsFieldXmlValid(parser.ParseString(originalFieldXml), parser, web.Context))
                    {
                        var listIdentifier = templateFieldElement.Attribute("List") != null?templateFieldElement.Attribute("List").Value : null;

                        if (listIdentifier != null)
                        {
                            // Temporary remove list attribute from list
                            templateFieldElement.Attribute("List").Remove();
                        }

                        foreach (var attribute in templateFieldElement.Attributes())
                        {
                            if (existingFieldElement.Attribute(attribute.Name) != null)
                            {
                                existingFieldElement.Attribute(attribute.Name).Value = attribute.Value;
                            }
                            else
                            {
                                existingFieldElement.Add(attribute);
                            }
                        }
                        foreach (var element in templateFieldElement.Elements())
                        {
                            if (existingFieldElement.Element(element.Name) != null)
                            {
                                existingFieldElement.Element(element.Name).Remove();
                            }
                            existingFieldElement.Add(element);
                        }

                        if (string.Equals(templateFieldElement.Attribute("Type").Value, "Calculated", StringComparison.OrdinalIgnoreCase))
                        {
                            var fieldRefsElement = existingFieldElement.Descendants("FieldRefs").FirstOrDefault();
                            if (fieldRefsElement != null)
                            {
                                fieldRefsElement.Remove();
                            }
                        }

                        if (existingFieldElement.Attribute("Version") != null)
                        {
                            existingFieldElement.Attributes("Version").Remove();
                        }
                        existingField.SchemaXml = parser.ParseString(existingFieldElement.ToString(), "~sitecollection", "~site");
                        existingField.UpdateAndPushChanges(true);
                        web.Context.Load(existingField, f => f.TypeAsString, f => f.DefaultValue);
                        web.Context.ExecuteQueryRetry();

                        bool isDirty = false;
#if !SP2013
                        if (originalFieldXml.ContainsResourceToken())
                        {
                            var originalFieldElement = XElement.Parse(originalFieldXml);
                            var nameAttributeValue   = originalFieldElement.Attribute("DisplayName") != null?originalFieldElement.Attribute("DisplayName").Value : "";

                            if (nameAttributeValue.ContainsResourceToken())
                            {
                                existingField.TitleResource.SetUserResourceValue(nameAttributeValue, parser);
                                isDirty = true;
                            }
                            var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null?originalFieldElement.Attribute("Description").Value : "";

                            if (descriptionAttributeValue.ContainsResourceToken())
                            {
                                existingField.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser);
                                isDirty = true;
                            }
                        }
#endif
                        if (isDirty)
                        {
                            existingField.Update();
                            web.Context.ExecuteQueryRetry();
                        }
                        if ((existingField.TypeAsString == "TaxonomyFieldType" || existingField.TypeAsString == "TaxonomyFieldTypeMulti") && !string.IsNullOrEmpty(existingField.DefaultValue))
                        {
                            var taxField = web.Context.CastTo <TaxonomyField>(existingField);
                            ValidateTaxonomyFieldDefaultValue(taxField);
                        }
                    }
                    else
                    {
                        // The field Xml was found invalid
                        var tokenString = parser.GetLeftOverTokens(originalFieldXml).Aggregate(String.Empty, (acc, i) => acc + " " + i);
                        scope.LogError("The field was found invalid: {0}", tokenString);
                        throw new Exception(string.Format("The field was found invalid: {0}", tokenString));
                    }
                }
                else
                {
                    var fieldName = existingFieldElement.Attribute("Name") != null?existingFieldElement.Attribute("Name").Value : existingFieldElement.Attribute("StaticName").Value;

                    WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_Fields_Field__0____1___exists_but_is_of_different_type__Skipping_field_, fieldName, fieldId), ProvisioningMessageType.Warning);
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_Fields_Field__0____1___exists_but_is_of_different_type__Skipping_field_, fieldName, fieldId);
                }
            }
        }
Пример #24
0
        private void ProcessApps(Web web, ProvisioningTemplate template, TokenParser parser, PnPMonitoredScope scope)
        {
            if (template.Tenant.AppCatalog != null && template.Tenant.AppCatalog.Packages.Count > 0)
            {
                var manager = new AppManager(web.Context as ClientContext);

                var appCatalogUri = web.GetAppCatalog();
                if (appCatalogUri != null)
                {
                    foreach (var app in template.Tenant.AppCatalog.Packages)
                    {
                        AppMetadata appMetadata = null;

                        if (app.Action == PackageAction.Upload || app.Action == PackageAction.UploadAndPublish)
                        {
                            var appBytes = GetFileBytes(template, app.Src);

                            var appFilename = app.Src.Substring(app.Src.LastIndexOf('\\') + 1);
                            appMetadata = manager.Add(appBytes, appFilename, app.Overwrite);

                            parser.Tokens.Add(new AppPackageIdToken(web, appFilename, appMetadata.Id));
                        }

                        if (app.Action == PackageAction.Publish || app.Action == PackageAction.UploadAndPublish)
                        {
                            if (appMetadata == null)
                            {
                                appMetadata = manager.GetAvailable()
                                              .FirstOrDefault(a => a.Id == Guid.Parse(parser.ParseString(app.PackageId)));
                            }
                            if (appMetadata != null)
                            {
                                manager.Deploy(appMetadata, app.SkipFeatureDeployment);
                            }
                            else
                            {
                                scope.LogError("Referenced App Package {0} not available", app.PackageId);
                                throw new Exception($"Referenced App Package {app.PackageId} not available");
                            }
                        }

                        if (app.Action == PackageAction.Remove)
                        {
                            var appId = Guid.Parse(parser.ParseString(app.PackageId));

                            // Get the apps already installed in the site
                            var appExists = manager.GetAvailable()?.Any(a => a.Id == appId);

                            if (appExists.HasValue && appExists.Value)
                            {
                                manager.Remove(appId);
                            }
                            else
                            {
                                WriteMessage($"App Package with ID {appId} does not exist in the AppCatalog and cannot be removed!", ProvisioningMessageType.Warning);
                            }
                        }
                    }
                }
                else
                {
                    WriteMessage($"Tenant app catalog doesn't exist. ALM step will be skipped!", ProvisioningMessageType.Warning);
                }
            }
        }
Пример #25
0
        public List<DataRow> ExtractItems( ProvisioningTemplateCreationInformation creationInfo, TokenParser parser, PnPMonitoredScope scope)
        {
            List<DataRow> dataRows = new List<DataRow>();

            bool isPageLib = (List.BaseTemplate == (int)ListTemplateType.WebPageLibrary) ||
                (List.BaseTemplate == (int)ListTemplateType.HomePageLibrary) ||
                (List.BaseTemplate == (int)ListTemplateType.PublishingPages);

            CamlQuery query = isPageLib ? CamlQuery.CreateAllFoldersQuery() : CamlQuery.CreateAllItemsQuery();
            query.DatesInUtc = true;
            ListItemCollection items = this.List.GetItems(query);
            this.Context.Load(items, col => col.IncludeWithDefaultProperties(i => i.HasUniqueRoleAssignments));
            this.Context.Load(this.List.Fields);
            this.Context.Load(this.List, l=> l.RootFolder.ServerRelativeUrl, l=> l.BaseType);
            this.Context.ExecuteQueryRetry();

            ItemPathProvider itemPathProvider = new ItemPathProvider(this.List, this.Web);

            List<Field> fields = GetListContentSerializableFields(true);
            foreach (ListItem item in items)
            {
                try
                {
                    Dictionary<string, string> values = new Dictionary<string, string>();
                    foreach (Field field in fields)
                    {
                        if (CanFieldContentBeIncluded(field, true))
                        {
                            string str = "";
                            object value = null; ;
                            try
                            {
                                value = item[field.InternalName];
                            }
                            catch (Exception ex)
                            {
                                scope.LogWarning(ex,
                                    "Failed to read item field value. List:{0}, Item ID:{1}, Field: {2}", this.List.Title, item.Id, field.InternalName);
                            }
                            if (null != value)
                            {
                                try
                                {
                                    FieldValueProvider provider = GetFieldValueProvider(field, this.Web);
                                    str = provider.GetValidatedValue(value);
                                }
                                catch (Exception ex)
                                {
                                    scope.LogWarning(ex,
                                        "Failed to serialize item field value. List:{0}, Item ID:{1}, Field: {2}", this.List.Title, item.Id, field.InternalName);
                                }
                                if (!string.IsNullOrEmpty(str))
                                {
                                    values.Add(field.InternalName, str);
                                }
                            }
                        }
                    }

                    string fileSrc;
                    itemPathProvider.ExtractItemPathValues(item, values, creationInfo, out fileSrc);

                    if (values.Any())
                    {
                        ObjectSecurity security = null;
                        if (item.HasUniqueRoleAssignments)
                        {
                            try
                            {
                                security = item.GetSecurity(parser);
                                security.ClearSubscopes = true;
                            }
                            catch (Exception ex)
                            {
                                scope.LogWarning(ex, "Failed to get item security. Item ID: {0}, List: '{1}'.", item.Id, this.List.Title);
                            }
                        }

                        DataRow row = new DataRow(values, security, fileSrc);
                        dataRows.Add(row);
                    }
                }
                catch (Exception ex)
                {
                    scope.LogError(ex, "Failed to save item in template. Item ID: {0}, List: '{1}'.", item.Id, this.List.Title);
                }
            }

            return dataRows;
        }
Пример #26
0
        private static TokenParser ProvisionFeaturesImplementation <T>(T parent, IEnumerable <Feature> features, TokenParser parser, PnPMonitoredScope scope)
        {
            var  activeFeatures = new List <Microsoft.SharePoint.Client.Feature>();
            Web  web            = null;
            Site site           = null;

            if (parent is Site)
            {
                site = parent as Site;
                site.Context.Load(site.Features, fs => fs.Include(f => f.DefinitionId));
                site.Context.ExecuteQueryRetry();
                activeFeatures = site.Features.ToList();
            }
            else
            {
                web = parent as Web;
                web.Context.Load(web.Features, fs => fs.Include(f => f.DefinitionId));
                web.Context.ExecuteQueryRetry();
                activeFeatures = web.Features.ToList();
            }

            if (features != null)
            {
                foreach (var feature in features)
                {
                    if (!feature.Deactivate)
                    {
                        if (activeFeatures.FirstOrDefault(f => f.DefinitionId == feature.Id) == null)
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Features_Activating__0__scoped_feature__1_, site != null ? "site" : "web", feature.Id);
                            if (site != null)
                            {
                                try
                                {
                                    site.ActivateFeature(feature.Id);
                                }
                                catch (ServerException ex)
                                {
                                    scope.LogError("Error activating feature {0}: {1}", feature.Id, ex.Message);
                                }
                            }
                            else
                            {
                                try
                                {
                                    web.ActivateFeature(feature.Id);
                                }
                                catch (ServerException ex)
                                {
                                    scope.LogError("Error activating feature {0}: {1}", feature.Id, ex.Message);
                                }
                            }
                        }
                    }
                    else
                    {
                        if (activeFeatures.FirstOrDefault(f => f.DefinitionId == feature.Id) != null)
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Features_Deactivating__0__scoped_feature__1_, site != null ? "site" : "web", feature.Id);
                            if (site != null)
                            {
                                try
                                {
                                    site.DeactivateFeature(feature.Id);
                                }
                                catch (ServerException ex)
                                {
                                    scope.LogError("Error deactivating feature {0}: {1}", feature.Id, ex.Message);
                                }
                            }
                            else
                            {
                                try
                                {
                                    web.DeactivateFeature(feature.Id);
                                }
                                catch (ServerException ex)
                                {
                                    scope.LogError("Error deactivating feature {0}: {1}", feature.Id, ex.Message);
                                }
                            }
                        }
                    }
                }
            }
            if (parent is Site)
            {
                parser.RebuildListTokens((parent as Site).RootWeb);
            }
            else
            {
                parser.RebuildListTokens(parent as Web);
            }
            return(parser);
        }
Пример #27
0
        private static void AddUserToGroup(Web web, Group group, List<User> members, PnPMonitoredScope scope)
        {
            if (members.Any())
            {
                scope.LogDebug("Adding users to group {0}", group.Title);
                try
                {
                    foreach (var user in members)
                    {
                        scope.LogDebug("Adding user {0}", user.Name);
                        var existingUser = web.EnsureUser(user.Name);
                        group.Users.AddUser(existingUser);

                    }
                    web.Context.ExecuteQueryRetry();
                }
                catch (Exception ex)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_SiteSecurity_Add_users_failed_for_group___0_____1_____2_, group.Title, ex.Message, ex.StackTrace);
                    throw;
                }
            }
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (!template.Lists.Any())
                {
                    return(parser);
                }

                web.EnsureProperties(w => w.ServerRelativeUrl);

                web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                web.Context.ExecuteQueryRetry();

                #region DataRows

                foreach (var listInstance in template.Lists)
                {
                    if (listInstance.DataRows != null && listInstance.DataRows.Any())
                    {
                        scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Processing_data_rows_for__0_, listInstance.Title);
                        // Retrieve the target list
                        var list = web.Lists.GetByTitle(parser.ParseString(listInstance.Title));
                        web.Context.Load(list);

                        // Retrieve the fields' types from the list
                        Microsoft.SharePoint.Client.FieldCollection fields = list.Fields;
                        web.Context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind, f => f.TypeAsString, f => f.ReadOnlyField, f => f.Title));
                        web.Context.ExecuteQueryRetry();

                        var keyColumnType   = "Text";
                        var parsedKeyColumn = parser.ParseString(listInstance.DataRows.KeyColumn);
                        if (!string.IsNullOrEmpty(parsedKeyColumn))
                        {
                            var keyColumn = fields.FirstOrDefault(f => f.InternalName.Equals(parsedKeyColumn, StringComparison.InvariantCultureIgnoreCase));
                            if (keyColumn != null)
                            {
                                switch (keyColumn.FieldTypeKind)
                                {
                                case FieldType.User:
                                case FieldType.Lookup:
                                    keyColumnType = "Lookup";
                                    break;

                                case FieldType.URL:
                                    keyColumnType = "Url";
                                    break;

                                case FieldType.DateTime:
                                    keyColumnType = "DateTime";
                                    break;

                                case FieldType.Number:
                                case FieldType.Counter:
                                    keyColumnType = "Number";
                                    break;
                                }
                            }
                        }

                        foreach (var dataRow in listInstance.DataRows)
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, listInstance.DataRows.IndexOf(dataRow) + 1);

                                bool     processItem = true;
                                ListItem listitem    = null;

                                if (!string.IsNullOrEmpty(listInstance.DataRows.KeyColumn))
                                {
                                    // Get value from key column
                                    var dataRowValues = dataRow.Values.Where(v => v.Key == listInstance.DataRows.KeyColumn).ToList();

                                    // if it is empty, skip the check
                                    if (dataRowValues.Any())
                                    {
                                        var query     = $@"<View><Query><Where><Eq><FieldRef Name=""{parsedKeyColumn}""/><Value Type=""{keyColumnType}"">{parser.ParseString(dataRowValues.FirstOrDefault().Value)}</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>";
                                        var camlQuery = new CamlQuery()
                                        {
                                            ViewXml = query
                                        };
                                        var existingItems = list.GetItems(camlQuery);
                                        list.Context.Load(existingItems);
                                        list.Context.ExecuteQueryRetry();
                                        if (existingItems.Count > 0)
                                        {
                                            if (listInstance.DataRows.UpdateBehavior == UpdateBehavior.Skip)
                                            {
                                                processItem = false;
                                            }
                                            else
                                            {
                                                listitem    = existingItems[0];
                                                processItem = true;
                                            }
                                        }
                                    }
                                }

                                if (processItem)
                                {
                                    bool IsNewItem = false;
                                    if (listitem == null)
                                    {
                                        var listitemCI = new ListItemCreationInformation();
                                        listitem  = list.AddItem(listitemCI);
                                        IsNewItem = true;
                                    }

                                    ListItemUtilities.UpdateListItem(listitem, parser, dataRow.Values, ListItemUtilities.ListItemUpdateType.UpdateOverwriteVersion, IsNewItem);

                                    if (dataRow.Security != null && (dataRow.Security.ClearSubscopes || dataRow.Security.CopyRoleAssignments || dataRow.Security.RoleAssignments.Count > 0))
                                    {
                                        listitem.SetSecurity(parser, dataRow.Security);
                                    }

                                    if (dataRow.Attachments != null && dataRow.Attachments.Count > 0)
                                    {
                                        foreach (var attachment in dataRow.Attachments)
                                        {
                                            attachment.Name = parser.ParseString(attachment.Name);
                                            attachment.Src  = parser.ParseString(attachment.Src);
                                            if (!IsNewItem)
                                            {
                                                var overwrite = attachment.Overwrite;
                                                listitem.EnsureProperty(l => l.AttachmentFiles);

                                                Attachment existingItem = null;
                                                if (listitem.AttachmentFiles.Count > 0)
                                                {
                                                    existingItem = listitem.AttachmentFiles.FirstOrDefault(a => a.FileName.Equals(attachment.Name, StringComparison.OrdinalIgnoreCase));
                                                }
                                                if (existingItem != null)
                                                {
                                                    if (overwrite)
                                                    {
                                                        existingItem.DeleteObject();
                                                        web.Context.ExecuteQueryRetry();
                                                        AddAttachment(template, listitem, attachment);
                                                    }
                                                }
                                                else
                                                {
                                                    AddAttachment(template, listitem, attachment);
                                                }
                                            }
                                            else
                                            {
                                                AddAttachment(template, listitem, attachment, IsNewItem);
                                            }
                                        }
                                        if (IsNewItem)
                                        {
                                            listitem.Context.ExecuteQueryRetry();
                                        }
                                    }
                                }
                            }
                            catch (ServerException ex)
                            {
                                if (ex.ServerErrorTypeName.Equals("Microsoft.SharePoint.SPDuplicateValuesFoundException", StringComparison.InvariantCultureIgnoreCase) &&
                                    applyingInformation.IgnoreDuplicateDataRowErrors)
                                {
                                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_duplicate);
                                    continue;
                                }
                                if (ex.ServerErrorTypeName.Equals("Microsoft.SharePoint.SPException", StringComparison.InvariantCultureIgnoreCase) &&
                                    ex.Message.Equals("To add an item to a document library, use SPFileCollection.Add()", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    // somebody tries to add new items to a document library
                                    var warning = string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_notsupported_0, listInstance.Title);
                                    scope.LogWarning(warning);
                                    WriteMessage(warning, ProvisioningMessageType.Warning);
                                    continue;
                                }
                            }
                            catch (Exception ex)
                            {
                                scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, ex.Message, ex.StackTrace);
                                throw;
                            }
                        }
                    }
                }


                #endregion DataRows
            }


            return(parser);
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {

                if (template.Lists.Any())
                {
                    var rootWeb = (web.Context as ClientContext).Site.RootWeb;

                    web.EnsureProperties(w => w.ServerRelativeUrl);

                    web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                    web.Context.ExecuteQueryRetry();
                    var existingLists = web.Lists.AsEnumerable<List>().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList();
                    var serverRelativeUrl = web.ServerRelativeUrl;

                    #region DataRows

                    foreach (var listInstance in template.Lists)
                    {
                        if (listInstance.DataRows != null && listInstance.DataRows.Any())
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Processing_data_rows_for__0_, listInstance.Title);
                            // Retrieve the target list
                            var list = web.Lists.GetByTitle(listInstance.Title);
                            web.Context.Load(list);

                            // Retrieve the fields' types from the list
                            FieldCollection fields = list.Fields;
                            web.Context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind));
                            web.Context.ExecuteQueryRetry();

                            foreach (var dataRow in listInstance.DataRows)
                            {
                                try
                                {
                                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, listInstance.DataRows.IndexOf(dataRow) + 1);
                                    var listitemCI = new ListItemCreationInformation();
                                    var listitem = list.AddItem(listitemCI);

                                    foreach (var dataValue in dataRow.Values)
                                    {
                                        Field dataField = fields.FirstOrDefault(
                                            f => f.InternalName == parser.ParseString(dataValue.Key));

                                        if (dataField != null)
                                        {
                                            String fieldValue = parser.ParseString(dataValue.Value);

                                            switch (dataField.FieldTypeKind)
                                            {
                                                case FieldType.Geolocation:
                                                    // FieldGeolocationValue - Expected format: Altitude,Latitude,Longitude,Measure
                                                    var geolocationArray = fieldValue.Split(',');
                                                    if (geolocationArray.Length == 4)
                                                    {
                                                        var geolocationValue = new FieldGeolocationValue
                                                        {
                                                            Altitude = Double.Parse(geolocationArray[0]),
                                                            Latitude = Double.Parse(geolocationArray[1]),
                                                            Longitude = Double.Parse(geolocationArray[2]),
                                                            Measure = Double.Parse(geolocationArray[3]),
                                                        };
                                                        listitem[parser.ParseString(dataValue.Key)] = geolocationValue;
                                                    }
                                                    else
                                                    {
                                                        listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    }
                                                    break;
                                                case FieldType.Lookup:
                                                    // FieldLookupValue - Expected format: LookupID
                                                    var lookupValue = new FieldLookupValue
                                                    {
                                                        LookupId = Int32.Parse(fieldValue),
                                                    };
                                                    listitem[parser.ParseString(dataValue.Key)] = lookupValue;
                                                    break;
                                                case FieldType.URL:
                                                    // FieldUrlValue - Expected format: URL,Description
                                                    var urlArray = fieldValue.Split(',');
                                                    var linkValue = new FieldUrlValue();
                                                    if (urlArray.Length == 2)
                                                    {
                                                        linkValue.Url = urlArray[0];
                                                        linkValue.Description = urlArray[1];
                                                    }
                                                    else
                                                    {
                                                        linkValue.Url = urlArray[0];
                                                        linkValue.Description = urlArray[0];
                                                    }
                                                    listitem[parser.ParseString(dataValue.Key)] = linkValue;
                                                    break;
                                                case FieldType.User:
                                                    // FieldUserValue - Expected format: loginName
                                                    var user = web.EnsureUser(fieldValue);
                                                    web.Context.Load(user);
                                                    web.Context.ExecuteQueryRetry();

                                                    if (user != null)
                                                    {
                                                        var userValue = new FieldUserValue
                                                        {
                                                            LookupId = user.Id,
                                                        };
                                                        listitem[parser.ParseString(dataValue.Key)] = userValue;
                                                    }
                                                    else
                                                    {
                                                        listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    }
                                                    break;
                                                default:
                                                    listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    break;
                                            }
                                        }
                                        listitem.Update();
                                    }
                                    web.Context.ExecuteQueryRetry(); // TODO: Run in batches?

                                    if (dataRow.Security != null)
                                    {
                                        listitem.SetSecurity(parser, dataRow.Security);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, ex.Message, ex.StackTrace);
                                    throw;
                                }
                            }
                        }
                    }

                    #endregion
                }
            }

            return parser;
        }
        private void ExtractFileSettings(Web web, List siteList, string fileServerRelativeUrl, ref Model.File pnpFile, PnPMonitoredScope scope)
#endif
        {
            try
            {
#if !SP2013 && !SP2016
                var file = web.GetFileById(fileUniqueId);
#else
                var file = web.GetFileByServerRelativeUrl(fileServerRelativeUrl);
#endif
                web.Context.Load(file,
                                 f => f.Level,
                                 f => f.ServerRelativeUrl,
#if !SP2013 && !SP2016
                                 f => f.Properties,
#endif
                                 f => f.ListItemAllFields,
                                 f => f.ListItemAllFields.RoleAssignments,
                                 f => f.ListItemAllFields.RoleAssignments.Include(r => r.Member, r => r.RoleDefinitionBindings),
                                 f => f.ListItemAllFields.HasUniqueRoleAssignments,
                                 f => f.ListItemAllFields.ParentList,
                                 f => f.ListItemAllFields.ContentType.StringId);

                web.Context.ExecuteQueryRetry();

                //export PnPFile FieldValues
                if (file.ListItemAllFields.FieldValues.Any())
                {
                    var fieldValues = file.ListItemAllFields.FieldValues;

                    var fieldValuesAsText = file.ListItemAllFields.EnsureProperty(li => li.FieldValuesAsText).FieldValues;

                    #region //**** get correct Content Type
                    string ctId = string.Empty;
                    foreach (var ct in web.ContentTypes.OrderByDescending(c => c.StringId.Length))
                    {
                        if (file.ListItemAllFields.ContentType.StringId.StartsWith(ct.StringId))
                        {
                            pnpFile.Properties.Add("ContentTypeId", ct.StringId);
                            break;
                        }
                    }
                    #endregion //**** get correct Content Type

                    foreach (var fieldValue in fieldValues)
                    {
                        if (fieldValue.Value != null && !string.IsNullOrEmpty(fieldValue.Value.ToString()))
                        {
                            var    field = siteList.Fields.FirstOrDefault(fs => fs.InternalName == fieldValue.Key);
                            string value = string.Empty;
                            //ignore read only fields
                            if (!field.ReadOnlyField || WriteableReadOnlyField.Contains(field.InternalName.ToLower()))
                            {
                                value = TokenizeValue(web, field.TypeAsString, fieldValue, fieldValuesAsText[field.InternalName]);

                                if (fieldValue.Key == "ContentTypeId")
                                {
                                    value = null; //it's already in Properties - we can ignore here
                                }
                            }

                            // We process real values only
                            if (value != null && !String.IsNullOrEmpty(value) && value != "[]")
                            {
                                pnpFile.Properties.Add(fieldValue.Key, value);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
#if !SP2013 && !SP2016
                scope.LogError(ex, "Extract of File with uniqueId {0} failed", fileUniqueId);
#else
                scope.LogError(ex, "Extract of File with url {0} failed", fileServerRelativeUrl);
#endif
            }
        }
Пример #31
0
        private static Field CreateField(XElement fieldElement, ListInfo listInfo, TokenParser parser, string originalFieldXml, ClientRuntimeContext context, PnPMonitoredScope scope)
        {
            Field field = null;
            fieldElement = PrepareField(fieldElement);

            var fieldXml = parser.ParseString(fieldElement.ToString(), "~sitecollection", "~site");
            if (IsFieldXmlValid(parser.ParseString(originalFieldXml), parser, context))
            {
                field = listInfo.SiteList.Fields.AddFieldAsXml(fieldXml, false, AddFieldOptions.AddFieldInternalNameHint);
                listInfo.SiteList.Context.Load(field);
                listInfo.SiteList.Context.ExecuteQueryRetry();

                bool isDirty = false;
            #if !SP2013
                if (originalFieldXml.ContainsResourceToken())
                {
                    var originalFieldElement = XElement.Parse(originalFieldXml);
                    var nameAttributeValue = originalFieldElement.Attribute("DisplayName") != null ? originalFieldElement.Attribute("DisplayName").Value : "";
                    if (nameAttributeValue.ContainsResourceToken())
                    {
                        if (field.TitleResource.SetUserResourceValue(nameAttributeValue, parser))
                        {
                            isDirty = true;
                        }
                    }
                    var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null ? originalFieldElement.Attribute("Description").Value : "";
                    if (descriptionAttributeValue.ContainsResourceToken())
                    {
                        if (field.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser))
                        {
                            isDirty = true;
                        }
                    }
                }
            #endif
                if (isDirty)
                {
                    field.Update();
                    listInfo.SiteList.Context.ExecuteQueryRetry();
                }
            }
            else
            {
                // The field Xml was found invalid
                var tokenString = parser.GetLeftOverTokens(originalFieldXml).Aggregate(String.Empty, (acc, i) => acc + " " + i);
                scope.LogError("The field was found invalid: {0}", tokenString);
                throw new Exception(string.Format("The field was found invalid: {0}", tokenString));
            }
            return field;
        }
        public Model.Folder ExtractFolderSettings(Web web, List siteList, string serverRelativePathToFolder, PnPMonitoredScope scope, Model.Configuration.Lists.Lists.ExtractQueryConfiguration queryConfig)
        {
            Model.Folder pnpFolder = null;
            try
            {
                Microsoft.SharePoint.Client.Folder spFolder = web.GetFolderByServerRelativeUrl(serverRelativePathToFolder);
                web.Context.Load(spFolder,
                                 f => f.Name,
                                 f => f.ServerRelativeUrl,
                                 f => f.Properties,
                                 f => f.ListItemAllFields,
                                 f => f.ListItemAllFields.RoleAssignments,
                                 f => f.ListItemAllFields.RoleAssignments.Include(r => r.Member, r => r.RoleDefinitionBindings),
                                 f => f.ListItemAllFields.HasUniqueRoleAssignments,
                                 f => f.ListItemAllFields.ParentList,
                                 f => f.ListItemAllFields.ContentType.StringId);
                web.Context.Load(web,
                                 w => w.AssociatedOwnerGroup,
                                 w => w.AssociatedMemberGroup,
                                 w => w.AssociatedVisitorGroup,
                                 w => w.Title,
                                 w => w.Url,
                                 w => w.RoleDefinitions.Include(r => r.RoleTypeKind, r => r.Name),
                                 w => w.ContentTypes.Include(c => c.Id, c => c.Name, c => c.StringId));
                web.Context.ExecuteQueryRetry();

                pnpFolder = new Model.Folder(spFolder.Name);

                //export PnPFolder Properties
                if (spFolder.Properties.FieldValues.Any())
                {
                    foreach (var propKey in spFolder.Properties.FieldValues.Keys.Where(k => !k.StartsWith("vti_") && !k.StartsWith("docset_")))
                    {
                        pnpFolder.PropertyBagEntries.Add(new PropertyBagEntry()
                        {
                            Key = propKey, Value = spFolder.Properties.FieldValues[propKey].ToString()
                        });
                    }
                }

                //export PnPFolder FieldValues
                if (spFolder.ListItemAllFields.FieldValues.Any())
                {
                    var list = spFolder.ListItemAllFields.ParentList;

                    var fields = list.Fields;
                    web.Context.Load(fields, fs => fs.IncludeWithDefaultProperties(f => f.TypeAsString, f => f.InternalName, f => f.Title));
                    web.Context.ExecuteQueryRetry();

                    var fieldValues = spFolder.ListItemAllFields.FieldValues;

                    var fieldValuesAsText = spFolder.ListItemAllFields.EnsureProperty(li => li.FieldValuesAsText).FieldValues;

                    #region //**** get correct Content Type
                    string ctId = string.Empty;
                    foreach (var ct in web.ContentTypes.OrderByDescending(c => c.StringId.Length))
                    {
                        if (spFolder.ListItemAllFields.ContentType.StringId.StartsWith(ct.StringId))
                        {
                            pnpFolder.ContentTypeID = ct.StringId;
                            break;
                        }
                    }
                    #endregion //**** get correct Content Type

                    var filteredFieldValues = fieldValues.ToList();
                    if (queryConfig != null && queryConfig.ViewFields != null && queryConfig.ViewFields.Count > 0)
                    {
                        filteredFieldValues = fieldValues.Where(f => queryConfig.ViewFields.Contains(f.Key)).ToList();
                    }
                    foreach (var fieldValue in filteredFieldValues)
                    {
                        if (fieldValue.Value != null && !string.IsNullOrEmpty(fieldValue.Value.ToString()))
                        {
                            var    field = siteList.Fields.FirstOrDefault(fs => fs.InternalName == fieldValue.Key);
                            string value = string.Empty;

                            //ignore read only fields
                            if (!field.ReadOnlyField || WriteableReadOnlyField.Contains(field.InternalName.ToLower()))
                            {
                                value = TokenizeValue(web, field.TypeAsString, fieldValue, fieldValuesAsText[field.InternalName]);
                            }

                            if (fieldValue.Key.Equals("ContentTypeId", StringComparison.CurrentCultureIgnoreCase))
                            {
                                value = null; //ignore here since already in dataRow
                            }

                            if (fieldValue.Key.Equals("HTML_x0020_File_x0020_Type", StringComparison.CurrentCultureIgnoreCase) &&
                                fieldValuesAsText["HTML_x0020_File_x0020_Type"] == "OneNote.Notebook")
                            {
                                pnpFolder.Properties.Add("File_x0020_Type", "OneNote.Notebook");
                                pnpFolder.Properties.Add(fieldValue.Key, "OneNote.Notebook");
                                value = null;
                            }

                            // We process real values only
                            if (!string.IsNullOrWhiteSpace(value) && value != "[]")
                            {
                                pnpFolder.Properties.Add(fieldValue.Key, value);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                scope.LogError(ex, "Extract of Folder {0} failed", serverRelativePathToFolder);
            }
            return(pnpFolder);
        }
        private void CallWebHooks(ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateWebhookKind kind, String objectHandler = null, Exception exception = null)
        {
            if (template != null)
            {
                using (var scope = new PnPMonitoredScope("ProvisioningTemplate WebHook Call"))
                {
                    var webhooks = new List <ProvisioningWebhookBase>();

                    // Merge the webhooks at template level with those at global level
                    if (template.ProvisioningTemplateWebhooks != null && template.ProvisioningTemplateWebhooks.Any())
                    {
                        webhooks.AddRange(template.ProvisioningTemplateWebhooks);
                    }
                    if (template.ParentHierarchy?.ProvisioningWebhooks != null && template.ParentHierarchy.ProvisioningWebhooks.Any())
                    {
                        webhooks.AddRange(template.ParentHierarchy.ProvisioningWebhooks);
                    }

                    // If there is any webhook
                    if (webhooks.Count > 0)
                    {
                        foreach (var webhook in webhooks.Where(w => w.Kind == kind))
                        {
                            var requestParameters = new Dictionary <String, String>();

                            if (exception != null)
                            {
                                // For GET requests we limit the size of the exception to avoid issues
                                requestParameters["__exception"] =
                                    webhook.Method == ProvisioningTemplateWebhookMethod.GET ?
                                    exception.Message : exception.ToString();
                            }

                            SimpleTokenParser internalParser = new SimpleTokenParser();
                            foreach (var webhookparam in webhook.Parameters)
                            {
                                requestParameters.Add(webhookparam.Key, parser.ParseString(webhookparam.Value));
                                internalParser.AddToken(new WebhookParameter(webhookparam.Key, requestParameters[webhookparam.Key]));
                            }
                            var url = parser.ParseString(webhook.Url); // parse for template scoped parameters
                            url = internalParser.ParseString(url);     // parse for webhook scoped parameters

                            switch (webhook.Method)
                            {
                            case ProvisioningTemplateWebhookMethod.GET:
                            {
                                url += $"&__webhookKind={kind.ToString()}";         // add the webhook kind to the REST request URL

                                foreach (var k in requestParameters.Keys)
                                {
                                    url += $"&{HttpUtility.UrlEncode(k)}={HttpUtility.UrlEncode(requestParameters[k])}";
                                }

                                if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted ||
                                    kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted ||
                                    kind == ProvisioningTemplateWebhookKind.ExceptionOccurred)
                                {
                                    url += $"&__handler={HttpUtility.UrlEncode(objectHandler)}";         // add the handler name to the REST request URL
                                }
                                try
                                {
                                    if (webhook.Async)
                                    {
                                        Task.Factory.StartNew(async() =>
                                            {
                                                await httpClient.GetAsync(url);
                                            });
                                    }
                                    else
                                    {
                                        httpClient.GetAsync(url).GetAwaiter().GetResult();
                                    }
                                }
                                catch (HttpRequestException ex)
                                {
                                    scope.LogError(ex, "Error calling provisioning template webhook");
                                }
                                break;
                            }

                            case ProvisioningTemplateWebhookMethod.POST:
                            {
                                requestParameters.Add("__webhookKind", kind.ToString());         // add the webhook kind to the parameters of the request body

                                if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted ||
                                    kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted ||
                                    kind == ProvisioningTemplateWebhookKind.ExceptionOccurred)
                                {
                                    requestParameters.Add("__handler", objectHandler);         // add the handler name to the parameters of the request body
                                }
                                try
                                {
                                    if (webhook.Async)
                                    {
                                        Task.Factory.StartNew(async() =>
                                            {
                                                switch (webhook.BodyFormat)
                                                {
                                                case ProvisioningTemplateWebhookBodyFormat.Json:
                                                    await httpClient.PostAsJsonAsync(url, requestParameters);
                                                    break;

                                                case ProvisioningTemplateWebhookBodyFormat.Xml:
                                                    await httpClient.PostAsXmlAsync(url, requestParameters);
                                                    break;

                                                case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                                    var content = new FormUrlEncodedContent(requestParameters);
                                                    await httpClient.PostAsync(url, content);
                                                    break;
                                                }
                                            });
                                    }
                                    else
                                    {
                                        switch (webhook.BodyFormat)
                                        {
                                        case ProvisioningTemplateWebhookBodyFormat.Json:
                                            httpClient.PostAsJsonAsync(url, requestParameters).GetAwaiter().GetResult();
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.Xml:
                                            httpClient.PostAsXmlAsync(url, requestParameters).GetAwaiter().GetResult();
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                            var content = new FormUrlEncodedContent(requestParameters);
                                            httpClient.PostAsync(url, content).GetAwaiter().GetResult();
                                            break;
                                        }
                                    }
                                }
                                catch (HttpRequestException ex)
                                {
                                    scope.LogError(ex, "Error calling provisioning template webhook");
                                }
                                break;
                            }
                            }
                        }
                    }
                }
            }
        }
        private static void UpdateContentType(Web web, Microsoft.SharePoint.Client.ContentType existingContentType, ContentType templateContentType, TokenParser parser, PnPMonitoredScope scope)
        {
            var isDirty = false;
            if (existingContentType.Hidden != templateContentType.Hidden)
            {
                scope.LogPropertyUpdate("Hidden");
                existingContentType.Hidden = templateContentType.Hidden;
                isDirty = true;
            }
            if (existingContentType.ReadOnly != templateContentType.ReadOnly)
            {
                scope.LogPropertyUpdate("ReadOnly");
                existingContentType.ReadOnly = templateContentType.ReadOnly;
                isDirty = true;
            }
            if (existingContentType.Sealed != templateContentType.Sealed)
            {
                scope.LogPropertyUpdate("Sealed");
                existingContentType.Sealed = templateContentType.Sealed;
                isDirty = true;
            }
            if (templateContentType.Description != null && existingContentType.Description != parser.ParseString(templateContentType.Description))
            {
                scope.LogPropertyUpdate("Description");
                existingContentType.Description = parser.ParseString(templateContentType.Description);
                isDirty = true;
            }
            if (templateContentType.DocumentTemplate != null && existingContentType.DocumentTemplate != parser.ParseString(templateContentType.DocumentTemplate))
            {
                scope.LogPropertyUpdate("DocumentTemplate");
                existingContentType.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate);
                isDirty = true;
            }
            if (existingContentType.Name != parser.ParseString(templateContentType.Name))
            {
                scope.LogPropertyUpdate("Name");
                existingContentType.Name = parser.ParseString(templateContentType.Name);
                isDirty = true;
            }
            if (templateContentType.Group != null && existingContentType.Group != parser.ParseString(templateContentType.Group))
            {
                scope.LogPropertyUpdate("Group");
                existingContentType.Group = parser.ParseString(templateContentType.Group);
                isDirty = true;
            }
            if (isDirty)
            {
                existingContentType.Update(true);
                web.Context.ExecuteQueryRetry();
            }
            // Delta handling
            List<Guid> targetIds = existingContentType.FieldLinks.AsEnumerable().Select(c1 => c1.Id).ToList();
            List<Guid> sourceIds = templateContentType.FieldRefs.Select(c1 => c1.Id).ToList();

            var fieldsNotPresentInTarget = sourceIds.Except(targetIds).ToArray();

            if (fieldsNotPresentInTarget.Any())
            {
                foreach (var fieldId in fieldsNotPresentInTarget)
                {
                    var fieldRef = templateContentType.FieldRefs.Find(fr => fr.Id == fieldId);
                    var field = web.Fields.GetById(fieldId);
                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Adding_field__0__to_content_type, fieldId);
                    web.AddFieldToContentType(existingContentType, field, fieldRef.Required, fieldRef.Hidden);
                }
            }

            isDirty = false;
            foreach (var fieldId in targetIds.Intersect(sourceIds))
            {
                var fieldLink = existingContentType.FieldLinks.FirstOrDefault(fl => fl.Id == fieldId);
                var fieldRef = templateContentType.FieldRefs.Find(fr => fr.Id == fieldId);
                if (fieldRef != null)
                {
                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Field__0__exists_in_content_type, fieldId);
                    if (fieldLink.Required != fieldRef.Required)
                    {
                        scope.LogPropertyUpdate("Required");
                        fieldLink.Required = fieldRef.Required;
                        isDirty = true;
                    }
                    if (fieldLink.Hidden != fieldRef.Hidden)
                    {
                        scope.LogPropertyUpdate("Hidden");
                        fieldLink.Hidden = fieldRef.Hidden;
                        isDirty = true;
                    }
                }
            }

            // The new CT is a DocumentSet, and the target should be, as well
            if (templateContentType.DocumentSetTemplate != null)
            {
                if (!Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.IsChildOfDocumentSetContentType(web.Context, existingContentType).Value)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ContentTypes_InvalidDocumentSet_Update_Request, existingContentType.Id, existingContentType.Name);
                }
                else
                {
                    Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate templateToUpdate =
                        Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, existingContentType);

                    // TODO: Implement Delta Handling
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_DocumentSet_DeltaHandling_OnHold, existingContentType.Id, existingContentType.Name);
                }
            }

            if (isDirty)
            {
                existingContentType.Update(true);
                web.Context.ExecuteQueryRetry();
            }
        }
        private TokenParser ProcessLookupFields(Web web, ProvisioningTemplate template, TokenParser parser, PnPMonitoredScope scope)
        {
            var rootWeb = (web.Context as ClientContext).Site.RootWeb;

            rootWeb.Context.Load(rootWeb.Lists, lists => lists.Include(l => l.Id, l => l.RootFolder.ServerRelativeUrl, l => l.Fields).Where(l => l.Hidden == false));
            rootWeb.Context.ExecuteQueryRetry();

            foreach (var siteField in template.SiteFields)
            {
                var fieldElement = XElement.Parse(siteField.SchemaXml);

                if (fieldElement.Attribute("List") != null)
                {
                    var fieldId                    = Guid.Parse(fieldElement.Attribute("ID").Value);
                    var listIdentifier             = parser.ParseString(fieldElement.Attribute("List").Value);
                    var relationshipDeleteBehavior = fieldElement.Attribute("RelationshipDeleteBehavior") != null?fieldElement.Attribute("RelationshipDeleteBehavior").Value : string.Empty;

                    var webId = string.Empty;

                    var field = rootWeb.Fields.GetById(fieldId);
                    rootWeb.Context.Load(field, f => f.SchemaXmlWithResourceTokens);
                    rootWeb.Context.ExecuteQueryRetry();

                    List sourceList = FindSourceList(listIdentifier, web, rootWeb);

                    if (sourceList != null)
                    {
                        rootWeb.Context.Load(sourceList.ParentWeb);
                        rootWeb.Context.ExecuteQueryRetry();

                        webId = sourceList.ParentWeb.Id.ToString();

                        ProcessField(field, sourceList.Id, webId, relationshipDeleteBehavior);
                    }
                }
            }

            web.Context.Load(web.Lists, lists => lists.Include(l => l.Id, l => l.RootFolder.ServerRelativeUrl, l => l.Fields).Where(l => l.Hidden == false));
            web.Context.ExecuteQueryRetry();

            foreach (var listInstance in template.Lists)
            {
                foreach (var listField in listInstance.Fields)
                {
                    var fieldElement = XElement.Parse(listField.SchemaXml);
                    if (fieldElement.Attribute("List") == null)
                    {
                        continue;
                    }

                    var fieldId                    = Guid.Parse(fieldElement.Attribute("ID").Value);
                    var listIdentifier             = parser.ParseString(fieldElement.Attribute("List").Value);
                    var relationshipDeleteBehavior = fieldElement.Attribute("RelationshipDeleteBehavior") != null?fieldElement.Attribute("RelationshipDeleteBehavior").Value : string.Empty;

                    var webId = string.Empty;

                    var listUrl = UrlUtility.Combine(web.ServerRelativeUrl, parser.ParseString(listInstance.Url));

                    var createdList = web.Lists.FirstOrDefault(l => l.RootFolder.ServerRelativeUrl.Equals(listUrl, StringComparison.OrdinalIgnoreCase));
                    if (createdList != null)
                    {
                        try
                        {
                            var field = createdList.Fields.GetById(fieldId);
                            web.Context.Load(field, f => f.SchemaXmlWithResourceTokens);
                            web.Context.ExecuteQueryRetry();

                            List sourceList = FindSourceList(listIdentifier, web, rootWeb);

                            if (sourceList != null)
                            {
                                web.Context.Load(sourceList.ParentWeb);
                                web.Context.ExecuteQueryRetry();

                                webId = sourceList.ParentWeb.Id.ToString();
                                ProcessField(field, sourceList.Id, webId, relationshipDeleteBehavior);
                            }
                        }
                        catch (ArgumentException ex)
                        {
                            // We skip and log any issues related to not existing lookup fields
                            scope.LogError($"Exception searching for field! {ex.Message}");
                        }
                    }
                }
            }

            return(parser);
        }
Пример #36
0
        private void ExtractMasterPagesAndPageLayouts(Web web, ProvisioningTemplate template, TokenParser parser, PnPMonitoredScope scope, ProvisioningTemplateCreationInformation creationInfo)
        {
            String webApplicationUrl = TokenParser.GetWebApplicationUrl(web);

            if (!String.IsNullOrEmpty(webApplicationUrl))
            {
                // Get the Publishing Feature reference template
                ProvisioningTemplate publishingFeatureTemplate = GetPublishingFeatureBaseTemplate();

                // Get a reference to the root folder of the master page gallery
                var gallery = web.GetCatalog(116);
                web.Context.Load(gallery, g => g.RootFolder);
                web.Context.ExecuteQueryRetry();

                var masterPageGalleryFolder = gallery.RootFolder;

                // Load the files in the master page gallery
                web.Context.Load(masterPageGalleryFolder.Files);
                web.Context.ExecuteQueryRetry();

                var sourceFiles = masterPageGalleryFolder.Files.AsEnumerable().Where(
                    f => f.Name.EndsWith(".aspx", StringComparison.InvariantCultureIgnoreCase) ||
                    f.Name.EndsWith(".html", StringComparison.InvariantCultureIgnoreCase) ||
                    f.Name.EndsWith(".master", StringComparison.InvariantCultureIgnoreCase));

                foreach (var file in sourceFiles)
                {
                    try
                    {

                    var listItem = file.EnsureProperty(f => f.ListItemAllFields);
                    listItem.ContentType.EnsureProperties(ct => ct.Id, ct => ct.StringId);

                    // Check if the content type is of type Master Page or Page Layout
                    if (listItem.ContentType.StringId.StartsWith(MASTER_PAGE_CONTENT_TYPE_ID) ||
                        listItem.ContentType.StringId.StartsWith(PAGE_LAYOUT_CONTENT_TYPE_ID) ||
                        listItem.ContentType.StringId.StartsWith(HTML_MASTER_PAGE_CONTENT_TYPE_ID) ||
                        listItem.ContentType.StringId.StartsWith(HTML_PAGE_LAYOUT_CONTENT_TYPE_ID))
                    {
                        // Skip any .ASPX or .MASTER file related to an .HTML designer file
                        if ((file.Name.EndsWith(".aspx", StringComparison.InvariantCultureIgnoreCase)
                            && sourceFiles.Any(f => f.Name.Equals(file.Name.ToLower().Replace(".aspx", ".html"),
                                StringComparison.InvariantCultureIgnoreCase))) ||
                            (file.Name.EndsWith(".master", StringComparison.InvariantCultureIgnoreCase)
                            && sourceFiles.Any(f => f.Name.Equals(file.Name.ToLower().Replace(".master", ".html"),
                                StringComparison.InvariantCultureIgnoreCase))))
                        {
                            continue;
                        }

                        // If the file is a custom one, and not one native
                        // and coming out from the publishing feature
                        if (creationInfo.IncludeNativePublishingFiles ||
                            !IsPublishingFeatureNativeFile(publishingFeatureTemplate, file.Name))
                        {
                            var fullUri = new Uri(UrlUtility.Combine(webApplicationUrl, file.ServerRelativeUrl));

                            var folderPath = fullUri.Segments.Take(fullUri.Segments.Count() - 1).ToArray().Aggregate((i, x) => i + x).TrimEnd('/');
                            var fileName = fullUri.Segments[fullUri.Segments.Count() - 1];

                                string fileSrc = (null != template.Connector) ?
                                    Path.Combine(template.Connector.GetConnectionString(), fileName) : fileName;
                            var publishingFile = new Model.File()
                            {
                                Folder = TokenizeUrl(folderPath, parser),
                                    Src = HttpUtility.UrlDecode(fileSrc),
                                Overwrite = true,
                            };

                            // Add field values to file
                            RetrieveFieldValues(web, file, publishingFile, parser);

                            // Add the file to the template
                            template.Files.Add(publishingFile);

                            // Persist file using connector, if needed
                            if (creationInfo.PersistPublishingFiles)
                            {
                                PersistFile(web, creationInfo, scope, folderPath, fileName, true);
                            }

                            if (listItem.ContentType.StringId.StartsWith(MASTER_PAGE_CONTENT_TYPE_ID))
                            {
                                scope.LogWarning(String.Format("The file \"{0}\" is a custom MasterPage. Accordingly to the PnP Guidance (http://aka.ms/o365pnpguidancemasterpages) you should try to avoid using custom MasterPages.", file.Name));
                            }
                        }
                        else
                        {
                            scope.LogWarning(String.Format("Skipping file \"{0}\" because it is native in the publishing feature.", file.Name));
                        }
                    }

                }
                    catch (Exception ex)
                    {
                        scope.LogError(String.Format("Could not extract master page or layout: {0} - {1}", ex.Message, ex.StackTrace));
            }
            }
            }
        }
        public override ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                scope.LogInfo(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Retrieving_current_composed_look);

                // Ensure that we have URL property loaded for web and site
                web.EnsureProperty(w => w.Url);
                Site site = (web.Context as ClientContext).Site;
                site.EnsureProperty(s => s.Url);

                SharePointConnector spConnector = new SharePointConnector(web.Context, web.Url, "dummy");
                // to get files from theme catalog we need a connector linked to the root site
                SharePointConnector spConnectorRoot;
                if (!site.Url.Equals(web.Url, StringComparison.InvariantCultureIgnoreCase))
                {
                    spConnectorRoot = new SharePointConnector(web.Context.Clone(site.Url), site.Url, "dummy");
                }
                else
                {
                    spConnectorRoot = spConnector;
                }

                // Check if we have composed look info in the property bag, if so, use that, otherwise try to detect the current composed look
                if (web.PropertyBagContainsKey("_PnP_ProvisioningTemplateComposedLookInfo"))
                {
                    scope.LogInfo(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Using_ComposedLookInfoFromPropertyBag);

                    try
                    {
                        var composedLook = JsonConvert.DeserializeObject <ComposedLook>(web.GetPropertyBagValueString("_PnP_ProvisioningTemplateComposedLookInfo", ""));
                        if (composedLook.Name == null || composedLook.BackgroundFile == null || composedLook.FontFile == null)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_ComposedLookInfoFailedToDeserialize);
                            throw new JsonSerializationException();
                        }

                        composedLook.BackgroundFile = Tokenize(composedLook.BackgroundFile, web.Url);
                        composedLook.FontFile       = Tokenize(composedLook.FontFile, web.Url);
                        composedLook.ColorFile      = Tokenize(composedLook.ColorFile, web.Url);
                        template.ComposedLook       = composedLook;

                        if (!web.IsSubSite() && creationInfo != null &&
                            creationInfo.PersistBrandingFiles && creationInfo.FileConnector != null)
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Creating_SharePointConnector);
                            // Let's create a SharePoint connector since our files anyhow are in SharePoint at this moment
                            TokenParser parser = new TokenParser(web, template);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.BackgroundFile), scope);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.ColorFile), scope);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.FontFile), scope);
                        }
                        // Create file entries for the custom theme files
                        if (!string.IsNullOrEmpty(template.ComposedLook.BackgroundFile))
                        {
                            var f = GetComposedLookFile(template.ComposedLook.BackgroundFile);
                            f.Folder = Tokenize(f.Folder, web.Url);
                            template.Files.Add(f);
                        }
                        if (!string.IsNullOrEmpty(template.ComposedLook.ColorFile))
                        {
                            var f = GetComposedLookFile(template.ComposedLook.ColorFile);
                            f.Folder = Tokenize(f.Folder, web.Url);
                            template.Files.Add(f);
                        }
                        if (!string.IsNullOrEmpty(template.ComposedLook.FontFile))
                        {
                            var f = GetComposedLookFile(template.ComposedLook.FontFile);
                            f.Folder = Tokenize(f.Folder, web.Url);
                            template.Files.Add(f);
                        }
                    }
                    catch (JsonSerializationException)
                    {
                        // cannot deserialize the object, fall back to composed look detection
                        template = DetectComposedLook(web, template, creationInfo, scope, spConnector, spConnectorRoot);
                    }
                }
                else
                {
                    template = DetectComposedLook(web, template, creationInfo, scope, spConnector, spConnectorRoot);
                }

                if (creationInfo != null && creationInfo.BaseTemplate != null)
                {
                    template = CleanupEntities(template, creationInfo.BaseTemplate);
                }
            }
            return(template);
        }
        public override ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                // Load object if not there
            #if !CLIENTSDKV15
                web.EnsureProperties(w => w.Url, w => w.MasterUrl, w => w.AlternateCssUrl, w => w.SiteLogoUrl);
            #else
                web.EnsureProperties(w => w.Url, w => w.MasterUrl);
            #endif

                // Information coming from the site
                template.ComposedLook.MasterPage = Tokenize(web.MasterUrl, web.Url);
            #if !CLIENTSDKV15
                template.ComposedLook.AlternateCSS = Tokenize(web.AlternateCssUrl, web.Url);
                template.ComposedLook.SiteLogo = Tokenize(web.SiteLogoUrl, web.Url);
            #else
                template.ComposedLook.AlternateCSS = null;
                template.ComposedLook.SiteLogo = null;
            #endif
                scope.LogInfo(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Retrieving_current_composed_look);

                Site site = (web.Context as ClientContext).Site;
                if (!site.IsObjectPropertyInstantiated("Url"))
                {
                    web.Context.Load(site);
                    web.Context.ExecuteQueryRetry();
                }

                SharePointConnector spConnector = new SharePointConnector(web.Context, web.Url, "dummy");

                // to get files from theme catalog we need a connector linked to the root site
                SharePointConnector spConnectorRoot;
                if (!site.Url.Equals(web.Url, StringComparison.InvariantCultureIgnoreCase))
                {
                    spConnectorRoot = new SharePointConnector(web.Context.Clone(site.Url), site.Url, "dummy");
                }
                else
                {
                    spConnectorRoot = spConnector;
                }

                // Check if we have composed look info in the property bag, if so, use that, otherwise try to detect the current composed look

                if (web.PropertyBagContainsKey("_PnP_ProvisioningTemplateComposedLookInfo"))
                {
                    scope.LogInfo(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Using_ComposedLookInfoFromPropertyBag);

                    try
                    {
                        var composedLook = JsonConvert.DeserializeObject<ComposedLook>(web.GetPropertyBagValueString("_PnP_ProvisioningTemplateComposedLookInfo", ""));
                        if (composedLook.Name == null || composedLook.BackgroundFile == null || composedLook.FontFile == null || composedLook.MasterPage == null || composedLook.SiteLogo == null)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_ComposedLookInfoFailedToDeserialize);
                            throw new JsonSerializationException();
                        }

                        template.ComposedLook = composedLook;
                        if (creationInfo != null && creationInfo.PersistComposedLookFiles && creationInfo.FileConnector != null)
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Creating_SharePointConnector);
                            // Let's create a SharePoint connector since our files anyhow are in SharePoint at this moment

                            // Download the theme/branding specific files
            #if !CLIENTSDKV15
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, web.AlternateCssUrl, scope);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, web.SiteLogoUrl, scope);
            #endif
                            TokenParser parser = new TokenParser(web, template);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.BackgroundFile), scope);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.ColorFile), scope);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.FontFile), scope);

                        }
                        // Create file entries for the custom theme files
                        if (!string.IsNullOrEmpty(template.ComposedLook.BackgroundFile))
                        {
                            template.Files.Add(GetComposedLookFile(template.ComposedLook.BackgroundFile));
                        }
                        if (!string.IsNullOrEmpty(template.ComposedLook.ColorFile))
                        {
                            template.Files.Add(GetComposedLookFile(template.ComposedLook.ColorFile));
                        }
                        if (!string.IsNullOrEmpty(template.ComposedLook.FontFile))
                        {

                            template.Files.Add(GetComposedLookFile(template.ComposedLook.FontFile));
                        }
                        if (!string.IsNullOrEmpty(template.ComposedLook.SiteLogo))
                        {
                            template.Files.Add(GetComposedLookFile(template.ComposedLook.SiteLogo));
                        }

                    }
                    catch (JsonSerializationException)
                    {
                        // cannot deserialize the object, fall back to composed look detection
                        template = DetectComposedLook(web, template, creationInfo, scope, spConnector, spConnectorRoot);
                    }

                }
                else
                {
                    template = DetectComposedLook(web, template, creationInfo, scope, spConnector, spConnectorRoot);
                }

                if (creationInfo != null && creationInfo.BaseTemplate != null)
                {
                    template = CleanupEntities(template, creationInfo.BaseTemplate);
                }
            }
            return template;
        }
Пример #39
0
        private static void CreateField(Web web, XElement templateFieldElement, PnPMonitoredScope scope, TokenParser parser, string originalFieldXml)
        {
            var listIdentifier = templateFieldElement.Attribute("List") != null?templateFieldElement.Attribute("List").Value : null;

            if (listIdentifier != null)
            {
                // Temporary remove list attribute from list
                templateFieldElement.Attribute("List").Remove();
            }

            var fieldXml = parser.ParseString(templateFieldElement.ToString(), "~sitecollection", "~site");

            if (IsFieldXmlValid(fieldXml, parser, web.Context))
            {
                var field = web.Fields.AddFieldAsXml(fieldXml, false, AddFieldOptions.AddFieldInternalNameHint);
                web.Context.Load(field, f => f.TypeAsString, f => f.DefaultValue, f => f.InternalName, f => f.Title);
                web.Context.ExecuteQueryRetry();

                // Add newly created field to token set, this allows to create a field + use it in a formula in the same provisioning template
                parser.AddToken(new FieldTitleToken(web, field.InternalName, field.Title));

                bool isDirty = false;
#if !SP2013
                if (originalFieldXml.ContainsResourceToken())
                {
                    var originalFieldElement = XElement.Parse(originalFieldXml);
                    var nameAttributeValue   = originalFieldElement.Attribute("DisplayName") != null?originalFieldElement.Attribute("DisplayName").Value : "";

                    if (nameAttributeValue.ContainsResourceToken())
                    {
                        field.TitleResource.SetUserResourceValue(nameAttributeValue, parser);
                        isDirty = true;
                    }
                    var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null?originalFieldElement.Attribute("Description").Value : "";

                    if (descriptionAttributeValue.ContainsResourceToken())
                    {
                        field.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser);
                        isDirty = true;
                    }
                }
#endif
                if (isDirty)
                {
                    field.Update();
                    web.Context.ExecuteQueryRetry();
                }

                if ((field.TypeAsString == "TaxonomyFieldType" || field.TypeAsString == "TaxonomyFieldTypeMulti") && !string.IsNullOrEmpty(field.DefaultValue))
                {
                    var taxField = web.Context.CastTo <TaxonomyField>(field);
                    ValidateTaxonomyFieldDefaultValue(taxField);
                }
            }
            else
            {
                // The field Xml was found invalid
                var tokenString = parser.GetLeftOverTokens(fieldXml).Aggregate(String.Empty, (acc, i) => acc + " " + i);
                scope.LogError("The field was found invalid: {0}", tokenString);
                throw new Exception(string.Format("The field was found invalid: {0}", tokenString));
            }
        }
Пример #40
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            web.EnsureProperty(w => w.Url);

            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.Tenant != null)
                {
                    ProcessCdns(web, template.Tenant, parser, scope);

                    var manager = new AppManager(web.Context as ClientContext);

                    if (template.Tenant.AppCatalog != null && template.Tenant.AppCatalog.Packages.Count > 0)
                    {
                        var appCatalogUri = web.GetAppCatalog();
                        if (appCatalogUri != null)
                        {
                            foreach (var app in template.Tenant.AppCatalog.Packages)
                            {
                                AppMetadata appMetadata = null;

                                if (app.Action == PackageAction.Upload ||
                                    app.Action == PackageAction.UploadAndPublish)
                                {
                                    using (var packageStream = GetPackageStream(template, app))
                                    {
                                        var memStream = new MemoryStream();
                                        packageStream.CopyTo(memStream);
                                        memStream.Position = 0;

                                        var appFilename = app.Src.Substring(app.Src.LastIndexOf('\\') + 1);
                                        appMetadata = manager.Add(memStream.ToArray(),
                                                                  appFilename,
                                                                  app.Overwrite);

                                        parser.Tokens.Add(new AppPackageIdToken(web, appFilename, appMetadata.Id));
                                    }
                                }

                                if (app.Action == PackageAction.Publish || app.Action == PackageAction.UploadAndPublish)
                                {
                                    if (appMetadata == null)
                                    {
                                        appMetadata = manager.GetAvailable()
                                                      .FirstOrDefault(a => a.Id == Guid.Parse(parser.ParseString(app.PackageId)));
                                    }
                                    if (appMetadata != null)
                                    {
                                        manager.Deploy(appMetadata, app.SkipFeatureDeployment);
                                    }
                                    else
                                    {
                                        scope.LogError("Referenced App Package {0} not available", app.PackageId);
                                        throw new Exception($"Referenced App Package {app.PackageId} not available");
                                    }
                                }

                                if (app.Action == PackageAction.Remove)
                                {
                                    var appId = Guid.Parse(parser.ParseString(app.PackageId));

                                    // Get the apps already installed in the site
                                    var appExists = manager.GetAvailable()?.Any(a => a.Id == appId);

                                    if (appExists.HasValue && appExists.Value)
                                    {
                                        manager.Remove(appId);
                                    }
                                    else
                                    {
                                        WriteMessage($"App Package with ID {appId} does not exist in the AppCatalog and cannot be removed!", ProvisioningMessageType.Warning);
                                    }
                                }
                            }
                        }
                        else
                        {
                            WriteMessage($"Tenant app catalog doesn't exist. ALM step will be skipped!", ProvisioningMessageType.Warning);
                        }
                    }

                    // So far we do not provision CDN settings
                    // It will come in the near future
                    // NOOP on CDN
                }
            }

            return(parser);
        }
Пример #41
0
        private bool PersistFile(Web web, ProvisioningTemplateCreationInformation creationInfo, PnPMonitoredScope scope, string serverRelativeUrl)
        {
            var success = false;
            if (creationInfo.PersistBrandingFiles)
            {
                if (creationInfo.FileConnector != null)
                {

                    try
                    {
                        var file = web.GetFileByServerRelativeUrl(serverRelativeUrl);
                        string fileName = string.Empty;
                        if (serverRelativeUrl.IndexOf("/") > -1)
                        {
                            fileName = serverRelativeUrl.Substring(serverRelativeUrl.LastIndexOf("/") + 1);
                        }
                        else
                        {
                            fileName = serverRelativeUrl;
                        }
                        web.Context.Load(file);
                        web.Context.ExecuteQueryRetry();
                        ClientResult<Stream> stream = file.OpenBinaryStream();
                        web.Context.ExecuteQueryRetry();

                        using (Stream memStream = new MemoryStream())
                        {
                            CopyStream(stream.Value, memStream);
                            memStream.Position = 0;
                            creationInfo.FileConnector.SaveFileStream(fileName, memStream);
                        }
                        success = true;
                    }
                    catch (ServerException ex1)
                    {
                        // If we are referring a file from a location outside of the current web or at a location where we cannot retrieve the file an exception is thrown. We swallow this exception.
                        if (ex1.ServerErrorCode != -2147024809)
                        {
                            throw;
                        }
                        else
                        {
                            scope.LogWarning("File is not necessarily located in the current web. Not retrieving {0}", serverRelativeUrl);
                        }
                    }
                }
                else
                {
                    WriteWarning("No connector present to persist homepage.", ProvisioningMessageType.Error);
                    scope.LogError("No connector present to persist homepage");
                }
            }
            else
            {
                success = true;
            }
            return success;
        }
Пример #42
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.Lists.Any())
                {
                    var rootWeb = (web.Context as ClientContext).Site.RootWeb;

                    web.EnsureProperties(w => w.ServerRelativeUrl);

                    web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                    web.Context.ExecuteQueryRetry();
                    var existingLists     = web.Lists.AsEnumerable <List>().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList();
                    var serverRelativeUrl = web.ServerRelativeUrl;

                    #region DataRows

                    foreach (var listInstance in template.Lists)
                    {
                        if (listInstance.DataRows != null && listInstance.DataRows.Any())
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Processing_data_rows_for__0_, listInstance.Title);
                            // Retrieve the target list
                            var list = web.Lists.GetByTitle(listInstance.Title);
                            web.Context.Load(list);

                            // Retrieve the fields' types from the list
                            Microsoft.SharePoint.Client.FieldCollection fields = list.Fields;
                            web.Context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind));
                            web.Context.ExecuteQueryRetry();

                            foreach (var dataRow in listInstance.DataRows)
                            {
                                try
                                {
                                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, listInstance.DataRows.IndexOf(dataRow) + 1);
                                    var listitemCI = new ListItemCreationInformation();
                                    var listitem   = list.AddItem(listitemCI);

                                    foreach (var dataValue in dataRow.Values)
                                    {
                                        Field dataField = fields.FirstOrDefault(
                                            f => f.InternalName == parser.ParseString(dataValue.Key));

                                        if (dataField != null)
                                        {
                                            String fieldValue = parser.ParseString(dataValue.Value);

                                            switch (dataField.FieldTypeKind)
                                            {
                                            case FieldType.Geolocation:
                                                // FieldGeolocationValue - Expected format: Altitude,Latitude,Longitude,Measure
                                                var geolocationArray = fieldValue.Split(',');
                                                if (geolocationArray.Length == 4)
                                                {
                                                    var geolocationValue = new FieldGeolocationValue
                                                    {
                                                        Altitude  = Double.Parse(geolocationArray[0]),
                                                        Latitude  = Double.Parse(geolocationArray[1]),
                                                        Longitude = Double.Parse(geolocationArray[2]),
                                                        Measure   = Double.Parse(geolocationArray[3]),
                                                    };
                                                    listitem[parser.ParseString(dataValue.Key)] = geolocationValue;
                                                }
                                                else
                                                {
                                                    listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                }
                                                break;

                                            case FieldType.Lookup:
                                                // FieldLookupValue - Expected format: LookupID or LookupID,LookupID,LookupID...
                                                if (fieldValue.Contains(","))
                                                {
                                                    var lookupValues = new List <FieldLookupValue>();
                                                    fieldValue.Split(',').All(value =>
                                                    {
                                                        lookupValues.Add(new FieldLookupValue
                                                        {
                                                            LookupId = int.Parse(value),
                                                        });
                                                        return(true);
                                                    });
                                                    listitem[parser.ParseString(dataValue.Key)] = lookupValues.ToArray();
                                                }
                                                else
                                                {
                                                    var lookupValue = new FieldLookupValue
                                                    {
                                                        LookupId = int.Parse(fieldValue),
                                                    };
                                                    listitem[parser.ParseString(dataValue.Key)] = lookupValue;
                                                }
                                                break;

                                            case FieldType.URL:
                                                // FieldUrlValue - Expected format: URL,Description
                                                var urlArray  = fieldValue.Split(',');
                                                var linkValue = new FieldUrlValue();
                                                if (urlArray.Length == 2)
                                                {
                                                    linkValue.Url         = urlArray[0];
                                                    linkValue.Description = urlArray[1];
                                                }
                                                else
                                                {
                                                    linkValue.Url         = urlArray[0];
                                                    linkValue.Description = urlArray[0];
                                                }
                                                listitem[parser.ParseString(dataValue.Key)] = linkValue;
                                                break;

                                            case FieldType.User:
                                                // FieldUserValue - Expected format: loginName or loginName,loginName,loginName...
                                                if (fieldValue.Contains(","))
                                                {
                                                    var userValues = new List <FieldUserValue>();
                                                    fieldValue.Split(',').All(value =>
                                                    {
                                                        var user = web.EnsureUser(value);
                                                        web.Context.Load(user);
                                                        web.Context.ExecuteQueryRetry();
                                                        if (user != null)
                                                        {
                                                            userValues.Add(new FieldUserValue
                                                            {
                                                                LookupId = user.Id,
                                                            });;
                                                        }
                                                        return(true);
                                                    });
                                                    listitem[parser.ParseString(dataValue.Key)] = userValues.ToArray();
                                                }
                                                else
                                                {
                                                    var user = web.EnsureUser(fieldValue);
                                                    web.Context.Load(user);
                                                    web.Context.ExecuteQueryRetry();
                                                    if (user != null)
                                                    {
                                                        var userValue = new FieldUserValue
                                                        {
                                                            LookupId = user.Id,
                                                        };
                                                        listitem[parser.ParseString(dataValue.Key)] = userValue;
                                                    }
                                                    else
                                                    {
                                                        listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    }
                                                }
                                                break;

                                            case FieldType.DateTime:
                                                var dateTime = DateTime.MinValue;
                                                if (DateTime.TryParse(fieldValue, out dateTime))
                                                {
                                                    listitem[parser.ParseString(dataValue.Key)] = dateTime;
                                                }
                                                break;

                                            default:
                                                listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                break;
                                            }
                                        }
                                        listitem.Update();
                                    }
                                    web.Context.ExecuteQueryRetry();                                     // TODO: Run in batches?

                                    if (dataRow.Security != null && dataRow.Security.RoleAssignments.Count != 0)
                                    {
                                        listitem.SetSecurity(parser, dataRow.Security);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, ex.Message, ex.StackTrace);
                                    throw;
                                }
                            }
                        }
                    }

                    #endregion
                }
            }

            return(parser);
        }
Пример #43
0
        public static TokenParser ProcessApps(Tenant tenant, ProvisioningTenant provisioningTenant, FileConnectorBase connector, TokenParser parser, PnPMonitoredScope scope, ApplyConfiguration configuration, ProvisioningMessagesDelegate messagesDelegate)
        {
            if (provisioningTenant.AppCatalog != null && provisioningTenant.AppCatalog.Packages.Count > 0)
            {
                var rootSiteUrl = tenant.GetRootSiteUrl();
                tenant.Context.ExecuteQueryRetry();
                using (var context = ((ClientContext)tenant.Context).Clone(rootSiteUrl.Value, configuration.AccessTokens))
                {
                    var web = context.Web;

                    Uri appCatalogUri = null;

                    try
                    {
                        appCatalogUri = web.GetAppCatalog();
                    }
                    catch (System.Net.WebException ex)
                    {
                        if (ex.Response != null)
                        {
                            var httpResponse = ex.Response as System.Net.HttpWebResponse;
                            if (httpResponse != null && httpResponse.StatusCode == HttpStatusCode.Unauthorized)
                            {
                                // Ignore any security exception and simply keep
                                // the AppCatalog URI null
                            }
                            else
                            {
                                throw ex;
                            }
                        }
                        else
                        {
                            throw ex;
                        }
                    }

                    if (appCatalogUri != null)
                    {
                        var manager = new AppManager(context);

                        foreach (var app in provisioningTenant.AppCatalog.Packages)
                        {
                            AppMetadata appMetadata = null;

                            if (app.Action == PackageAction.Upload || app.Action == PackageAction.UploadAndPublish)
                            {
                                var appSrc   = parser.ParseString(app.Src);
                                var appBytes = ConnectorFileHelper.GetFileBytes(connector, appSrc);

                                var hash = string.Empty;
                                using (var memoryStream = new MemoryStream(appBytes))
                                {
                                    hash = CalculateHash(memoryStream);
                                }

                                var exists = false;
                                var appId  = Guid.Empty;

                                using (var appCatalogContext = ((ClientContext)tenant.Context).Clone(appCatalogUri, configuration.AccessTokens))
                                {
                                    // check if the app already is present
                                    var appList   = appCatalogContext.Web.GetListByUrl("AppCatalog");
                                    var camlQuery = new CamlQuery
                                    {
                                        ViewXml = string.Format(appExistsQuery, hash)
                                    };
                                    var items = appList.GetItems(camlQuery);
                                    appCatalogContext.Load(items, i => i.IncludeWithDefaultProperties());
                                    appCatalogContext.ExecuteQueryRetry();
                                    if (items.Count > 0)
                                    {
                                        exists = true;
                                        appId  = Guid.Parse(items[0].FieldValues["UniqueId"].ToString());
                                    }
                                }
                                var appFilename = appSrc.Substring(appSrc.LastIndexOf('\\') + 1);

                                if (!exists)
                                {
                                    messagesDelegate?.Invoke($"Processing solution {app.Src}", ProvisioningMessageType.Progress);
                                    appMetadata = manager.Add(appBytes, appFilename, app.Overwrite, timeoutSeconds: 500);
                                }
                                else
                                {
                                    messagesDelegate?.Invoke($"Skipping existing solution {app.Src}", ProvisioningMessageType.Progress);
                                    appMetadata = manager.GetAvailable().FirstOrDefault(a => a.Id == appId);
                                }
                                if (appMetadata != null)
                                {
                                    parser.AddToken(new AppPackageIdToken(web, appFilename, appMetadata.Id));
                                    parser.AddToken(new AppPackageIdToken(web, appMetadata.Title, appMetadata.Id));
                                }
                            }

                            if (app.Action == PackageAction.Publish || app.Action == PackageAction.UploadAndPublish)
                            {
                                if (appMetadata == null)
                                {
                                    appMetadata = manager.GetAvailable()
                                                  .FirstOrDefault(a => a.Id == Guid.Parse(parser.ParseString(app.PackageId)));
                                }
                                if (appMetadata != null)
                                {
                                    manager.Deploy(appMetadata, app.SkipFeatureDeployment);
                                }
                                else
                                {
                                    scope.LogError("Referenced App Package {0} not available", app.PackageId);
                                    throw new Exception($"Referenced App Package {app.PackageId} not available");
                                }
                            }

                            if (app.Action == PackageAction.Remove)
                            {
                                var appId = Guid.Parse(parser.ParseString(app.PackageId));

                                // Get the apps already installed in the site
                                var appExists = manager.GetAvailable()?.Any(a => a.Id == appId);

                                if (appExists.HasValue && appExists.Value)
                                {
                                    manager.Remove(appId);
                                }
                                else
                                {
                                    messagesDelegate?.Invoke($"App Package with ID {appId} does not exist in the AppCatalog and cannot be removed!", ProvisioningMessageType.Warning);
                                }
                            }
                        }
                    }
                    else
                    {
                        messagesDelegate?.Invoke($"Tenant app catalog doesn't exist. ALM step will be skipped!", ProvisioningMessageType.Warning);
                    }
                }
            }
            return(parser);
        }
Пример #44
0
        /// <summary>
        /// Helper method to create or update an object through the Microsoft Graph
        /// </summary>
        /// <param name="scope">The PnP Provisioning Scope</param>
        /// <param name="method">The HTTP method to use</param>
        /// <param name="uri">The URI for the Graph request</param>
        /// <param name="content">The content of the Graph request</param>
        /// <param name="contentType">The content type of the Graph request</param>
        /// <param name="accessToken">The OAuth 2.0 Access Token</param>
        /// <param name="alreadyExistsErrorMessage">The error message token that identifies an already existing item</param>
        /// <param name="warningMessage">The warning message to log when the target item already exists</param>
        /// <param name="matchingFieldName">The name of a field to match an already existing instance of the target item</param>
        /// <param name="matchingFieldValue">The value of a field to match an already existing instance of the target item</param>
        /// <param name="errorMessage">The error message to log when the create or update action fails</param>
        /// <param name="canPatch">Defines whether a Patch HTTP request can be executed to update an already existing target item</param>
        /// <returns>The ID of the create or updated target item</returns>
        public static String CreateOrUpdateGraphObject(
            PnPMonitoredScope scope,
            HttpMethodVerb method,
            String uri,
            Object content,
            String contentType,
            String accessToken,
            String alreadyExistsErrorMessage,
            String warningMessage,
            String matchingFieldName,
            String matchingFieldValue,
            String errorMessage,
            Boolean canPatch
            )
        {
            try
            {
                String itemId = null;
                String json   = null;
                HttpResponseHeaders responseHeaders;

                // Try to create the Graph object
                switch (method)
                {
                case HttpMethodVerb.POST:
                    json = HttpHelper.MakePostRequestForString(uri, content, contentType, accessToken);
                    if (!string.IsNullOrEmpty(json))
                    {
                        itemId = JToken.Parse(json).Value <String>("id");
                    }
                    break;

                case HttpMethodVerb.PUT:
                    json = HttpHelper.MakePutRequestForString(uri, content, contentType, accessToken);
                    if (!string.IsNullOrEmpty(json))
                    {
                        itemId = JToken.Parse(json).Value <String>("id");
                    }
                    break;

                case HttpMethodVerb.POST_WITH_RESPONSE_HEADERS:
                    responseHeaders = HttpHelper.MakePostRequestForHeaders(uri, content, contentType, accessToken);
                    itemId          = responseHeaders.Location.ToString().Split('\'')[1];
                    break;
                }

                // Return the ID of the just created item
                return(itemId);
            }
            catch (Exception ex)
            {
                // In case of exception, let's see if the target item already exists
                if (!String.IsNullOrEmpty(alreadyExistsErrorMessage) &&
                    !String.IsNullOrEmpty(matchingFieldName) &&
                    !String.IsNullOrEmpty(matchingFieldValue) &&
                    ex.InnerException.Message.Contains(alreadyExistsErrorMessage))
                {
                    try
                    {
                        if (!String.IsNullOrEmpty(warningMessage))
                        {
                            scope.LogWarning(warningMessage);
                        }

                        // If it's a POST we need to look for any existing item
                        String id = null;

                        // In case of PUT we already have the id
                        if (method == HttpMethodVerb.POST || method == HttpMethodVerb.POST_WITH_RESPONSE_HEADERS)
                        {
                            // Filter by field and value specified
                            id  = ItemAlreadyExists(uri, matchingFieldName, matchingFieldValue, accessToken);
                            uri = $"{uri}/{id}";
                        }
                        else
                        {
                            id = matchingFieldValue;
                        }

                        // Patch the item, if supported
                        if (canPatch)
                        {
                            HttpHelper.MakePatchRequestForString(uri, content, contentType, accessToken);
                        }

                        return(id);
                    }
                    catch (Exception exUpdate)
                    {
                        if (!String.IsNullOrEmpty(errorMessage))
                        {
                            scope.LogError(errorMessage, exUpdate.Message);
                        }
                        return(null);
                    }
                }
                else
                {
                    return(null);
                }
            }
        }
Пример #45
0
        private static void CreateField(Web web, XElement templateFieldElement, PnPMonitoredScope scope, TokenParser parser, string originalFieldXml)
        {
            var listIdentifier = templateFieldElement.Attribute("List") != null ? templateFieldElement.Attribute("List").Value : null;

            if (listIdentifier != null)
            {
                // Temporary remove list attribute from list
                templateFieldElement.Attribute("List").Remove();
            }

            var fieldXml = parser.ParseString(templateFieldElement.ToString(), "~sitecollection", "~site");

            if (IsFieldXmlValid(fieldXml, parser, web.Context))
            {
                var field = web.Fields.AddFieldAsXml(fieldXml, false, AddFieldOptions.AddFieldInternalNameHint);
                web.Context.Load(field, f => f.TypeAsString, f => f.DefaultValue);
                web.Context.ExecuteQueryRetry();

                bool isDirty = false;
            #if !CLIENTSDKV15
                if (originalFieldXml.ContainsResourceToken())
                {
                    var originalFieldElement = XElement.Parse(originalFieldXml);
                    var nameAttributeValue = originalFieldElement.Attribute("Name") != null ? originalFieldElement.Attribute("Name").Value : "";
                    if (nameAttributeValue.ContainsResourceToken())
                    {
                        field.TitleResource.SetUserResourceValue(nameAttributeValue, parser);
                        isDirty = true;
                    }
                    var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null ? originalFieldElement.Attribute("Description").Value : "";
                    if (descriptionAttributeValue.ContainsResourceToken())
                    {
                        field.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser);
                        isDirty = true;
                    }
                }
            #endif
                if (isDirty)
                {
                    field.Update();
                    web.Context.ExecuteQuery();
                }

                if ((field.TypeAsString == "TaxonomyFieldType" || field.TypeAsString == "TaxonomyFieldTypeMulti") && !string.IsNullOrEmpty(field.DefaultValue))
                {
                    var taxField = web.Context.CastTo<TaxonomyField>(field);
                    ValidateTaxonomyFieldDefaultValue(taxField);
                }

            }
            else
            {
                // The field Xml was found invalid
                var tokenString = parser.GetLeftOverTokens(fieldXml).Aggregate(String.Empty, (acc, i) => acc + " " + i);
                scope.LogError("The field was found invalid: {0}", tokenString);
                throw new Exception(string.Format("The field was found invalid: {0}", tokenString));
            }
        }
        private void CallWebHooks(ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateWebhookKind kind, ObjectHandlerBase objectHandler = null)
        {
            using (var scope = new PnPMonitoredScope("ProvisioningTemplate WebHook Call"))
            {
                if (template.ProvisioningTemplateWebhooks != null && template.ProvisioningTemplateWebhooks.Any())
                {
                    foreach (var webhook in template.ProvisioningTemplateWebhooks.Where(w => w.Kind == kind))
                    {
                        var requestParameters = new Dictionary <String, String>();

                        SimpleTokenParser internalParser = new SimpleTokenParser();
                        foreach (var webhookparam in webhook.Parameters)
                        {
                            requestParameters.Add(webhookparam.Key, parser.ParseString(webhookparam.Value));
                            internalParser.AddToken(new WebhookParameter(webhookparam.Key, requestParameters[webhookparam.Key]));
                        }
                        var url = parser.ParseString(webhook.Url); // parse for template scoped parameters
                        url = internalParser.ParseString(url);     // parse for webhook scoped parameters

                        switch (webhook.Method)
                        {
                        case ProvisioningTemplateWebhookMethod.GET:
                        {
                            if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted || kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted)
                            {
                                url += $"&__handler={objectHandler.InternalName}";  // add the handler name to the REST request URL
                                url += $"&__webhookKind={kind.ToString()}";         // add the webhook kind to the REST request URL
                            }
                            try
                            {
                                if (webhook.Async)
                                {
                                    Task.Factory.StartNew(async() =>
                                        {
                                            await httpClient.GetAsync(url);
                                        });
                                }
                                else
                                {
                                    httpClient.GetAsync(url).GetAwaiter().GetResult();
                                }
                            }
                            catch (HttpRequestException ex)
                            {
                                scope.LogError(ex, "Error calling provisioning template webhook");
                            }
                            break;
                        }

                        case ProvisioningTemplateWebhookMethod.POST:
                        {
                            requestParameters.Add("__webhookKind", kind.ToString());         // add the webhook kind to the parameters of the request body
                            if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted || kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted)
                            {
                                requestParameters.Add("__handler", objectHandler.InternalName);         // add the handler name to the parameters of the request body
                            }
                            try
                            {
                                if (webhook.Async)
                                {
                                    Task.Factory.StartNew(async() =>
                                        {
                                            switch (webhook.BodyFormat)
                                            {
                                            case ProvisioningTemplateWebhookBodyFormat.Json:
                                                await httpClient.PostAsJsonAsync(url, requestParameters);
                                                break;

                                            case ProvisioningTemplateWebhookBodyFormat.Xml:
                                                await httpClient.PostAsXmlAsync(url, requestParameters);
                                                break;

                                            case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                                var content = new FormUrlEncodedContent(requestParameters);
                                                await httpClient.PostAsync(url, content);
                                                break;
                                            }
                                        });
                                }
                                else
                                {
                                    switch (webhook.BodyFormat)
                                    {
                                    case ProvisioningTemplateWebhookBodyFormat.Json:
                                        httpClient.PostAsJsonAsync(url, requestParameters).GetAwaiter().GetResult();
                                        break;

                                    case ProvisioningTemplateWebhookBodyFormat.Xml:
                                        httpClient.PostAsXmlAsync(url, requestParameters).GetAwaiter().GetResult();
                                        break;

                                    case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                        var content = new FormUrlEncodedContent(requestParameters);
                                        httpClient.PostAsync(url, content).GetAwaiter().GetResult();
                                        break;
                                    }
                                }
                            }
                            catch (HttpRequestException ex)
                            {
                                scope.LogError(ex, "Error calling provisioning template webhook");
                            }
                            break;
                        }
                        }
                    }
                }
            }
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.Lists.Any())
                {
                    var rootWeb = (web.Context as ClientContext).Site.RootWeb;

                    web.EnsureProperties(w => w.ServerRelativeUrl);

                    web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                    web.Context.ExecuteQueryRetry();
                    var existingLists = web.Lists.AsEnumerable().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList();
                    var serverRelativeUrl = web.ServerRelativeUrl;

                    var processedLists = new List<ListInfo>();

                    #region Lists

                    foreach (var templateList in template.Lists)
                    {
                        // Check for the presence of the references content types and throw an exception if not present or in template
                        if (templateList.ContentTypesEnabled)
                        {
                            var existingCts = web.Context.LoadQuery(web.AvailableContentTypes);
                            web.Context.ExecuteQueryRetry();
                            foreach (var ct in templateList.ContentTypeBindings)
                            {
                                var found = template.ContentTypes.Any(t => t.Id.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant());
                                if (found == false)
                                {
                                    found = existingCts.Any(t => t.StringId.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant());
                                }
                                if (!found)
                                {
                                    scope.LogError("Referenced content type {0} not available in site or in template", ct.ContentTypeId);
                                    throw new Exception(string.Format("Referenced content type {0} not available in site or in template", ct.ContentTypeId));
                                }
                            }
                        }
                        var index = existingLists.FindIndex(x => x.Equals(UrlUtility.Combine(serverRelativeUrl, templateList.Url), StringComparison.OrdinalIgnoreCase));
                        if (index == -1)
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0_, templateList.Title);
                                var returnTuple = CreateList(web, templateList, parser, scope);
                                var createdList = returnTuple.Item1;
                                parser = returnTuple.Item2;
                                processedLists.Add(new ListInfo { SiteList = createdList, TemplateList = templateList });

                                parser.AddToken(new ListIdToken(web, templateList.Title, createdList.Id));

                                parser.AddToken(new ListUrlToken(web, templateList.Title, createdList.RootFolder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length + 1)));
                            }
                            catch (Exception ex)
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace);
                                throw;
                            }
                        }
                        else
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0_, templateList.Title);
                                var existingList = web.Lists[index];
                                var returnTuple = UpdateList(web, existingList, templateList, parser, scope);
                                var updatedList = returnTuple.Item1;
                                parser = returnTuple.Item2;
                                if (updatedList != null)
                                {
                                    processedLists.Add(new ListInfo { SiteList = updatedList, TemplateList = templateList });
                                }
                            }
                            catch (Exception ex)
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace);
                                throw;
                            }
                        }
                    }

                    #endregion

                    #region FieldRefs

                    foreach (var listInfo in processedLists)
                    {

                        if (listInfo.TemplateList.FieldRefs.Any())
                        {

                            foreach (var fieldRef in listInfo.TemplateList.FieldRefs)
                            {
                                var field = rootWeb.GetFieldById<Field>(fieldRef.Id);
                                if (field != null)
                                {
                                    if (!listInfo.SiteList.FieldExistsById(fieldRef.Id))
                                    {
                                        CreateFieldRef(listInfo, field, fieldRef);
                                    }
                                    else
                                    {
                                        UpdateFieldRef(listInfo.SiteList, field.Id, fieldRef);
                                    }
                                }

                            }
                            listInfo.SiteList.Update();
                            web.Context.ExecuteQueryRetry();
                        }
                    }

                    #endregion

                    #region Fields

                    foreach (var listInfo in processedLists)
                    {
                        if (listInfo.TemplateList.Fields.Any())
                        {
                            foreach (var field in listInfo.TemplateList.Fields)
                            {
                                var fieldElement = XElement.Parse(parser.ParseString(field.SchemaXml, "~sitecollection", "~site"));
                                if (fieldElement.Attribute("ID") == null)
                                {
                                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml);
                                    throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml));
                                }
                                var id = fieldElement.Attribute("ID").Value;

                                Guid fieldGuid;
                                if (!Guid.TryParse(id, out fieldGuid))
                                {
                                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, field.SchemaXml);
                                    throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, id));
                                }
                                else
                                {
                                    var fieldFromList = listInfo.SiteList.GetFieldById<Field>(fieldGuid);
                                    if (fieldFromList == null)
                                    {
                                        try
                                        {
                                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0_, fieldGuid);
                                            CreateField(fieldElement, listInfo, parser);
                                        }
                                        catch (Exception ex)
                                        {
                                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace);
                                            throw;
                                        }
                                    }
                                    else
                                    {
                                        try
                                        {
                                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0_, fieldGuid);
                                            UpdateField(web, listInfo, fieldGuid, fieldElement, fieldFromList, scope, parser);
                                        }
                                        catch (Exception ex)
                                        {
                                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace);
                                            throw;
                                        }

                                    }
                                }
                            }
                        }
                        listInfo.SiteList.Update();
                        web.Context.ExecuteQueryRetry();
                    }

                    #endregion

                    #region Default Field Values
                    foreach (var listInfo in processedLists)
                    {
                        if (listInfo.TemplateList.FieldDefaults.Any())
                        {
                            foreach (var fieldDefault in listInfo.TemplateList.FieldDefaults)
                            {
                                var field = listInfo.SiteList.Fields.GetByInternalNameOrTitle(fieldDefault.Key);
                                field.DefaultValue = fieldDefault.Value;
                                field.Update();
                                web.Context.ExecuteQueryRetry();
                            }
                        }
                    }
                    #endregion

                    #region Views

                    foreach (var listInfo in processedLists)
                    {
                        var list = listInfo.TemplateList;
                        var createdList = listInfo.SiteList;

                        if (list.Views.Any() && list.RemoveExistingViews)
                        {
                            while (createdList.Views.Any())
                            {
                                createdList.Views[0].DeleteObject();
                            }
                            web.Context.ExecuteQueryRetry();
                        }

                        var existingViews = createdList.Views;
                        web.Context.Load(existingViews, vs => vs.Include(v => v.Title, v => v.Id));
                        web.Context.ExecuteQueryRetry();
                        foreach (var view in list.Views)
                        {

                            CreateView(web, view, existingViews, createdList, scope);

                        }

                        //// Removing existing views set the OnQuickLaunch option to false and need to be re-set.
                        //if (list.OnQuickLaunch && list.RemoveExistingViews && list.Views.Count > 0)
                        //{
                        //    createdList.RefreshLoad();
                        //    web.Context.ExecuteQueryRetry();
                        //    createdList.OnQuickLaunch = list.OnQuickLaunch;
                        //    createdList.Update();
                        //    web.Context.ExecuteQueryRetry();
                        //}
                    }

                    #endregion

                    // If an existing view is updated, and the list is to be listed on the QuickLaunch, it is removed because the existing view will be deleted and recreated from scratch.
                    foreach (var listInfo in processedLists)
                    {
                        listInfo.SiteList.OnQuickLaunch = listInfo.TemplateList.OnQuickLaunch;
                        listInfo.SiteList.Update();
                    }
                    web.Context.ExecuteQueryRetry();

                }
            }
            return parser;
        }
Пример #48
0
        public static TokenParser ProcessO365GroupSettings(Tenant tenant, ProvisioningTenant provisioningTenant, TokenParser parser, PnPMonitoredScope scope, ProvisioningMessagesDelegate messagesDelegate)
        {
            if (provisioningTenant.Office365GroupsSettings != null && provisioningTenant.Office365GroupsSettings.Properties.Any())
            {
                messagesDelegate?.Invoke("Processing Office 365 Group Settings", ProvisioningMessageType.Progress);
                bool siteClassificationSettingsExists = false;
                if (PnPProvisioningContext.Current != null)
                {
                    string accessToken = string.Empty;
                    try
                    {
                        // Get a fresh Access Token for every request
                        accessToken = PnPProvisioningContext.Current.AcquireToken(GraphHelper.MicrosoftGraphBaseURI, "Directory.ReadWrite.All");

                        if (accessToken != null)
                        {
                            try
                            {
                                var siteClassificationSettings = tenant.GetSiteClassificationsSettings(accessToken);
                                siteClassificationSettingsExists = true;
                            }
                            catch (Exception)
                            {
                                // Tenant classification doesn't exist, just swallow the exception.
                            }

                            var azureEnvironment = AzureEnvironment.Production;
                            if (PnPProvisioningContext.Current != null)
                            {
                                azureEnvironment = PnPProvisioningContext.Current.AzureEnvironment;
                            }

                            if (siteClassificationSettingsExists)
                            {
                                // Tenant classification exists, update the necessary values for Group Settings.
                                try
                                {
                                    string directorySettingTemplatesUrl  = $"{GraphHttpClient.GetGraphEndPointUrl(azureEnvironment)}groupSettings";
                                    var    directorySettingTemplatesJson = GraphHttpClient.MakeGetRequestForString(directorySettingTemplatesUrl, accessToken);
                                    var    directorySettingTemplates     = JsonConvert.DeserializeObject <DirectorySettingTemplates>(directorySettingTemplatesJson);

                                    // Retrieve the setinngs for "Group.Unified"
                                    var unifiedGroupSetting = directorySettingTemplates.Templates.FirstOrDefault(t => t.DisplayName == "Group.Unified");

                                    if (unifiedGroupSetting != null)
                                    {
                                        var props = provisioningTenant.Office365GroupsSettings.Properties;
                                        foreach (var v in unifiedGroupSetting.SettingValues)
                                        {
                                            var item = props.Where(p => p.Key == v.Name).FirstOrDefault();
                                            if (!string.IsNullOrEmpty(item.Key))
                                            {
                                                v.Value = parser.ParseString(item.Value);
                                            }
                                        }

                                        string updateDirectorySettingUrl    = $"{GraphHttpClient.GetGraphEndPointUrl(azureEnvironment)}groupSettings/{unifiedGroupSetting.Id}";
                                        var    updateDirectorySettingResult = GraphHttpClient.MakePatchRequestForString(
                                            updateDirectorySettingUrl,
                                            content: new
                                        {
                                            templateId = unifiedGroupSetting.Id,
                                            values     = from v in unifiedGroupSetting.SettingValues select new { name = v.Name, value = v.Value },
                                        },
                                            contentType: "application/json",
                                            accessToken: accessToken);
                                    }
                                    else
                                    {
                                        throw new ApplicationException("Missing DirectorySettingTemplate for \"Group.Unified\"");
                                    }
                                }
                                catch (Exception ex)
                                {
                                    scope.LogError($"Error occurred processing O365 Group settings ${ex.Message}");
                                }
                            }
                            else
                            {
                                // Tenant classification doesn't exist, create the necessary template for Group Settings.

                                try
                                {
                                    string directorySettingTemplatesUrl  = $"{GraphHttpClient.GetGraphEndPointUrl(azureEnvironment)}groupSettingTemplates";
                                    var    directorySettingTemplatesJson = GraphHttpClient.MakeGetRequestForString(directorySettingTemplatesUrl, accessToken);
                                    var    directorySettingTemplates     = JsonConvert.DeserializeObject <DirectorySettingTemplates>(directorySettingTemplatesJson);

                                    // Retrieve the setinngs for "Group.Unified"
                                    var unifiedGroupSetting = directorySettingTemplates.Templates.FirstOrDefault(t => t.DisplayName == "Group.Unified");

                                    if (unifiedGroupSetting != null)
                                    {
                                        var props = provisioningTenant.Office365GroupsSettings.Properties;
                                        foreach (var v in unifiedGroupSetting.SettingValues)
                                        {
                                            var item = props.Where(p => p.Key == v.Name).FirstOrDefault();
                                            if (!string.IsNullOrEmpty(item.Key))
                                            {
                                                v.Value = parser.ParseString(item.Value);
                                            }
                                            else
                                            {
                                                // Set default value because null is not supported
                                                // It only accepts entire collection and not individual properties
                                                v.Value = v.DefaultValue;
                                            }
                                        }

                                        string updateDirectorySettingUrl    = $"{GraphHttpClient.GetGraphEndPointUrl(azureEnvironment)}groupSettings";
                                        var    updateDirectorySettingResult = GraphHttpClient.MakePostRequestForString(
                                            updateDirectorySettingUrl,
                                            content: new
                                        {
                                            templateId = unifiedGroupSetting.Id,
                                            values     = from v in unifiedGroupSetting.SettingValues select new { name = v.Name, value = v.Value },
                                        },
                                            contentType: "application/json",
                                            accessToken: accessToken);
                                    }
                                    else
                                    {
                                        throw new ApplicationException("Missing DirectorySettingTemplate for \"Group.Unified\"");
                                    }
                                }
                                catch (Exception ex)
                                {
                                    scope.LogError($"Error occurred processing O365 Group settings ${ex.Message}");
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        scope.LogError($"Error occurred processing O365 Group settings ${ex.Message}");
                    }
                }
            }
            return(parser);
        }
 public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
 {
     using (var scope = new PnPMonitoredScope(this.Name))
     {
         var context = web.Context as ClientContext;
         foreach (var handler in template.ExtensibilityHandlers
             .Union(template.Providers)
             .Union(applyingInformation.ExtensibilityHandlers))
         {
             if (handler.Enabled)
             {
                 try
                 {
                     if (!string.IsNullOrEmpty(handler.Configuration))
                     {
                         //replace tokens in configuration data
                         handler.Configuration = parser.ParseString(handler.Configuration);
                     }
                     scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ExtensibilityProviders_Calling_extensibility_callout__0_, handler.Assembly);
                     _extManager.ExecuteExtensibilityProvisionCallOut(context, handler, template, applyingInformation, parser, scope);
                 }
                 catch (Exception ex)
                 {
                     scope.LogError(CoreResources.Provisioning_ObjectHandlers_ExtensibilityProviders_callout_failed___0_____1_, ex.Message, ex.StackTrace);
                     throw;
                 }
             }
         }
     }
     return parser;
 }
        /// <summary>
        /// Actual implementation of the apply templates
        /// </summary>
        /// <param name="web"></param>
        /// <param name="template"></param>
        /// <param name="provisioningInfo"></param>
        internal void ApplyRemoteTemplate(Web web, ProvisioningTemplate template, ProvisioningTemplateApplyingInformation provisioningInfo)
        {
            using (var scope = new PnPMonitoredScope(CoreResources.Provisioning_ObjectHandlers_Provisioning))
            {
                ProvisioningProgressDelegate progressDelegate = null;
                ProvisioningMessagesDelegate messagesDelegate = null;
                if (provisioningInfo != null)
                {
                    if (provisioningInfo.OverwriteSystemPropertyBagValues == true)
                    {
                        scope.LogInfo(CoreResources.SiteToTemplateConversion_ApplyRemoteTemplate_OverwriteSystemPropertyBagValues_is_to_true);
                    }
                    progressDelegate = provisioningInfo.ProgressDelegate;
                    if (provisioningInfo.ProgressDelegate != null)
                    {
                        scope.LogInfo(CoreResources.SiteToTemplateConversion_ProgressDelegate_registered);
                    }
                    messagesDelegate = provisioningInfo.MessagesDelegate;
                    if (provisioningInfo.MessagesDelegate != null)
                    {
                        scope.LogInfo(CoreResources.SiteToTemplateConversion_MessagesDelegate_registered);
                    }
                }
                else
                {
                    // When no provisioning info was passed then we want to execute all handlers
                    provisioningInfo = new ProvisioningTemplateApplyingInformation();
                    provisioningInfo.HandlersToProcess = Handlers.All;
                }

                // Check if scope is present and if so, matches the current site. When scope was not set the returned value will be ProvisioningTemplateScope.Undefined
                if (template.Scope == ProvisioningTemplateScope.RootSite)
                {
                    if (web.IsSubSite())
                    {
                        scope.LogError(CoreResources.SiteToTemplateConversion_ScopeOfTemplateDoesNotMatchTarget);
                        throw new Exception(CoreResources.SiteToTemplateConversion_ScopeOfTemplateDoesNotMatchTarget);
                    }
                }
                var currentCultureInfoValue = System.Threading.Thread.CurrentThread.CurrentCulture.LCID;
                if (!string.IsNullOrEmpty(template.TemplateCultureInfo))
                {
                    int cultureInfoValue = System.Threading.Thread.CurrentThread.CurrentCulture.LCID;
                    if (int.TryParse(template.TemplateCultureInfo, out cultureInfoValue))
                    {
                        System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureInfoValue);
                    }
                    else
                    {
                        System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(template.TemplateCultureInfo);
                    }
                }

                // Check if the target site shares the same base template with the template's source site
                var targetSiteTemplateId = web.GetBaseTemplateId();
                if (!String.IsNullOrEmpty(targetSiteTemplateId) && !String.IsNullOrEmpty(template.BaseSiteTemplate))
                {
                    if (!targetSiteTemplateId.Equals(template.BaseSiteTemplate, StringComparison.InvariantCultureIgnoreCase))
                    {
                        var templatesNotMatchingWarning = String.Format(CoreResources.Provisioning_Asymmetric_Base_Templates, template.BaseSiteTemplate, targetSiteTemplateId);
                        scope.LogWarning(templatesNotMatchingWarning);
                        if (provisioningInfo.MessagesDelegate != null)
                        {
                            provisioningInfo.MessagesDelegate(templatesNotMatchingWarning, ProvisioningMessageType.Warning);
                        }
                    }
                }

                // Always ensure the Url property is loaded. In the tokens we need this and we don't want to call ExecuteQuery as this can
                // impact delta scenarions (calling ExecuteQuery before the planned update is called)
                web.EnsureProperty(w => w.Url);


                List <ObjectHandlerBase> objectHandlers = new List <ObjectHandlerBase>();

                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.RegionalSettings))
                {
                    objectHandlers.Add(new ObjectRegionalSettings());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.SupportedUILanguages))
                {
                    objectHandlers.Add(new ObjectSupportedUILanguages());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.AuditSettings))
                {
                    objectHandlers.Add(new ObjectAuditSettings());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.SitePolicy))
                {
                    objectHandlers.Add(new ObjectSitePolicy());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.SiteSecurity))
                {
                    objectHandlers.Add(new ObjectSiteSecurity());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Features))
                {
                    objectHandlers.Add(new ObjectFeatures());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.TermGroups))
                {
                    objectHandlers.Add(new ObjectTermGroups());
                }

                // Process 3 times these providers to handle proper ordering of artefact creation when dealing with lookup fields

                // 1st. create fields, content and list without lookup fields
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Fields) || provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectField(FieldAndListProvisioningStepHelper.Step.ListAndStandardFields));
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ContentTypes))
                {
                    objectHandlers.Add(new ObjectContentType(FieldAndListProvisioningStepHelper.Step.ListAndStandardFields));
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectListInstance(FieldAndListProvisioningStepHelper.Step.ListAndStandardFields));
                }

                // 2nd. create lookup fields (which requires lists to be present
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Fields) || provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectField(FieldAndListProvisioningStepHelper.Step.LookupFields));
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ContentTypes))
                {
                    objectHandlers.Add(new ObjectContentType(FieldAndListProvisioningStepHelper.Step.LookupFields));
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectListInstance(FieldAndListProvisioningStepHelper.Step.LookupFields));
                }

                // 3rd. Create remaining objects in lists (views, user custom actions, ...)
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectListInstance(FieldAndListProvisioningStepHelper.Step.ListSettings));
                }

                //if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Fields) || provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists)) objectHandlers.Add(new ObjectLookupFields());

                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Fields) || provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectListInstanceDataRows());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Workflows))
                {
                    objectHandlers.Add(new ObjectWorkflows());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Files))
                {
                    objectHandlers.Add(new ObjectFiles());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Pages))
                {
                    objectHandlers.Add(new ObjectPages());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.PageContents))
                {
                    objectHandlers.Add(new ObjectPageContents());
                }
#if !ONPREMISES
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Tenant))
                {
                    objectHandlers.Add(new ObjectTenant());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ApplicationLifecycleManagement))
                {
                    objectHandlers.Add(new ObjectApplicationLifecycleManagement());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.WebApiPermissions))
                {
                    objectHandlers.Add(new ObjectWebApiPermissions());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Pages))
                {
                    objectHandlers.Add(new ObjectClientSidePages());
                }
#endif
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.CustomActions))
                {
                    objectHandlers.Add(new ObjectCustomActions());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Publishing))
                {
                    objectHandlers.Add(new ObjectPublishing());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ComposedLook))
                {
                    objectHandlers.Add(new ObjectComposedLook());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.SearchSettings))
                {
                    objectHandlers.Add(new ObjectSearchSettings());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.PropertyBagEntries))
                {
                    objectHandlers.Add(new ObjectPropertyBagEntry());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.WebSettings))
                {
                    objectHandlers.Add(new ObjectWebSettings());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Navigation))
                {
                    objectHandlers.Add(new ObjectNavigation());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ImageRenditions))
                {
                    objectHandlers.Add(new ObjectImageRenditions());
                }
                objectHandlers.Add(new ObjectLocalization()); // Always add this one, check is done in the handler
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ExtensibilityProviders))
                {
                    objectHandlers.Add(new ObjectExtensibilityHandlers());
                }

                // Only persist template information in case this flag is set: this will allow the engine to
                // work with lesser permissions
                if (provisioningInfo.PersistTemplateInfo)
                {
                    objectHandlers.Add(new ObjectPersistTemplateInfo());
                }
                var count = objectHandlers.Count(o => o.ReportProgress && o.WillProvision(web, template, provisioningInfo)) + 1;

                if (progressDelegate != null)
                {
                    progressDelegate("Initializing engine", 1, count); // handlers + initializing message)
                }
                var tokenParser = new TokenParser(web, template);
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ExtensibilityProviders))
                {
                    var extensibilityHandler = objectHandlers.OfType <ObjectExtensibilityHandlers>().First();
                    extensibilityHandler.AddExtendedTokens(web, template, tokenParser, provisioningInfo);
                }

                int step = 2;

                // Remove potentially unsupported artifacts

                var cleaner = new NoScriptTemplateCleaner(web);
                if (messagesDelegate != null)
                {
                    cleaner.MessagesDelegate = messagesDelegate;
                }
                template = cleaner.CleanUpBeforeProvisioning(template);

                foreach (var handler in objectHandlers)
                {
                    if (handler.WillProvision(web, template, provisioningInfo))
                    {
                        if (messagesDelegate != null)
                        {
                            handler.MessagesDelegate = messagesDelegate;
                        }
                        if (handler.ReportProgress && progressDelegate != null)
                        {
                            progressDelegate(handler.Name, step, count);
                            step++;
                        }
                        tokenParser = handler.ProvisionObjects(web, template, tokenParser, provisioningInfo);
                    }
                }

                System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(currentCultureInfoValue);
            }
        }
Пример #51
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(CoreResources.Provisioning_ObjectHandlers_Pages))
            {

                var context = web.Context as ClientContext;

                if (!web.IsPropertyAvailable("ServerRelativeUrl"))
                {
                    context.Load(web, w => w.ServerRelativeUrl);
                    context.ExecuteQueryRetry();
                }

                foreach (var page in template.Pages)
                {
                    var url = parser.ParseString(page.Url);

                    if (!url.ToLower().StartsWith(web.ServerRelativeUrl.ToLower()))
                    {
                        url = UrlUtility.Combine(web.ServerRelativeUrl, url);
                    }

                    var exists = true;
                    Microsoft.SharePoint.Client.File file = null;
                    try
                    {
                        file = web.GetFileByServerRelativeUrl(url);
                        web.Context.Load(file);
                        web.Context.ExecuteQuery();
                    }
                    catch (ServerException ex)
                    {
                        if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException")
                        {
                            exists = false;
                        }
                    }
                    if (exists)
                    {
                        if (page.Overwrite)
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0_, url);
                                file.DeleteObject();
                                web.Context.ExecuteQueryRetry();
                                web.AddWikiPageByUrl(url);
                                web.AddLayoutToWikiPage(page.Layout, url);
                            }
                            catch (Exception ex)
                            {
                                scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0__failed___1_____2_,url,ex.Message,ex.StackTrace);
                            }
                        }
                    }
                    else
                    {
                        try
                        {

                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0_, url);

                            web.AddWikiPageByUrl(url);
                            web.AddLayoutToWikiPage(page.Layout, url);
                        }
                        catch (Exception ex)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0__failed___1_____2_,url, ex.Message,ex.StackTrace);
                        }
                    }

                    if (page.WelcomePage)
                    {
                        if (!web.IsPropertyAvailable("RootFolder"))
                        {
                            web.Context.Load(web.RootFolder);
                            web.Context.ExecuteQueryRetry();
                        }

                        var rootFolderRelativeUrl = url.Substring(web.RootFolder.ServerRelativeUrl.Length);
                        web.SetHomePage(rootFolderRelativeUrl);
                    }

                    if (page.WebParts != null & page.WebParts.Any())
                    {
                        var existingWebParts = web.GetWebParts(url);

                        foreach (var webpart in page.WebParts)
                        {
                            if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == webpart.Title) == null)
                            {
                                WebPartEntity wpEntity = new WebPartEntity();
                                wpEntity.WebPartTitle = webpart.Title;
                                wpEntity.WebPartXml = parser.ParseString(webpart.Contents).Trim(new[] {'\n', ' '});
                                web.AddWebPartToWikiPage(url, wpEntity, (int) webpart.Row, (int) webpart.Column, false);
                            }
                        }
                    }
                }
            }
            return parser;
        }
Пример #52
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                var context = web.Context as ClientContext;

                web.EnsureProperties(w => w.ServerRelativeUrl, w => w.RootFolder.WelcomePage);

                foreach (var page in template.Pages)
                {
                    var url = parser.ParseString(page.Url);

                    if (!url.ToLower().StartsWith(web.ServerRelativeUrl.ToLower()))
                    {
                        url = UrlUtility.Combine(web.ServerRelativeUrl, url);
                    }

                    var exists = true;
                    Microsoft.SharePoint.Client.File file = null;
                    try
                    {
                        file = web.GetFileByServerRelativeUrl(url);
                        web.Context.Load(file);
                        web.Context.ExecuteQuery();
                    }
                    catch (ServerException ex)
                    {
                        if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException")
                        {
                            exists = false;
                        }
                    }
                    if (exists)
                    {
                        if (page.Overwrite)
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0_, url);

                                if (page.WelcomePage && url.Contains(web.RootFolder.WelcomePage))
                                {
                                    web.SetHomePage(string.Empty);
                                }

                                file.DeleteObject();
                                web.Context.ExecuteQueryRetry();
                                web.AddWikiPageByUrl(url);
                                web.AddLayoutToWikiPage(page.Layout, url);
                            }
                            catch (Exception ex)
                            {
                                scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace);
                            }
                        }
                    }
                    else
                    {
                        try
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0_, url);

                            web.AddWikiPageByUrl(url);
                            web.AddLayoutToWikiPage(page.Layout, url);
                        }
                        catch (Exception ex)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace);
                        }
                    }

                    if (page.WelcomePage)
                    {
                        web.RootFolder.EnsureProperty(p => p.ServerRelativeUrl);
                        var rootFolderRelativeUrl = url.Substring(web.RootFolder.ServerRelativeUrl.Length);
                        web.SetHomePage(rootFolderRelativeUrl);
                    }

                    if (page.WebParts != null & page.WebParts.Any())
                    {
                        var existingWebParts = web.GetWebParts(url);

                        foreach (var webpart in page.WebParts)
                        {
                            if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == webpart.Title) == null)
                            {
                                WebPartEntity wpEntity = new WebPartEntity();
                                wpEntity.WebPartTitle = webpart.Title;
                                wpEntity.WebPartXml   = parser.ParseString(webpart.Contents).Trim(new[] { '\n', ' ' });
                                web.AddWebPartToWikiPage(url, wpEntity, (int)webpart.Row, (int)webpart.Column, false);
                            }
                        }
                    }
                    if (page.Security != null && page.Security.RoleAssignments.Count != 0)
                    {
                        file = web.GetFileByServerRelativeUrl(url);
                        web.Context.Load(file.ListItemAllFields);
                        web.Context.ExecuteQuery();
                        file.ListItemAllFields.SetSecurity(parser, page.Security);
                    }
                }
            }
            return(parser);
        }
Пример #53
0
        private void CreateView(Web web, View view, Microsoft.SharePoint.Client.ViewCollection existingViews, List createdList, PnPMonitoredScope monitoredScope)
        {
            try
            {

                var viewElement = XElement.Parse(view.SchemaXml);
                var displayNameElement = viewElement.Attribute("DisplayName");
                if (displayNameElement == null)
                {
                    throw new ApplicationException("Invalid View element, missing a valid value for the attribute DisplayName.");
                }

                monitoredScope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_view__0_, displayNameElement.Value);
                var existingView = existingViews.FirstOrDefault(v => v.Title == displayNameElement.Value);

                if (existingView != null)
                {
                    existingView.DeleteObject();
                    web.Context.ExecuteQueryRetry();
                }

                var viewTitle = displayNameElement.Value;

                // Type
                var viewTypeString = viewElement.Attribute("Type") != null ? viewElement.Attribute("Type").Value : "None";
                viewTypeString = viewTypeString[0].ToString().ToUpper() + viewTypeString.Substring(1).ToLower();
                var viewType = (ViewType)Enum.Parse(typeof(ViewType), viewTypeString);

                // Fields
                string[] viewFields = null;
                var viewFieldsElement = viewElement.Descendants("ViewFields").FirstOrDefault();
                if (viewFieldsElement != null)
                {
                    viewFields = (from field in viewElement.Descendants("ViewFields").Descendants("FieldRef") select field.Attribute("Name").Value).ToArray();
                }

                // Default view
                var viewDefault = viewElement.Attribute("DefaultView") != null && Boolean.Parse(viewElement.Attribute("DefaultView").Value);

                // Row limit
                var viewPaged = true;
                uint viewRowLimit = 30;
                var rowLimitElement = viewElement.Descendants("RowLimit").FirstOrDefault();
                if (rowLimitElement != null)
                {
                    if (rowLimitElement.Attribute("Paged") != null)
                    {
                        viewPaged = bool.Parse(rowLimitElement.Attribute("Paged").Value);
                    }
                    viewRowLimit = uint.Parse(rowLimitElement.Value);
                }

                // Query
                var viewQuery = new StringBuilder();
                foreach (var queryElement in viewElement.Descendants("Query").Elements())
                {
                    viewQuery.Append(queryElement.ToString());
                }

                var viewCI = new ViewCreationInformation
                {
                    ViewFields = viewFields,
                    RowLimit = viewRowLimit,
                    Paged = viewPaged,
                    Title = viewTitle,
                    Query = viewQuery.ToString(),
                    ViewTypeKind = viewType,
                    PersonalView = false,
                    SetAsDefaultView = viewDefault,
                };

                // Allow to specify a custom view url. View url is taken from title, so we first set title to the view url value we need,
                // create the view and then set title back to the original value
                var urlAttribute = viewElement.Attribute("Url");
                var urlHasValue = urlAttribute != null && !string.IsNullOrEmpty(urlAttribute.Value);
                if (urlHasValue)
                {
                    //set Title to be equal to url (in order to generate desired url)
                    viewCI.Title = Path.GetFileNameWithoutExtension(urlAttribute.Value);
                }

                var createdView = createdList.Views.Add(viewCI);
                web.Context.Load(createdView, v => v.Scope, v => v.JSLink, v => v.Title);
                web.Context.ExecuteQueryRetry();

                if (urlHasValue)
                {
                    //restore original title
                    createdView.Title = viewTitle;
                    createdView.Update();
                }

                // ContentTypeID
                var contentTypeID = viewElement.Attribute("ContentTypeID") != null ? viewElement.Attribute("ContentTypeID").Value : null;
                if (!string.IsNullOrEmpty(contentTypeID) && (contentTypeID != BuiltInContentTypeId.System))
                {
                    ContentTypeId childContentTypeId = null;
                    if (contentTypeID == BuiltInContentTypeId.RootOfList)
                    {
                        var childContentType = web.GetContentTypeById(contentTypeID);
                        childContentTypeId = childContentType != null ? childContentType.Id : null;
                    }
                    else
                    {
                        childContentTypeId = createdList.ContentTypes.BestMatch(contentTypeID);
                    }
                    if (childContentTypeId != null)
                    {
                        createdView.ContentTypeId = childContentTypeId;
                        createdView.Update();
                    }
                }

                // Default for content type
                bool parsedDefaultViewForContentType;
                var defaultViewForContentType = viewElement.Attribute("DefaultViewForContentType") != null ? viewElement.Attribute("DefaultViewForContentType").Value : null;
                if (!string.IsNullOrEmpty(defaultViewForContentType) && bool.TryParse(defaultViewForContentType, out parsedDefaultViewForContentType))
                {
                    createdView.DefaultViewForContentType = parsedDefaultViewForContentType;
                    createdView.Update();
                }

                // Scope
                var scope = viewElement.Attribute("Scope") != null ? viewElement.Attribute("Scope").Value : null;
                ViewScope parsedScope = ViewScope.DefaultValue;
                if (!string.IsNullOrEmpty(scope) && Enum.TryParse<ViewScope>(scope, out parsedScope))
                {
                    createdView.Scope = parsedScope;
                    createdView.Update();
                }

                // JSLink
                var jslinkElement = viewElement.Descendants("JSLink").FirstOrDefault();
                if (jslinkElement != null)
                {
                    var jslink = jslinkElement.Value;
                    if (createdView.JSLink != jslink)
                    {
                        createdView.JSLink = jslink;
                        createdView.Update();
                    }
                }

                createdList.Update();
                web.Context.ExecuteQueryRetry();
            }
            catch (Exception ex)
            {
                monitoredScope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_view_failed___0_____1_, ex.Message, ex.StackTrace);
                throw;
            }
        }
Пример #54
0
        public void AddListItems(DataRowCollection dataRows, ProvisioningTemplate template, TokenParser parser, PnPMonitoredScope scope)
        {
            Microsoft.SharePoint.Client.FieldCollection fields = this.List.Fields;
            this.Context.Load(fields);
            this.Context.Load(this.List, l => l.RootFolder.ServerRelativeUrl);
            this.Context.ExecuteQueryRetry();

            ItemPathProvider itemPathProvider = new ItemPathProvider(this.List, this.Web);

            bool isDocLib = ( this.List.BaseType == BaseType.DocumentLibrary );

            var items = new List<ListItemInfo>();
            this.Context.ExecuteQueryBatch(dataRows.ToList(), (dataRow) =>
            {
                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, dataRows.IndexOf(dataRow) + 1);

                var listitem = itemPathProvider.CreateListItem(dataRow, template);
                if (null != listitem)
                {
                    foreach (var dataValue in dataRow.Values)
                    {
                        Field dataField = fields.FirstOrDefault(
                            f => f.InternalName == parser.ParseString(dataValue.Key));

                        if ((dataField != null) && CanFieldContentBeIncluded(dataField, false))
                        {
                            string fieldValue = parser.ParseString(dataValue.Value);
                            if (!string.IsNullOrEmpty(fieldValue))
                            {
                                FieldValueProvider valueProvider = GetFieldValueProvider(dataField, this.Web);
                                if (null != valueProvider)
                                {
                                    object itemValue = valueProvider.GetFieldValueTyped(fieldValue);
                                    if (null != itemValue)
                                    {
                                        if (dataField.FieldTypeKind == FieldType.Lookup)
                                        {
                                            FieldLookup lookupField = (FieldLookup)dataField;
                                            RegisterLookupReference(lookupField, listitem, itemValue);
                                        }
                                        else
                                        {
                                            listitem[dataField.InternalName] = itemValue;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    listitem.Update();

                    this.Context.Load(listitem);
                    if (isDocLib)
                    {
                        this.Context.Load(listitem.File);
                    }

                    items.Add(new ListItemInfo()
                    {
                        Item = listitem,
                        Row = dataRow
                    });
                }

            }, (error, dataRow) =>
            {
                for (var i = items.Count - 1; i >= 0; i--)
                {
                    if (items[i].Row == dataRow)
                    {
                        items.RemoveAt(i);
                    }
                }
                scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, error, "");
            }, isDocLib ? 1 : BATCH_SIZE);

            //Ensure files CheckIn
            if (isDocLib)
            {
                this.Context.ExecuteQueryBatch(items, (itemInfo) =>
                {
                    Microsoft.SharePoint.Client.File file = itemInfo.Item.File;
                    if ((null != file.ServerObjectIsNull) && (!(bool)file.ServerObjectIsNull) &&
                            (file.CheckOutType != CheckOutType.None))
                    {
                        file.CheckIn("", CheckinType.MajorCheckIn);
                    }
                }, BATCH_SIZE);
            }

            foreach (ListItemInfo itemInfo in items)
            {
                try
                {
                    var listitem = itemInfo.Item;
                    var dataRow = itemInfo.Row;
                    if (0 < listitem.Id)
                    {
                        AddIDMappingEntry(listitem, dataRow);

                        if (dataRow.Security != null && dataRow.Security.RoleAssignments.Count != 0)
                        {
                            //Should be optimized (run in batch)
                            listitem.SetSecurity(parser, dataRow.Security);
                        }
                    }
                }
                catch (Exception ex)
                {
                }
            }
        }
Пример #55
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.Lists.Any())
                {
                    var rootWeb = (web.Context as ClientContext).Site.RootWeb;

                    web.EnsureProperties(w => w.ServerRelativeUrl);

                    web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                    web.Context.ExecuteQueryRetry();
                    var existingLists = web.Lists.AsEnumerable().ToList();
                    var serverRelativeUrl = web.ServerRelativeUrl;

                    var processedLists = new List<ListInfo>();

                    // Check if this is not a noscript site as we're not allowed to update some properties
                    bool isNoScriptSite = web.IsNoScriptSite();

                    #region Lists

                    foreach (var templateList in template.Lists)
                    {
                        // Check for the presence of the references content types and throw an exception if not present or in template
                        if (templateList.ContentTypesEnabled)
                        {
                            var existingCts = web.Context.LoadQuery(web.AvailableContentTypes);
                            web.Context.ExecuteQueryRetry();
                            foreach (var ct in templateList.ContentTypeBindings)
                            {
                                var found = template.ContentTypes.Any(t => t.Id.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant());
                                if (found == false)
                                {
                                    found = existingCts.Any(t => t.StringId.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant());
                                }
                                if (!found)
                                {
                                    scope.LogError("Referenced content type {0} not available in site or in template", ct.ContentTypeId);
                                    throw new Exception(string.Format("Referenced content type {0} not available in site or in template", ct.ContentTypeId));
                                }
                            }
                        }
                        // check if the List exists by url or by title
                        var index = existingLists.FindIndex(x => x.Title.Equals(templateList.Title, StringComparison.OrdinalIgnoreCase) || x.RootFolder.ServerRelativeUrl.Equals(UrlUtility.Combine(serverRelativeUrl, templateList.Url), StringComparison.OrdinalIgnoreCase));

                        if (index == -1)
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0_, templateList.Title);
                                var returnTuple = CreateList(web, templateList, parser, scope, isNoScriptSite);
                                var createdList = returnTuple.Item1;
                                parser = returnTuple.Item2;
                                processedLists.Add(new ListInfo { SiteList = createdList, TemplateList = templateList });

                                parser.AddToken(new ListIdToken(web, templateList.Title, createdList.Id));

                                parser.AddToken(new ListUrlToken(web, templateList.Title, createdList.RootFolder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length + 1)));
                            }
                            catch (Exception ex)
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace);
                                throw;
                            }
                        }
                        else
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0_, templateList.Title);
                                var existingList = web.Lists[index];
                                var returnTuple = UpdateList(web, existingList, templateList, parser, scope, isNoScriptSite);
                                var updatedList = returnTuple.Item1;
                                parser = returnTuple.Item2;
                                if (updatedList != null)
                                {
                                    processedLists.Add(new ListInfo { SiteList = updatedList, TemplateList = templateList });
                                }
                            }
                            catch (Exception ex)
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace);
                                throw;
                            }
                        }
                    }

                    #endregion

                    #region FieldRefs

                    foreach (var listInfo in processedLists)
                    {

                        if (listInfo.TemplateList.FieldRefs.Any())
                        {

                            foreach (var fieldRef in listInfo.TemplateList.FieldRefs)
                            {
                                var field = rootWeb.GetFieldById<Field>(fieldRef.Id);
                                if (field == null)
                                {
                                    // log missing referenced field
                                    this.WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_InvalidFieldReference, listInfo.TemplateList.Title, fieldRef.Name, fieldRef.Id), ProvisioningMessageType.Error);

                                    // move onto next field reference
                                    continue;
                                }

                                if (!listInfo.SiteList.FieldExistsById(fieldRef.Id))
                                {
                                    field = CreateFieldRef(listInfo, field, fieldRef);
                                }
                                else
                                {
                                    field = UpdateFieldRef(listInfo.SiteList, field.Id, fieldRef);
                                }

                                field.EnsureProperties(f => f.InternalName, f => f.Title);

                                parser.AddToken(new FieldTitleToken(web, field.InternalName, field.Title));

            #if !SP2013
                                var siteField = template.SiteFields.FirstOrDefault(f => Guid.Parse(XElement.Parse(f.SchemaXml).Attribute("ID").Value).Equals(field.Id));

                                if (siteField != null && siteField.SchemaXml.ContainsResourceToken())
                                {
                                    var isDirty = false;
                                    var originalFieldElement = XElement.Parse(siteField.SchemaXml);
                                    var nameAttributeValue = originalFieldElement.Attribute("DisplayName") != null ? originalFieldElement.Attribute("DisplayName").Value : "";
                                    if (nameAttributeValue.ContainsResourceToken())
                                    {
                                        if (field.TitleResource.SetUserResourceValue(nameAttributeValue, parser))
                                        {
                                            isDirty = true;
                                        }
                                    }
                                    var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null ? originalFieldElement.Attribute("Description").Value : "";
                                    if (descriptionAttributeValue.ContainsResourceToken())
                                    {
                                        if (field.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser))
                                        {
                                            isDirty = true;
                                        }
                                    }

                                    if (isDirty)
                                    {
                                        field.Update();
                                        field.Context.ExecuteQueryRetry();
                                    }
                                }
            #endif
                            }

                            listInfo.SiteList.Update();
                            web.Context.ExecuteQueryRetry();
                        }
                    }

                    #endregion

                    #region Fields

                    foreach (var listInfo in processedLists)
                    {
                        if (listInfo.TemplateList.Fields.Any())
                        {
                            foreach (var field in listInfo.TemplateList.Fields)
                            {
                                var fieldElement = XElement.Parse(parser.ParseString(field.SchemaXml, "~sitecollection", "~site"));
                                if (fieldElement.Attribute("ID") == null)
                                {
                                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml);
                                    throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml));
                                }
                                var id = fieldElement.Attribute("ID").Value;

                                Guid fieldGuid;
                                if (!Guid.TryParse(id, out fieldGuid))
                                {
                                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, field.SchemaXml);
                                    throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, id));
                                }
                                else
                                {
                                    var fieldFromList = listInfo.SiteList.GetFieldById<Field>(fieldGuid);
                                    if (fieldFromList == null)
                                    {
                                        try
                                        {
                                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0_, fieldGuid);
                                            var createdField = CreateField(fieldElement, listInfo, parser, field.SchemaXml, web.Context, scope);
                                            if (createdField != null)
                                            {
                                                createdField.EnsureProperties(f => f.InternalName, f => f.Title);
                                                parser.AddToken(new FieldTitleToken(web, createdField.InternalName,
                                                    createdField.Title));
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace);
                                            throw;
                                        }
                                    }
                                    else
                                    {
                                        try
                                        {
                                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0_, fieldGuid);
                                            var updatedField = UpdateField(web, listInfo, fieldGuid, fieldElement, fieldFromList, scope, parser, field.SchemaXml);
                                            if (updatedField != null)
                                            {
                                                updatedField.EnsureProperties(f => f.InternalName, f => f.Title);
                                                parser.AddToken(new FieldTitleToken(web, updatedField.InternalName,
                                                    updatedField.Title));
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace);
                                            throw;
                                        }

                                    }
                                }
                            }
                        }
                        listInfo.SiteList.Update();
                        web.Context.ExecuteQueryRetry();
                    }

                    #endregion

                    #region Default Field Values
                    foreach (var listInfo in processedLists)
                    {
                        if (listInfo.TemplateList.FieldDefaults.Any())
                        {
                            foreach (var fieldDefault in listInfo.TemplateList.FieldDefaults)
                            {
                                var field = listInfo.SiteList.Fields.GetByInternalNameOrTitle(fieldDefault.Key);
                                field.DefaultValue = fieldDefault.Value;
                                field.Update();
                                web.Context.ExecuteQueryRetry();
                            }
                        }
                    }
                    #endregion

                    #region Views

                    foreach (var listInfo in processedLists)
                    {
                        var list = listInfo.TemplateList;
                        var createdList = listInfo.SiteList;

                        if (list.Views.Any() && list.RemoveExistingViews)
                        {
                            while (createdList.Views.Any())
                            {
                                createdList.Views[0].DeleteObject();
                            }
                            web.Context.ExecuteQueryRetry();
                        }

                        var existingViews = createdList.Views;
                        web.Context.Load(existingViews, vs => vs.Include(v => v.Title, v => v.Id));
                        web.Context.ExecuteQueryRetry();
                        foreach (var view in list.Views)
                        {

                            CreateView(web, view, existingViews, createdList, scope);

                        }

                        //// Removing existing views set the OnQuickLaunch option to false and need to be re-set.
                        //if (list.OnQuickLaunch && list.RemoveExistingViews && list.Views.Count > 0)
                        //{
                        //    createdList.RefreshLoad();
                        //    web.Context.ExecuteQueryRetry();
                        //    createdList.OnQuickLaunch = list.OnQuickLaunch;
                        //    createdList.Update();
                        //    web.Context.ExecuteQueryRetry();
                        //}
                    }

                    #endregion

                    #region Folders

                    // Folders are supported for document libraries and generic lists only
                    foreach (var list in processedLists)
                    {
                        list.SiteList.EnsureProperties(l => l.BaseType);
                        if ((list.SiteList.BaseType == BaseType.DocumentLibrary |
                            list.SiteList.BaseType == BaseType.GenericList) &&
                            list.TemplateList.Folders != null && list.TemplateList.Folders.Count > 0)
                        {
                            list.SiteList.EnableFolderCreation = true;
                            list.SiteList.Update();
                            web.Context.ExecuteQueryRetry();

                            var rootFolder = list.SiteList.RootFolder;
                            foreach (var folder in list.TemplateList.Folders)
                            {
                                CreateFolderInList(rootFolder, folder, parser, scope);
                            }
                        }
                    }

                    #endregion

                    // If an existing view is updated, and the list is to be listed on the QuickLaunch, it is removed because the existing view will be deleted and recreated from scratch.
                    foreach (var listInfo in processedLists)
                    {
                        listInfo.SiteList.OnQuickLaunch = listInfo.TemplateList.OnQuickLaunch;
                        listInfo.SiteList.Update();
                    }
                    web.Context.ExecuteQueryRetry();

                }
            }
            return parser;
        }
Пример #56
0
        /// <summary>
        /// Creates or updates a Team object via Graph
        /// </summary>
        /// <param name="scope">The PnP Provisioning Scope</param>
        /// <param name="team">The Team to create</param>
        /// <param name="parser">The PnP Token Parser</param>
        /// <param name="accessToken">The OAuth 2.0 Access Token</param>
        /// <returns>The ID of the created or update Team</returns>
        private static string CreateOrUpdateTeam(PnPMonitoredScope scope, Team team, TokenParser parser, string accessToken)
        {
            var parsedMailNickname = !string.IsNullOrEmpty(team.MailNickname) ? parser.ParseString(team.MailNickname).ToLower() : null;

            if (string.IsNullOrEmpty(parsedMailNickname))
            {
                parsedMailNickname = CreateMailNicknameFromDisplayName(team.DisplayName);
            }

            // Check if the Group/Team already exists
            var alreadyExistingGroupId = GetGroupIdByMailNickname(scope, parsedMailNickname, accessToken);

            // If the Group already exists, we don't need to create it
            if (String.IsNullOrEmpty(alreadyExistingGroupId))
            {
                // Otherwise we create the Group, first

                // Prepare the IDs for owners and members
                String[] desideredOwnerIds;
                String[] desideredMemberIds;
                try
                {
                    var userIdsByUPN = team.Security.Owners
                                       .Select(o => o.UserPrincipalName)
                                       .Concat(team.Security.Members.Select(m => m.UserPrincipalName))
                                       .Distinct(StringComparer.OrdinalIgnoreCase)
                                       .ToDictionary(k => k, k =>
                    {
                        var jsonUser = HttpHelper.MakeGetRequestForString($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/users/{k}?$select=id", accessToken);
                        return(JToken.Parse(jsonUser).Value <string>("id"));
                    });

                    desideredOwnerIds  = team.Security.Owners.Select(o => userIdsByUPN[o.UserPrincipalName]).ToArray();
                    desideredMemberIds = team.Security.Members.Select(o => userIdsByUPN[o.UserPrincipalName]).Union(desideredOwnerIds).ToArray();
                }
                catch (Exception ex)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_FetchingUserError, ex.Message);
                    return(null);
                }

                var groupCreationRequest = new
                {
                    displayName = parser.ParseString(team.DisplayName),
                    description = parser.ParseString(team.Description),
                    groupTypes  = new String[]
                    {
                        "Unified"
                    },
                    mailEnabled        = true,
                    mailNickname       = parsedMailNickname,
                    securityEnabled    = false,
                    visibility         = team.Visibility.ToString(),
                    owners_odata_bind  = (from o in desideredOwnerIds select $"{GraphHelper.MicrosoftGraphBaseURI}v1.0/users/{o}").ToArray(),
                    members_odata_bind = (from m in desideredMemberIds select $"{GraphHelper.MicrosoftGraphBaseURI}v1.0/users/{m}").ToArray()
                };

                // Make the Graph request to create the Office 365 Group
                var createdGroupJson = HttpHelper.MakePostRequestForString($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/groups",
                                                                           groupCreationRequest, HttpHelper.JsonContentType, accessToken);
                var createdGroupId = JToken.Parse(createdGroupJson).Value <string>("id");

                // Wait for the Group to be ready
                Boolean wait       = true;
                Int32   iterations = 0;
                while (wait)
                {
                    iterations++;

                    try
                    {
                        var jsonGroup = HttpHelper.MakeGetRequestForString($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/groups/{createdGroupId}", accessToken);
                        if (!String.IsNullOrEmpty(jsonGroup))
                        {
                            wait = false;
                        }
                    }
                    catch (Exception)
                    {
                        // In case of exception wait for 5 secs
                        System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
                    }

                    // Don't wait more than 1 minute
                    if (iterations > 12)
                    {
                        wait = false;
                    }
                }

                team.GroupId = createdGroupId;
            }
            else
            {
                // Otherwise use the already existing Group ID
                team.GroupId = alreadyExistingGroupId;
            }

            // Then we Teamify the Group
            var teamId = CreateOrUpdateTeamFromGroup(scope, team, parser, team.GroupId, accessToken);

            return(teamId);
        }
Пример #57
0
        /// <summary>
        /// Creates a new Team from a PnP Provisioning Schema definition
        /// </summary>
        /// <param name="scope">The PnP Provisioning Scope</param>
        /// <param name="parser">The PnP Token Parser</param>
        /// <param name="connector">The PnP File connector</param>
        /// <param name="team">The Team to provision</param>
        /// <param name="accessToken">The OAuth 2.0 Access Token</param>
        /// <returns>The provisioned Team as a JSON object</returns>
        private static JToken CreateTeamFromProvisioningSchema(PnPMonitoredScope scope, TokenParser parser, FileConnectorBase connector, Team team, string accessToken)
        {
            String teamId = null;

            // If we have to Clone an existing Team
            if (!String.IsNullOrWhiteSpace(team.CloneFrom))
            {
                teamId = CloneTeam(scope, team, parser, accessToken);
            }
            // If we start from an already existing Group
            else if (!String.IsNullOrEmpty(team.GroupId))
            {
                // We need to parse the GroupId, if it is a token
                var parsedGroupId = parser.ParseString(team.GroupId);

                // Check if the Group exists
                if (GroupExistsById(scope, parsedGroupId, accessToken))
                {
                    // Then promote the Group into a Team or update it, if it already exists. Patching a team doesn't return an ID, so use the parsedGroupId directly (teamId and groupId are the same).
                    teamId = CreateOrUpdateTeamFromGroup(scope, team, parser, parsedGroupId, accessToken) ?? parsedGroupId;
                }
                else
                {
                    // Log the exception and return NULL (i.e. cancel)
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_GroupDoesNotExists, parsedGroupId);
                    return(null);
                }
            }
            // Otherwise create a Team from scratch
            else
            {
                teamId = CreateOrUpdateTeam(scope, team, parser, accessToken);
            }

            if (!String.IsNullOrEmpty(teamId))
            {
                // Wait to be sure that the Team is ready before configuring it
                WaitForTeamToBeReady(accessToken, teamId);

                // And now we configure security, channels, and apps
                if (!SetGroupSecurity(scope, team, teamId, accessToken))
                {
                    return(null);
                }
                if (!SetTeamChannels(scope, parser, team, teamId, accessToken))
                {
                    return(null);
                }
                if (!SetTeamApps(scope, team, teamId, accessToken))
                {
                    return(null);
                }

                // So far the Team's photo cannot be set if we don't have an already existing mailbox
                // if (!SetTeamPhoto(scope, parser, connector, team, teamId, accessToken)) return null;

                // Call Archive or Unarchive for the current Team
                ArchiveTeam(scope, teamId, team.Archived, accessToken);

                try
                {
                    // Get the whole Team that we just created and return it back as the method result
                    return(JToken.Parse(HttpHelper.MakeGetRequestForString($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/teams/{teamId}", accessToken)));
                }
                catch (Exception ex)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_FetchingError, ex.Message);
                }
            }

            return(null);
        }
Пример #58
0
        /// <summary>
        /// Synchronizes Owners and Members with Team settings
        /// </summary>
        /// <param name="scope">The PnP Provisioning Scope</param>
        /// <param name="team">The Team settings, including security settings</param>
        /// <param name="teamId">The ID of the target Team</param>
        /// <param name="accessToken">The OAuth 2.0 Access Token</param>
        /// <returns>Whether the Security settings have been provisioned or not</returns>
        private static bool SetGroupSecurity(PnPMonitoredScope scope, Team team, string teamId, string accessToken)
        {
            String[] desideredOwnerIds;
            String[] desideredMemberIds;
            String[] finalOwnerIds;
            try
            {
                var userIdsByUPN = team.Security.Owners
                                   .Select(o => o.UserPrincipalName)
                                   .Concat(team.Security.Members.Select(m => m.UserPrincipalName))
                                   .Distinct(StringComparer.OrdinalIgnoreCase)
                                   .ToDictionary(k => k, k =>
                {
                    var jsonUser = HttpHelper.MakeGetRequestForString($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/users/{k}?$select=id", accessToken);
                    return(JToken.Parse(jsonUser).Value <string>("id"));
                });

                desideredOwnerIds  = team.Security.Owners.Select(o => userIdsByUPN[o.UserPrincipalName]).ToArray();
                desideredMemberIds = team.Security.Members.Select(o => userIdsByUPN[o.UserPrincipalName]).Union(desideredOwnerIds).ToArray();
            }
            catch (Exception ex)
            {
                scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_FetchingUserError, ex.Message);
                return(false);
            }

            String[] ownerIdsToAdd;
            String[] ownerIdsToRemove;
            try
            {
                // Get current group owners
                var jsonOwners = HttpHelper.MakeGetRequestForString($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/groups/{teamId}/owners?$select=id", accessToken);

                string[] currentOwnerIds = GraphHelper.GetIdsFromList(jsonOwners);

                // Exclude owners already into the group
                ownerIdsToAdd = desideredOwnerIds.Except(currentOwnerIds).ToArray();

                if (team.Security.ClearExistingOwners)
                {
                    ownerIdsToRemove = currentOwnerIds.Except(desideredOwnerIds).ToArray();
                }
                else
                {
                    ownerIdsToRemove = new string[0];
                }

                // Define the complete set of owners
                finalOwnerIds = currentOwnerIds.Union(ownerIdsToAdd).Except(ownerIdsToRemove).ToArray();
            }
            catch (Exception ex)
            {
                scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_ListingOwnersError, ex.Message);
                return(false);
            }

            // Add new owners
            foreach (string ownerId in ownerIdsToAdd)
            {
                try
                {
                    object content = new JObject
                    {
                        ["@odata.id"] = $"{GraphHelper.MicrosoftGraphBaseURI}v1.0/users/{ownerId}"
                    };
                    HttpHelper.MakePostRequest($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/groups/{teamId}/owners/$ref", content, "application/json", accessToken);
                }
                catch (Exception ex)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_AddingOwnerError, ex.Message);
                    return(false);
                }
            }

            // Remove exceeding owners
            foreach (string ownerId in ownerIdsToRemove)
            {
                try
                {
                    HttpHelper.MakeDeleteRequest($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/groups/{teamId}/owners/{ownerId}/$ref", accessToken);
                }
                catch (Exception ex)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_RemovingOwnerError, ex.Message);
                    return(false);
                }
            }

            String[] memberIdsToAdd;
            String[] memberIdsToRemove;
            try
            {
                // Get current group members
                var jsonMembers = HttpHelper.MakeGetRequestForString($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/groups/{teamId}/members?$select=id", accessToken);

                string[] currentMemberIds = GraphHelper.GetIdsFromList(jsonMembers);

                // Exclude members already into the group
                memberIdsToAdd = desideredMemberIds.Except(currentMemberIds).ToArray();

                if (team.Security.ClearExistingMembers)
                {
                    memberIdsToRemove = currentMemberIds.Except(desideredMemberIds.Union(finalOwnerIds)).ToArray();
                }
                else
                {
                    memberIdsToRemove = new string[0];
                }
            }
            catch (Exception ex)
            {
                scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_ListingMembersError, ex.Message);
                return(false);
            }

            // Add new members
            foreach (string memberId in memberIdsToAdd)
            {
                try
                {
                    object content = new JObject
                    {
                        ["@odata.id"] = $"{GraphHelper.MicrosoftGraphBaseURI}v1.0/users/{memberId}"
                    };
                    HttpHelper.MakePostRequest($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/groups/{teamId}/members/$ref", content, "application/json", accessToken);
                }
                catch (Exception ex)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_AddingMemberError, ex.Message);
                    return(false);
                }
            }

            // Remove exceeding members
            foreach (string memberId in memberIdsToRemove)
            {
                try
                {
                    HttpHelper.MakeDeleteRequest($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/groups/{teamId}/members/{memberId}/$ref", accessToken);
                }
                catch (Exception ex)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_RemovingMemberError, ex.Message);
                    return(false);
                }
            }

            return(true);
        }
Пример #59
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                var context = web.Context as ClientContext;

                web.EnsureProperties(w => w.ServerRelativeUrl, w => w.RootFolder.WelcomePage);

                // Check if this is not a noscript site as we're not allowed to update some properties
                bool isNoScriptSite = web.IsNoScriptSite();

                foreach (var page in template.Pages)
                {
                    var url = parser.ParseString(page.Url);

                    if (!url.ToLower().StartsWith(web.ServerRelativeUrl.ToLower()))
                    {
                        url = UrlUtility.Combine(web.ServerRelativeUrl, url);
                    }

                    var exists = true;
                    Microsoft.SharePoint.Client.File file = null;
                    try
                    {
                        file = web.GetFileByServerRelativeUrl(url);
                        web.Context.Load(file);
                        web.Context.ExecuteQueryRetry();
                    }
                    catch (ServerException ex)
                    {
                        if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException")
                        {
                            exists = false;
                        }
                    }
                    if (exists)
                    {
                        if (page.Overwrite)
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0_, url);

                                // determine url of current home page
                                string welcomePageUrl = web.RootFolder.WelcomePage;
                                string welcomePageServerRelativeUrl = welcomePageUrl != null
                                    ? UrlUtility.Combine(web.ServerRelativeUrl, web.RootFolder.WelcomePage)
                                    : null;

                                bool overwriteWelcomePage = string.Equals(url, welcomePageServerRelativeUrl, StringComparison.InvariantCultureIgnoreCase);

                                // temporarily reset home page so we can delete it
                                if (overwriteWelcomePage)
                                {
                                    web.SetHomePage(string.Empty);
                                }

                                file.DeleteObject();
                                web.Context.ExecuteQueryRetry();
                                web.AddWikiPageByUrl(url);
                                if (page.Layout == WikiPageLayout.Custom)
                                {
                                    web.AddLayoutToWikiPage(WikiPageLayout.OneColumn, url);
                                }
                                else
                                {
                                    web.AddLayoutToWikiPage(page.Layout, url);
                                }

                                if (overwriteWelcomePage)
                                {
                                    // restore welcome page to previous value
                                    web.SetHomePage(welcomePageUrl);
                                }
                            }
                            catch (Exception ex)
                            {
                                scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace);
                            }
                        }
                    }
                    else
                    {
                        try
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0_, url);

                            web.AddWikiPageByUrl(url);
                            if (page.Layout == WikiPageLayout.Custom)
                            {
                                web.AddLayoutToWikiPage(WikiPageLayout.OneColumn, url);
                            }
                            else
                            {
                                web.AddLayoutToWikiPage(page.Layout, url);
                            }
                        }
                        catch (Exception ex)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace);
                        }
                    }

#pragma warning disable 618
                    if (page.WelcomePage)
#pragma warning restore 618
                    {
                        web.RootFolder.EnsureProperty(p => p.ServerRelativeUrl);
                        var rootFolderRelativeUrl = url.Substring(web.RootFolder.ServerRelativeUrl.Length);
                        web.SetHomePage(rootFolderRelativeUrl);
                    }

#if !SP2013
                    bool webPartsNeedLocalization = false;
#endif
                    if (page.WebParts != null & page.WebParts.Any())
                    {
                        if (!isNoScriptSite)
                        {
                            var existingWebParts = web.GetWebParts(url);

                            foreach (var webPart in page.WebParts)
                            {
                                if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == parser.ParseString(webPart.Title)) == null)
                                {
                                    WebPartEntity wpEntity = new WebPartEntity
                                    {
                                        WebPartTitle = parser.ParseString(webPart.Title),
                                        WebPartXml   = parser.ParseXmlStringWebpart(webPart.Contents.Trim(new[] { '\n', ' ' }), web)
                                    };
                                    var wpd = web.AddWebPartToWikiPage(url, wpEntity, (int)webPart.Row, (int)webPart.Column, false);
#if !SP2013
                                    if (webPart.Title.ContainsResourceToken())
                                    {
                                        // update data based on where it was added - needed in order to localize wp title
                                        wpd.EnsureProperties(w => w.ZoneId, w => w.WebPart, w => w.WebPart.Properties);
                                        webPart.Zone             = wpd.ZoneId;
                                        webPart.Order            = (uint)wpd.WebPart.ZoneIndex;
                                        webPartsNeedLocalization = true;
                                    }
#endif
                                }
                            }

                            // Remove any existing WebPartIdToken tokens in the parser that were added by other pages. They won't apply to this page,
                            // and they'll cause issues if this page contains web parts with the same name as web parts on other pages.
                            parser.Tokens.RemoveAll(t => t is WebPartIdToken);

                            var allWebParts = web.GetWebParts(url);
                            foreach (var webpart in allWebParts)
                            {
                                parser.AddToken(new WebPartIdToken(web, webpart.WebPart.Title, webpart.Id));
                            }
                        }
                        else
                        {
                            scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_Pages_SkipAddingWebParts, page.Url);
                        }
                    }

#if !SP2013
                    if (webPartsNeedLocalization)
                    {
                        page.LocalizeWebParts(web, parser, scope);
                    }
#endif

                    file = web.GetFileByServerRelativeUrl(url);
                    file.EnsureProperty(f => f.ListItemAllFields);

                    if (page.Fields.Any())
                    {
                        var item = file.ListItemAllFields;
                        foreach (var fieldValue in page.Fields)
                        {
                            item[fieldValue.Key] = parser.ParseString(fieldValue.Value);
                        }
                        item.Update();
                        web.Context.ExecuteQueryRetry();
                    }
                    if (page.Security != null && page.Security.RoleAssignments.Count != 0)
                    {
                        web.Context.Load(file.ListItemAllFields);
                        web.Context.ExecuteQueryRetry();
                        file.ListItemAllFields.SetSecurity(parser, page.Security);
                    }
                }
            }
            return(parser);
        }
Пример #60
0
        private void CallWebHooks(ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateWebhookKind kind, ObjectHandlerBase objectHandler = null)
        {
            using (var scope = new PnPMonitoredScope("ProvisioningTemplate WebHook Call"))
            {
                if (template.ProvisioningTemplateWebhooks != null && template.ProvisioningTemplateWebhooks.Any())
                {
                    foreach (var webhook in template.ProvisioningTemplateWebhooks.Where(w => w.Kind == kind))
                    {
                        SimpleTokenParser internalParser = new SimpleTokenParser();
                        foreach (var webhookparam in webhook.Parameters)
                        {
                            internalParser.AddToken(new WebhookParameter(parser.ParseString(webhookparam.Key), parser.ParseString(webhookparam.Value)));
                        }
                        var url = parser.ParseString(webhook.Url); // parse for template scoped parameters
                        url = internalParser.ParseString(url);     // parse for webhook scoped parameters


                        switch (webhook.Method)
                        {
                        case ProvisioningTemplateWebhookMethod.GET:
                        {
                            if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted || kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted)
                            {
                                url += $"&__handler={objectHandler.InternalName}";
                            }
                            try
                            {
                                using (var client = new HttpClient())
                                {
                                    if (webhook.Async)
                                    {
                                        client.GetAsync(url);
                                    }
                                    else
                                    {
                                        client.GetAsync(url).GetAwaiter().GetResult();
                                    }
                                }
                            }
                            catch (HttpRequestException ex)
                            {
                                scope.LogError(ex, "Error calling provisioning template webhook");
                            }
                            break;
                        }

                        case ProvisioningTemplateWebhookMethod.POST:
                        {
                            if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted || kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted)
                            {
                                webhook.Parameters.Add("__handler", objectHandler.InternalName);
                            }
                            try
                            {
                                using (var client = new HttpClient())
                                {
                                    if (webhook.Async)
                                    {
                                        switch (webhook.BodyFormat)
                                        {
                                        case ProvisioningTemplateWebhookBodyFormat.Json:
                                            client.PostAsJsonAsync(url, webhook.Parameters);
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.Xml:
                                            client.PostAsXmlAsync(url, webhook.Parameters);
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                            var content = new FormUrlEncodedContent(webhook.Parameters);
                                            client.PostAsync(url, content);
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        switch (webhook.BodyFormat)
                                        {
                                        case ProvisioningTemplateWebhookBodyFormat.Json:
                                            client.PostAsJsonAsync(url, webhook.Parameters).GetAwaiter().GetResult();
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.Xml:
                                            client.PostAsXmlAsync(url, webhook.Parameters).GetAwaiter().GetResult();
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                            var content = new FormUrlEncodedContent(webhook.Parameters);
                                            client.PostAsync(url, content).GetAwaiter().GetResult();
                                            break;
                                        }
                                    }
                                }
                            }
                            catch (HttpRequestException ex)
                            {
                                scope.LogError(ex, "Error calling provisioning template webhook");
                            }
                            break;
                        }
                        }
                    }
                }
            }
        }