Skip to content

Commit

Permalink
[preview] Delayed Get Service for Security on the UserMappign Enriche…
Browse files Browse the repository at this point in the history
…r. (#1976)
  • Loading branch information
MrHinsh authored Mar 12, 2024
1 parent 714be9b commit f2ff9c2
Show file tree
Hide file tree
Showing 5 changed files with 259 additions and 261 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,30 @@ namespace MigrationTools.ProcessorEnrichers.Tests
public class TfsNodeStructureTests
{
private ServiceProvider _services;
private TfsNodeStructure _structure;

[TestInitialize]
public void Setup()
{
_services = ServiceProviderHelper.GetServices();
_structure = _services.GetRequiredService<TfsNodeStructure>();
_structure.ApplySettings(new TfsNodeStructureSettings
{
FoundNodes = new Dictionary<string, bool>(),
SourceProjectName = "SourceServer",
TargetProjectName = "TargetServer",
});
_structure.Configure(new TfsNodeStructureOptions
{
AreaMaps = new Dictionary<string, string>
{
{ "SourceServer", "TargetServer" }
},
IterationMaps = new Dictionary<string, string>
{
{ "SourceServer", "TargetServer" }
},
});
}

[TestMethod(), TestCategory("L0"), TestCategory("AzureDevOps.ObjectModel")]
Expand Down Expand Up @@ -46,5 +65,168 @@ public void GetTfsNodeStructure_WithDifferentAreaPath()
Assert.AreEqual(newNodeName, @"TargetProject\test\PUL");

}

[TestMethod, TestCategory("L0")]
public void TestFixAreaPath_WhenNoAreaPathOrIterationPath_DoesntChangeQuery()
{
string WIQLQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";

string targetWIQLQueryBit = _structure.FixAreaPathAndIterationPathForTargetQuery(WIQLQueryBit, "SourceServer", "TargetServer", null);

Assert.AreEqual(WIQLQueryBit, targetWIQLQueryBit);
}


[TestMethod, TestCategory("L0")]
public void TestFixAreaPath_WhenAreaPathInQuery_ChangesQuery()
{
string WIQLQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] = 'SourceServer\Area\Path1' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";
string expectTargetQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] = 'TargetServer\Area\Path1' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";

string targetWIQLQueryBit = _structure.FixAreaPathAndIterationPathForTargetQuery(WIQLQueryBit, "SourceServer", "TargetServer", null);

Assert.AreEqual(expectTargetQueryBit, targetWIQLQueryBit);
}

[TestMethod, TestCategory("L1")]
public void TestFixAreaPath_WhenAreaPathInQuery_WithPrefixProjectToNodesEnabled_ChangesQuery()
{
var nodeStructure = _services.GetRequiredService<TfsNodeStructure>();

// For this test we use the prefixing of the project node and no remapping rule


nodeStructure.Configure(new TfsNodeStructureOptions
{
AreaMaps = new Dictionary<string, string>()
{
{ "^SourceServer\\\\(.*)" , "TargetServer\\SourceServer\\$1" }
},
IterationMaps = new Dictionary<string, string>(){
{ "^SourceServer\\\\(.*)" , "TargetServer\\SourceServer\\$1" }
},
});

string WIQLQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] = 'SourceServer\Area\Path1' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";
string expectTargetQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] = 'TargetServer\SourceServer\Area\Path1' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";

string targetWIQLQuery = _structure.FixAreaPathAndIterationPathForTargetQuery(WIQLQueryBit, "SourceServer", "TargetServer", null);

Assert.AreEqual(expectTargetQueryBit, targetWIQLQuery);
}

[TestMethod, TestCategory("L1")]
public void TestFixAreaPath_WhenAreaPathInQuery_WithPrefixProjectToNodesDisabled_SupportsWhitespaces()
{
var nodeStructure = _services.GetRequiredService<TfsNodeStructure>();

nodeStructure.ApplySettings(new TfsNodeStructureSettings
{
FoundNodes = new Dictionary<string, bool>(),
SourceProjectName = "Source Project",
TargetProjectName = "Target Project",
});

// For this test we use no remapping rule
nodeStructure.Configure(new TfsNodeStructureOptions
{
AreaMaps = new Dictionary<string, string>(),
IterationMaps = new Dictionary<string, string>(),
});

string WIQLQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] = 'Source Project\Area\Path1' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";
string expectTargetQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] = 'Target Project\Area\Path1' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";

string targetWIQLQueryBit = _structure.FixAreaPathAndIterationPathForTargetQuery(WIQLQueryBit, "Source Project", "Target Project", null);

Assert.AreEqual(expectTargetQueryBit, targetWIQLQueryBit);
}

[TestMethod, TestCategory("L1")]
public void TestFixAreaPath_WhenAreaPathInQuery_WithPrefixProjectToNodesEnabled_SupportsWhitespaces()
{
var nodeStructure = _services.GetRequiredService<TfsNodeStructure>();

nodeStructure.ApplySettings(new TfsNodeStructureSettings
{
FoundNodes = new Dictionary<string, bool>(),
SourceProjectName = "Source Project",
TargetProjectName = "Target Project",
});

// For this test we use the prefixing of the project node and no remapping rules
nodeStructure.Configure(new TfsNodeStructureOptions
{
AreaMaps = new Dictionary<string, string>()
{
{ "^Source Project\\\\(.*)" , "Target Project\\Source Project\\$1" }
},
IterationMaps = new Dictionary<string, string>(){
{ "^Source Project\\\\(.*)" , "Target Project\\Source Project\\$1" }
},
});

var WIQLQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] = 'Source Project\Area\Path1' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";
var expectTargetQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] = 'Target Project\Source Project\Area\Path1' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";

var targetWIQLQueryBit = _structure.FixAreaPathAndIterationPathForTargetQuery(WIQLQueryBit, "Source Project", "Target Project", null);

Assert.AreEqual(expectTargetQueryBit, targetWIQLQueryBit);
}

[TestMethod, TestCategory("L0")]
public void TestFixAreaPath_WhenMultipleAreaPathInQuery_ChangesQuery()
{
string WIQLQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] = 'SourceServer\Area\Path1' OR [System.AreaPath] = 'SourceServer\Area\Path2' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";
string expectTargetQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.AreaPath] = 'TargetServer\Area\Path1' OR [System.AreaPath] = 'TargetServer\Area\Path2' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";

string targetWIQLQueryBit = _structure.FixAreaPathAndIterationPathForTargetQuery(WIQLQueryBit, "SourceServer", "TargetServer", null);

Assert.AreEqual(expectTargetQueryBit, targetWIQLQueryBit);
}

[TestMethod, TestCategory("L0")]
public void TestFixAreaPath_WhenAreaPathAtEndOfQuery_ChangesQuery()
{
string WIQLQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan') AND [System.AreaPath] = 'SourceServer\Area\Path1'";
string expectTargetQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan') AND [System.AreaPath] = 'TargetServer\Area\Path1'";

string targetWIQLQueryBit = _structure.FixAreaPathAndIterationPathForTargetQuery(WIQLQueryBit, "SourceServer", "TargetServer", null);

Assert.AreEqual(expectTargetQueryBit, targetWIQLQueryBit);
}

[TestMethod, TestCategory("L0")]
public void TestFixIterationPath_WhenInQuery_ChangesQuery()
{
string WIQLQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.IterationPath] = 'SourceServer\Iteration\Path1' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";
string expectTargetQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.IterationPath] = 'TargetServer\Iteration\Path1' AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";

string targetWIQLQueryBit = _structure.FixAreaPathAndIterationPathForTargetQuery(WIQLQueryBit, "SourceServer", "TargetServer", null);

Assert.AreEqual(expectTargetQueryBit, targetWIQLQueryBit);
}

[TestMethod, TestCategory("L0")]
public void TestFixAreaPathAndIteration_WhenMultipleOccuranceInQuery_ChangesQuery()
{
string WIQLQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND ([System.AreaPath] = 'SourceServer\Area\Path1' OR [System.AreaPath] = 'SourceServer\Area\Path2') AND ([System.IterationPath] = 'SourceServer\Iteration\Path1' OR [System.IterationPath] = 'SourceServer\Iteration\Path2') AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";
string expectTargetQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND ([System.AreaPath] = 'TargetServer\Area\Path1' OR [System.AreaPath] = 'TargetServer\Area\Path2') AND ([System.IterationPath] = 'TargetServer\Iteration\Path1' OR [System.IterationPath] = 'TargetServer\Iteration\Path2') AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";

string targetWIQLQueryBit = _structure.FixAreaPathAndIterationPathForTargetQuery(WIQLQueryBit, "SourceServer", "TargetServer", null);

Assert.AreEqual(expectTargetQueryBit, targetWIQLQueryBit);
}

[TestMethod, TestCategory("L0")]
public void TestFixAreaPathAndIteration_WhenMultipleOccuranceWithMixtureOrEqualAndUnderOperatorsInQuery_ChangesQuery()
{
string WIQLQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND ([System.AreaPath] = 'SourceServer\Area\Path1' OR [System.AreaPath] UNDER 'SourceServer\Area\Path2') AND ([System.IterationPath] UNDER 'SourceServer\Iteration\Path1' OR [System.IterationPath] = 'SourceServer\Iteration\Path2') AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";
string expectTargetQueryBit = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND ([System.AreaPath] = 'TargetServer\Area\Path1' OR [System.AreaPath] UNDER 'TargetServer\Area\Path2') AND ([System.IterationPath] UNDER 'TargetServer\Iteration\Path1' OR [System.IterationPath] = 'TargetServer\Iteration\Path2') AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')";

string targetWIQLQueryBit = _structure.FixAreaPathAndIterationPathForTargetQuery(WIQLQueryBit, "SourceServer", "TargetServer", null);

Assert.AreEqual(expectTargetQueryBit, targetWIQLQueryBit);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -692,5 +692,56 @@ public string GetMappingForMissingItem(NodeStructureItem missingItem)
return null;
}

private const string RegexPatternForAreaAndIterationPathsFix = "\\[?(?<key>System.AreaPath|System.IterationPath)+\\]?[^']*'(?<value>[^']*(?:''.[^']*)*)'";

public string FixAreaPathAndIterationPathForTargetQuery(string sourceWIQLQuery, string sourceProject, string targetProject, ILogger? contextLog)
{

string targetWIQLQuery = sourceWIQLQuery;

if (string.IsNullOrWhiteSpace(targetWIQLQuery))
{
return targetWIQLQuery;
}

var matches = Regex.Matches(targetWIQLQuery, RegexPatternForAreaAndIterationPathsFix);


if (string.IsNullOrWhiteSpace(sourceProject)
|| string.IsNullOrWhiteSpace(targetProject)
|| sourceProject == targetProject)
{
return targetWIQLQuery;
}

foreach (Match match in matches)
{
var value = match.Groups["value"].Value;
if (string.IsNullOrWhiteSpace(value) || !value.StartsWith(sourceProject))
continue;

var fieldType = match.Groups["key"].Value;
TfsNodeStructureType structureType;
switch (fieldType)
{
case "System.AreaPath":
structureType = TfsNodeStructureType.Area;
break;
case "System.IterationPath":
structureType = TfsNodeStructureType.Iteration;
break;
default:
throw new InvalidOperationException($"Field type {fieldType} is not supported for query remapping.");
}

var remappedPath = GetNewNodeName(value, structureType);
targetWIQLQuery = targetWIQLQuery.Replace(value, remappedPath);
}

contextLog?.Information("[FilterWorkItemsThatAlreadyExistInTarget] is enabled. Source project {sourceProject} is replaced with target project {targetProject} on the WIQLQueryBit which resulted into this target WIQLQueryBit \"{targetWIQLQueryBit}\" .", sourceProject, targetProject, targetWIQLQuery);

return targetWIQLQuery;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,32 @@ public class TfsUserMappingEnricher : WorkItemProcessorEnricher
IGroupSecurityService _gssSourse;
private IGroupSecurityService _gssTarget;

private IGroupSecurityService GssSource
{ get {
if (_gssSourse == null)
{
_gssSourse = Engine.Source.GetService<IGroupSecurityService>();
}
return _gssSourse;
} }

private IGroupSecurityService GssTarget
{
get
{
if (_gssTarget == null)
{
_gssTarget = Engine.Target.GetService<IGroupSecurityService>();
}
return _gssTarget;
}
}

public TfsUserMappingEnricherOptions Options { get; private set; }

public TfsUserMappingEnricher(IServiceProvider services, ILogger<TfsUserMappingEnricher> logger) : base(services, logger)
{
Engine = services.GetRequiredService<IMigrationEngine>();
_gssSourse = Engine.Source.GetService<IGroupSecurityService>();
_gssTarget = Engine.Target.GetService<IGroupSecurityService>();
}

public override void Configure(IProcessorEnricherOptions options)
Expand Down Expand Up @@ -154,9 +173,9 @@ public List<IdentityMapData> GetUsersInSourceMappedToTarget()
Log.LogDebug("TfsUserMappingEnricher::GetUsersInSourceMappedToTarget");
if (Options.Enabled)
{
var sourceUsers = GetUsersListFromServer(_gssSourse);
var sourceUsers = GetUsersListFromServer(GssSource);
Log.LogDebug($"TfsUserMappingEnricher::GetUsersInSourceMappedToTarget [SourceUsersCount|{sourceUsers.Count}]");
var targetUsers = GetUsersListFromServer(_gssTarget);
var targetUsers = GetUsersListFromServer(GssTarget);
Log.LogDebug($"TfsUserMappingEnricher::GetUsersInSourceMappedToTarget [targetUsersCount|{targetUsers.Count}]");
return sourceUsers.Select(sUser => new IdentityMapData { Source = sUser, target = targetUsers.SingleOrDefault(tUser => tUser.FriendlyName == sUser.FriendlyName) }).ToList();
}
Expand Down
Loading

0 comments on commit f2ff9c2

Please sign in to comment.