['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); } }