companyModel = new CompanyModel(); } public function __invoke(ServerRequestInterface $request): \React\Http\Message\Response { if (!$this->isAuthorized($request)) { return Payload::fail('Unauthorized', [], 'E_VALIDATE', 401); } $body = json_decode((string) $request->getBody(), true); if (!is_array($body)) { return Payload::fail('Invalid JSON payload', [], 'E_VALIDATE', 400); } $company = is_array($body['company'] ?? null) ? $body['company'] : []; $admin = is_array($body['admin'] ?? null) ? $body['admin'] : []; $error = $this->validate($company, $admin); if ($error !== null) { return Payload::fail($error, [], 'E_VALIDATE', 400); } try { $result = $this->companyModel->createCompanyWithAdmin($company, $admin); } catch (\Throwable $e) { Logger::error('Failed to register company', ['error' => $e->getMessage()]); return Payload::fail('Failed to register company', [], 'E_GENERIC', 500); } switch ($result['status']) { case 'cnpj_exists': return Payload::fail('CNPJ already registered', [], 'E_VALIDATE', 400); case 'email_exists': return Payload::fail('Email already exists', [], 'E_VALIDATE', 400); case 'created': return Payload::ok( ['company' => $result['company'], 'user' => $result['user']], 'S_CREATED', 'Company created.' ); default: return Payload::fail('Failed to register company', [], 'E_GENERIC', 500); } } /** * Valida os campos da empresa e do admin. Retorna a mensagem de erro ou null. */ private function validate(array $company, array $admin): ?string { $cnpj = preg_replace('/\D/', '', (string) ($company['cnpj'] ?? '')); $validator = (new Validator([ 'company_name' => $company['name'] ?? null, 'cnpj' => $cnpj, 'name' => $admin['name'] ?? null, 'email' => $admin['email'] ?? null, 'phone' => $admin['phone'] ?? null, 'password' => $admin['password'] ?? null, ])) ->required('company_name')->maxLength('company_name', 100) ->required('cnpj') ->required('name')->maxLength('name', 100) ->required('email')->email('email')->maxLength('email', 100) ->required('phone')->phone('phone')->maxLength('phone', 20) ->required('password')->minLength('password', 8)->maxLength('password', 255); if ($validator->fails()) { return $validator->firstError(); } if (strlen($cnpj) !== 14) { return 'CNPJ must have 14 digits'; } return null; } private function isAuthorized(ServerRequestInterface $request): bool { $expected = (string) ($_ENV['PROVISION_SECRET'] ?? ''); if ($expected === '') { Logger::error('PROVISION_SECRET is not configured; rejecting company provisioning'); return false; } return hash_equals($expected, $request->getHeaderLine('X-Provision-Secret')); } }