55 lines
5.1 KiB
PHP
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);
|
|
}
|
|
}
|