Пример #1
0
        public void CanProvisionObjects()
        {
            var template = new ProvisioningTemplate();
            var listInstance = new Core.Framework.Provisioning.Model.ListInstance();

            listInstance.Url = string.Format("lists/{0}", listName);
            listInstance.Title = listName;
            listInstance.TemplateType = (int) ListTemplateType.GenericList;

            Dictionary<string, string> dataValues = new Dictionary<string, string>();
            dataValues.Add("Title","Test");
            DataRow dataRow = new DataRow(dataValues);

            listInstance.DataRows.Add(dataRow);

            template.Lists.Add(listInstance);

            using (var ctx = TestCommon.CreateClientContext())
            {
                TokenParser.Initialize(ctx.Web, template);

                new ObjectListInstance().ProvisionObjects(ctx.Web, template);

                var list = ctx.Web.GetListByUrl(listInstance.Url);
                Assert.IsNotNull(list);
                
                var items = list.GetItems(CamlQuery.CreateAllItemsQuery());
                ctx.Load(items, itms => itms.Include(item => item["Title"]));
                ctx.ExecuteQueryRetry();

                Assert.IsTrue(items.Count == 1);
                Assert.IsTrue(items[0]["Title"].ToString() == "Test");
            }
        }
Пример #2
0
        public ListItem CreateListItem(DataRow dataRow, ProvisioningTemplate template)
        {
            ListItem listitem = null;

            string dir = null;
            string dirValue;
            if (dataRow.Values.TryGetValue(FIELD_ItemDir, out dirValue) && !string.IsNullOrEmpty(dirValue))
            {
                dir = TokenParser.CombineUrl(m_listServerRelativeUrl, dirValue);
            }

            string objType;
            if (!dataRow.Values.TryGetValue(FIELD_ItemType, out objType))
            {
                objType = "";
            }
            switch (objType)
            {
                case FIELD_ItemType_FolderValue:
                    {
                        string name;
                        if (dataRow.Values.TryGetValue(FIELD_ItemName, out name))
                        {
                            ListItemCreationInformation creationInfo = new ListItemCreationInformation()
                            {
                                UnderlyingObjectType = FileSystemObjectType.Folder,
                                LeafName = name,
                                FolderUrl = dir
                            };
                            listitem = this.List.AddItem(creationInfo);
                        }
                        break;
                    }
                case FIELD_ItemType_FileValue:
                    {
                        string name;
                        if (dataRow.Values.TryGetValue(FIELD_ItemName, out name) && !string.IsNullOrEmpty(dataRow.FileSrc))
                        {

                            if (string.IsNullOrEmpty(dir))
                            {
                                dir = this.List.RootFolder.ServerRelativeUrl;
                            }
                            FileCreationInformation creationInfo = new FileCreationInformation()
                            {
                                Overwrite = true,
                                ContentStream = template.Connector.GetFileStream(dataRow.FileSrc),
                                Url = TokenParser.CombineUrl(dir, name)
                            };
                            var newFile = this.List.RootFolder.Files.Add(creationInfo);
                            listitem = newFile.ListItemAllFields;
                        }

                        break;
                    }
                default:
                    {
                        ListItemCreationInformation creationInfo = new ListItemCreationInformation()
                        {
                            FolderUrl = dir
                        };
                        listitem = this.List.AddItem(creationInfo);
                        break;
                    }
            }

            return listitem;
        }
Пример #3
0
        private void AddIDMappingEntry(ListItem item, DataRow dataRow)
        {
            int oldId;
            string strId;
            if (dataRow.Values.TryGetValue("ID", out strId) && int.TryParse(strId, out oldId) && (0 < oldId))
            {
                if (null == m_mappingIDs)
                {
                    m_mappingIDs = new Dictionary<int, int>();
                }
                m_mappingIDs[oldId] = item.Id;

            }
        }
Пример #4
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;
        }
Пример #5
0
        internal override void OverrideXmlData(XElement sourceObject, XElement targetObject)
        {
            XNamespace ns = SchemaVersion;

            #region Property handling
            // Base property handling
            // Drop list properties if they're not provided in the source XML
            string[] ListProperties = new string[] { "Description", "DocumentTemplate", "MinorVersionLimit", "MaxVersionLimit", "DraftVersionVisibility", "TemplateFeatureID", "EnableAttachments" };
            foreach (string listProperty in ListProperties)
            {
                if (sourceObject.Attribute(listProperty) == null)
                {
                    DropAttribute(targetObject, listProperty);
                }
            }

            // Drop list elements if they're not provided in the source XML
            string[] ListElements = new string[] { "ContentTypeBindings", "Views", "FieldRefs", "Fields" };
            foreach (var listElement in ListElements)
            {
                var sourceListElementXML = sourceObject.Descendants(ns + listElement);
                var targetListElementXML = targetObject.Descendants(ns + listElement);
                if (sourceListElementXML.Any() == false && targetListElementXML.Any() == true)
                {
                    targetListElementXML.Remove();
                }
            }

#if ONPREMISES
            // MaxVersionLimit cannot be set in on-premises, so remove it before comparing before and after
            if (sourceObject.Attribute("MaxVersionLimit") != null)
            {
                DropAttribute(targetObject, "MaxVersionLimit");
                DropAttribute(sourceObject, "MaxVersionLimit");
            }
#endif
            #endregion

            #region Contenttype handling
            // If RemoveExistingContentTypes is set then remove the attribute from source since on target we don't add this. 
            var contentTypeBindings = targetObject.Descendants(ns + "ContentTypeBinding");
            bool removeExistingContentTypes = false;
            if (sourceObject.Attribute("RemoveExistingContentTypes") != null)
            {
                removeExistingContentTypes = sourceObject.Attribute("RemoveExistingContentTypes").Value.ToBoolean();
                DropAttribute(sourceObject, "RemoveExistingContentTypes");
            }

            if (contentTypeBindings != null && contentTypeBindings.Any())
            {
                // One can add ContentTypeBindings without specifying ContentTypesEnabled. The engine will turn on ContentTypesEnabled automatically in that case
                if (sourceObject.Attribute("ContentTypesEnabled") == null)
                {
                    DropAttribute(targetObject, "ContentTypesEnabled");
                }

                if (removeExistingContentTypes)
                {
                    foreach (var contentTypeBinding in contentTypeBindings.ToList())
                    {
                        // Remove the folder content type if present because we're not removing that one via RemoveExistingContentTypes
                        if (contentTypeBinding.Attribute("ContentTypeID").Value == "0x0120")
                        {
                            contentTypeBinding.Remove();
                        }
                    }
                }
                else // We did not remove existing content types
                {
                    var sourceContentTypeBindings = sourceObject.Descendants(ns + "ContentTypeBinding");
                    foreach (var contentTypeBinding in contentTypeBindings.ToList())
                    {
                        string value = contentTypeBinding.Attribute("ContentTypeID").Value;
                        // drop all content types which are not mentioned in the source
                        if (sourceContentTypeBindings.Where(p => p.Attribute("ContentTypeID").Value == value).Any() == false)
                        {
                            contentTypeBinding.Remove();
                        }
                    }
                }
            }
            #endregion

            #region FieldRef handling
            var fieldRefs = sourceObject.Descendants(ns + "FieldRef");
            if (fieldRefs != null && fieldRefs.Any())
            {
                foreach (var fieldRef in fieldRefs.ToList())
                {
                    // Drop the name attribute from the source fieldrefs since this is just an informational attribute
                    if (fieldRef.Attribute("Name") != null)
                    {
                        DropAttribute(fieldRef, "Name");
                    }

                    // Drop hidden fieldrefs since they're not retreived by the engine again
                    if (fieldRef.Attribute("Hidden") != null && fieldRef.Attribute("Hidden").Value.ToBoolean() == true)
                    {
                        fieldRef.Remove();
                    }
                }
            }
            var targetFieldRefs = targetObject.Descendants(ns + "FieldRef");
            if (targetFieldRefs != null && targetFieldRefs.Any())
            {
                foreach (var targetFieldRef in targetFieldRefs.ToList())
                {
                    // Drop the name attribute from the source fieldrefs since this is just an informational attribute
                    if (targetFieldRef.Attribute("Name") != null)
                    {
                        DropAttribute(targetFieldRef, "Name");
                    }

                    // Drop the fields which were not present in source (there's always some OOB fieldrefs)
                    if (!fieldRefs.Where(p => p.Attribute("ID").Value == targetFieldRef.Attribute("ID").Value).Any())
                    {
                        targetFieldRef.Remove();
                    }
                    else
                    {
                        // If the source object does not have a DisplayName attribute then also remove it from the target
                        if (!(fieldRefs.Where(p => p.Attribute("ID").Value == targetFieldRef.Attribute("ID").Value).FirstOrDefault().Attribute("DisplayName") != null))
                        {
                            DropAttribute(targetFieldRef, "DisplayName");
                        }
                    }
                }
            }
            #endregion

            #region Field handling
            var targetFields = targetObject.Descendants("Field");
            var sourceFields = sourceObject.Descendants("Field");

            if (sourceFields != null && sourceFields.Any())
            {
                foreach (var sourceField in sourceFields.ToList())
                {
                    // Ensure both target and source using the same casing
                    UpperCaseAttribute(sourceField, "ID");
                }
            }

            if (targetFields != null && targetFields.Any())
            {
                foreach (var targetField in targetFields.ToList())
                {
                    // Ensure both target and source using the same casing
                    UpperCaseAttribute(targetField, "ID");

                    // Drop attributes before comparison
                    DropAttribute(targetField, "SourceID");
                    DropAttribute(targetField, "StaticName");
                    DropAttribute(targetField, "ColName");
                    DropAttribute(targetField, "RowOrdinal");
                    DropAttribute(targetField, "Version");

                    // If target field does not exist in source then drop it (SPO can add additional fields e.g. _IsRecord field refering the _ComplianceFlags field)
                    if (sourceFields != null && sourceFields.Any())
                    {
                        if (!sourceFields.Where(p => p.Attribute("ID").Value.Equals(targetField.Attribute("ID").Value)).Any())
                        { 
                            targetField.Remove();
                        }
                    }                    
                }
            }
            #endregion

            #region View handling
            var sourceViews = sourceObject.Descendants("View");
            var targetViews = targetObject.Descendants("View");

            if (sourceViews != null && sourceViews.Any())
            {
                int sourceViewCount = 0;
                int targetViewCount = 0;
                foreach (var sourceView in sourceViews)
                {
                    sourceViewCount++;
                    string sourceViewName = sourceView.Attribute("DisplayName").Value;

                    if (targetViews.Where(v => v.Attribute("DisplayName").Value.Equals(sourceViewName, StringComparison.InvariantCultureIgnoreCase)).First() != null)
                    {
                        targetViewCount++;
                    }
                }

                if (sourceViewCount == targetViewCount)
                {
                    // if RemoveExistingViews was checked then we should have the same count of source and target views
                    if (sourceObject.Descendants(ns + "Views").First().Attribute("RemoveExistingViews") != null && sourceObject.Descendants(ns + "Views").First().Attribute("RemoveExistingViews").Value.ToBoolean() == true)
                    {
                        if (sourceViews.Count() == targetViews.Count())
                        {
                            // we've found the source views in the target + the original views were dropped, so we're good. Drop the view element to ensure valid XML comparison
                            sourceObject.Descendants(ns + "Views").Remove();
                            targetObject.Descendants(ns + "Views").Remove();
                        }
                    }
                    else
                    {
                        // we've found the source views in the target so we're good. Drop the view element to ensure valid XML comparison
                        sourceObject.Descendants(ns + "Views").Remove();
                        targetObject.Descendants(ns + "Views").Remove();
                    }
                }
            }
            #endregion

            #region FieldDefaults handling
            var sourceFieldDefaults = sourceObject.Descendants(ns + "FieldDefault");
            if (sourceFieldDefaults != null && sourceFieldDefaults.Any())
            {
                bool validFieldDefaults = true;

                foreach(var sourceFieldDefault in sourceFieldDefaults)
                {
                    string fieldDefaultValue = sourceFieldDefault.Value;
                    string fieldDefaultName = sourceFieldDefault.Attribute("FieldName").Value;

                    if (fieldDefaultValue != null && fieldDefaultName != null)
                    {
                        var targetField = targetFields.Where(p => p.Attribute("Name").Value.Equals(fieldDefaultName, StringComparison.InvariantCultureIgnoreCase)).First();
                        if (targetField.Descendants("Default").Any())
                        {
                            string targetFieldDefaultValue = targetField.Descendants("Default").First().Value;
                            if (!targetFieldDefaultValue.Equals(fieldDefaultValue, StringComparison.InvariantCultureIgnoreCase))
                            {
                                validFieldDefaults = false;
                            }
                            else
                            {
                                // remove the Default node
                                targetField.Descendants("Default").First().Remove();
                            }
                        }
                        else
                        {
                            validFieldDefaults = false;
                        }
                    }
                }

                if (validFieldDefaults)
                {
                    sourceObject.Descendants(ns + "FieldDefaults").Remove();
                }
            }

            // Drop any remaining Default node
            foreach (var targetField in targetFields)
            {
                if (targetField.Descendants("Default").Any())
                {
                    targetField.Descendants("Default").First().Remove();
                }
            }
            #endregion

            #region Folder handling
            // Folders are not extracted, so manual validation needed
            var sourceFolders = sourceObject.Descendants(ns + "Folders");
            if (sourceFolders != null && sourceFolders.Any())
            {
                // use CSOM to verify the folders are listed in target and only remove the source folder from the XML when this is the case
                if (this.cc != null)
                {
                    var foldersValid = true;
                    var list = this.cc.Web.GetListByUrl(sourceObject.Attribute("Url").Value);
                    if (list != null)
                    {
                        list.EnsureProperty(w => w.RootFolder);
                        foreach(var folder in sourceFolders.Descendants(ns + "Folder"))
                        {
                            // only verify first level folders
                            if (folder.Parent.Equals(sourceFolders.First()))
                            {
                                if (!list.RootFolder.FolderExists(folder.Attribute("Name").Value))
                                {
                                    foldersValid = false;
                                }

                                // if the folder has a security element then verify this as well
                                var sourceFolderSecurity = folder.Descendants(ns + "Security");
                                if (sourceFolderSecurity != null && sourceFolderSecurity.Any())
                                {
                                    // convert XML in ObjectSecurity object
                                    ObjectSecurity sourceFolderSecurityElement = new ObjectSecurity();
                                    sourceFolderSecurityElement.ClearSubscopes = sourceFolderSecurity.Descendants(ns + "BreakRoleInheritance").First().Attribute("ClearSubscopes").Value.ToBoolean();
                                    sourceFolderSecurityElement.CopyRoleAssignments = sourceFolderSecurity.Descendants(ns + "BreakRoleInheritance").First().Attribute("CopyRoleAssignments").Value.ToBoolean();

                                    var sourceRoleAssignments = folder.Descendants(ns + "RoleAssignment");
                                    foreach (var sourceRoleAssignment in sourceRoleAssignments)
                                    {
                                        sourceFolderSecurityElement.RoleAssignments.Add(new Core.Framework.Provisioning.Model.RoleAssignment()
                                            { Principal = sourceRoleAssignment.Attribute("Principal").Value,
                                              RoleDefinition = sourceRoleAssignment.Attribute("RoleDefinition").Value
                                        });
                                    }

                                    // grab the "Securable" for the folder
                                    var currentFolderItem = list.RootFolder.EnsureFolder(folder.Attribute("Name").Value).ListItemAllFields;
                                    cc.Load(currentFolderItem);
                                    cc.ExecuteQueryRetry();

                                    // use CSOM to verify security settings
                                    if (ValidateSecurityCSOM(this.cc, sourceFolderSecurityElement, currentFolderItem))
                                    {
                                        sourceFolderSecurity.Remove();
                                    }
                                }
                            }
                        }
                    }

                    if (foldersValid)
                    {
                        sourceFolders.Remove();
                    }
                }
            }
            #endregion

            #region DataRows handling
            var sourceDataRows = sourceObject.Descendants(ns + "DataRow");
            if (sourceDataRows != null && sourceDataRows.Any())
            {
                bool dataRowsValidated = true;

                var list = this.cc.Web.GetListByUrl(sourceObject.Attribute("Url").Value);
                if (list != null)
                {
                    int dataRowCount = 0;
                    foreach (var sourceDataRow in sourceDataRows)
                    {
                        // Convert XML in DataRow object
                        DataRow sourceDataRowElement = null;
                        Dictionary<string, string> values = new Dictionary<string, string>();
                        foreach (var dataValue in sourceDataRow.Descendants(ns + "DataValue"))
                        {
                            values.Add(dataValue.Attribute("FieldName").Value, dataValue.Value);
                        }

                        ObjectSecurity sourceDataRowSecurityElement = null;
                        var sourceDataRowSecurity = sourceDataRow.Descendants(ns + "Security");
                        if (sourceDataRowSecurity != null && sourceDataRowSecurity.Any())
                        {
                            // convert XML in ObjectSecurity object
                            sourceDataRowSecurityElement = new ObjectSecurity();
                            sourceDataRowSecurityElement.ClearSubscopes = sourceDataRowSecurity.Descendants(ns + "BreakRoleInheritance").First().Attribute("ClearSubscopes").Value.ToBoolean();
                            sourceDataRowSecurityElement.CopyRoleAssignments = sourceDataRowSecurity.Descendants(ns + "BreakRoleInheritance").First().Attribute("CopyRoleAssignments").Value.ToBoolean();

                            var sourceRoleAssignments = sourceDataRowSecurity.Descendants(ns + "RoleAssignment");
                            foreach (var sourceRoleAssignment in sourceRoleAssignments)
                            {
                                sourceDataRowSecurityElement.RoleAssignments.Add(new Core.Framework.Provisioning.Model.RoleAssignment()
                                {
                                    Principal = sourceRoleAssignment.Attribute("Principal").Value,
                                    RoleDefinition = sourceRoleAssignment.Attribute("RoleDefinition").Value
                                });
                            }
                        }

                        if (sourceDataRowSecurityElement != null)
                        {
                            sourceDataRowElement = new DataRow(values, sourceDataRowSecurityElement);
                        }
                        else
                        {
                            sourceDataRowElement = new DataRow(values);
                        }

                        dataRowCount++;
                        ListItem itemToValidate = null;
                        try
                        {
                            itemToValidate = list.GetItemById(dataRowCount);
                        }
                        catch
                        { }

                        if (itemToValidate == null || !ValidateDataRowsCSOM(cc, sourceDataRowElement, itemToValidate))
                        {
                            dataRowsValidated = false;
                        }
                    }
                }

                // If all datarows are validated then we can drop 
                if (dataRowsValidated)
                {
                    sourceObject.Descendants(ns + "DataRows").First().Remove();
                }
            }
            #endregion

            #region Security handling
            var sourceSecurity = sourceObject.Descendants(ns + "Security");
            if (sourceSecurity != null && sourceSecurity.Any())
            {
                var targetSecurity = targetObject.Descendants(ns + "Security");
                if (ValidateSecurityXml(sourceSecurity.First(), targetSecurity.First()))
                {
                    sourceSecurity.Remove();
                    targetSecurity.Remove();
                }
            }
            #endregion

            #region CustomAction handling
            var sourceCustomActions = sourceObject.Descendants(ns + "UserCustomActions");
            if (sourceCustomActions != null && sourceCustomActions.Any())
            {
                // delete custom actions since we validate these latter on
                var targetCustomActions = targetObject.Descendants(ns + "UserCustomActions");

                sourceCustomActions.Remove();
                if (targetCustomActions != null && targetCustomActions.Any())
                {
                    targetCustomActions.Remove();
                }
            }
            #endregion
        }