Skip to content

Commit

Permalink
Fixes an issue where adding members during group creation can fail wi…
Browse files Browse the repository at this point in the history
…th message 'Resource Not Found: groupKey [404]' (#7)

Fixes an issue where an Exported-change-not-reimported error occurs after deleting the last alias (#8)
  • Loading branch information
ryannewington committed Sep 6, 2016
1 parent 2fd7d6b commit a01d9b9
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/Lithnet.GoogleApps.MA.Setup/Product.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<Product Id="*"
Name="Lithnet GoogleApps Management Agent"
Language="1033"
Version="1.1.6090"
Version="1.1.6093"
Manufacturer="Lithnet"
UpgradeCode="3410d571b358426281edb2990ae57cae" >

Expand Down
79 changes: 78 additions & 1 deletion src/Lithnet.GoogleApps.MA.UnitTests/GroupTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ public void Update()
}
}
}

[TestMethod]
public void Delete()
{
Expand Down Expand Up @@ -628,6 +628,80 @@ public void ReplaceAliases()

}

[TestMethod]
public void AddGroupWithMembers()
{
string dn = $"{Guid.NewGuid()}@{UnitTestControl.TestParameters.Domain}";

CSEntryChange cs = CSEntryChange.Create();
cs.ObjectModificationType = ObjectModificationType.Add;
cs.DN = dn;
cs.ObjectType = SchemaConstants.Group;
cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("name", Guid.NewGuid().ToString()));

Group group1;
Group group2;
string member1 = this.CreateGroup(out group1);
string member2 = this.CreateGroup(out group2);
string member3 = $"{Guid.NewGuid()}@{UnitTestControl.TestParameters.Domain}";

ManagedObjects.User e = new ManagedObjects.User
{
PrimaryEmail = member3,
Password = Guid.NewGuid().ToString(),
Name =
{
GivenName = "test",
FamilyName = "test"
}
};

e = UserRequestFactory.Add(e);

cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("member", new List<object>() { member1, member2 }));
cs.AttributeChanges.Add(AttributeChange.CreateAttributeAdd("owner", new List<object>() { member3 }));

CSEntryChangeResult result = null;

try
{
result = ExportProcessor.PutCSEntryChange(cs, UnitTestControl.Schema.GetSchema().Types[SchemaConstants.Group]);

if (result.ErrorCode != MAExportError.Success)
{
Assert.Fail(result.ErrorName);
}

System.Threading.Thread.Sleep(10000);

CollectionAssert.AreEquivalent(new string[] { member1, member2 }, GroupMemberRequestFactory.GetMembership(cs.DN).Members.ToArray());
}
finally
{
string id = result?.AnchorAttributes.FirstOrDefault()?.GetValueAdd<string>();

if (id != null)
{
GroupRequestFactory.Delete(id);
}

if (group1?.Id != null)
{
GroupRequestFactory.Delete(group1.Id);
}

if (group2?.Id != null)
{
GroupRequestFactory.Delete(group2.Id);
}

if (e?.Id != null)
{
UserRequestFactory.Delete(e.Id);
}
}
}

[TestMethod]
public void AddMembers()
{
Expand Down Expand Up @@ -668,6 +742,9 @@ public void AddMembers()
{
GroupRequestFactory.Delete(id);
}

GroupRequestFactory.Delete(member1);
GroupRequestFactory.Delete(member2);
}

}
Expand Down
5 changes: 4 additions & 1 deletion src/Lithnet.GoogleApps.MA/ApiInterfaces/ApiInterfaceGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ public IList<AttributeChange> ApplyChanges(CSEntryChange csentry, SchemaType typ
{
result.Group = GroupRequestFactory.Add(group.Group);
group.Group = result.Group;

// Group membership operations fail on newly created groups if processed too quickly
System.Threading.Thread.Sleep(1000);
}
else if (csentry.ObjectModificationType == ObjectModificationType.Replace || csentry.ObjectModificationType == ObjectModificationType.Update)
{
Expand All @@ -111,7 +114,7 @@ public IList<AttributeChange> ApplyChanges(CSEntryChange csentry, SchemaType typ

changes.AddRange(this.GetLocalChanges(csentry.DN, csentry.ObjectModificationType, type, result));
}

foreach (IApiInterface i in ApiInterfaceGroup.internalInterfaces)
{
foreach (AttributeChange c in i.ApplyChanges(csentry, type, ref target, patch))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ public IList<AttributeChange> GetChanges(string dn, ObjectModificationType modTy
return attributeChanges;
}

private static void GetGroupAliasChanges(CSEntryChange csentry, Group group, out IList<string> aliasAdds, out IList<string> aliasDeletes)
private static void GetGroupAliasChanges(CSEntryChange csentry, out IList<string> aliasAdds, out IList<string> aliasDeletes, out bool deletingAll)
{
aliasAdds = new List<string>();
aliasDeletes = new List<string>();
AttributeChange change = csentry.AttributeChanges.FirstOrDefault(t => t.Name == "aliases");
deletingAll = false;

if (csentry.ObjectModificationType == ObjectModificationType.Replace)
{
Expand Down Expand Up @@ -87,6 +88,8 @@ private static void GetGroupAliasChanges(CSEntryChange csentry, Group group, out
{
aliasDeletes.Add(alias);
}

deletingAll = true;
break;

case AttributeModificationType.Replace:
Expand All @@ -113,8 +116,9 @@ private static AttributeChange ApplyGroupAliasChanges(CSEntryChange csentry, Gro
{
IList<string> aliasAdds;
IList<string> aliasDeletes;
bool deletingAll;

ApiInterfaceGroupAliases.GetGroupAliasChanges(csentry, group, out aliasAdds, out aliasDeletes);
ApiInterfaceGroupAliases.GetGroupAliasChanges(csentry, out aliasAdds, out aliasDeletes, out deletingAll);

if (aliasAdds.Count == 0 && aliasDeletes.Count == 0)
{
Expand Down Expand Up @@ -157,7 +161,14 @@ private static AttributeChange ApplyGroupAliasChanges(CSEntryChange csentry, Gro
{
if (csentry.ObjectModificationType == ObjectModificationType.Update)
{
change = AttributeChange.CreateAttributeUpdate("aliases", valueChanges);
if (deletingAll && valueChanges.Count == aliasDeletes?.Count)
{
change = AttributeChange.CreateAttributeDelete("aliases");
}
else
{
change = AttributeChange.CreateAttributeUpdate("aliases", valueChanges);
}
}
else
{
Expand All @@ -169,5 +180,4 @@ private static AttributeChange ApplyGroupAliasChanges(CSEntryChange csentry, Gro
return change;
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ public IList<AttributeChange> ApplyChanges(CSEntryChange csentry, SchemaType typ
}
catch (AggregateGroupUpdateException ex)
{
Logger.WriteLine("The following member removals failed");
foreach (Exception e in ex.Exceptions)
{
Logger.WriteException(e);
}

ApiInterfaceGroupMembership.AddAttributeChange("member", modificationType, membershipToDelete.Members.Except(ex.FailedMembers).ToValueChange(ValueModificationType.Delete), changes);
ApiInterfaceGroupMembership.AddAttributeChange("externalMember", modificationType, membershipToDelete.ExternalMembers.Except(ex.FailedMembers).ToValueChange(ValueModificationType.Delete), changes);
ApiInterfaceGroupMembership.AddAttributeChange("manager", modificationType, membershipToDelete.Managers.Except(ex.FailedMembers).ToValueChange(ValueModificationType.Delete), changes);
Expand Down Expand Up @@ -94,6 +100,12 @@ public IList<AttributeChange> ApplyChanges(CSEntryChange csentry, SchemaType typ
}
catch (AggregateGroupUpdateException ex)
{
Logger.WriteLine("The following member additions failed");
foreach(Exception e in ex.Exceptions)
{
Logger.WriteException(e);
}

ApiInterfaceGroupMembership.AddAttributeChange("member", modificationType, membershipToAdd.Members.Except(ex.FailedMembers).ToValueChange(ValueModificationType.Add), changes);
ApiInterfaceGroupMembership.AddAttributeChange("externalMember", modificationType, membershipToAdd.ExternalMembers.Except(ex.FailedMembers).ToValueChange(ValueModificationType.Add), changes);
ApiInterfaceGroupMembership.AddAttributeChange("manager", modificationType, membershipToAdd.Managers.Except(ex.FailedMembers).ToValueChange(ValueModificationType.Add), changes);
Expand Down Expand Up @@ -228,7 +240,7 @@ private static void GetMemberChangesFromCSEntryChange(CSEntryChange csentry, out
{
adds = new GroupMembership();
deletes = new GroupMembership();
GroupMembership existingGroupMembership = null;
GroupMembership existingGroupMembership;

if (ApiInterfaceGroupMembership.ExistingMembershipRequiredForUpdate(csentry) | replacing)
{
Expand Down
19 changes: 15 additions & 4 deletions src/Lithnet.GoogleApps.MA/ApiInterfaces/ApiInterfaceUserAliases.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ public IList<AttributeChange> GetChanges(string dn, ObjectModificationType modTy
return attributeChanges;
}

private static void GetUserAliasChanges(CSEntryChange csentry, User user, out IList<string> aliasAdds, out IList<string> aliasDeletes)
private static void GetUserAliasChanges(CSEntryChange csentry, out IList<string> aliasAdds, out IList<string> aliasDeletes, out bool deletingAll)
{
aliasAdds = new List<string>();
aliasDeletes = new List<string>();
AttributeChange change = csentry.AttributeChanges.FirstOrDefault(t => t.Name == "aliases");
deletingAll = false;

if (csentry.ObjectModificationType == ObjectModificationType.Replace)
{
Expand Down Expand Up @@ -79,6 +80,8 @@ private static void GetUserAliasChanges(CSEntryChange csentry, User user, out IL
{
aliasDeletes.Add(alias);
}

deletingAll = true;
break;

case AttributeModificationType.Replace:
Expand All @@ -105,8 +108,9 @@ private static AttributeChange ApplyUserAliasChanges(CSEntryChange csentry, User
{
IList<string> aliasAdds;
IList<string> aliasDeletes;
bool deletingAll;

ApiInterfaceUserAliases.GetUserAliasChanges(csentry, user, out aliasAdds, out aliasDeletes);
ApiInterfaceUserAliases.GetUserAliasChanges(csentry, out aliasAdds, out aliasDeletes, out deletingAll);

if (aliasAdds.Count == 0 && aliasDeletes.Count == 0)
{
Expand Down Expand Up @@ -165,7 +169,14 @@ private static AttributeChange ApplyUserAliasChanges(CSEntryChange csentry, User
{
if (csentry.ObjectModificationType == ObjectModificationType.Update)
{
change = AttributeChange.CreateAttributeUpdate("aliases", valueChanges);
if (deletingAll && valueChanges.Count == aliasDeletes?.Count)
{
change = AttributeChange.CreateAttributeDelete("aliases");
}
else
{
change = AttributeChange.CreateAttributeUpdate("aliases", valueChanges);
}
}
else
{
Expand All @@ -177,4 +188,4 @@ private static AttributeChange ApplyUserAliasChanges(CSEntryChange csentry, User
return change;
}
}
}
}
1 change: 1 addition & 0 deletions src/Lithnet.GoogleApps.MA/Lithnet.GoogleApps.MA.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="ClassDiagram1.cd" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
Expand Down

0 comments on commit a01d9b9

Please sign in to comment.