Gerado em 2025-12-07 08:26:22
| Chave | Valor |
|---|---|
APP_DEBUG |
true |
APP_ENV |
production |
APP_KEY |
********** |
APP_NAME |
Syrios |
APP_TIMEZONE |
America/Sao_Paulo |
APP_TRUSTED_PROXIES |
* |
APP_URL |
https://syrios.up.railway.app |
ASSET_URL |
null |
CACHE_DRIVER |
file |
DB_CONNECTION |
mysql |
DB_DATABASE |
********** |
DB_HOST |
********** |
DB_PASSWORD |
********** |
DB_PORT |
3306 |
DB_USERNAME |
********** |
GPG_KEYS |
39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC |
HOME |
/root |
HOSTNAME |
c202a791efda |
LOG_CHANNEL |
stack |
LOG_LEVEL |
debug |
PATH |
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |
PHPIZE_DEPS |
autoconf dpkg-dev file g++ gcc libc-dev make pkg-config re2c |
PHP_ASC_URL |
https://www.php.net/distributions/php-8.2.29.tar.xz.asc |
PHP_CFLAGS |
-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 |
PHP_CPPFLAGS |
-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 |
PHP_INI_DIR |
/usr/local/etc/php |
PHP_LDFLAGS |
-Wl,-O1 -pie |
PHP_SHA256 |
475f991afd2d5b901fb410be407d929bc00c46285d3f439a02c59e8b6fe3589c |
PHP_URL |
https://www.php.net/distributions/php-8.2.29.tar.xz |
PHP_VERSION |
8.2.29 |
PORT |
8080 |
PWD |
/app/public |
QUEUE_CONNECTION |
sync |
RAILWAY_BETA_ENABLE_RUNTIME_V2 |
1 |
RAILWAY_DEPLOYMENT_ID |
d48dc75c-0f61-4410-98f1-b597c6aa02d7 |
RAILWAY_ENVIRONMENT |
production |
RAILWAY_ENVIRONMENT_ID |
5e108015-ced5-4394-8462-27f0ac14d80d |
RAILWAY_ENVIRONMENT_NAME |
production |
RAILWAY_GIT_AUTHOR |
DavidFenix |
RAILWAY_GIT_BRANCH |
main |
RAILWAY_GIT_COMMIT_MESSAGE |
idem |
RAILWAY_GIT_COMMIT_SHA |
ceb7151001aeaa6b8c7d9dfe150fb9caa315ffec |
RAILWAY_GIT_REPO_NAME |
syrios |
RAILWAY_GIT_REPO_OWNER |
DavidFenix |
RAILWAY_PRIVATE_DOMAIN |
virtuous-curiosity.railway.internal |
RAILWAY_PROJECT_ID |
00910e33-8565-4fe0-a225-fec4029d7d61 |
RAILWAY_PROJECT_NAME |
Projeto Syrios |
RAILWAY_PUBLIC_DOMAIN |
syrios.up.railway.app |
RAILWAY_REPLICA_ID |
e769e47b-c31e-4338-a837-e4b75d095d93 |
RAILWAY_REPLICA_REGION |
us-west2 |
RAILWAY_SERVICE_ID |
2b198754-5238-4ad4-9aff-c98e6508e955 |
RAILWAY_SERVICE_NAME |
Syrios |
RAILWAY_SERVICE_SYRIOSIA_URL |
syriosia.up.railway.app |
RAILWAY_SERVICE_SYRIOS_FAIL_URL |
syrios-fail.up.railway.app |
RAILWAY_SERVICE_SYRIOS_URL |
syrios.up.railway.app |
RAILWAY_SNAPSHOT_ID |
dfa0aac7-8219-4f41-8a21-2ac0babb2066 |
RAILWAY_STATIC_URL |
syrios.up.railway.app |
SESSION_DOMAIN |
syrios.up.railway.app |
SESSION_DRIVER |
file |
SESSION_LIFETIME |
120 |
SESSION_SAME_SITE |
none |
SESSION_SECURE_COOKIE |
true |
SHELL_VERBOSITY |
0 |
container |
podman |
{
"paths": [
"api/*",
"login",
"sanctum/csrf-cookie"
],
"allowed_methods": [
"*"
],
"allowed_origins": [
"*"
],
"allowed_origins_patterns": [],
"allowed_headers": [
"*"
],
"exposed_headers": [],
"max_age": 0,
"supports_credentials": false
}
# Usa imagem leve e moderna do PHP
FROM php:8.2-cli
# Define o diretório de trabalho
WORKDIR /app
# Copia todos os arquivos do projeto Laravel para dentro da imagem
COPY . .
# Instala dependências do sistema e extensões do PHP
RUN apt-get update && apt-get install -y unzip git libzip-dev && \
docker-php-ext-install pdo_mysql zip
# 🔹 Instala o Composer (copiando da imagem oficial do Composer)
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# 🔹 Instala as dependências do Laravel
RUN composer install --no-dev --optimize-autoloader
# Expõe a porta padrão usada pelo Railway
EXPOSE 8080
# Comando de inicialização do Laravel (servidor embutido)
CMD ["php", "artisan", "serve", "--host=0.0.0.0", "--port=8080"]
<?php
namespace App\Providers;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
use Symfony\Component\HttpFoundation\Request;
use Carbon\Carbon;
use Illuminate\Pagination\Paginator;
use Illuminate\Database\Migrations\Migrator;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
//
}
public function boot()
{
// debug:passo2::Impede execução de migrações definindo um diretório vazio
$this->app->afterResolving('migrator', function (Migrator $migrator) {
$migrator->path('database/migrations_disabled');
});
// 🔧 Configurações gerais
Schema::defaultStringLength(191);
Carbon::setLocale('pt_BR');
Paginator::defaultView('vendor.pagination.default');
/*
|--------------------------------------------------------------------------
| Força HTTPS somente quando houver proxy indicando isso
|--------------------------------------------------------------------------
*/
if ($this->app->environment('production')) {
if (request()->header('x-forwarded-proto') === 'https') {
URL::forceScheme('https');
}
}
/*
|--------------------------------------------------------------------------
| Criação automática do symlink storage → public/storage
| Somente em produção e somente se ainda não existir
|--------------------------------------------------------------------------
*/
if ($this->app->environment('production')) {
$public = public_path('storage');
$target = storage_path('app/public');
// Se o link ainda NÃO existir
if (!is_link($public)) {
try {
// garante que o diretório de destino existe
if (!is_dir($target)) {
@mkdir($target, 0755, true);
}
// cria o link
symlink($target, $public);
} catch (\Throwable $e) {
// silencioso para não quebrar o sistema
// railway não permite mkdir em certas horas
}
}
}
}
// public function boot()
// {
// // 🔧 Configurações gerais
// Schema::defaultStringLength(191);
// Carbon::setLocale('pt_BR');
// //date_default_timezone_set('America/Sao_Paulo');
// Paginator::defaultView('vendor.pagination.default');
// // if (App::environment('production')) {
// // URL::forceScheme('https');
// // }
// if ($this->app->environment('production')) {
// if (request()->header('x-forwarded-proto') === 'https') {
// URL::forceScheme('https');
// }
// }
// }
}
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array<int, class-string|string>
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array<string, class-string|string>
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'role' => \App\Http\Middleware\RoleMiddleware::class,
'ensure.context' => \App\Http\Middleware\EnsureContextSelected::class,
];
}
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
protected $proxies = '*';
protected $headers = Request::HEADER_X_FORWARDED_ALL;
}
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
protected $addHttpCookie = true;
protected $except = [
// Rotas públicas sem CSRF (se houver)
];
}
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/
'paths' => ['api/*', 'login', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];
<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Artisan;
use Symfony\Component\HttpFoundation\Cookie;
// Auth
use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\DiagController;
// Master
use App\Http\Controllers\Master\EscolaController as MasterEscolaController;
use App\Http\Controllers\Master\RoleController as MasterRoleController;
use App\Http\Controllers\Master\UsuarioController as MasterUsuarioController;
use App\Http\Controllers\Master\DashboardController as MasterDashboardController;
use App\Http\Controllers\Master\ImagemController;
// Secretaria
use App\Http\Controllers\Secretaria\EscolaController as SecretariaEscolaController;
use App\Http\Controllers\Secretaria\UsuarioController as SecretariaUsuarioController;
// Escola
use App\Http\Controllers\Escola\AlunoController;
use App\Http\Controllers\Escola\DashboardController;
use App\Http\Controllers\Escola\DisciplinaController;
use App\Http\Controllers\Escola\ProfessorController;
use App\Http\Controllers\Escola\TurmaController;
use App\Http\Controllers\Escola\UsuarioController as EscolaUsuarioController;
use App\Http\Controllers\Escola\RegimentoController;
use App\Http\Controllers\Escola\ModeloMotivoController;
use App\Http\Controllers\Escola\AlunoFotoController;
use App\Http\Controllers\Escola\AlunoFotoLoteController;
use App\Http\Controllers\Escola\EnturmacaoController;
use App\Http\Controllers\Escola\LotacaoController;
use App\Http\Controllers\Escola\DiretorTurmaController;
use App\Http\Controllers\Escola\IdentidadeController;
// Professor
use App\Http\Controllers\Professor\{
DashboardController as ProfessorDashboardController,
OfertaController,
OcorrenciaController,
RelatorioController,
PerfilController
};
//somente para testes, remova em produção
Route::get('/kill-cookie', function () {
return response('Cookie removido')
->cookie('syriosia_session', null, -1, '/', 'syriosia.up.railway.app', true, true, false, 'None')
->cookie('XSRF-TOKEN', null, -1, '/', 'syriosia.up.railway.app', true, true, false, 'None');
});
/*
|--------------------------------------------------------------------------
| Rotas Públicas (sem login)
|--------------------------------------------------------------------------
| Observação: por padrão, o RouteServiceProvider aplica o grupo "web".
| Mantemos explícito aqui para clareza do fluxo.
*/
Route::middleware(['web'])->group(function () {
// Página inicial → login
Route::get('/', fn() => redirect()->route('login'));
Route::prefix('diag')->group(function () {
Route::get('/', [DiagController::class, 'index'])->name('diag.index');
Route::get('/headers', [DiagController::class, 'headers'])->name('diag.headers');
Route::get('/cookies', [DiagController::class, 'cookies'])->name('diag.cookies');
Route::get('/set-cookie', [DiagController::class, 'setCookie'])->name('diag.setcookie');
Route::get('/configs', [DiagController::class, 'configs'])->name('diag.configs');
Route::get('/cookie-test', function () {
return response('ok')->cookie( 'probe', '1', 0, null, null, true, true, false, 'None' );
});
});
Route::get('/cache-clear', function () {
Artisan::call('config:clear');
Artisan::call('cache:clear');
Artisan::call('route:clear');
Artisan::call('view:clear');
return "Cache limpo!";
});
// Login / Logout (públicas)
Route::get('/login', [LoginController::class, 'showLoginForm'])->name('login');
Route::post('/login', [LoginController::class, 'login']);
Route::post('/logout', [LoginController::class, 'logout'])->name('logout');
// Rotas de diagnóstico e testes rápidos (públicas)
Route::get('/way', function () {
return '
<h2>Login Teste</h2>
<form method="post" action="/waylogin">
<input type="email" name="email" placeholder="Email" required><br><br>
<input type="password" name="password" placeholder="Senha" required><br><br>
<button type="submit">Entrar</button>
</form>
<hr><a href="/waydiag">Diagnóstico</a>';
});
Route::post('/waylogin', function (Request $request) {
Session::put('user', [
'email' => $request->email,
'logged_at' => now()->toDateTimeString()
]);
return redirect('/waydashboard');
});
Route::get('/waydashboard', function () {
if (!Session::has('user')) {
return redirect('/way');
}
$u = Session::get('user');
return "
<h2>Área Protegida</h2>
<p>Email: <b>{$u['email']}</b></p>
<p>Login em: {$u['logged_at']}</p>
<a href='/waylogout'>Sair</a> | <a href='/waydiag'>Diagnóstico</a>";
});
Route::get('/waylogout', function () {
Session::flush();
return redirect('/way');
});
Route::get('/waydiag', function (Request $r) {
$headers = [];
foreach ($r->headers->all() as $k => $v) {
$headers[$k] = implode('; ', $v);
}
return response()->make("
<h2>Diagnóstico</h2>
<p>HTTPS detectado: " . ($r->isSecure() ? 'Sim' : 'Não') . "</p>
<h3>Cookies</h3><pre>" . print_r($r->cookies->all(), true) . "</pre>
<h3>Sessão</h3><pre>" . print_r(session()->all(), true) . "</pre>
<h3>Headers</h3><pre>" . print_r($headers, true) . "</pre>
<a href='/way'>Voltar</a>", 200, ['Content-Type' => 'text/html']);
});
// Debugs e testes auxiliares
Route::get('/header-debug', function (Request $request) {
if (!Session::isStarted()) {
Session::start();
}
Session::put('debug_test', now()->toDateTimeString());
$data = [
'timestamp' => now()->toDateTimeString(),
'client_ip' => $request->ip(),
'session_value' => Session::get('debug_test'),
'cookies_received' => $request->cookies->all(),
'headers_received' => $request->headers->all(),
];
$response = response()->json([
'debug_info' => $data,
'note' => 'Check if headers or cookies below are modified by proxies.'
]);
$response->headers->set('X-Debug-App', 'Syrios');
$response->headers->set('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
$response->headers->set('Pragma', 'no-cache');
$testCookie = new Cookie(
'test_cookie',
'ok',
time() + 3600,
'/',
null,
true,
false,
false,
'None'
);
$response->headers->setCookie($testCookie);
return $response;
});
Route::get('/debug', fn() => ['secure' => request()->isSecure(), 'url' => url('/')]);
Route::get('/debug-headers', fn() => response()->json(['headers' => request()->headers->all()]));
Route::get('/cookie-test', function (Request $request) {
$response = response('<h1>cookie test</h1>');
// Observação: domínio aqui era "syrios.onrender.com" no original; mantive como estava,
// mas considere ajustar para o domínio atual quando usar este teste.
$response->cookie('cookie_test', 'ok', 10, '/', 'syrios.onrender.com', true, true, false, 'None');
return $response;
});
Route::get('/session-debug', function () {
return response()->json([
'session_id' => session()->getId(),
'has_token' => session()->has('_token'),
'csrf_token' => csrf_token(),
'cookies' => request()->cookies->all(),
]);
});
Route::get('/cookie-proxy-test', function () {
$response = new Response('<h1>Teste manual de cookie</h1><p>Verifique se o navegador recebeu o cookie chamado <b>proxy_test_cookie</b>.</p>');
$response->header('Set-Cookie', 'proxy_test_cookie=OK_FROM_SERVER; Path=/; Max-Age=600; SameSite=None; Secure');
return $response;
});
// Regimento público
Route::get('regimento/{school}', [RegimentoController::class, 'visualizar'])
->name('regimento.visualizar');
});
/*
|--------------------------------------------------------------------------
| Pós-Login (com sessão carregada) — Escolha de Contexto
|--------------------------------------------------------------------------
| Essas rotas precisam apenas do usuário autenticado, sem exigir contexto.
| Aqui o cookie de sessão já foi entregue ao navegador.
*/
Route::middleware(['auth'])->group(function () {
Route::get('/choose-school', [LoginController::class, 'chooseSchool'])->name('choose.school');
Route::get('/choose-role/{schoolId}', [LoginController::class, 'chooseRole'])->name('choose.role');
Route::post('/set-context', [LoginController::class, 'setContextPost'])->name('set.context');
});
/*
|--------------------------------------------------------------------------
| Rotas Protegidas por Contexto (auth + ensure.context)
|--------------------------------------------------------------------------
| A partir daqui, o contexto (current_school_id/current_role) já deve existir.
| Evitamos rodar ensure.context antes do cookie ser entregue (problema original).
*/
Route::middleware(['auth', 'ensure.context'])->group(function () {
/*
|--------------------------------------------------------------------------
| Rotas do Master
|--------------------------------------------------------------------------
*/
Route::prefix('master')
->middleware(['role:master'])
->name('master.')
->group(function () {
Route::get('dashboard', [MasterDashboardController::class, 'index'])->name('dashboard');
Route::get('/', fn () => redirect()->route('master.dashboard'));
Route::resource('escolas', MasterEscolaController::class)->except(['show']);
Route::get('escolas/{escola}/detalhes', [MasterEscolaController::class, 'detalhes'])
->name('escolas.detalhes');
Route::resource('roles', MasterRoleController::class)->only(['index']);
Route::resource('usuarios', MasterUsuarioController::class);
// Associações Escola Mãe ↔ Escola Filha
Route::get('associacoes', [MasterEscolaController::class, 'associacoes'])->name('escolas.associacoes');
Route::post('associacoes', [MasterEscolaController::class, 'associarFilha'])->name('escolas.associar');
Route::post('usuarios/{usuario}/vincular', [MasterUsuarioController::class, 'vincular'])
->name('usuarios.vincular');
// Gestão de roles específicas por usuario
Route::get('usuarios/{usuario}/roles', [MasterUsuarioController::class, 'editRoles'])
->name('usuarios.roles.edit');
Route::post('usuarios/{usuario}/roles', [MasterUsuarioController::class, 'updateRoles'])
->name('usuarios.roles.update');
// Confirmação/Exclusão
Route::get('usuarios/{usuario}/confirm-destroy', [MasterUsuarioController::class, 'confirmDestroy'])
->name('usuarios.confirmDestroy');
Route::delete('usuarios/{usuario}', [MasterUsuarioController::class, 'destroy'])
->name('usuarios.destroy');
// Imagens
Route::get('imagens', [ImagemController::class, 'index'])->name('imagens.index');
Route::post('imagens/limpar', [ImagemController::class, 'limpar'])->name('imagens.limpar');
});
/*
|--------------------------------------------------------------------------
| Rotas da Secretaria
|--------------------------------------------------------------------------
*/
Route::prefix('secretaria')
->middleware(['role:secretaria'])
->name('secretaria.')
->group(function () {
Route::get('/', fn () => redirect()->route('secretaria.escolas.index'))->name('dashboard');
Route::resource('escolas', SecretariaEscolaController::class)->except(['show']);
Route::resource('usuarios', SecretariaUsuarioController::class)->except(['show']);
Route::post('usuarios/{usuario}/vincular', [SecretariaUsuarioController::class, 'vincular'])
->name('usuarios.vincular');
Route::get('usuarios/{usuario}/roles', [SecretariaUsuarioController::class, 'editRoles'])
->name('usuarios.roles.edit');
Route::post('usuarios/{usuario}/roles', [SecretariaUsuarioController::class, 'updateRoles'])
->name('usuarios.roles.update');
});
/*
|--------------------------------------------------------------------------
| Rotas da Escola
|--------------------------------------------------------------------------
*/
Route::prefix('escola')
->middleware(['role:escola'])
->name('escola.')
->group(function () {
Route::get('/', fn () => redirect()->route('escola.dashboard'));
Route::get('dashboard', [DashboardController::class, 'index'])->name('dashboard');
// Usuários (professores, pais, etc.)
Route::resource('usuarios', EscolaUsuarioController::class)->except(['show']);
Route::post('usuarios/{usuario}/vincular', [EscolaUsuarioController::class, 'vincular'])->name('usuarios.vincular');
// Professores
Route::resource('professores', ProfessorController::class)->except(['show']);
// Disciplinas
Route::resource('disciplinas', DisciplinaController::class)->except(['show']);
// Turmas
Route::resource('turmas', TurmaController::class)->except(['show']);
// Alunos
Route::resource('alunos', AlunoController::class)->except(['show']);
// Roles por usuário da Escola
Route::get('usuarios/{usuario}/roles', [EscolaUsuarioController::class, 'editRoles'])
->name('usuarios.roles.edit');
Route::post('usuarios/{usuario}/roles', [EscolaUsuarioController::class, 'updateRoles'])
->name('usuarios.roles.update');
// Vincular aluno existente à escola atual
Route::post('alunos/{aluno}/vincular', [AlunoController::class, 'vincular'])
->name('alunos.vincular');
// Enturmações (vínculos aluno–turma)
Route::resource('enturmacao', EnturmacaoController::class)->except(['show']);
Route::post('enturmacao/storeBatch', [EnturmacaoController::class, 'storeBatch'])
->name('enturmacao.storeBatch');
// Lotação
Route::resource('lotacao', LotacaoController::class)->except(['show']);
Route::prefix('lotacao')->name('lotacao.')->group(function () {
Route::get('diretor_turma', [DiretorTurmaController::class, 'index'])
->name('diretor_turma.index');
Route::post('diretor_turma/update', [DiretorTurmaController::class, 'update'])
->name('diretor_turma.update');
Route::delete('diretor_turma/{id}', [DiretorTurmaController::class, 'destroy'])
->name('diretor_turma.destroy');
});
// Identidade visual
Route::get('identidade', [IdentidadeController::class, 'edit'])
->name('identidade.edit');
Route::post('identidade', [IdentidadeController::class, 'update'])
->name('identidade.update');
// Regimento (painel da escola)
Route::get('regimento', [RegimentoController::class, 'index'])->name('regimento.index');
Route::post('regimento', [RegimentoController::class, 'update'])->name('regimento.update');
// Motivos de Ocorrência
Route::resource('motivos', ModeloMotivoController::class)->except(['show']);
// Importar motivos de outras escolas
Route::get('motivos/importar', [ModeloMotivoController::class, 'importar'])
->name('motivos.importar');
Route::post('motivos/importar', [ModeloMotivoController::class, 'importarSalvar'])
->name('motivos.importar.salvar');
// Uploads de fotos
Route::get('alunos/{aluno}/foto', [AlunoFotoController::class, 'edit'])->name('alunos.foto.edit');
Route::post('alunos/{aluno}/foto', [AlunoFotoController::class, 'update'])->name('alunos.foto.update');
Route::get('alunos/fotos-lote', [AlunoFotoLoteController::class, 'index'])->name('alunos.fotos.lote');
Route::post('alunos/fotos-lote', [AlunoFotoLoteController::class, 'store'])->name('alunos.fotos.lote.store');
});
/*
|--------------------------------------------------------------------------
| Rotas do Professor
|--------------------------------------------------------------------------
*/
Route::prefix('professor')
->middleware(['role:professor'])
->name('professor.')
->group(function () {
// Painel e perfil
Route::get('dashboard', [ProfessorDashboardController::class, 'index'])
->name('dashboard');
Route::get('perfil', [PerfilController::class, 'index'])
->name('perfil');
// Ofertas
Route::prefix('ofertas')->name('ofertas.')->group(function () {
Route::get('/', [OfertaController::class, 'index'])->name('index');
Route::get('{oferta}/alunos', [OfertaController::class, 'alunos'])->name('alunos');
Route::post('{oferta}/alunos', [OfertaController::class, 'alunosPost'])->name('alunos.post');
// Ocorrências por oferta
Route::get('{oferta}/ocorrencias/create', [OcorrenciaController::class, 'create'])
->name('ocorrencias.create');
Route::post('ocorrencias/store', [OcorrenciaController::class, 'store'])
->name('ocorrencias.store');
});
// Ocorrências (rotas gerais)
Route::prefix('ocorrencias')->name('ocorrencias.')->group(function () {
Route::get('/', [OcorrenciaController::class, 'index'])->name('index');
Route::get('{id}', [OcorrenciaController::class, 'show'])->name('show');
Route::get('{id}/edit', [OcorrenciaController::class, 'edit'])->name('edit');
Route::put('{id}', [OcorrenciaController::class, 'update'])->name('update');
Route::delete('{id}', [OcorrenciaController::class, 'destroy'])->name('destroy');
Route::patch('{id}/status', [OcorrenciaController::class, 'updateStatus'])->name('updateStatus');
// Encaminhar / arquivar (somente diretor)
Route::get('{id}/encaminhar', [OcorrenciaController::class, 'encaminhar'])
->name('encaminhar');
Route::post('{id}/encaminhar', [OcorrenciaController::class, 'salvarEncaminhamento'])
->name('encaminhar.salvar');
// Histórico do aluno
Route::get('historico/{aluno}', [OcorrenciaController::class, 'historico'])
->name('historico');
// Histórico resumido (visual e PDF)
Route::get('historico-resumido/{aluno}', [OcorrenciaController::class, 'historicoResumido'])
->name('historico_resumido');
Route::get('pdf/{aluno}', [OcorrenciaController::class, 'gerarPdf'])
->name('pdf');
});
// Rota pública sob /professor (mantida como no original)
Route::get('regimento/{school}', [RegimentoController::class, 'visualizar'])
->name('regimento.visualizar');
// Relatórios
Route::get('relatorios', [RelatorioController::class, 'index'])
->name('relatorios.index');
});
});
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>