Files
SGF/scripts/sgf-profiles-check.php
2026-11-11 09:00:17 +02:00

19 lines
2.6 KiB
PHP

<?php
$book=$argv[1]??'regression';require __DIR__.'/sgf-single-bootstrap.php';
$clientsBefore=$host->table('a_clients')->orderBy('id')->get()->toJson();$associationsBefore=$host->table('identity_audit')->where('action','module.record.associated')->orderBy('id')->get()->toJson();
$p=App\Shared\Installation\SyntheticProfiles::policy();$result=(new App\Shared\Installation\SyntheticProfiles)->install();$checks=[];
$ok=function($v,$name)use(&$checks){if(!$v)throw new RuntimeException($name);$checks[]=$name;};
$ok($result['replayed']===true&&count($result['profiles'])===10,'profile installation is idempotent and contains exactly ten approved profiles');
foreach($p['profiles'] as $profile){
$id=$result['profiles'][$profile['id']]['user_id'];$rows=$host->table('permission_grants')->where('user_id',$id)->get();
$expected=[];foreach($profile['rights'] as $right)$expected[]=$right['permission'].':'.($right['scope']==='unit'?2:'company');
foreach(($p['integration_grants'][$profile['id']]??[]) as $scope=>$rights)foreach($rights as $right)$expected[]=$right.':'.($scope==='unit'?2:'company');
$expected=array_values(array_unique($expected));sort($expected);$actual=$rows->map(fn($r)=>$r->permission.':'.($r->unit_id??'company'))->all();sort($actual);
$ok($actual===$expected&&$rows->every(fn($r)=>(int)$r->tenant_id===1&&(int)$r->company_id===2&&($r->unit_id===null||(int)$r->unit_id===2)&&$r->permission!=='access.manage'),'exact approved grants including listed integration reads and no foreign authority: '.$profile['id']);
$blocked=false;try{app(App\Shared\Context\CompanyContext::class)->selectFor($id,1,2,3);}catch(Symfony\Component\HttpKernel\Exception\HttpExceptionInterface $e){$blocked=$e->getStatusCode()===403;}
$ok($blocked,'foreign unit refused: '.$profile['id']);
}
$ok($host->table('permission_grants')->where('permission','stock.operations.prepare')->where('user_id',2)->where('unit_id',2)->count()===1,'existing synthetic warehouse profile receives the reviewed Stock right once');
$ok($host->table('a_clients')->orderBy('id')->get()->toJson()===$clientsBefore&&$host->table('identity_audit')->where('action','module.record.associated')->orderBy('id')->get()->toJson()===$associationsBefore,'idempotent profile installation preserves all client data and every existing module association');
$out=['passed'=>true,'checks'=>$checks,'book'=>$book,'new_databases'=>0,'new_database_roles'=>0,'business_commands'=>0];file_put_contents($work.'/profiles-check.json',json_encode($out,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo json_encode(['passed'=>true,'checks'=>count($checks),'proof'=>$work.'/profiles-check.json']).PHP_EOL;