1313use OCA \Libresign \Db \PermissionSetBindingMapper ;
1414use OCA \Libresign \Db \PermissionSetMapper ;
1515use OCA \Libresign \Service \Policy \Model \PolicyContext ;
16+ use OCA \Libresign \Service \Policy \Provider \DocMdp \DocMdpPolicy ;
1617use OCA \Libresign \Service \Policy \Provider \Signature \SignatureFlowPolicy ;
1718use OCA \Libresign \Service \Policy \Runtime \PolicyRegistry ;
1819use OCA \Libresign \Service \Policy \Runtime \PolicySource ;
@@ -36,19 +37,30 @@ protected function setUp(): void {
3637 $ container = $ this ->createMock (ContainerInterface::class);
3738 $ container
3839 ->method ('get ' )
39- ->with (SignatureFlowPolicy::class)
40- ->willReturn (new SignatureFlowPolicy ());
40+ ->willReturnCallback (static function (string $ class ): object {
41+ return match ($ class ) {
42+ SignatureFlowPolicy::class => new SignatureFlowPolicy (),
43+ DocMdpPolicy::class => new DocMdpPolicy (),
44+ default => throw new \RuntimeException ('Unexpected provider class: ' . $ class ),
45+ };
46+ });
4147 $ this ->registry = new PolicyRegistry ($ container );
4248 }
4349
4450 public function testLoadSystemPolicyReturnsForcedLayerWhenAppConfigIsSet (): void {
4551 $ calls = 0 ;
52+ $ this ->appConfig
53+ ->expects ($ this ->once ())
54+ ->method ('hasAppKey ' )
55+ ->with ('policy.signature_flow.system ' )
56+ ->willReturn (true );
57+
4658 $ this ->appConfig
4759 ->expects ($ this ->exactly (2 ))
4860 ->method ('getAppValueString ' )
4961 ->willReturnCallback (static function (string $ key , string $ default ) use (&$ calls ): string {
5062 $ calls += 1 ;
51- if ($ key === 'policy.signature_flow.system ' && $ default === '' ) {
63+ if ($ key === 'policy.signature_flow.system ' && $ default === 'none ' ) {
5264 return 'ordered_numeric ' ;
5365 }
5466
@@ -73,9 +85,13 @@ public function testLoadSystemPolicyReturnsForcedLayerWhenAppConfigIsSet(): void
7385 public function testLoadSystemPolicyReturnsInheritableLayerWhenAppConfigMatchesDefault (): void {
7486 $ this ->appConfig
7587 ->expects ($ this ->once ())
76- ->method ('getAppValueString ' )
77- ->with ('policy.signature_flow.system ' , '' )
78- ->willReturn ('' );
88+ ->method ('hasAppKey ' )
89+ ->with ('policy.signature_flow.system ' )
90+ ->willReturn (false );
91+
92+ $ this ->appConfig
93+ ->expects ($ this ->never ())
94+ ->method ('getAppValueString ' );
7995
8096 $ source = $ this ->getSource ();
8197 $ layer = $ source ->loadSystemPolicy ('signature_flow ' );
@@ -152,7 +168,7 @@ public function testSaveUserPreferenceNormalizesAndPersistsUserConfigValue(): vo
152168 ->with ('john ' , 'policy.signature_flow ' , 'ordered_numeric ' );
153169
154170 $ source = $ this ->getSource ();
155- $ source ->saveUserPreference ('signature_flow ' , PolicyContext::fromUserId ('john ' ), 2 );
171+ $ source ->saveUserPreference ('signature_flow ' , PolicyContext::fromUserId ('john ' ), ' ordered_numeric ' );
156172 }
157173
158174 public function testClearUserPreferenceDeletesUserConfig (): void {
@@ -215,7 +231,7 @@ public function testSaveSystemPolicyNormalizesAndPersistsAppConfigValue(): void
215231 });
216232
217233 $ source = $ this ->getSource ();
218- $ source ->saveSystemPolicy ('signature_flow ' , 2 , true );
234+ $ source ->saveSystemPolicy ('signature_flow ' , ' ordered_numeric ' , true );
219235
220236 $ this ->assertSame ([
221237 'policy.signature_flow.system ' => 'ordered_numeric ' ,
@@ -225,12 +241,18 @@ public function testSaveSystemPolicyNormalizesAndPersistsAppConfigValue(): void
225241
226242 public function testLoadSystemPolicyRespectsPersistedAllowChildOverride (): void {
227243 $ calls = 0 ;
244+ $ this ->appConfig
245+ ->expects ($ this ->once ())
246+ ->method ('hasAppKey ' )
247+ ->with ('policy.signature_flow.system ' )
248+ ->willReturn (true );
249+
228250 $ this ->appConfig
229251 ->expects ($ this ->exactly (2 ))
230252 ->method ('getAppValueString ' )
231253 ->willReturnCallback (static function (string $ key , string $ default ) use (&$ calls ): string {
232254 $ calls += 1 ;
233- if ($ key === 'policy.signature_flow.system ' && $ default === '' ) {
255+ if ($ key === 'policy.signature_flow.system ' && $ default === 'none ' ) {
234256 return 'ordered_numeric ' ;
235257 }
236258
@@ -253,11 +275,17 @@ public function testLoadSystemPolicyRespectsPersistedAllowChildOverride(): void
253275 }
254276
255277 public function testLoadSystemPolicyTreatsPersistedDefaultAsExplicitWhenAllowChildOverrideIsSet (): void {
278+ $ this ->appConfig
279+ ->expects ($ this ->once ())
280+ ->method ('hasAppKey ' )
281+ ->with ('policy.signature_flow.system ' )
282+ ->willReturn (true );
283+
256284 $ this ->appConfig
257285 ->expects ($ this ->exactly (2 ))
258286 ->method ('getAppValueString ' )
259287 ->willReturnCallback (static function (string $ key , string $ default ): string {
260- if ($ key === 'policy.signature_flow.system ' && $ default === '' ) {
288+ if ($ key === 'policy.signature_flow.system ' && $ default === 'none ' ) {
261289 return 'none ' ;
262290 }
263291
@@ -278,6 +306,57 @@ public function testLoadSystemPolicyTreatsPersistedDefaultAsExplicitWhenAllowChi
278306 $ this ->assertSame ([], $ layer ->getAllowedValues ());
279307 }
280308
309+ public function testLoadSystemPolicyReturnsDocMdpLayerFromTypedIntConfig (): void {
310+ $ this ->appConfig
311+ ->expects ($ this ->once ())
312+ ->method ('hasAppKey ' )
313+ ->with ('docmdp_level ' )
314+ ->willReturn (true );
315+
316+ $ this ->appConfig
317+ ->expects ($ this ->once ())
318+ ->method ('getAppValueInt ' )
319+ ->with ('docmdp_level ' , 0 )
320+ ->willReturn (2 );
321+
322+ $ this ->appConfig
323+ ->expects ($ this ->once ())
324+ ->method ('getAppValueString ' )
325+ ->willReturnCallback (static function (string $ key , string $ default ): string {
326+ if ($ key === 'docmdp_level.allow_child_override ' && $ default === '0 ' ) {
327+ return '0 ' ;
328+ }
329+
330+ throw new \RuntimeException ('Unexpected app config key request: ' . $ key );
331+ });
332+
333+ $ source = $ this ->getSource ();
334+ $ layer = $ source ->loadSystemPolicy (DocMdpPolicy::KEY );
335+
336+ $ this ->assertNotNull ($ layer );
337+ $ this ->assertSame ('global ' , $ layer ->getScope ());
338+ $ this ->assertSame (2 , $ layer ->getValue ());
339+ $ this ->assertFalse ($ layer ->isAllowChildOverride ());
340+ $ this ->assertSame ([2 ], $ layer ->getAllowedValues ());
341+ }
342+
343+ public function testSaveSystemPolicyPersistsDocMdpLevelAsTypedInt (): void {
344+ $ this ->appConfig
345+ ->expects ($ this ->once ())
346+ ->method ('setAppValueInt ' )
347+ ->with ('docmdp_level ' , 2 )
348+ ->willReturn (true );
349+
350+ $ this ->appConfig
351+ ->expects ($ this ->once ())
352+ ->method ('setAppValueString ' )
353+ ->with ('docmdp_level.allow_child_override ' , '0 ' )
354+ ->willReturn (true );
355+
356+ $ source = $ this ->getSource ();
357+ $ source ->saveSystemPolicy (DocMdpPolicy::KEY , 2 , false );
358+ }
359+
281360 public function testLoadGroupPolicyConfigReturnsBoundPolicyLayer (): void {
282361 $ binding = new PermissionSetBinding ();
283362 $ binding ->setPermissionSetId (77 );
@@ -355,7 +434,49 @@ public function testSaveGroupPolicyCreatesPermissionSetAndBinding(): void {
355434 }));
356435
357436 $ source = $ this ->getSource ();
358- $ source ->saveGroupPolicy ('signature_flow ' , 'finance ' , 2 , false );
437+ $ source ->saveGroupPolicy ('signature_flow ' , 'finance ' , 'ordered_numeric ' , false );
438+ }
439+
440+ public function testSaveGroupPolicyCreatesDocMdpPermissionSetWithNormalizedLevel (): void {
441+ $ this ->bindingMapper
442+ ->expects ($ this ->once ())
443+ ->method ('getByTarget ' )
444+ ->with ('group ' , 'finance ' )
445+ ->willThrowException (new DoesNotExistException ('missing ' ));
446+
447+ $ this ->permissionSetMapper
448+ ->expects ($ this ->once ())
449+ ->method ('insert ' )
450+ ->with ($ this ->callback (function (PermissionSet $ permissionSet ): bool {
451+ $ this ->assertSame ('group ' , $ permissionSet ->getScopeType ());
452+ $ this ->assertSame ('group:finance ' , $ permissionSet ->getName ());
453+ $ this ->assertSame ([
454+ 'docmdp ' => [
455+ 'defaultValue ' => 3 ,
456+ 'allowChildOverride ' => false ,
457+ 'visibleToChild ' => true ,
458+ 'allowedValues ' => [3 ],
459+ ],
460+ ], $ permissionSet ->getDecodedPolicyJson ());
461+ return true ;
462+ }))
463+ ->willReturnCallback (static function (PermissionSet $ permissionSet ): PermissionSet {
464+ $ permissionSet ->setId (91 );
465+ return $ permissionSet ;
466+ });
467+
468+ $ this ->bindingMapper
469+ ->expects ($ this ->once ())
470+ ->method ('insert ' )
471+ ->with ($ this ->callback (function (PermissionSetBinding $ binding ): bool {
472+ $ this ->assertSame (91 , $ binding ->getPermissionSetId ());
473+ $ this ->assertSame ('group ' , $ binding ->getTargetType ());
474+ $ this ->assertSame ('finance ' , $ binding ->getTargetId ());
475+ return true ;
476+ }));
477+
478+ $ source = $ this ->getSource ();
479+ $ source ->saveGroupPolicy (DocMdpPolicy::KEY , 'finance ' , 3 , false );
359480 }
360481
361482 public function testClearGroupPolicyDeletesBindingAndPermissionSetWhenItIsTheLastPolicy (): void {
0 commit comments