Skip to content

Commit

Permalink
Catch exception when trying to convert permissions table to three col…
Browse files Browse the repository at this point in the history
…umns (#298)

* Catch exception when trying to convert permissions table to three columns

* Move Regex to static variable

* Correctly extract permissions table when the HTML metadata spans more than one line
  • Loading branch information
millicentachieng authored Dec 3, 2024
1 parent a34a80d commit 7d8ebd4
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 25 deletions.
2 changes: 1 addition & 1 deletion ApiDoctor.Console/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static class PermissionsConstants
" For details about delegated and application permissions, see [Permission types](/graph/permissions-overview#permission-types). To learn more about these permissions, see the [permissions reference](/graph/permissions-reference).";
public const string MultipleTableBoilerPlateText = "The following tables show the least privileged permission or permissions required to call this API on each supported resource type." +
" Follow [best practices](/graph/permissions-overview#best-practices-for-using-microsoft-graph-permissions) to request least privileged permissions." +
" For details about delegated and application permissions, see [Permission types](/graph/permissions-overview#permission-types). To learn more about these permissions, see the [permissions reference](/graph/permissions-reference).";
" For details about delegated and application permissions, see [Permission types](/graph/permissions-overview#permission-types). To learn more about these permissions, see the [permissions reference](/graph/permissions-reference).";
}
public static readonly Regex FunctionParameterRegex = new(@"(?<=\=)[^)]+(?=\))", RegexOptions.Compiled, TimeSpan.FromSeconds(5));
public static readonly Regex QueryOptionSegementRegex = new(@"(\$.*)", RegexOptions.Compiled, TimeSpan.FromSeconds(5));
Expand Down
61 changes: 37 additions & 24 deletions ApiDoctor.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2647,7 +2647,7 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
bool finishedParsing = false, isBootstrapped = false, ignorePermissionTableUpdate = false,
foundAllPermissionTables = false, mergePermissions = false, hasBoilerplateText = false;
int insertionStartLine = -1, insertionEndLine = -1, httpRequestStartLine = -1, httpRequestEndLine = -1, boilerplateStartLine = -1,
boilerplateEndLine = -1, permissionsHeaderIndex = -1, codeBlockAnnotationEndLine = -1, permissionsBlockLineCount = -1;
boilerplateEndLine = -1, permissionsHeaderIndex = -1, codeBlockAnnotationEndLine = -1, permissionsBlockLineCount = -1, permissionsTableStartLine = -1;
string[] requestUrlsForPermissions = null;
for (var currentIndex = 0; currentIndex < originalFileContents.Length && !finishedParsing; currentIndex++)
{
Expand All @@ -2662,8 +2662,8 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
}
break;
case PermissionsInsertionState.FindInsertionStartLine:
if (foundPermissionTablesOrBlocks == 0 && currentLine.Equals(Constants.PermissionsConstants.DefaultBoilerPlateText, StringComparison.OrdinalIgnoreCase)
|| currentLine.Equals(Constants.PermissionsConstants.MultipleTableBoilerPlateText, StringComparison.OrdinalIgnoreCase))
if (foundPermissionTablesOrBlocks == 0 && (currentLine.Equals(Constants.PermissionsConstants.DefaultBoilerPlateText, StringComparison.OrdinalIgnoreCase)
|| currentLine.Equals(Constants.PermissionsConstants.MultipleTableBoilerPlateText, StringComparison.OrdinalIgnoreCase)))
{
hasBoilerplateText = true;
boilerplateStartLine = boilerplateEndLine = currentIndex;
Expand All @@ -2674,6 +2674,7 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
{
isBootstrapped = true;
foundPermissionTablesOrBlocks++;
permissionsTableStartLine = currentIndex;
insertionEndLine = currentIndex; // [!INCLUDE [permissions-table]... is the end of the insertion block

if (!options.BootstrappingOnly)
Expand Down Expand Up @@ -2717,6 +2718,7 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
}
else if (currentLine.Contains('|') && currentLine.Contains("Permission type", StringComparison.OrdinalIgnoreCase)) // found the permissions table
{
permissionsTableStartLine = currentIndex;
foundPermissionTablesOrBlocks++;
var annotation = ExtractCodeBlockAnnotationForPermissionsTable(
docFile.DisplayName,
Expand Down Expand Up @@ -2848,8 +2850,8 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
var permissionFileContents = string.Empty;
if (!isBootstrapped)
{
var existingPermissionsTable = originalFileContents.Skip(insertionStartLine + 2).Take(insertionEndLine - insertionStartLine - 1);
permissionFileContents = $"{includeFileMetadata}{ConvertToThreeColumnPermissionsTable(existingPermissionsTable)}";
var existingPermissionsTable = originalFileContents.Skip(permissionsTableStartLine).Take(insertionEndLine - permissionsTableStartLine + 1);
permissionFileContents = $"{includeFileMetadata}{ConvertToThreeColumnPermissionsTable(existingPermissionsTable, docFile.DisplayName)}";
}

if (!options.BootstrappingOnly)
Expand Down Expand Up @@ -2950,7 +2952,7 @@ private static async Task<bool> GeneratePermissionFilesAsync(GeneratePermissionF
: insertionStartLine + permissionsBlockLineCount - 1;
originalFileContents = newFileContents;
insertionStartLine = insertionEndLine = httpRequestStartLine = httpRequestEndLine =
codeBlockAnnotationEndLine = permissionsBlockLineCount = -1;
codeBlockAnnotationEndLine = permissionsBlockLineCount = permissionsTableStartLine = -1;
mergePermissions = false;
requestUrlsForPermissions = null;
foundHttpRequestBlocks = 0;
Expand Down Expand Up @@ -3039,32 +3041,41 @@ private static CodeBlockAnnotation ExtractCodeBlockAnnotationForPermissionsTable
return null;
}

private static string ConvertToThreeColumnPermissionsTable(IEnumerable<string> tableRows)
private static string ConvertToThreeColumnPermissionsTable(IEnumerable<string> tableRows, string fileName)
{
var tableString = new StringBuilder("|Permission type|Least privileged permissions|Higher privileged permissions|");
tableString.Append("\r\n|:---|:---|:---|");
foreach (string row in tableRows)
{
string[] cells = Regex.Split(row.Trim(), @"\s*\|\s*").Where(static x => !string.IsNullOrWhiteSpace(x)).ToArray();

// We already have the 3 column permissions table, abort
if (cells.Length == 3)
try
{
return string.Join("\r\n", tableRows);
}
string[] cells = PipeDelimiterRegex.Split(row.Trim()).Where(static x => !string.IsNullOrWhiteSpace(x)).ToArray();

// We already have the 3 column permissions table, abort
if (cells.Length == 3)
{
return string.Join("\r\n", tableRows);
}

var allPermissions = cells[1].Trim().Split(',', StringSplitOptions.TrimEntries)
.Where(x => !string.IsNullOrWhiteSpace(x) && !PermissionKeywordsToIgnore.Contains(x))
.ToList();
var allPermissions = cells[1].Trim().Split(',', StringSplitOptions.TrimEntries)
.Where(x => !string.IsNullOrWhiteSpace(x) && !PermissionKeywordsToIgnore.Contains(x))
.ToList();

var permissionType = cells[0];
var leastPrivilegePermission = allPermissions.Any() ? allPermissions.First().Trim() : "Not supported.";
var higherPrivilegePermissions = !allPermissions.Any()
? "Not supported."
: allPermissions.Count() == 1
? "Not available."
: string.Join(", ", allPermissions.Skip(1).Select(x => x.Trim()).ToList());
tableString.Append($"\r\n|{permissionType}|{leastPrivilegePermission}|{higherPrivilegePermissions}|");
}
catch (Exception ex)
{
Console.WriteLine($"Could not convert permissions table in {fileName} to three columns: {ex.Message}");
return string.Join(Environment.NewLine, tableRows);
}

var permissionType = cells[0];
var leastPrivilegePermission = allPermissions.Any() ? allPermissions.First().Trim() : "Not supported.";
var higherPrivilegePermissions = !allPermissions.Any()
? "Not supported."
: allPermissions.Count() == 1
? "Not available."
: string.Join(", ", allPermissions.Skip(1).Select(x => x.Trim()).ToList());
tableString.Append($"\r\n|{permissionType}|{leastPrivilegePermission}|{higherPrivilegePermissions}|");
}
return tableString.ToString();
}
Expand Down Expand Up @@ -3194,6 +3205,8 @@ private enum PermissionsInsertionState
FindNextPermissionBlock
}

private static readonly Regex PipeDelimiterRegex = new Regex(@"\s*\|\s*", RegexOptions.Compiled);

#endregion

/// <summary>
Expand Down

0 comments on commit 7d8ebd4

Please sign in to comment.