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 Tempo

Explorar 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 .= '

Percursos em instalações separadas

Controlo orçamental de Compras

Obrigações a fornecedores no SGF

Compras autónomo

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