Skip to content

Commit

Permalink
Merge pull request #757 from StefanMaron/BugfixesForIndirectPermissions
Browse files Browse the repository at this point in the history
Bugfixes for indirect permissions
  • Loading branch information
StefanMaron authored Sep 3, 2024
2 parents a322e39 + 4101303 commit 6d99530
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 14 deletions.
2 changes: 2 additions & 0 deletions BusinessCentral.LinterCop.Test/Rule0068.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public async Task HasDiagnostic(string testCase)
#if Fall2023RV1
[TestCase("ProcedureCallsPermissionsPropertyFullyQualified")]
#endif
// [TestCase("IntegerTable")]
[TestCase("XMLPortWithTableElementProps")]
public async Task NoDiagnostic(string testCase)
{
var code = await File.ReadAllTextAsync(Path.Combine(_testCaseDir, "NoDiagnostic", $"{testCase}.al"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
codeunit 50000 MyCodeunit
{
trigger OnRun()
var
Integer: Record Integer;
begin
[|Integer.FindFirst();|]
end;
}

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
codeunit 50000 MyCodeunit
{

[InherentPermissions(PermissionObjectType::TableData, Database::MyTable, 'rimd')]
[InherentPermissions(PermissionObjectType::TableData, Database::MyTable, 'RIMD')]
local procedure Test()
var
MyTable: Record MyTable;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
xmlport 50000 MyXmlport
{
Direction = Import;

schema
{
textelement(NodeName1)
{
[|tableelement(NodeName2; MyTable)|]
{
AutoReplace = false; // modify permissions
AutoSave = false; // insert permissions
AutoUpdate = false; //modify permissions

fieldattribute(NodeName3; NodeName2.MyField)
{

}
}
}
}
}

table 50000 MyTable
{
Caption = '', Locked = true;

fields
{
field(1; MyField; Integer)
{
Caption = '', Locked = true;
DataClassification = ToBeClassified;
}
field(2; MyField2; Integer)
{
Caption = '', Locked = true;
DataClassification = ToBeClassified;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@ private void AnalyzeInternalProcedures(SyntaxNodeAnalysisContext ctx)
if (ctx.IsObsoletePendingOrRemoved()) return;

if (ctx.ContainingSymbol.GetContainingObjectTypeSymbol().DeclaredAccessibility != Accessibility.Public) return;

MethodDeclarationSyntax methodDeclarationSyntax = (MethodDeclarationSyntax)ctx.Node;
SyntaxNodeOrToken accessModifier = methodDeclarationSyntax.ProcedureKeyword.GetPreviousToken();

if (accessModifier.Kind == SyntaxKind.LocalKeyword || accessModifier.Kind == SyntaxKind.InternalKeyword) return;

if (methodDeclarationSyntax.GetLeadingTrivia().Where(x => x.Kind == SyntaxKind.SingleLineDocumentationCommentTrivia).Any()) return;

ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0025InternalProcedureModifier, methodDeclarationSyntax.ProcedureKeyword.GetLocation()));
if (!ctx.Node.IsKind(SyntaxKind.MethodDeclaration)) return;

try
{
MethodDeclarationSyntax methodDeclarationSyntax = (MethodDeclarationSyntax)ctx.Node;
SyntaxNodeOrToken accessModifier = methodDeclarationSyntax.ProcedureKeyword.GetPreviousToken();
if (accessModifier.Kind == SyntaxKind.LocalKeyword || accessModifier.Kind == SyntaxKind.InternalKeyword) return;
if (methodDeclarationSyntax.GetLeadingTrivia().Where(x => x.Kind == SyntaxKind.SingleLineDocumentationCommentTrivia).Any()) return;
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0025InternalProcedureModifier, methodDeclarationSyntax.ProcedureKeyword.GetLocation()));
}
catch (System.InvalidCastException)
{
return;
}
}
}
}
19 changes: 15 additions & 4 deletions BusinessCentral.LinterCop/Design/Rule0068CheckObjectPermission.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,22 @@ private void CheckXmlportNodeObjectPermission(SymbolAnalysisContext ctx)
else
direction = directionProperty.ValueText;

bool? AutoReplace = (bool?)ctx.Symbol.Properties.FirstOrDefault(property => property.PropertyKind == PropertyKind.AutoReplace)?.Value; // modify permissions
bool? AutoUpdate = (bool?)ctx.Symbol.Properties.FirstOrDefault(property => property.PropertyKind == PropertyKind.AutoUpdate)?.Value; // modify permissions
bool? AutoSave = (bool?)ctx.Symbol.Properties.FirstOrDefault(property => property.PropertyKind == PropertyKind.AutoSave)?.Value; // insert permissions

AutoReplace ??= true;
AutoUpdate ??= true;
AutoSave ??= true;

direction = direction.ToLowerInvariant();

if (direction == "import" || direction == "both")
{
CheckProcedureInvocation(objectPermissions, targetSymbol, 'm', ctx.ReportDiagnostic, ctx.Symbol.GetLocation(), (ITableTypeSymbol)targetSymbol.OriginalDefinition);
CheckProcedureInvocation(objectPermissions, targetSymbol, 'i', ctx.ReportDiagnostic, ctx.Symbol.GetLocation(), (ITableTypeSymbol)targetSymbol.OriginalDefinition);
if (AutoReplace == true || AutoUpdate == true)
CheckProcedureInvocation(objectPermissions, targetSymbol, 'm', ctx.ReportDiagnostic, ctx.Symbol.GetLocation(), (ITableTypeSymbol)targetSymbol.OriginalDefinition);
if (AutoSave == true)
CheckProcedureInvocation(objectPermissions, targetSymbol, 'i', ctx.ReportDiagnostic, ctx.Symbol.GetLocation(), (ITableTypeSymbol)targetSymbol.OriginalDefinition);
}
if (direction == "export" || direction == "both")
CheckProcedureInvocation(objectPermissions, targetSymbol, 'r', ctx.ReportDiagnostic, ctx.Symbol.GetLocation(), (ITableTypeSymbol)targetSymbol.OriginalDefinition);
Expand Down Expand Up @@ -161,7 +171,7 @@ private bool ProcedureHasInherentPermission(IEnumerable<IAttributeSymbol> inhere
if (permissions?[1].Trim() != "PermissionObjectType::TableData") continue;

var typeAndObjectName = permissions[2].Trim();
var permissionValue = permissions[3].Trim().Trim(new[] { '\'', ' ' });
var permissionValue = permissions[3].Trim().Trim(new[] { '\'', ' ' }).ToLowerInvariant();

var typeParts = typeAndObjectName.Split(new[] { "::" }, StringSplitOptions.RemoveEmptyEntries);
if (typeParts.Length < 2) continue;
Expand All @@ -173,7 +183,7 @@ private bool ProcedureHasInherentPermission(IEnumerable<IAttributeSymbol> inhere
#endif
continue;

if (permissionValue.Contains(requestedPermission))
if (permissionValue.Contains(requestedPermission.ToString().ToLowerInvariant()[0]))
{
return true;
}
Expand All @@ -183,6 +193,7 @@ private bool ProcedureHasInherentPermission(IEnumerable<IAttributeSymbol> inhere

private void CheckProcedureInvocation(IPropertySymbol? objectPermissions, ITypeSymbol variableType, char requestedPermission, Action<Diagnostic> ReportDiagnostic, Microsoft.Dynamics.Nav.CodeAnalysis.Text.Location location, ITableTypeSymbol targetTable)
{
if (targetTable.Id > 2000000000) return;
if (TableHasInherentPermission(targetTable, requestedPermission)) return;

if (objectPermissions == null)
Expand Down

0 comments on commit 6d99530

Please sign in to comment.