public override bool UpdateField(CSEntryChange csentry, object obj) { if (this.IsReadOnly) { return(false); } if (!csentry.HasAttributeChange(this.MmsAttributeName)) { return(false); } AttributeModificationType modType = csentry.AttributeChanges[this.MmsAttributeName].ModificationType; object value = csentry.GetValueAdd <object>(this.MmsAttributeName); User user = obj as User; if (user == null) { throw new NotSupportedException("The provided object was not of a 'user' type"); } if (value == null && !this.HasSchemaField(user)) { return(false); } IDictionary <string, object> schema = this.GetOrCreateSchema(user, out bool created); if (modType == AttributeModificationType.Delete) { if (this.HasSchemaField(user)) { schema[this.FieldName] = Utilities.GetNullRepresentation(this.NullValueRepresentation); Logger.WriteLine($"Deleting {this.MmsAttributeName}"); return(true); } return(false); } if (value == null) { value = Utilities.GetNullRepresentation(this.NullValueRepresentation); } else { value = this.ConvertToNativeGoogleFormat(value); } schema[this.FieldName] = value; Logger.WriteLine($"Set {this.MmsAttributeName} -> {value ?? "<null>"}"); return(true); }
private void AddAttributeChange(AttributeModificationType type, AcmaSchemaAttribute attribute) { this.ValidateAttributeChangeType(type); switch (type) { case AttributeModificationType.Replace: case AttributeModificationType.Update: case AttributeModificationType.Delete: case AttributeModificationType.Add: this.AttributeChanges.Add(Utils.CreateAttributeChange(attribute.Name, type)); break; case AttributeModificationType.Unconfigured: default: throw new UnknownOrUnsupportedModificationTypeException(type); } }
/// <summary> /// Creates a CSEntryChange of the specified modification type for the supplied MAObjectHologram /// </summary> /// <param name="maObject">The MAObjectHologram to create the CSEntryChange from</param> /// <param name="objectModificationType">The object modification type to apply</param> /// <returns>A new CSEntryChange object representing the current state of the specified MAObjectHologram </returns> public static AcmaCSEntryChange CreateCSEntryChangeFromMAObjectHologram(this MAObjectHologram maObject, ObjectModificationType objectModificationType) { AcmaCSEntryChange csentry = new AcmaCSEntryChange(); csentry.ObjectModificationType = objectModificationType; csentry.DN = maObject.ObjectID.ToString(); csentry.ObjectType = maObject.ObjectClass.Name; if (objectModificationType != ObjectModificationType.Delete) { AttributeModificationType attributeModificationType = objectModificationType == ObjectModificationType.Update ? AttributeModificationType.Replace : AttributeModificationType.Add; foreach (AcmaSchemaAttribute attribute in maObject.ObjectClass.Attributes.Where(t => t.Name != "objectId" && t.Name != "objectClass")) { AttributeValues values = maObject.GetAttributeValues(attribute); if (values.IsEmptyOrNull) { continue; } if (attributeModificationType == AttributeModificationType.Add) { AttributeChange change = AttributeChange.CreateAttributeAdd(attribute.Name, values.ToObjectList()); csentry.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(attribute.Name, values.ToObjectList())); } else { csentry.AttributeChanges.Add(AttributeChange.CreateAttributeReplace(attribute.Name, values.ToObjectList())); } } } if (csentry.ErrorCodeImport == MAImportError.Success) { MAStatistics.AddImportOperation(); } else { MAStatistics.AddImportError(); } return(csentry); }
/// <summary> /// Creates an AttributeChange of the specified type, provided that the attribute is present in the provided schema type /// </summary> /// <param name="csentry">The CSEntryChange to add the AttributeChange to</param> /// <param name="type">The schema type of the object class of the CSEntryChange</param> /// <param name="attributeName">The name of the attribute</param> /// <param name="modificationType">The type of modification to apply to the attribute</param> /// <param name="value">The value to apply to the modification operation</param> public static void CreateAttributeChangeIfInSchema(this CSEntryChange csentry, SchemaType type, string attributeName, AttributeModificationType modificationType, byte[] value) { csentry.CreateAttributeChangeIfInSchemaInternal(type, attributeName, modificationType, value); }
/// <summary> /// Creates an AttributeChange of the specified type, provided that the attribute is present in the provided schema type /// </summary> /// <param name="csentry">The CSEntryChange to add the AttributeChange to</param> /// <param name="type">The schema type of the object class of the CSEntryChange</param> /// <param name="attributeName">The name of the attribute</param> /// <param name="modificationType">The type of modification to apply to the attribute</param> /// <param name="value">The value to apply to the modification operation</param> public static void CreateAttributeChangeIfInSchema(this CSEntryChange csentry, SchemaType type, string attributeName, AttributeModificationType modificationType, string value) { if (!string.IsNullOrWhiteSpace(value)) { csentry.CreateAttributeChangeIfInSchemaInternal(type, attributeName, modificationType, value); } }
/// <summary> /// Creates an AttributeChange of the specified type, provided that the attribute is present in the provided schema type /// </summary> /// <param name="csentry">The CSEntryChange to add the AttributeChange to</param> /// <param name="type">The schema type of the object class of the CSEntryChange</param> /// <param name="attributeName">The name of the attribute</param> /// <param name="modificationType">The type of modification to apply to the attribute</param> /// <param name="value">The value to apply to the modification operation</param> public static void CreateAttributeChangeIfInSchema(this CSEntryChange csentry, SchemaType type, string attributeName, AttributeModificationType modificationType, long?value) { if (value != null && value.HasValue) { csentry.CreateAttributeChangeIfInSchemaInternal(type, attributeName, modificationType, value); } }
/// <summary> /// Creates an AttributeChange of the specified type, provided that the attribute is present in the provided schema type /// </summary> /// <param name="csentry">The CSEntryChange to add the AttributeChange to</param> /// <param name="type">The schema type of the object class of the CSEntryChange</param> /// <param name="attributeName">The name of the attribute</param> /// <param name="modificationType">The type of modification to apply to the attribute</param> /// <param name="valueChanges">The value changes to apply to the modification operation</param> public static void CreateAttributeChangeIfInSchema(this CSEntryChange csentry, SchemaType type, string attributeName, AttributeModificationType modificationType, IList <ValueChange> valueChanges) { if (type.HasAttribute(attributeName) && valueChanges != null && valueChanges.Count > 0) { csentry.CreateAttributeChange(attributeName, modificationType, valueChanges); } }
/// <summary> /// Creates an AttributeChange of the specified type /// </summary> /// <param name="csentry">The CSEntryChange to add the AttributeChange to</param> /// <param name="attributeName">The name of the attribute</param> /// <param name="modificationType">The type of modification to apply to the attribute</param> /// <param name="value">The value to apply to the modification operation</param> /// <typeparam name="T">The type of data</typeparam> public static void CreateAttributeChange <T>(this CSEntryChange csentry, string attributeName, AttributeModificationType modificationType, Nullable <T> value) where T : struct { switch (modificationType) { case AttributeModificationType.Add: if (value != null) { csentry.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(attributeName, value.Value)); } break; case AttributeModificationType.Delete: csentry.AttributeChanges.Add(AttributeChange.CreateAttributeDelete(attributeName)); break; case AttributeModificationType.Replace: if (value == null) { csentry.AttributeChanges.Add(AttributeChange.CreateAttributeReplace(attributeName, value)); } else { csentry.AttributeChanges.Add(AttributeChange.CreateAttributeDelete(attributeName)); } break; case AttributeModificationType.Update: if (value != null) { csentry.AttributeChanges.Add(AttributeChange.CreateAttributeUpdate(attributeName, value)); } break; case AttributeModificationType.Unconfigured: default: throw new InvalidOperationException("Unknown modification type"); } }
/// <summary> /// Reads the <![CDATA[<attribute-change]]> node of the XML representation of the <see cref="Microsoft.MetadirectoryServices.CSEntryChange">CSEntryChange</see> /// </summary> /// <param name="element">An <c ref="System.Linq.Xml.XElement">XElement</c> containing an <![CDATA[<attribute-change>]]> element</param> /// <param name="csentry">The <see cref="Microsoft.MetadirectoryServices.CSEntryChange">CSEntryChange</see> to populate</param> private static void XmlReadAttributeChangeNode(XElement element, CSEntryChange csentry) { string name = null; AttributeModificationType modificationType = AttributeModificationType.Unconfigured; AttributeType dataType = AttributeType.Undefined; List <ValueChange> valueChanges = null; AttributeChange attributeChange = null; foreach (XElement child in element.Elements()) { if (child.Name.LocalName == "name") { name = (string)child; } else if (child.Name.LocalName == "modification-type") { string modificationTypeString = (string)child; if (!Enum.TryParse <AttributeModificationType>(modificationTypeString, out modificationType)) { throw new InvalidCastException(string.Format("Cannot convert '{0}' to type {1}", modificationTypeString, typeof(AttributeModificationType).Name)); } } else if (child.Name.LocalName == "data-type") { string dataTypeString = (string)child; if (!Enum.TryParse <AttributeType>(dataTypeString, out dataType)) { throw new InvalidCastException(string.Format("Cannot convert '{0}' to type '{1}'", dataTypeString, typeof(AttributeType).Name)); } } else if (child.Name.LocalName == "value-changes") { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("The attribute name must appear first in the list of <attribute-change> elements"); } if (dataType == AttributeType.Undefined) { dataType = AttributeType.String; } valueChanges = CSEntryChangeDeserializer.XmlReadValueChangesNode(child, dataType); } } if (valueChanges == null) { return; } switch (modificationType) { case AttributeModificationType.Add: if (valueChanges.Count == 0) { // discard attribute change with no values return; } attributeChange = AttributeChange.CreateAttributeAdd(name, (valueChanges.Where(t => t.ModificationType == ValueModificationType.Add)).Select(t => t.Value).ToList()); break; case AttributeModificationType.Replace: if (valueChanges.Count == 0) { // discard attribute change with no values return; //throw new ArgumentException("The attribute replace in the CSEntry provided no values"); } attributeChange = AttributeChange.CreateAttributeReplace(name, (valueChanges.Where(t => t.ModificationType == ValueModificationType.Add)).Select(t => t.Value).ToList()); break; case AttributeModificationType.Delete: attributeChange = AttributeChange.CreateAttributeDelete(name); break; case AttributeModificationType.Update: if (valueChanges.Count == 0) { // discard attribute change with no values return; //throw new ArgumentException("The attribute update in the CSEntry provided no values"); } attributeChange = AttributeChange.CreateAttributeUpdate(name, valueChanges); break; case AttributeModificationType.Unconfigured: default: throw new NotSupportedException($"The modification type is not supported {modificationType}"); } csentry.AttributeChanges.Add(attributeChange); }
public AcmaInheritedAttributeChange(AcmaSchemaAttribute attribute, AttributeModificationType modificationType, IList <ValueChange> valueChanges) : base(attribute.Name, modificationType, valueChanges) { }
private void ValidateAttributeChangeType(AttributeModificationType type) { DetachedUtils.ValidateAttributeModificationType(this.ModificationType, type); }
private AttributeChange AvpToAttributeChange(KeyValuePair <string, IList <string> > kvp, AttributeModificationType modificationType) { ExtendedAttributeType type = ActiveConfig.DB.GetAttribute(kvp.Key).Type; switch (modificationType) { case AttributeModificationType.Replace: if (kvp.Value == null) { return(AttributeChangeDetached.CreateAttributeDelete(kvp.Key)); } else { return(AttributeChangeDetached.CreateAttributeReplace(kvp.Key, kvp.Value.Select(t => TypeConverter.ConvertData(t, type)).ToList <object>())); } case AttributeModificationType.Add: return(AttributeChangeDetached.CreateAttributeAdd(kvp.Key, kvp.Value.Select(t => TypeConverter.ConvertData(t, type)).ToList <object>())); case AttributeModificationType.Delete: return(AttributeChangeDetached.CreateAttributeDelete(kvp.Key)); default: case AttributeModificationType.Update: case AttributeModificationType.Unconfigured: throw new InvalidOperationException(); } }
public override bool UpdateField(CSEntryChange csentry, object obj) { if (this.IsReadOnly) { return(false); } if (!csentry.HasAttributeChange(this.MmsAttributeName)) { return(false); } AttributeModificationType modType = csentry.AttributeChanges[this.MmsAttributeName].ModificationType; IList <object> valueAdds = csentry.GetValueAdds <object>(this.MmsAttributeName); IList <object> valueDeletes = csentry.GetValueDeletes <object>(this.MmsAttributeName); valueAdds = this.ConvertToNativeGoogleFormat(valueAdds); valueDeletes = this.ConvertToNativeGoogleFormat(valueDeletes); User user = obj as User; if (user == null) { throw new NotSupportedException("The provided object was not of a 'user' type"); } if (valueAdds.Count == 0 && !this.HasSchemaField(user)) { return(false); } IDictionary <string, object> schema = this.GetOrCreateSchema(user, out bool created); if (modType == AttributeModificationType.Delete) { if (this.HasSchemaField(user)) { schema[this.FieldName] = Utilities.GetNullRepresentation(this.NullValueRepresentation); Logger.WriteLine($"Deleting {this.MmsAttributeName}"); return(true); } return(false); } IList <object> list = null; if (!this.HasSchemaField(user) || modType == AttributeModificationType.Replace || modType == AttributeModificationType.Add) { list = new List <object>(); } else { list = this.GetValuesFromArray(schema[this.FieldName], "value"); list = this.ConvertToNativeGoogleFormat(list); } if (modType == AttributeModificationType.Update) { foreach (object value in valueDeletes) { list.Remove(value); Logger.WriteLine($"Removing value {this.MmsAttributeName} -> {value}"); } } foreach (object value in valueAdds) { list.Add(value); Logger.WriteLine($"Adding value {this.MmsAttributeName} -> {value}"); } if (list.Count > 0) { List <Dictionary <string, object> > items = new List <Dictionary <string, object> >(); foreach (object value in list) { Dictionary <string, object> item = new Dictionary <string, object>(); item.Add("value", value); items.Add(item); } schema[this.FieldName] = items; } else { object value = null; value = Utilities.GetNullRepresentation(this.NullValueRepresentation); Logger.WriteLine($"Set {this.MmsAttributeName} -> {value ?? "<null>"}"); schema[this.FieldName] = value; } return(true); }
public IList<AttributeChange> ApplyChanges(CSEntryChange csentry, SchemaType type, ref object target, bool patch = false) { Logger.WriteLine($"Processing students for course {csentry.DN}"); List<AttributeChange> changes = new List<AttributeChange>(); this.GetStudentChangesFromCSEntryChange(csentry, out CourseStudents studentsToAdd, out CourseStudents studentsToDelete, out CourseStudents reportedAdds, out CourseStudents reportedDeletes, csentry.ObjectModificationType == ObjectModificationType.Replace); HashSet<string> allStudentsToDelete = studentsToDelete.GetAllStudents(); List<Student> allStudentsToAdd = studentsToAdd.ToStudentList(); AttributeModificationType modificationType = csentry.ObjectModificationType == ObjectModificationType.Update ? AttributeModificationType.Update : AttributeModificationType.Add; try { if (csentry.ObjectModificationType != ObjectModificationType.Add && allStudentsToDelete.Count > 0) { try { this.config.ClassroomService.StudentFactory.RemoveStudents(csentry.DN, allStudentsToDelete.ToList(), false); foreach (string student in allStudentsToDelete) { Logger.WriteLine($"Deleted student {student} from course {csentry.DN}", LogLevel.Debug); } if (allStudentsToDelete.Count == 1) { Logger.WriteLine($"Deleted {allStudentsToDelete.Count} student from course {csentry.DN}"); } else { Logger.WriteLine($"Deleted {allStudentsToDelete.Count} students from course {csentry.DN}"); } } catch (AggregateCourseStudentException ex) { Logger.WriteLine("The following students removals failed"); foreach (Exception e in ex.Exceptions) { Logger.WriteException(e); } reportedDeletes.RemoveStudents(ex.FailedStudents); throw; } } if (allStudentsToAdd.Count > 0) { try { this.config.ClassroomService.StudentFactory.AddStudents(csentry.DN, allStudentsToAdd, false); foreach (Student student in allStudentsToAdd) { Logger.WriteLine($"Added student {student.UserId} to {csentry.DN}", LogLevel.Debug); } if (allStudentsToAdd.Count == 1) { Logger.WriteLine($"Added {allStudentsToAdd.Count} student to {csentry.DN}"); } else { Logger.WriteLine($"Added {allStudentsToAdd.Count} students to {csentry.DN}"); } } catch (AggregateCourseStudentException ex) { Logger.WriteLine("The following student additions failed"); foreach (Exception e in ex.Exceptions) { Logger.WriteException(e); } reportedAdds.RemoveStudents(ex.FailedStudents); throw; } } } finally { ApiInterfaceCourseStudents.AddAttributeChange(SchemaConstants.Students, modificationType, reportedDeletes.Students.ToValueChange(ValueModificationType.Delete), changes); ApiInterfaceCourseStudents.AddAttributeChange(SchemaConstants.Students, modificationType, reportedAdds.Students.ToValueChange(ValueModificationType.Add), changes); } Logger.WriteLine($"Processed students for course {csentry.DN}"); return changes; }
private static void AddAttributeChange(string attributeName, AttributeModificationType modificationType, IList<ValueChange> changes, IList<AttributeChange> attributeChanges) { AttributeChange existingChange = attributeChanges.FirstOrDefault(t => t.Name == attributeName); if (modificationType == AttributeModificationType.Delete) { if (existingChange != null) { attributeChanges.Remove(existingChange); } attributeChanges.Add(AttributeChange.CreateAttributeDelete(attributeName)); return; } if (changes == null || changes.Count == 0) { return; } IList<object> adds; switch (modificationType) { case AttributeModificationType.Add: if (existingChange != null) { foreach (ValueChange valueChange in changes.Where(t => t.ModificationType == ValueModificationType.Add)) { existingChange.ValueChanges.Add(valueChange); } } else { adds = changes.Where(t => t.ModificationType == ValueModificationType.Add).Select(t => t.Value).ToList(); if (adds.Count > 0) { attributeChanges.Add(AttributeChange.CreateAttributeAdd(attributeName, adds)); } } break; case AttributeModificationType.Replace: if (existingChange != null) { attributeChanges.Remove(existingChange); } adds = changes.Where(t => t.ModificationType == ValueModificationType.Add).Select(t => t.Value).ToList(); if (adds.Count > 0) { attributeChanges.Add(AttributeChange.CreateAttributeReplace(attributeName, adds)); } break; case AttributeModificationType.Update: if (existingChange != null) { if (existingChange.ModificationType != AttributeModificationType.Update) { throw new InvalidOperationException(); } foreach (ValueChange valueChange in changes) { existingChange.ValueChanges.Add(valueChange); } } else { if (changes.Count > 0) { attributeChanges.Add(AttributeChange.CreateAttributeUpdate(attributeName, changes)); } } break; case AttributeModificationType.Delete: case AttributeModificationType.Unconfigured: default: throw new InvalidOperationException(); } }
private static void CreateAttributeChangeIfInSchemaInternal(this CSEntryChange csentry, SchemaType type, string attributeName, AttributeModificationType modificationType, object value) { if (type.HasAttribute(attributeName)) { csentry.CreateAttributeChange(attributeName, modificationType, value); } }
private static void TestAttributeChangeResults(CSEntryChange csentry, AcmaSchemaAttribute testAttribute, AttributeModificationType expectedModificationType, IList <object> expectedValues) { AttributeChange attributeChange = null; if (csentry.AttributeChanges.Contains(testAttribute.Name)) { attributeChange = csentry.AttributeChanges[testAttribute.Name]; } if (attributeChange == null && expectedModificationType == AttributeModificationType.Unconfigured) { return; } else if (attributeChange == null && expectedModificationType != AttributeModificationType.Unconfigured) { Assert.Fail("An AttributeChange was found where none were expected"); } else if (attributeChange == null) { Assert.Fail("An AttributeChange was expected but not found"); } if (attributeChange.ModificationType != expectedModificationType) { Assert.Fail("The AttributeChange was not of the expected type"); } if (expectedModificationType != AttributeModificationType.Delete) { List <AttributeValue> comparerValues1 = attributeChange.ValueChanges.Select(t => new AttributeValue(testAttribute, t.Value)).ToList(); List <AttributeValue> comparerValues2 = expectedValues.Select(t => new AttributeValue(testAttribute, t)).ToList(); CollectionAssert.AreEquivalent(comparerValues1, comparerValues2); } }
private static void XmlReadAttributeChangeNode(XElement element, CSEntryChange csentry) { string name = null; AttributeModificationType modificationType = AttributeModificationType.Unconfigured; AcmaSchemaAttribute attribute = null; List <ValueChange> valueChanges = null; AttributeChange attributeChange = null; foreach (var child in element.Elements()) { if (child.Name.LocalName == "name") { name = (string)child; attribute = ActiveConfig.DB.GetAttribute(name); } else if (child.Name.LocalName == "modification-type") { string modificationTypeString = (string)child; if (!Enum.TryParse <AttributeModificationType>(modificationTypeString, out modificationType)) { throw new InvalidCastException(string.Format("Cannot convert '{0}' to type {1}", modificationTypeString, typeof(AttributeModificationType).Name)); } } else if (child.Name.LocalName == "value-changes") { if (attribute == null) { throw new ArgumentException("The attribute name must appear first in the list of <attribute-change> elements"); } valueChanges = ImportExportEngine.GetValueChanges(child, attribute.Type); } } switch (modificationType) { case AttributeModificationType.Add: if (valueChanges.Count == 0) { // discard attribute change with no values return; } attributeChange = AttributeChange.CreateAttributeAdd(name, valueChanges.Where(t => t.ModificationType == ValueModificationType.Add).Select(t => t.Value).ToList()); break; case AttributeModificationType.Replace: if (valueChanges.Count == 0) { // discard attribute change with no values return; //throw new ArgumentException("The attribute replace in the CSEntry provided no values"); } attributeChange = AttributeChange.CreateAttributeReplace(name, valueChanges.Where(t => t.ModificationType == ValueModificationType.Add).Select(t => t.Value).ToList()); break; case AttributeModificationType.Delete: attributeChange = AttributeChange.CreateAttributeDelete(name); break; case AttributeModificationType.Update: if (valueChanges.Count == 0) { // discard attribute change with no values return; //throw new ArgumentException("The attribute update in the CSEntry provided no values"); } attributeChange = AttributeChange.CreateAttributeUpdate(name, valueChanges); break; case AttributeModificationType.Unconfigured: default: throw new UnknownOrUnsupportedModificationTypeException(modificationType); } csentry.AttributeChanges.Add(attributeChange); }
/// <summary> /// Initializes a new instance of the UnknownOrUnsupportedModificationTypeException class /// </summary> /// <param name="modificationType">The modification type that was unknown or supported</param> public UnknownOrUnsupportedModificationTypeException(AttributeModificationType modificationType) : base(string.Format("An unknown or unsupported attribute modification type was used: {0}", modificationType.ToSmartString())) { }
/// <summary> /// Creates an AttributeChange of the specified type /// </summary> /// <param name="csentry">The CSEntryChange to add the AttributeChange to</param> /// <param name="attributeName">The name of the attribute</param> /// <param name="modificationType">The type of modification to apply to the attribute</param> /// <param name="values">The values to apply to the modification operation</param> public static void CreateAttributeChange(this CSEntryChange csentry, string attributeName, AttributeModificationType modificationType, IList <object> values) { switch (modificationType) { case AttributeModificationType.Add: if (values.Count > 0) { csentry.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(attributeName, values)); } break; case AttributeModificationType.Delete: csentry.AttributeChanges.Add(AttributeChange.CreateAttributeDelete(attributeName)); break; case AttributeModificationType.Replace: if (values.Count > 0) { csentry.AttributeChanges.Add(AttributeChange.CreateAttributeReplace(attributeName, values)); } else { csentry.AttributeChanges.Add(AttributeChange.CreateAttributeDelete(attributeName)); } break; case AttributeModificationType.Update: throw new NotSupportedException("Update operations are not supported by this method"); case AttributeModificationType.Unconfigured: default: throw new InvalidOperationException("Unknown modification type"); } }
/// <summary> /// Creates an AttributeChange of the specified type /// </summary> /// <param name="csentry">The CSEntryChange to add the AttributeChange to</param> /// <param name="attributeName">The name of the attribute</param> /// <param name="modificationType">The type of modification to apply to the attribute</param> /// <param name="values">The value changes to apply to the modification operation</param> public static void CreateAttributeChange(this CSEntryChange csentry, string attributeName, AttributeModificationType modificationType, IList <ValueChange> values) { switch (modificationType) { case AttributeModificationType.Delete: csentry.AttributeChanges.Add(AttributeChange.CreateAttributeDelete(attributeName)); break; case AttributeModificationType.Add: csentry.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(attributeName, values)); break; case AttributeModificationType.Replace: if (values == null || values.Count == 0) { csentry.AttributeChanges.Add(AttributeChange.CreateAttributeDelete(attributeName)); } else { csentry.AttributeChanges.Add(AttributeChange.CreateAttributeReplace(attributeName, values)); } break; case AttributeModificationType.Update: csentry.AttributeChanges.Add(AttributeChange.CreateAttributeUpdate(attributeName, values)); break; case AttributeModificationType.Unconfigured: default: throw new InvalidOperationException("Unknown modification type"); } }
private static void XmlReadAttributeChangeNode(XElement element, CSEntryChange csentry, bool throwOnMissingAttribute) { string name = null; AttributeModificationType modificationType = AttributeModificationType.Unconfigured; ExtendedAttributeType dataType = ExtendedAttributeType.Undefined; List <ValueChange> valueChanges = null; AttributeChange attributeChange = null; foreach (var child in element.Elements()) { if (child.Name.LocalName == "name") { name = (string)child; } else if (child.Name.LocalName == "modification-type") { string modificationTypeString = (string)child; if (!Enum.TryParse <AttributeModificationType>(modificationTypeString, out modificationType)) { throw new InvalidCastException(string.Format("Cannot convert '{0}' to type {1}", modificationTypeString, typeof(AttributeModificationType).Name)); } } else if (child.Name.LocalName == "data-type") { string dataTypeString = (string)child; if (!Enum.TryParse <ExtendedAttributeType>(dataTypeString, out dataType)) { throw new InvalidCastException(string.Format("Cannot convert '{0}' to type '{1}'", dataTypeString, typeof(ExtendedAttributeType).Name)); } } else if (child.Name.LocalName == "value-changes") { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("The attribute name must appear first in the list of <attribute-change> elements"); } if (dataType == ExtendedAttributeType.Undefined) { if (ActiveConfig.DB == null) { throw new NotConnectedException("The CSEntryChange did not specify a data type in the attribute change, and there was no active connection to the database to resolve it internally"); } else { AcmaSchemaAttribute attribute = null; try { attribute = ActiveConfig.DB.GetAttribute(name); dataType = attribute.Type; } catch (NoSuchAttributeException) { if (throwOnMissingAttribute) { throw; } else { continue; } } } } valueChanges = CSEntryChangeXmlImport.GetValueChanges(child, dataType); } } switch (modificationType) { case AttributeModificationType.Add: if (valueChanges.Count == 0) { // discard attribute change with no values return; } attributeChange = AttributeChange.CreateAttributeAdd(name, valueChanges.Where(t => t.ModificationType == ValueModificationType.Add).Select(t => t.Value).ToList()); break; case AttributeModificationType.Replace: if (valueChanges.Count == 0) { // discard attribute change with no values return; //throw new ArgumentException("The attribute replace in the CSEntry provided no values"); } attributeChange = AttributeChange.CreateAttributeReplace(name, valueChanges.Where(t => t.ModificationType == ValueModificationType.Add).Select(t => t.Value).ToList()); break; case AttributeModificationType.Delete: attributeChange = AttributeChange.CreateAttributeDelete(name); break; case AttributeModificationType.Update: if (valueChanges.Count == 0) { // discard attribute change with no values return; //throw new ArgumentException("The attribute update in the CSEntry provided no values"); } attributeChange = AttributeChange.CreateAttributeUpdate(name, valueChanges); break; case AttributeModificationType.Unconfigured: default: throw new UnknownOrUnsupportedModificationTypeException(modificationType); } csentry.AttributeChanges.Add(attributeChange); }
public IList <AttributeChange> ApplyChanges(CSEntryChange csentry, SchemaType type, ref object target, bool patch = false) { List <AttributeChange> changes = new List <AttributeChange>(); this.GetMemberChangesFromCSEntryChange(csentry, out GroupMembership membershipToAdd, out GroupMembership membershipToDelete, out GroupMembership reportedAdds, out GroupMembership reportedDeletes, out IList <Member> roleChanges, csentry.ObjectModificationType == ObjectModificationType.Replace); HashSet <string> allMembersToDelete = membershipToDelete.GetAllMembers(); List <Member> allMembersToAdd = membershipToAdd.ToMemberList(); AttributeModificationType modificationType = csentry.ObjectModificationType == ObjectModificationType.Update ? AttributeModificationType.Update : AttributeModificationType.Add; try { if (csentry.ObjectModificationType != ObjectModificationType.Add && allMembersToDelete.Count > 0) { try { this.config.GroupsService.MemberFactory.RemoveMembers(csentry.DN, allMembersToDelete.ToList(), false); foreach (string member in allMembersToDelete) { Logger.WriteLine($"Deleted member {member} from group {csentry.DN}", LogLevel.Debug); } if (allMembersToDelete.Count == 1) { Logger.WriteLine($"Deleted {allMembersToDelete.Count} member from group {csentry.DN}"); } else { Logger.WriteLine($"Deleted {allMembersToDelete.Count} members from group {csentry.DN}"); } } catch (AggregateGroupUpdateException ex) { Logger.WriteLine("The following member removals failed"); foreach (Exception e in ex.Exceptions) { Logger.WriteException(e); } reportedDeletes.RemoveMembers(ex.FailedMembers); throw; } } if (csentry.ObjectModificationType != ObjectModificationType.Add && roleChanges?.Count > 0) { try { foreach (Member change in roleChanges) { try { this.config.GroupsService.MemberFactory.ChangeMemberRole(csentry.DN, change); Logger.WriteLine($"Changed member role {change.Email} to {change.Role}", LogLevel.Debug); } catch (GoogleApiException ex) { if (ex.HttpStatusCode == System.Net.HttpStatusCode.NotFound) { throw new UnexpectedDataException($"Member {change.Email} cannot be assigned {change.Role} without being made a member", ex); } throw; } } } catch (AggregateGroupUpdateException ex) { Logger.WriteLine("The following member role changes failed"); foreach (Exception e in ex.Exceptions) { Logger.WriteException(e); } throw; } } if (allMembersToAdd.Count > 0) { try { this.config.GroupsService.MemberFactory.AddMembers(csentry.DN, this.NormalizeMembershipList(allMembersToAdd), false); foreach (Member member in allMembersToAdd) { Logger.WriteLine($"Added {member.Role} {member.Email}", LogLevel.Debug); } if (allMembersToAdd.Count == 1) { Logger.WriteLine($"Added {allMembersToAdd.Count} member"); } else { Logger.WriteLine($"Added {allMembersToAdd.Count} members"); } } catch (AggregateGroupUpdateException ex) { Logger.WriteLine("The following member additions failed"); foreach (Exception e in ex.Exceptions) { Logger.WriteException(e); } reportedAdds.RemoveMembers(ex.FailedMembers); throw; } } } finally { ApiInterfaceGroupMembership.AddAttributeChange(this.config.GroupMemberAttributeName, modificationType, reportedDeletes.Members.ToValueChange(ValueModificationType.Delete), changes); ApiInterfaceGroupMembership.AddAttributeChange("externalMember", modificationType, reportedDeletes.ExternalMembers.ToValueChange(ValueModificationType.Delete), changes); ApiInterfaceGroupMembership.AddAttributeChange(this.config.GroupManagerAttributeName, modificationType, reportedDeletes.Managers.ToValueChange(ValueModificationType.Delete), changes); ApiInterfaceGroupMembership.AddAttributeChange("externalManager", modificationType, reportedDeletes.ExternalManagers.ToValueChange(ValueModificationType.Delete), changes); ApiInterfaceGroupMembership.AddAttributeChange(this.config.GroupOwnerAttributeName, modificationType, reportedDeletes.Owners.ToValueChange(ValueModificationType.Delete), changes); ApiInterfaceGroupMembership.AddAttributeChange("externalOwner", modificationType, reportedDeletes.ExternalOwners.ToValueChange(ValueModificationType.Delete), changes); ApiInterfaceGroupMembership.AddAttributeChange(this.config.GroupMemberAttributeName, modificationType, reportedAdds.Members.ToValueChange(ValueModificationType.Add), changes); ApiInterfaceGroupMembership.AddAttributeChange("externalMember", modificationType, reportedAdds.ExternalMembers.ToValueChange(ValueModificationType.Add), changes); ApiInterfaceGroupMembership.AddAttributeChange(this.config.GroupManagerAttributeName, modificationType, reportedAdds.Managers.ToValueChange(ValueModificationType.Add), changes); ApiInterfaceGroupMembership.AddAttributeChange("externalManager", modificationType, reportedAdds.ExternalManagers.ToValueChange(ValueModificationType.Add), changes); ApiInterfaceGroupMembership.AddAttributeChange(this.config.GroupOwnerAttributeName, modificationType, reportedAdds.Owners.ToValueChange(ValueModificationType.Add), changes); ApiInterfaceGroupMembership.AddAttributeChange("externalOwner", modificationType, reportedAdds.ExternalOwners.ToValueChange(ValueModificationType.Add), changes); } return(changes); }