Files
SGF/app/Modules/Purchasing/PurchasingEntry.php
T
2026-11-04 09:37:20 +02:00

55 lines
5.1 KiB
PHP

<?php
namespace App\Modules\Purchasing;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
/** Explicit access to existing synthetic identities, only in the selected local installation. */
final class PurchasingEntry
{
public static function profiles(array $fixture):array
{
$definitions=['requester'=>['Solicitante','Prepara e submete a necessidade.'],'approver'=>['Chefia','Decide requisições e adjudicações por identidade distinta.'],'actor'=>['Compras','Prepara fornecedores, propostas, comparação e ordens.'],'issuer'=>['Finanças','Revê fornecedores, avalia propostas, regista facturas e prepara obrigações.'],'validator'=>['Armazém','Confere e confirma a recepção física.'],'reviewer'=>['Revisor financeiro','Valida facturas e obrigações por identidade distinta.'],'auditor'=>['Consulta financeira','Consulta autorizada dos documentos financeiros.']];
$stages=['requests'=>'Requisições','suppliers'=>'Fornecedores','sourcing'=>'Propostas e adjudicação','orders'=>'Ordens','receipts'=>'Recepções','invoices'=>'Facturas','obligations'=>'Obrigações'];$profiles=[];
$grants=DB::table('permission_grants')->where($fixture['scope'])->whereIn('user_id',array_intersect_key($fixture,$definitions))->get(['user_id','permission'])->groupBy('user_id');
foreach($definitions as$key=>[$label,$description]){
if(!isset($fixture[$key]))continue;$available=[];
$rights=($grants[$fixture[$key]]??collect())->pluck('permission')->all();foreach($stages as$stage=>$name)if(in_array('purchasing_'.$stage.'.view',$rights,true))$available[$stage]=$name;
$profiles[$key]=['user_id'=>$fixture[$key],'label'=>$label,'description'=>$description,'stages'=>$available];
}return $profiles;
}
private static function guard():void
{
abort_unless(config('purchasing_workspace.single_installation')===true&&app()->environment('budget-testing')&&in_array(request()->ip(),['127.0.0.1','::1'],true),404);
BudgetAdapter::guard();
$id=(string)config('purchasing_workspace.id');$db=DB::connection();$run=(string)getenv('SGF_ISOLATED_REGRESSION_RUN');
abort_unless(preg_match('/^[a-f0-9]{12}$/D',$id)&&preg_match('/^[a-f0-9]{12}$/D',$run)
&&$db->getDatabaseName()==='budget_core_sgf_'.$id&&$db->getConfig('username')==='ir_composition_'.$id&&(int)$db->getConfig('port')===55439,403);
$identity=$db->selectOne("SELECT current_user role,current_setting('cluster_name') cluster,rolsuper OR rolcreatedb OR rolcreaterole OR rolreplication OR rolbypassrls elevated FROM pg_roles WHERE rolname=current_user");
abort_unless(!$identity->elevated&&$identity->role==='ir_composition_'.$id&&$identity->cluster==='sgf_modular_regression_'.$run,403);
}
public function screen(Request $r)
{
self::guard();$scope=config('purchasing_workspace.scope');
return response()->view('purchasing-entry',['profiles'=>config('purchasing_workspace.profiles'),'company'=>DB::table('companies')->find($scope['company_id']),'unit'=>DB::table('units')->find($scope['unit_id']),'returnTo'=>(string)$r->query('return_to','')])->header('Cache-Control','no-store')->header('X-SGF-Installation',config('purchasing_workspace.id'));
}
public function enter(Request $r)
{
self::guard();$d=$r->validate(['role'=>'required|string','stage'=>'required|string','return_to'=>'nullable|string|max:300']);abort_if(array_diff(array_keys($r->all()),['_token','role','stage','return_to']),422);
$profile=config('purchasing_workspace.profiles.'.$d['role']);abort_unless(is_array($profile)&&isset($profile['stages'][$d['stage']]),403);
$target='/purchasing/'.$d['stage'];
if(!empty($d['return_to'])){
$parts=parse_url($d['return_to']);abort_unless(is_array($parts)&&!isset($parts['scheme'])&&!isset($parts['host'])&&!isset($parts['fragment'])&&($parts['path']??null)===$target,422);
parse_str($parts['query']??'',$query);$allowed=['requests'=>['request'],'suppliers'=>['supplier'],'sourcing'=>['request'],'orders'=>['award'],'receipts'=>['order','receipt','movement'],'invoices'=>['order','invoice'],'obligations'=>['invoice']][$d['stage']];
abort_if(array_diff(array_keys($query),$allowed),422);foreach($query as$v)abort_unless(is_string($v)&&preg_match('/^[1-9][0-9]{0,14}$/D',$v),422);
$pairs=isset($parts['query'])?explode('&',$parts['query']):[];abort_unless(count($pairs)===count($query),422);
if($query){$primary=$d['stage']==='receipts'&&isset($query['movement'])?'movement':$allowed[0];abort_unless(isset($query[$primary]),422);if($primary==='movement')abort_unless(count($query)===1,422);}
$target.=isset($parts['query'])?'?'.http_build_query($query):'';
}
$user=User::findOrFail($profile['user_id']);auth()->login($user);$scope=config('purchasing_workspace.scope');$r->session()->put('auth_version',$user->auth_version);
$r->session()->put('company_context',$scope+['module_id'=>'purchasing','token'=>bin2hex(random_bytes(24))]);
return redirect($target);
}
}