environment('browser-testing')
&& in_array($request->ip(), ['127.0.0.1', '::1'], true)
&& in_array($request->getHost(), ['127.0.0.1', 'localhost', '::1'], true), 404);
TestingDatabaseGuard::assertSafe();
$manifest = json_decode(file_get_contents('C:/laragon/data/sgf-tempo/secrets/browser-fixture.json'), true, 64, JSON_THROW_ON_ERROR);
abort_unless(($manifest['product_demo']['version'] ?? '') === 'SGF-PRODUCT-DEMO-v1'
&& ($manifest['product_demo']['synthetic_only'] ?? false) === true, 404);
return $manifest;
};
Route::get('/avaliar', function (Request $request) use ($demoManifest) {
$demoManifest($request);
$csrf = htmlspecialchars(csrf_token(), ENT_QUOTES, 'UTF-8');
$html = '
Explorar SGF TempoExplorar SGF Tempo
Entrada de avaliação local, sem palavra-passe. Podes trocar de função sempre que quiseres, sem pedir concessões.
Aplicação integrada
Clientes, serviços, documentação, facturas de teste, recebimentos simulados, oficina, custos e orçamento industrial.
';
foreach (['proprietario' => 'Entrar como proprietário — todas as áreas desta instalação', 'preparador' => 'Preparar e gerir', 'validador' => 'Rever e validar', 'tecnico' => 'Registar trabalho de oficina', 'verificador' => 'Verificar trabalho de oficina'] as $role => $label) {
$html .= '';
}
$html .= 'Dados sintéticos persistentes e partilhados. A troca de função conserva os exemplos e o histórico. Esta entrada não concede administração da instalação real nem elimina as regras dos processos.
';
return response($html)->header('Cache-Control', 'no-store')->header('X-Robots-Tag', 'noindex, nofollow');
});
Route::post('/avaliar/entrar', function (Request $request) use ($demoManifest) {
$manifest = $demoManifest($request);
$data = $request->validate(['role' => 'required|in:proprietario,preparador,validador,tecnico,verificador']);
abort_if(array_diff(array_keys($request->all()), ['role', '_token']) !== [], 422);
if ($data['role'] === 'proprietario') {
$user = DB::transaction(function () use ($manifest) {
// Serialise provisioning, including first entry. Never touch customer accounts.
DB::select('select pg_advisory_xact_lock(?)', [80202910]);
$owner = User::firstOrCreate(['email' => 'proprietario-avaliacao@example.test'],
['name' => 'Proprietário — avaliação local', 'password' => bin2hex(random_bytes(32))]);
$actors = array_values($manifest['product_demo']['actors']);
$memberships = DB::table('company_memberships')->whereIn('user_id', $actors)->get(['tenant_id', 'company_id'])->unique('company_id');
$added = 0;
foreach ($memberships as $membership) {
DB::table('company_memberships')->insertOrIgnore(['user_id' => $owner->id, 'tenant_id' => $membership->tenant_id, 'company_id' => $membership->company_id]);
}
$grants = DB::table('permission_grants')->whereIn('user_id', $actors)->get(['tenant_id', 'company_id', 'permission', 'unit_id']);
foreach (['view', 'propose', 'approve'] as $action) {
$grants->push((object) ['tenant_id' => $manifest['tenant'], 'company_id' => $manifest['company'], 'permission' => 'catalogue_accounting.'.$action, 'unit_id' => null]);
}
foreach ($grants as $grant) {
$scope = ['user_id' => $owner->id, 'tenant_id' => $grant->tenant_id, 'company_id' => $grant->company_id, 'permission' => $grant->permission, 'unit_id' => $grant->unit_id];
if (!DB::table('permission_grants')->where($scope)->exists()) {
DB::table('permission_grants')->insert($scope + ['created_at' => now(), 'updated_at' => now()]);
$added++;
}
}
if ($added) {
Audit::record('demo.owner_access_prepared', $owner->id, $manifest['tenant'], $manifest['company'], $manifest['unit'], details: ['synthetic' => true, 'grants_added' => $added]);
}
return $owner;
});
} else {
$user = User::findOrFail($manifest['product_demo']['actors'][$data['role']]);
}
abort_unless(str_ends_with($user->email, '@example.test'), 403);
app(CompanyContext::class)->selectFor($user->id, $manifest['tenant'], $manifest['company'], $manifest['unit']);
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
Auth::login($user, false);
$request->session()->regenerate();
$request->session()->put('auth_version', (int) $user->auth_version);
$request->session()->put('company_context', ['tenant_id' => (int) $manifest['tenant'], 'company_id' => (int) $manifest['company'], 'unit_id' => (int) $manifest['unit'], 'token' => bin2hex(random_bytes(24))]);
Audit::record('demo.entered', $user->id, $manifest['tenant'], $manifest['company'], $manifest['unit'], details: ['role' => $data['role'], 'synthetic' => true]);
return redirect('/');
})->middleware('throttle:30,1');