Page 9802 Permission Sets
- App
- Base Application
- Namespace
- System.Security.AccessControl
- Versions
- 17-28
- Source table
- 9009
Versions171819202122232425262728
Source29
Source in 29
src/Layers/W1/BaseApp/System/Permissions/PermissionSets.Page.al650 lines, Copyright (c) Microsoft Corporation. MIT
namespace System.Security.AccessControl;
using System.Agents;
using System.Environment;
using System.IO;
using System.Reflection;
using System.Security.User;
using System.Utilities;
page 9802 "Permission Sets"
{
AdditionalSearchTerms = 'access rights privilege';
ApplicationArea = Basic, Suite;
Caption = 'Permission Sets';
DelayedInsert = true;
PageType = List;
Permissions = TableData "Permission Set Link" = rd,
TableData "Aggregate Permission Set" = rimd;
SourceTable = "Permission Set Buffer";
SourceTableTemporary = true;
UsageCategory = Lists;
AboutTitle = 'About permissions';
AboutText = 'You manage permissions by assigning permission sets to individual users and to security groups. You can only modify permission sets that you created, not the predefined ones.';
layout
{
area(content)
{
repeater(Group)
{
Caption = 'Permission Set';
field(PermissionSet; Rec."Role ID")
{
ApplicationArea = Basic, Suite;
Caption = 'Permission Set';
Editable = IsPermissionSetEditable;
trigger OnValidate()
var
PermissionPagesMgt: Codeunit "Permission Pages Mgt.";
begin
PermissionPagesMgt.DisallowEditingPermissionSetsForNonAdminUsers();
PermissionPagesMgt.VerifyPermissionSetRoleID(Rec."Role ID");
Rec.RenameTenantPermissionSet();
end;
trigger OnDrillDown()
var
PermisssionSetRelation: Codeunit "Permission Set Relation";
begin
PermisssionSetRelation.OpenPermissionSetPage(Rec.Name, Rec."Role ID", Rec."App ID", Rec.Scope);
end;
}
field(Name; Rec.Name)
{
Caption = 'Name';
ApplicationArea = Basic, Suite;
Editable = IsPermissionSetEditable;
trigger OnValidate()
var
PermissionPagesMgt: Codeunit "Permission Pages Mgt.";
begin
PermissionPagesMgt.DisallowEditingPermissionSetsForNonAdminUsers();
end;
}
field(Type; Rec.Type)
{
ApplicationArea = Basic, Suite;
Editable = false;
Enabled = false;
AboutTitle = 'The source of the permission set';
AboutText = 'You can modify or delete permission sets that your organization created but not those that are built-in (System). Extensions can define permission sets that are also not editable and that will be removed if the extension is uninstalled.';
}
field("App Name"; Rec."App Name")
{
ApplicationArea = Basic, Suite;
Caption = 'Extension Name';
Editable = false;
}
}
}
area(factboxes)
{
systempart(Notes; Notes)
{
ApplicationArea = Notes;
}
systempart(Links; Links)
{
ApplicationArea = RecordLinks;
}
part(ExpandedPermissions; "Expanded Permissions FactBox")
{
ApplicationArea = Basic, Suite;
Caption = 'Permissions';
Editable = false;
SubPageLink = "Role ID" = field("Role ID"),
"App ID" = field("App ID");
}
part("Included Permission Sets"; "Included PermissionSet FactBox")
{
ApplicationArea = Basic, Suite;
Caption = 'Included Permission Sets';
Editable = false;
}
part("Permission Set Assignments"; "Perm. Set Assignments Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Users';
SubPageLink = "Role ID" = field("Role ID"), "App ID" = field("App ID"), Scope = field(Scope);
AboutTitle = 'Permission set assignments';
AboutText = 'View or edit the list of users who are assigned a permission set.';
Visible = CanManageUsersOnTenant;
}
}
}
actions
{
area(navigation)
{
group(ShowPermissions)
{
Caption = 'Permissions';
Image = Permission;
action(PermissionSetContent)
{
ApplicationArea = Basic, Suite;
Caption = 'Permissions';
Image = Permission;
Scope = Repeater;
ToolTip = 'View or edit which feature objects users need to access, and set up the related permissions in permission sets that you can assign to the users.';
AboutTitle = 'View permission set details';
AboutText = 'Go here to see which permissions the selected permission set defines for which objects.';
trigger OnAction()
var
PermissionSetRelation: Codeunit "Permission Set Relation";
begin
PermissionSetRelation.OpenPermissionSetPage(Rec.Name, Rec."Role ID", Rec."App ID", Rec.Scope);
end;
}
action("Permission Set by User")
{
ApplicationArea = Basic, Suite;
Caption = 'Permission Set by User';
Image = Permission;
RunObject = Page "Permission Set by User";
ToolTip = 'View or edit the available permission sets and apply permission sets to existing users.';
}
action("Permission Set By Security Group")
{
ApplicationArea = Basic, Suite;
Caption = 'Permission Set by Security Group';
Image = Permission;
RunObject = Page "Permission Set By Sec. Group";
ToolTip = 'View or edit the available permission sets and apply permission sets to existing security groups.';
}
action("Show Permission Conflicts Overview")
{
ApplicationArea = Basic, Suite;
Caption = 'Show Permission Conflicts Overview';
Image = Permission;
RunObject = Page "Permission Conflicts Overview";
ToolTip = 'View the permission sets that provide more permissions than product licenses allow.';
Visible = IsSaaS;
}
action("Show Permission Conflicts")
{
ApplicationArea = Basic, Suite;
Caption = 'Show Permission Conflicts';
Image = Permission;
ToolTip = 'View details about the permission set that provides more permissions than the license allows.';
Visible = IsSaas;
trigger OnAction()
var
PermissionConflict: Page "Permission Conflicts";
begin
PermissionConflict.SetPermissionSetId(Rec."Role ID");
PermissionConflict.Run();
end;
}
}
group("User Groups")
{
Caption = 'Security Groups';
Image = Users;
action(SecurityGroups)
{
ApplicationArea = Basic, Suite;
Caption = 'Security Groups';
Image = Users;
RunObject = Page "Security Groups";
ToolTip = 'Set up or modify security groups as a fast way of giving users access to the functionality that is relevant to their work.';
}
}
group(PermissionsOverviewGroup)
{
Caption = 'Permissions Overview';
Image = Permission;
action("Where-Used")
{
ApplicationArea = Basic, Suite;
Caption = 'Where-Used';
Image = Track;
Scope = Repeater;
ToolTip = 'View where the selected permission set is used, including which users and security groups have been assigned with it.';
trigger OnAction()
var
PermissionsOverviewPage: Page "Permissions Overview";
begin
PermissionsOverviewPage.SetInitialRoleIDFilter(Rec."Role ID");
PermissionsOverviewPage.Run();
end;
}
action("Permissions Overview")
{
ApplicationArea = Basic, Suite;
Caption = 'Permissions Overview';
Image = Permission;
ToolTip = 'View an overview of how permissions are distributed across permission sets, users, and security groups.';
trigger OnAction()
var
PermissionsOverviewPage: Page "Permissions Overview";
begin
PermissionsOverviewPage.Run();
end;
}
}
}
area(processing)
{
group("<Functions>")
{
Caption = 'F&unctions';
Image = "Action";
action(CopyPermissionSet)
{
ApplicationArea = Basic, Suite;
Caption = 'Copy Permission Set';
Ellipsis = true;
Enabled = CanManageUsersOnTenant;
Image = Copy;
ToolTip = 'Create a copy of the selected permission set with a name that you specify.';
trigger OnAction()
var
AggregatePermissionSet: Record "Aggregate Permission Set";
CopyPermissionSet: Report "Copy Permission Set";
ZeroGuid: Guid;
begin
AggregatePermissionSet.SetRange(Scope, Rec.Scope);
AggregatePermissionSet.SetRange("App ID", Rec."App ID");
AggregatePermissionSet.SetRange("Role ID", Rec."Role ID");
CopyPermissionSet.SetTableView(AggregatePermissionSet);
CopyPermissionSet.RunModal();
if AggregatePermissionSet.Get(AggregatePermissionSet.Scope::Tenant, ZeroGuid, CopyPermissionSet.GetNewRoleID()) then begin
Rec.Init();
Rec.TransferFields(AggregatePermissionSet);
Rec.SetType();
Rec.Insert();
Rec.Get(Rec.Type, Rec."Role ID");
end;
end;
}
action(ImportPermissionSets)
{
ApplicationArea = Basic, Suite;
Caption = 'Import Permission Sets';
Enabled = CanManageUsersOnTenant;
Image = Import;
ToolTip = 'Import a file with permissions.';
trigger OnAction()
var
PermissionSetBuffer: Record "Permission Set Buffer";
TempBlob: Codeunit "Temp Blob";
ImportPermissionSets: XmlPort "Import Permission Sets";
FileName: Text;
InStream: InStream;
OutStream: OutStream;
UpdateExistingPermissions: Boolean;
begin
if not UploadIntoStream('Import', '', '', FileName, InStream) then
exit;
TempBlob.CreateOutStream(OutStream);
CopyStream(OutStream, InStream);
TempBlob.CreateInStream(InStream);
UpdateExistingPermissions := Confirm(UpdateExistingPermissionsLbl, true);
ImportPermissionSets.SetSource(InStream);
ImportPermissionSets.SetUpdatePermissions(UpdateExistingPermissions);
ImportPermissionSets.Import();
PermissionSetBuffer := Rec;
Rec.FillRecordBuffer();
if Rec.Get(PermissionSetBuffer.Type, PermissionSetBuffer."Role ID") then;
end;
}
action(ExportPermissionSets)
{
ApplicationArea = Basic, Suite;
Caption = 'Export Permission Sets';
Image = Export;
ToolTip = 'Export one or more permission sets to a file.';
trigger OnAction()
var
TenantPermissionSet: Record "Tenant Permission Set";
MetadataPermissionSet: Record "Metadata Permission Set";
TempBlob: Codeunit "Temp Blob";
EnvironmentInformation: Codeunit "Environment Information";
FileManagement: Codeunit "File Management";
OutStream: OutStream;
ExportToExtension, ExportSystem, ExportTenant : Boolean;
begin
ExportToExtension := false;
if EnvironmentInformation.IsSandbox() then
if Confirm(ExportExtensionSchemaQst) then
ExportToExtension := true;
GetSelectionFilter(MetadataPermissionSet);
GetSelectionFilter(TenantPermissionSet);
ExportSystem := MetadataPermissionSet.Count() > 0;
ExportTenant := TenantPermissionSet.Count() > 0;
TempBlob.CreateOutStream(OutStream);
if ExportSystem then
Message(ExportSystemPermissionSetsMsg);
if ExportSystem and ExportTenant then begin
ExportMixedPermissionSets(ExportToExtension, MetadataPermissionSet, TenantPermissionSet, OutStream);
FileManagement.BLOBExport(TempBlob, PermissionSetsLbl, true);
exit;
end;
if ExportSystem then begin
ExportSystemPermissionSets(ExportToExtension, MetadataPermissionSet, OutStream);
FileManagement.BLOBExport(TempBlob, PermissionSetsSystemLbl, true);
end else begin
ExportTenantPermissionSets(ExportToExtension, TenantPermissionSet, OutStream);
FileManagement.BLOBExport(TempBlob, PermissionSetsTenantLbl, true);
end;
end;
}
action(RemoveObsoletePermissions)
{
ApplicationArea = Basic, Suite;
Caption = 'Remove Obsolete Permissions';
Enabled = CanManageUsersOnTenant;
Image = Delete;
ToolTip = 'Remove all permissions related to the objects which are obsolete or removed.';
trigger OnAction()
var
TableMetadata: Record "Table Metadata";
Permission: Record Permission;
TenantPermission: Record "Tenant Permission";
AllObjWithCaption: Record AllObjWithCaption;
PermissionToDelete: Record Permission;
TenantPermissionToDelete: Record "Tenant Permission";
PermissionsCount: Integer;
begin
TableMetadata.SetRange(ObsoleteState, TableMetadata.ObsoleteState::Removed);
if TableMetadata.FindSet() then begin
Permission.SetRange("Object Type", Permission."Object Type"::"Table Data", Permission."Object Type"::Table);
TenantPermission.SetRange("Object Type", Permission."Object Type"::"Table Data", Permission."Object Type"::Table);
repeat
Permission.SetRange("Object ID", TableMetadata.ID);
TenantPermission.SetRange("Object ID", TableMetadata.ID);
PermissionsCount += Permission.Count + TenantPermission.Count();
Permission.DeleteAll();
TenantPermission.DeleteAll();
until TableMetadata.Next() = 0;
end;
Permission.SetFilter(
"Object Type", '%1|%2|%3|%4|%5',
Permission."Object Type"::Codeunit, Permission."Object Type"::Page, Permission."Object Type"::Query,
Permission."Object Type"::Report, Permission."Object Type"::XMLport);
Permission.SetFilter("Object ID", '<>0');
if Permission.FindSet() then
repeat
if not AllObjWithCaption.Get(Permission."Object Type", Permission."Object ID") then begin
PermissionToDelete.Get(Permission."Role ID", Permission."Object Type", Permission."Object ID");
PermissionToDelete.Delete();
PermissionsCount += 1;
end;
until Permission.Next() = 0;
TenantPermission.SetFilter(
"Object Type", '%1|%2|%3|%4|%5',
TenantPermission."Object Type"::Codeunit, TenantPermission."Object Type"::Page, TenantPermission."Object Type"::Query,
TenantPermission."Object Type"::Report, TenantPermission."Object Type"::XMLport);
TenantPermission.SetFilter("Object ID", '<>0');
if TenantPermission.FindSet() then
repeat
if not AllObjWithCaption.Get(TenantPermission."Object Type", TenantPermission."Object ID") then begin
TenantPermissionToDelete.Get(TenantPermission."App ID", TenantPermission."Role ID", TenantPermission."Object Type", TenantPermission."Object ID");
TenantPermissionToDelete.Delete();
PermissionsCount += 1;
end;
until TenantPermission.Next() = 0;
if PermissionsCount > 0 then
Message(StrSubstNo(ObsoletePermissionsMsg, PermissionsCount))
else
Message(NothingToRemoveMsg);
end;
}
}
}
area(Promoted)
{
group(Category_Process)
{
Caption = 'Process', Comment = 'Generated from the PromotedActionCategories property index 1.';
actionref(Permissions_Promoted; PermissionSetContent)
{
}
actionref(CopyPermissionSet_Promoted; CopyPermissionSet)
{
}
actionref(ImportPermissionSets_Promoted; ImportPermissionSets)
{
}
actionref(ExportPermissionSets_Promoted; ExportPermissionSets)
{
}
}
}
}
trigger OnAfterGetCurrRecord()
begin
IsPermissionSetEditable := Rec.Type = Rec.Type::"User-Defined";
CurrPage."Included Permission Sets".Page.UpdateIncludedPermissionSets(Rec."Role ID");
end;
trigger OnAfterGetRecord()
begin
IsPermissionSetEditable := Rec.Type = Rec.Type::"User-Defined";
end;
trigger OnDeleteRecord(): Boolean
var
TenantPermissionSet: Record "Tenant Permission Set";
PermissionPagesMgt: Codeunit "Permission Pages Mgt.";
begin
PermissionPagesMgt.DisallowEditingPermissionSetsForNonAdminUsers();
if Rec.Type <> Rec.Type::"User-Defined" then
Error(CannotDeletePermissionSetErr);
TenantPermissionSet.Get(Rec."App ID", Rec."Role ID");
TenantPermissionSet.Delete();
CurrPage.Update();
exit(true);
end;
trigger OnInit()
var
UserPermissions: Codeunit "User Permissions";
begin
CanManageUsersOnTenant := UserPermissions.CanManageUsersOnTenant(UserSecurityId());
end;
trigger OnInsertRecord(BelowxRec: Boolean): Boolean
var
TenantPermissionSet: Record "Tenant Permission Set";
PermissionPagesMgt: Codeunit "Permission Pages Mgt.";
ZeroGUID: Guid;
begin
PermissionPagesMgt.DisallowEditingPermissionSetsForNonAdminUsers();
PermissionPagesMgt.VerifyPermissionSetRoleID(Rec."Role ID");
TenantPermissionSet.Init();
TenantPermissionSet."App ID" := ZeroGUID;
TenantPermissionSet."Role ID" := Rec."Role ID";
TenantPermissionSet.Name := Rec.Name;
TenantPermissionSet.Insert();
Rec.Insert();
Rec.Get(Rec.Type::"User-Defined", Rec."Role ID");
exit(false);
end;
trigger OnModifyRecord(): Boolean
var
TenantPermissionSet: Record "Tenant Permission Set";
PermissionPagesMgt: Codeunit "Permission Pages Mgt.";
begin
PermissionPagesMgt.DisallowEditingPermissionSetsForNonAdminUsers();
if Rec.Type = Rec.Type::"User-Defined" then begin
PermissionPagesMgt.VerifyPermissionSetRoleID(Rec."Role ID");
TenantPermissionSet.Get(xRec."App ID", xRec."Role ID");
if xRec."Role ID" <> Rec."Role ID" then begin
TenantPermissionSet.Rename(xRec."App ID", Rec."Role ID");
TenantPermissionSet.Get(xRec."App ID", Rec."Role ID");
end;
TenantPermissionSet.Name := Rec.Name;
TenantPermissionSet.Modify();
CurrPage.Update(false);
exit(true);
end;
exit(false); // Causes UI to stop processing the action - we handled it manually
end;
trigger OnNewRecord(BelowxRec: Boolean)
begin
Rec.Type := Rec.Type::"User-Defined";
IsPermissionSetEditable := true;
Rec.Scope := Rec.Scope::Tenant;
end;
trigger OnOpenPage()
var
AgentUtilities: Codeunit "Agent Utilities";
PermissionPagesMgt: Codeunit "Permission Pages Mgt.";
EnvironmentInfo: Codeunit "Environment Information";
begin
AgentUtilities.BlockPageFromBeingOpenedByAgent();
IsSaas := EnvironmentInfo.IsSaaS();
PermissionPagesMgt.CheckAndRaiseNotificationIfAppDBPermissionSetsChanged();
Rec.FillRecordBuffer();
if PermissionManager.IsIntelligentCloud() then
Rec.SetRange("Role ID", IntelligentCloudTok);
end;
local procedure ExportMixedPermissionSets(ExportToExtension: Boolean; var MetadataPermissionSet: Record "Metadata Permission Set"; var TenantPermissionSet: Record "Tenant Permission Set"; var OutStreamDest: OutStream)
var
DataCompression: Codeunit "Data Compression";
TempBlobTenant: Codeunit "Temp Blob";
TempBlobSystem: Codeunit "Temp Blob";
InStream: InStream;
OutStream: OutStream;
begin
DataCompression.CreateZipArchive();
TempBlobSystem.CreateOutStream(OutStream);
ExportSystemPermissionSets(ExportToExtension, MetadataPermissionSet, OutStream);
TempBlobSystem.CreateInStream(InStream);
DataCompression.AddEntry(InStream, PermissionSetsSystemLbl);
TempBlobTenant.CreateOutStream(OutStream);
ExportTenantPermissionSets(ExportToExtension, TenantPermissionSet, OutStream);
TempBlobTenant.CreateInStream(InStream);
DataCompression.AddEntry(InStream, PermissionSetsTenantLbl);
DataCompression.SaveZipArchive(OutStreamDest);
end;
local procedure ExportTenantPermissionSets(ExportToExtension: Boolean; var TenantPermissionSet: Record "Tenant Permission Set"; var OutStream: OutStream)
var
ExportPermissionSetsTenant: XmlPort "Export Permission Sets Tenant";
begin
ExportPermissionSetsTenant.SetExportToExtensionSchema(ExportToExtension);
ExportPermissionSetsTenant.SetTableView(TenantPermissionSet);
ExportPermissionSetsTenant.SetDestination(OutStream);
ExportPermissionSetsTenant.Export();
end;
local procedure ExportSystemPermissionSets(ExportToExtension: Boolean; var MetadataPermissionSet: Record "Metadata Permission Set"; var OutStream: OutStream)
var
ExportPermissionSetsSystem: Xmlport "Export Permission Sets System";
begin
ExportPermissionSetsSystem.SetExportToExtensionSchema(ExportToExtension);
ExportPermissionSetsSystem.SetTableView(MetadataPermissionSet);
ExportPermissionSetsSystem.SetDestination(OutStream);
ExportPermissionSetsSystem.Export();
end;
local procedure GetSelectionFilter(var TenantPermissionSet: Record "Tenant Permission Set")
var
PermissionSetBuffer: Record "Permission Set Buffer";
begin
TenantPermissionSet.Reset();
PermissionSetBuffer.CopyFilters(Rec);
CurrPage.SetSelectionFilter(Rec);
if Rec.FindSet() then
repeat
if TenantPermissionSet.Get(Rec."App ID", Rec."Role ID") then
TenantPermissionSet.Mark(true);
until Rec.Next() = 0;
TenantPermissionSet.MarkedOnly(true);
Rec.Reset();
Rec.CopyFilters(PermissionSetBuffer);
end;
local procedure GetSelectionFilter(var MetadataPermissionSet: Record "Metadata Permission Set")
var
PermissionSetBuffer: Record "Permission Set Buffer";
begin
MetadataPermissionSet.Reset();
PermissionSetBuffer.CopyFilters(Rec);
CurrPage.SetSelectionFilter(Rec);
if Rec.FindSet() then
repeat
if MetadataPermissionSet.Get(Rec."App ID", Rec."Role ID") then
MetadataPermissionSet.Mark(true);
until Rec.Next() = 0;
MetadataPermissionSet.MarkedOnly(true);
Rec.Reset();
Rec.CopyFilters(PermissionSetBuffer);
end;
internal procedure GetSelectedRecords(var CurrSelectedRecords: Record "Permission Set Buffer")
begin
CurrPage.SetSelectionFilter(Rec);
if Rec.FindSet() then
repeat
CurrSelectedRecords.Copy(Rec);
CurrSelectedRecords.Insert();
until Rec.Next() = 0;
end;
var
PermissionManager: Codeunit "Permission Manager";
CanManageUsersOnTenant: Boolean;
IsPermissionSetEditable: Boolean;
IsSaas: Boolean;
CannotDeletePermissionSetErr: Label 'You can only delete user-created or copied permission sets.';
ExportExtensionSchemaQst: Label 'Do you want to export permission sets in a schema that is supported by the extension package?';
IntelligentCloudTok: Label 'INTELLIGENT CLOUD', Locked = true;
ObsoletePermissionsMsg: Label '%1 obsolete permissions were removed.', Comment = '%1 = number of deleted records.';
NothingToRemoveMsg: Label 'There is nothing to remove.';
UpdateExistingPermissionsLbl: Label 'Do you want to update the existing permission sets with those from the file? If you choose ''No'', the permissions from the import file will overwrite the existing ones for the included permission sets.';
ExportSystemPermissionSetsMsg: Label 'You are exporting system permission sets. These permission sets will become user-defined permission sets when they are imported.';
PermissionSetsLbl: Label 'PermissionSets.zip', Locked = true;
PermissionSetsTenantLbl: Label 'UserDefinedPermissionSets.xml', Locked = true;
PermissionSetsSystemLbl: Label 'SystemPermissionSets.xml', Locked = true;
}