Skip to content

Commit 42ee792

Browse files
authored
Importing Permissions with Overwrite Option (#3184)
<!-- Thank you for submitting a Pull Request. If you're new to contributing to BCApps please read our pull request guideline below * https://github.com/microsoft/BCApps/Contributing.md --> #### Summary <!-- Provide a general summary of your changes --> With this change, I have enabled the user to be able to overwrite permission sets contained in the import file. Up until now, the permissions from the import file were merged with the permissions already present in the permission sets. The majority of changes were done in this repo but the text for a confirmation dialog has been changed in the repo containing the Base App microsoft/BusinessCentralApps#1287 #### Description of the problem Importing user defined permissions sets leaves permissions in inconsistent state. Users tend to test the permissions sets in multiple rounds in a test system. After they are satisfied with the result they decide to import it in a production. However the outcome of the import is not reliable. Users would like to overwrite current user defined permission set with preserving assignment to the users/security groups. Currently if a permission set is imported there are two problems: 1. If in a test systems some permissions were reduced to indirect or removed those changes do not get imported into permissions. 1. If a permission for a certain object is removed in a test system and then exported and imported to production the permission cannot be removed. That means that importing permission sets is basically "additive" and can only give more "power". There is no easy way to import XX permission sets that are already assigned to users or security groups and that those are imported "as is" in the import file. #### Work Item(s) <!-- Add the issue number here after the #. The issue needs to be open and approved. Submitting PRs with no linked issues or unapproved issues is highly discouraged. --> Fixes #3162 Fixes [AB#559224](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/559224)
1 parent 15c8e45 commit 42ee792

File tree

2 files changed

+147
-6
lines changed

2 files changed

+147
-6
lines changed

src/System Application/App/Permission Sets/src/xmlports/ImportPermissionSets.xmlport.al

+22
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,20 @@ xmlport 9864 "Import Permission Sets"
120120
}
121121

122122
trigger OnBeforeInsertRecord()
123+
var
124+
TenantPermission: Record "Tenant Permission";
125+
TenantPermissionSetRel: Record "Tenant Permission Set Rel.";
123126
begin
124127
if TempTenantPermissionSet.Get(TempTenantPermissionSet."App ID", TempTenantPermissionSet."Role ID") then
125128
currXMLport.Skip();
129+
if not UpdatePermissions then begin
130+
TenantPermissionSetRel.SetFilter("App ID", TempTenantPermissionSet."App ID");
131+
TenantPermissionSetRel.SetFilter("Role ID", TempTenantPermissionSet."Role ID");
132+
TenantPermissionSetRel.DeleteAll();
133+
TenantPermission.SetFilter("App ID", TempTenantPermissionSet."App ID");
134+
TenantPermission.SetFilter("Role ID", TempTenantPermissionSet."Role ID");
135+
TenantPermission.DeleteAll();
136+
end;
126137
end;
127138
}
128139
tableelement(TempMetadataPermissionSet; "Metadata Permission Set")
@@ -211,9 +222,20 @@ xmlport 9864 "Import Permission Sets"
211222
}
212223

213224
trigger OnBeforeInsertRecord()
225+
var
226+
MetadataPermission: Record "Metadata Permission";
227+
MetadataPermissionSetRel: Record "Metadata Permission Set Rel.";
214228
begin
215229
if TempMetadataPermissionSet.Get(TempMetadataPermissionSet."App ID", TempMetadataPermissionSet."Role ID") then
216230
currXMLport.Skip();
231+
if not UpdatePermissions then begin
232+
MetadataPermissionSetRel.SetFilter("App ID", TempMetadataPermissionSet."App ID");
233+
MetadataPermissionSetRel.SetFilter("Role ID", TempMetadataPermissionSet."Role ID");
234+
MetadataPermissionSetRel.DeleteAll();
235+
MetadataPermission.SetFilter("App ID", TempMetadataPermissionSet."App ID");
236+
MetadataPermission.SetFilter("Role ID", TempTenantPermissionSet."Role ID");
237+
MetadataPermission.DeleteAll();
238+
end;
217239
end;
218240
}
219241
}

src/System Application/Test/Permission Sets/src/PermissionImportExportTests.Codeunit.al

+125-6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ codeunit 132437 "Permission Import Export Tests"
2828
MetadataPermissionSet: Record "Metadata Permission Set";
2929
TenantPermissionSetRel: Record "Tenant Permission Set Rel.";
3030
TempBlob: Codeunit "Temp Blob";
31+
ImportPermissionSets: XmlPort "Import Permission Sets";
3132
OutStr: OutStream;
3233
InStr: InStream;
3334
ZeroGuid: Guid;
@@ -52,7 +53,9 @@ codeunit 132437 "Permission Import Export Tests"
5253

5354
// [WHEN] Import exported permission set
5455
TempBlob.CreateInStream(InStr);
55-
Xmlport.Import(Xmlport::"Import Permission Sets", InStr);
56+
ImportPermissionSets.SetSource(InStr);
57+
ImportPermissionSets.SetUpdatePermissions(true);
58+
ImportPermissionSets.Import();
5659

5760
MetadataPermissionSet.SetFilter("Role ID", 'Permission Set A');
5861
MetadataPermissionSet.FindFirst();
@@ -72,6 +75,7 @@ codeunit 132437 "Permission Import Export Tests"
7275
MetadataPermissionSet: Record "Metadata Permission Set";
7376
TenantPermissionSetRel: Record "Tenant Permission Set Rel.";
7477
TempBlob: Codeunit "Temp Blob";
78+
ImportPermissionSets: XmlPort "Import Permission Sets";
7579
OutStr: OutStream;
7680
InStr: InStream;
7781
ZeroGuid: Guid;
@@ -96,7 +100,9 @@ codeunit 132437 "Permission Import Export Tests"
96100

97101
// [WHEN] Import exported permission set
98102
TempBlob.CreateInStream(InStr);
99-
Xmlport.Import(Xmlport::"Import Permission Sets", InStr);
103+
ImportPermissionSets.SetSource(InStr);
104+
ImportPermissionSets.SetUpdatePermissions(true);
105+
ImportPermissionSets.Import();
100106

101107
// [THEN] System PS "Permission Set C" is now found as a tenant permission set with relation
102108
LibraryAssert.IsTrue(TenantPermissionSet.Get(ZeroGuid, 'Permission Set C'), 'Permission Set C is missing');
@@ -116,6 +122,7 @@ codeunit 132437 "Permission Import Export Tests"
116122
MetadataPermissionSet: Record "Metadata Permission Set";
117123
TenantPermissionSetRel: Record "Tenant Permission Set Rel.";
118124
TempBlob: Codeunit "Temp Blob";
125+
ImportPermissionSets: XmlPort "Import Permission Sets";
119126
OutStr: OutStream;
120127
InStr: InStream;
121128
ZeroGuid: Guid;
@@ -140,7 +147,9 @@ codeunit 132437 "Permission Import Export Tests"
140147

141148
// [WHEN] Import exported permission set
142149
TempBlob.CreateInStream(InStr);
143-
Xmlport.Import(Xmlport::"Import Permission Sets", InStr);
150+
ImportPermissionSets.SetSource(InStr);
151+
ImportPermissionSets.SetUpdatePermissions(true);
152+
ImportPermissionSets.Import();
144153

145154
MetadataPermissionSet.SetFilter("Role ID", 'Permission Set A');
146155
MetadataPermissionSet.FindFirst();
@@ -164,6 +173,7 @@ codeunit 132437 "Permission Import Export Tests"
164173
TenantPermissionSetRel: Record "Tenant Permission Set Rel.";
165174
PermissionSetRelation: Codeunit "Permission Set Relation";
166175
TempBlob: Codeunit "Temp Blob";
176+
ImportPermissionSets: XmlPort "Import Permission Sets";
167177
OutStr: OutStream;
168178
InStr: InStream;
169179
ZeroGuid: Guid;
@@ -197,7 +207,9 @@ codeunit 132437 "Permission Import Export Tests"
197207

198208
// [WHEN] Import exported tenant permission set
199209
TempBlob.CreateInStream(InStr);
200-
Xmlport.Import(Xmlport::"Import Permission Sets", InStr);
210+
ImportPermissionSets.SetSource(InStr);
211+
ImportPermissionSets.SetUpdatePermissions(true);
212+
ImportPermissionSets.Import();
201213

202214
// [THEN] Tenant permission set is found with the correct permissions
203215
LibraryAssert.IsTrue(TenantPermissionSet.Get(ZeroGuid, NewRoleId), 'Test permission set is missing');
@@ -218,6 +230,7 @@ codeunit 132437 "Permission Import Export Tests"
218230
PermissionSetRelation: Codeunit "Permission Set Relation";
219231
TempBlobOriginal: Codeunit "Temp Blob";
220232
TempBlobModified: Codeunit "Temp Blob";
233+
ImportPermissionSets: XmlPort "Import Permission Sets";
221234
OutStr: OutStream;
222235
InStr: InStream;
223236
ZeroGuid: Guid;
@@ -274,7 +287,9 @@ codeunit 132437 "Permission Import Export Tests"
274287

275288
// [WHEN] Import the original tenant permission set that was exported
276289
TempBlobOriginal.CreateInStream(InStr);
277-
Xmlport.Import(Xmlport::"Import Permission Sets", InStr);
290+
ImportPermissionSets.SetSource(InStr);
291+
ImportPermissionSets.SetUpdatePermissions(true);
292+
ImportPermissionSets.Import();
278293

279294
// [THEN] Tenant permission set is found with the correct permissions
280295
LibraryAssert.IsTrue(TenantPermissionSet.Get(ZeroGuid, NewRoleId), 'Test permission set is missing');
@@ -287,7 +302,10 @@ codeunit 132437 "Permission Import Export Tests"
287302

288303
// [WHEN] Import the modified tenant permission set
289304
TempBlobModified.CreateInStream(InStr);
290-
Xmlport.Import(Xmlport::"Import Permission Sets", InStr);
305+
Clear(ImportPermissionSets);
306+
ImportPermissionSets.SetSource(InStr);
307+
ImportPermissionSets.SetUpdatePermissions(true);
308+
ImportPermissionSets.Import();
291309

292310
// [THEN] Tenant permission set is found with the modified permissions
293311
LibraryAssert.IsTrue(TenantPermissionSet.Get(ZeroGuid, NewRoleId), 'Test permission set is missing');
@@ -303,6 +321,107 @@ codeunit 132437 "Permission Import Export Tests"
303321
LibraryAssert.AreEqual(TenantPermission."Delete Permission", TenantPermission."Delete Permission"::" ", 'Delete permission is not set correctly.');
304322
end;
305323

324+
[Test]
325+
[Scope('OnPrem')]
326+
procedure ExportImportTenantPermissionSetUsingOverwriteOption()
327+
var
328+
TenantPermission: Record "Tenant Permission";
329+
TenantPermissionSet: Record "Tenant Permission Set";
330+
TenantPermissionSetRel: Record "Tenant Permission Set Rel.";
331+
PermissionSetRelation: Codeunit "Permission Set Relation";
332+
TempBlobOriginal: Codeunit "Temp Blob";
333+
TempBlobModified: Codeunit "Temp Blob";
334+
ImportPermissionSets: XmlPort "Import Permission Sets";
335+
OutStr: OutStream;
336+
InStr: InStream;
337+
ZeroGuid: Guid;
338+
AppId: Guid;
339+
NewRoleId: Code[20];
340+
NewName: Text;
341+
begin
342+
// [FEATURE] [Import] [XMLPORT] [Permission Set] [Tenant Permission Set]
343+
// [SCENARIO] Tenant permission set is exported and imported. Then the same permission set is imported again with changed permissions and should be imported as is without merging.
344+
345+
Initialize();
346+
347+
NewRoleId := 'Test Permission Set';
348+
NewName := 'Test Permission Set';
349+
350+
// [WHEN] Permission Set C is cloned to get a tenant permission set
351+
PermissionSetRelation.CopyPermissionSet(NewRoleId, NewName, 'Permission Set C', AppId, Scope::System, Enum::"Permission Set Copy Type"::Clone);
352+
353+
TenantPermissionSet.SetFilter("Role ID", NewRoleId);
354+
TempBlobOriginal.CreateOutStream(OutStr);
355+
356+
// [WHEN] Export Tenant permission set
357+
Xmlport.Export(Xmlport::"Export Permission Sets Tenant", OutStr, TenantPermissionSet);
358+
359+
LibraryAssert.IsTrue(TenantPermissionSet.Get(ZeroGuid, NewRoleId), 'Test permission set is missing');
360+
LibraryAssert.IsTrue(TenantPermission.Get(ZeroGuid, TenantPermissionSet."Role ID", TenantPermission."Object Type"::"Table Data", Database::"Tenant Permission"), 'Included permission to Test permission set is missing');
361+
362+
// [WHEN] Existing permission for the permission set is changed
363+
TenantPermission."Read Permission" := TenantPermission."Read Permission"::" "; // read permission is removed
364+
TenantPermission."Delete Permission" := TenantPermission."Delete Permission"::Yes; // delete permission is added
365+
TenantPermission.Modify();
366+
367+
// [WHEN] A new permission is added to the permission set
368+
TenantPermission.Init();
369+
TenantPermission."Role ID" := NewRoleId;
370+
TenantPermission."Object Type" := TenantPermission."Object Type"::"Table Data";
371+
TenantPermission."Object ID" := Database::"Metadata Permission";
372+
TenantPermission."Read Permission" := TenantPermission."Read Permission"::Indirect;
373+
TenantPermission."Insert Permission" := TenantPermission."Insert Permission"::" ";
374+
TenantPermission."Modify Permission" := TenantPermission."Modify Permission"::" ";
375+
TenantPermission."Delete Permission" := TenantPermission."Delete Permission"::" ";
376+
TenantPermission.Insert();
377+
378+
// [WHEN] Tenant permission set is exported again
379+
TempBlobModified.CreateOutStream(OutStr);
380+
Xmlport.Export(Xmlport::"Export Permission Sets Tenant", OutStr, TenantPermissionSet);
381+
382+
// [WHEN] No tenant permission sets exists
383+
TenantPermissionSet.DeleteAll();
384+
TenantPermissionSet.SetFilter("Role ID", NewRoleId);
385+
LibraryAssert.RecordIsEmpty(TenantPermissionSet);
386+
TenantPermissionSetRel.SetFilter("Role ID", NewRoleId);
387+
LibraryAssert.RecordIsEmpty(TenantPermissionSetRel);
388+
389+
// [WHEN] Import the original tenant permission set that was exported
390+
TempBlobOriginal.CreateInStream(InStr);
391+
ImportPermissionSets.SetSource(InStr);
392+
ImportPermissionSets.SetUpdatePermissions(false);
393+
ImportPermissionSets.Import();
394+
395+
// [THEN] Tenant permission set is found with the correct permissions
396+
LibraryAssert.IsTrue(TenantPermissionSet.Get(ZeroGuid, NewRoleId), 'Test permission set is missing');
397+
LibraryAssert.IsTrue(TenantPermission.Get(ZeroGuid, TenantPermissionSet."Role ID", TenantPermission."Object Type"::"Table Data", Database::"Tenant Permission"), 'Included permission to Test permission set is missing');
398+
LibraryAssert.AreEqual(TenantPermission."Read Permission", TenantPermission."Read Permission"::Yes, 'Read permission is not set correctly.');
399+
LibraryAssert.AreEqual(TenantPermission."Insert Permission", TenantPermission."Insert Permission"::Indirect, 'Insert permission is not set correctly.');
400+
LibraryAssert.AreEqual(TenantPermission."Modify Permission", TenantPermission."Modify Permission"::Indirect, 'Modify permission is not set correctly.');
401+
LibraryAssert.AreEqual(TenantPermission."Delete Permission", TenantPermission."Delete Permission"::" ", 'Delete permission is not set correctly.');
402+
LibraryAssert.IsFalse(TenantPermission.Get(ZeroGuid, TenantPermissionSet."Role ID", TenantPermission."Object Type"::"Table Data", Database::"Metadata Permission"), 'Metadata permission should not be included');
403+
404+
// [WHEN] Import the modified tenant permission set
405+
TempBlobModified.CreateInStream(InStr);
406+
Clear(ImportPermissionSets);
407+
ImportPermissionSets.SetSource(InStr);
408+
ImportPermissionSets.SetUpdatePermissions(false);
409+
ImportPermissionSets.Import();
410+
411+
// [THEN] Tenant permission set is found with the modified permissions
412+
LibraryAssert.IsTrue(TenantPermissionSet.Get(ZeroGuid, NewRoleId), 'Test permission set is missing');
413+
LibraryAssert.IsTrue(TenantPermission.Get(ZeroGuid, TenantPermissionSet."Role ID", TenantPermission."Object Type"::"Table Data", Database::"Tenant Permission"), 'Included permission to Test permission set is missing');
414+
LibraryAssert.AreEqual(TenantPermission."Read Permission", TenantPermission."Read Permission"::" ", 'Read permission is not set correctly.'); // Import is not additive, the permission should be imported as is
415+
LibraryAssert.AreEqual(TenantPermission."Insert Permission", TenantPermission."Insert Permission"::Indirect, 'Insert permission is not set correctly.');
416+
LibraryAssert.AreEqual(TenantPermission."Modify Permission", TenantPermission."Modify Permission"::Indirect, 'Modify permission is not set correctly.');
417+
LibraryAssert.AreEqual(TenantPermission."Delete Permission", TenantPermission."Delete Permission"::Yes, 'Delete permission is not set correctly.');
418+
LibraryAssert.IsTrue(TenantPermission.Get(ZeroGuid, TenantPermissionSet."Role ID", TenantPermission."Object Type"::"Table Data", Database::"Metadata Permission"), 'Included permission to Test permission set is missing');
419+
LibraryAssert.AreEqual(TenantPermission."Read Permission", TenantPermission."Read Permission"::Indirect, 'Read permission is not set correctly.');
420+
LibraryAssert.AreEqual(TenantPermission."Insert Permission", TenantPermission."Insert Permission"::" ", 'Insert permission is not set correctly.');
421+
LibraryAssert.AreEqual(TenantPermission."Modify Permission", TenantPermission."Modify Permission"::" ", 'Modify permission is not set correctly.');
422+
LibraryAssert.AreEqual(TenantPermission."Delete Permission", TenantPermission."Delete Permission"::" ", 'Delete permission is not set correctly.');
423+
end;
424+
306425
local procedure Initialize()
307426
var
308427
TenantPermission: Record "Tenant Permission";

0 commit comments

Comments
 (0)