| <?php |
| declare(strict_types=1); |
|
|
| require_once __DIR__ . '/src/Bootstrap.php'; |
| \SoftEdge\Env::load(__DIR__); |
| \SoftEdge\Bootstrap::init(); |
|
|
| use SoftEdge\Response; |
| use SoftEdge\Validation; |
| use SoftEdge\AuthService; |
| use SoftEdge\RateLimiter; |
| use SoftEdge\DB; |
| use PDO; |
|
|
| |
| if (!headers_sent()) { |
| header('Content-Type: application/json; charset=utf-8'); |
| header('X-Powered-By: SoftEdge'); |
| } |
|
|
| |
| if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { |
| header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); |
| header('Access-Control-Allow-Headers: Content-Type, X-CSRF-Token, Authorization'); |
| header('Access-Control-Max-Age: 86400'); |
| http_response_code(204); |
| exit; |
| } |
|
|
| |
| $origin = $_SERVER['HTTP_ORIGIN'] ?? ''; |
| $host = $_SERVER['HTTP_HOST'] ?? ''; |
| if ($origin && str_contains($origin, $host)) { |
| header('Access-Control-Allow-Origin: ' . $origin); |
| header('Vary: Origin'); |
| header('Access-Control-Allow-Credentials: true'); |
| } |
|
|
| function path(): string { |
| $uri = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/'; |
| |
| if (isset($_GET['r'])) { |
| $r = '/' . ltrim((string)$_GET['r'], '/'); |
| return $r; |
| } |
| if (preg_match('#/api(?:\.php)?(.*)$#', $uri, $m)) { |
| return $m[1] ? (string)$m[1] : '/'; |
| } |
| return $uri; |
| } |
|
|
| function json_body(): array { |
| $raw = file_get_contents('php://input'); |
| $data = json_decode((string)$raw, true); |
| return is_array($data) ? $data : []; |
| } |
|
|
| $method = strtoupper($_SERVER['REQUEST_METHOD'] ?? 'GET'); |
| $route = rtrim(path(), '/') ?: '/'; |
|
|
| try { |
| switch (true) { |
| case $method === 'GET' && $route === '/health': |
| Response::json([ |
| 'ok' => true, |
| 'time' => date('c'), |
| 'app' => 'SoftEdge API', |
| 'env' => \SoftEdge\Env::get('APP_ENV', 'production'), |
| ]); |
| break; |
|
|
| case $method === 'POST' && $route === '/auth/login': |
| $body = json_body(); |
| $csrf = (string)($body['csrf'] ?? ($_SERVER['HTTP_X_CSRF_TOKEN'] ?? '')); |
| if (!\SoftEdge\Csrf::validate($csrf)) { |
| Response::json(['ok' => false, 'error' => 'CSRF inválido'], 400); |
| break; |
| } |
| $email = trim((string)($body['email'] ?? '')); |
| $password = (string)($body['password'] ?? ''); |
| if (!Validation::email($email)) { |
| Response::json(['ok' => false, 'error' => 'Email inválido'], 422); |
| break; |
| } |
| $res = AuthService::login($email, $password); |
| Response::json($res, (int)($res['status'] ?? 200)); |
| break; |
|
|
| case $method === 'POST' && $route === '/auth/logout': |
| AuthService::logout(); |
| Response::json(['ok' => true]); |
| break; |
|
|
| case $method === 'POST' && $route === '/contact': |
| $body = json_body(); |
| $csrf = (string)($body['csrf'] ?? ($_SERVER['HTTP_X_CSRF_TOKEN'] ?? '')); |
| if (!\SoftEdge\Csrf::validate($csrf)) { |
| Response::json(['ok' => false, 'error' => 'CSRF inválido'], 400); |
| break; |
| } |
| $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; |
| if (!RateLimiter::allow('contact:' . $ip, \SoftEdge\Env::int('RATE_LIMIT_CONTACT', 3), 3600)) { |
| Response::json(['ok' => false, 'error' => 'Muitas solicitações. Tente mais tarde.'], 429); |
| break; |
| } |
| $name = trim((string)($body['name'] ?? '')); |
| $email = trim((string)($body['email'] ?? '')); |
| $message = trim((string)($body['message'] ?? '')); |
| $phone = trim((string)($body['phone'] ?? '')); |
| $company = trim((string)($body['company'] ?? '')); |
| $subject = trim((string)($body['subject'] ?? '')); |
|
|
| $errors = Validation::required(['name' => $name, 'email' => $email, 'message' => $message], ['name','email','message']); |
| if (!empty($errors) || !Validation::email($email)) { |
| $errors['email'] = $errors['email'] ?? (!Validation::email($email) ? 'Email inválido' : null); |
| Response::json(['ok' => false, 'errors' => array_filter($errors)], 422); |
| break; |
| } |
|
|
| $pdo = DB::pdo(); |
| $stmt = $pdo->prepare('INSERT INTO contact_submissions (name, email, phone, company, subject, message, status) VALUES (:name,:email,:phone,:company,:subject,:message,\'new\')'); |
| $stmt->execute([ |
| ':name' => $name, |
| ':email' => $email, |
| ':phone' => $phone ?: null, |
| ':company' => $company ?: null, |
| ':subject' => $subject ?: null, |
| ':message' => $message, |
| ]); |
| Response::json(['ok' => true, 'id' => (int)$pdo->lastInsertId()], 201); |
| break; |
|
|
| default: |
| Response::json(['ok' => false, 'error' => 'Rota não encontrada', 'route' => $route], 404); |
| break; |
| } |
| } catch (Throwable $e) { |
| Response::json([ |
| 'ok' => false, |
| 'error' => 'Erro interno', |
| ], 500); |
| } |
|
|