Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Commit 3db9024

Browse files
committed
Fix area and iteration path validation
1 parent d75befa commit 3db9024

File tree

3 files changed

+39
-14
lines changed

3 files changed

+39
-14
lines changed

src/ApiService/ApiService/OneFuzzTypes/Enums.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public enum ErrorCode {
4848
ADO_VALIDATION_UNEXPECTED_ERROR = 491,
4949
ADO_VALIDATION_MISSING_PAT_SCOPES = 492,
5050
ADO_WORKITEM_PROCESSING_DISABLED = 494,
51+
ADO_VALIDATION_INVALID_PATH = 495,
5152
// NB: if you update this enum, also update enums.py
5253
}
5354

src/ApiService/ApiService/onefuzzlib/notifications/Ado.cs

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,33 @@ private static bool IsTransient(Exception e) {
8989
return errorCodes.Any(errorStr.Contains);
9090
}
9191

92+
private static async Async.Task<OneFuzzResultVoid> ValidatePath(string project, string path, WorkItemTrackingHttpClient client) {
93+
var pathParts = path.Split('\\');
94+
if (pathParts[0] == project) {
95+
pathParts = pathParts[1..];
96+
}
97+
98+
var current = await client.GetClassificationNodeAsync(project, TreeStructureGroup.Areas);
99+
if (current == null) {
100+
return OneFuzzResultVoid.Error(ErrorCode.ADO_VALIDATION_INVALID_PATH, new string[] {
101+
$"Path {path} is invalid. {project} is not a valid project",
102+
});
103+
}
104+
105+
foreach (var part in pathParts) {
106+
var child = current.Children.FirstOrDefault(x => x.Name == part);
107+
if (child == null) {
108+
return OneFuzzResultVoid.Error(ErrorCode.ADO_VALIDATION_INVALID_PATH, new string[] {
109+
$"Path {path} is invalid. {part} is not a valid child of {current.Name}",
110+
});
111+
}
112+
113+
current = child;
114+
}
115+
116+
return OneFuzzResultVoid.Ok;
117+
}
118+
92119
public static async Async.Task<OneFuzzResultVoid> Validate(AdoTemplate config) {
93120
// Validate PAT is valid for the base url
94121
VssConnection connection;
@@ -164,7 +191,10 @@ await policy.ExecuteAsync(async () => {
164191
// Validate AreaPath exists
165192
try {
166193
if (config.AdoFields.TryGetValue("System.AreaPath", out var areaPathString)) {
167-
_ = await witClient.GetClassificationNodeAsync(config.Project, TreeStructureGroup.Areas, areaPathString);
194+
var validateAreaPath = await ValidatePath(config.Project, areaPathString, witClient);
195+
if (!validateAreaPath.IsOk) {
196+
return validateAreaPath;
197+
}
168198
}
169199
} catch (VssUnauthorizedException e) {
170200
return OneFuzzResultVoid.Error(ErrorCode.ADO_VALIDATION_INVALID_PAT, new string[] {
@@ -176,22 +206,20 @@ await policy.ExecuteAsync(async () => {
176206
$"[AreaPath] Failed to connect to {config.BaseUrl} using the provided token",
177207
$"Exception: {e}"
178208
});
179-
} catch (VssServiceException e) {
180-
return OneFuzzResultVoid.Error(ErrorCode.ADO_VALIDATION_UNEXPECTED_ERROR, new string[] {
181-
"AreaPath error",
182-
$"Exception: {e}",
183-
});
184209
} catch (Exception e) {
185210
return OneFuzzResultVoid.Error(ErrorCode.ADO_VALIDATION_UNEXPECTED_ERROR, new string[] {
186-
"Generic AreaPath error",
211+
"Failed to query and validate against the classification nodes for this project",
187212
$"Exception: {e}",
188213
});
189214
}
190215

191216
// Validate IterationPath exists
192217
try {
193218
if (config.AdoFields.TryGetValue("System.IterationPath", out var iterationPathString)) {
194-
_ = await witClient.GetClassificationNodeAsync(config.Project, TreeStructureGroup.Areas, iterationPathString);
219+
var validateIterationPath = await ValidatePath(config.Project, iterationPathString, witClient);
220+
if (!validateIterationPath.IsOk) {
221+
return validateIterationPath;
222+
}
195223
}
196224
} catch (VssUnauthorizedException e) {
197225
return OneFuzzResultVoid.Error(ErrorCode.ADO_VALIDATION_INVALID_PAT, new string[] {
@@ -203,14 +231,9 @@ await policy.ExecuteAsync(async () => {
203231
$"[IterationPath] Failed to connect to {config.BaseUrl} using the provided token",
204232
$"Exception: {e}"
205233
});
206-
} catch (VssServiceException e) {
207-
return OneFuzzResultVoid.Error(ErrorCode.ADO_VALIDATION_UNEXPECTED_ERROR, new string[] {
208-
"IterationPath error",
209-
$"Exception: {e}",
210-
});
211234
} catch (Exception e) {
212235
return OneFuzzResultVoid.Error(ErrorCode.ADO_VALIDATION_UNEXPECTED_ERROR, new string[] {
213-
"Generic IterationPath error",
236+
"Failed to query and validate against the classification nodes for this project",
214237
$"Exception: {e}",
215238
});
216239
}

src/pytypes/onefuzztypes/enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ class ErrorCode(Enum):
302302
ADO_VALIDATION_UNEXPECTED_HTTP_EXCEPTION = 490
303303
ADO_VALIDATION_UNEXPECTED_ERROR = 491
304304
ADO_VALIDATION_MISSING_PAT_SCOPES = 492
305+
ADO_VALIDATION_INVALID_PATH = 495
305306
# NB: if you update this enum, also update Enums.cs
306307

307308

0 commit comments

Comments
 (0)