requestMethod = strtoupper(string: $requestMethod); $containerBuilder = new ContainerBuilder(); $containerBuilder->addDefinitions([ DatabaseConnection::class => autowire()->constructorParameter(parameter: 'config', value: $this->config), ]); $this->container = $containerBuilder->build(); $this->domainRepository = $this->container->get(name: DomainRepository::class); $this->apikeyRepository = $this->container->get(name: ApikeyRepository::class); } /** * @return void */ public function processRequest() { if (empty($this->uri[2]) || !(($this->uri[2] == 'domains') || $this->uri[2] == 'ping')) { $this->header = '404 Not Found'; $this->status = "404 Not Found"; $this->message = "Endpoint not found."; } else { if ($this->checkPassword()) { if ($this->uri[2] == "ping") { $this->header = '200 OK'; $this->status = 'pong'; } else { try { match ($this->requestMethod) { 'GET' => $this->handleDomainGetRequest(), 'POST' => $this->handleDomainPostRequest(), 'PUT' => $this->handleDomainPutRequest(), 'DELETE' => $this->handleDomainDeleteRequest() }; } catch (UnhandledMatchError) { $this->header = '400 Bad Request'; $this->status = '400 Bad Request'; $this->message = "unknown request method: $this->requestMethod"; } } } } if (!empty($this->header)) { header(header: $_SERVER['SERVER_PROTOCOL'] . ' ' . $this->header); } if (!empty($this->result)) { echo json_encode(value: $this->result); } else { if (!empty($this->status) && $this->status == 'pong') { echo json_encode(value: [ 'response' => $this->status ]); } else { echo json_encode(value: [ 'status' => $this->status ?? "Error: No status", 'message' => $this->message ?? "Error: No message." ]); } } } /** * @return bool */ public function checkPassword(): bool { $headers = array_change_key_case(array: getallheaders(), case: CASE_UPPER); $apiKey = $headers['X-API-KEY'] ?? ''; if (empty($apiKey)) { $this->header = "401 Unauthorized"; $this->status = "401 Unauthorized"; $this->message = "API key is missing."; return false; } else { [$prefix,] = explode(separator: '.', string: $apiKey); if ($apiResult = $this->apikeyRepository->findByPrefix(prefix: $prefix)) { $storedHash = $apiResult->getApiToken(); if (!password_verify(password: $apiKey, hash: $storedHash)) { $this->header = "401 Unauthorized"; $this->status = "401 Unauthorized"; $this->message = "API key mismatch."; return false; } } else { $this->header = "401 Unauthorized"; $this->status = "401 Unauthorized"; $this->message = "Invalid API key."; return false; } } return true; } /** * @return void */ public function handleDomainGetRequest(): void { if (empty($this->uri[3])) { $domains = $this->domainRepository->findAll(); $resultDomain = []; foreach ($domains as $singleDomain) { $domain = [ 'id' => $singleDomain->getId(), 'name' => $singleDomain->getName(), 'panel_id' => $singleDomain->getPanelId(), 'a' => $singleDomain->getA(), 'aaaa' => $singleDomain->getAaaa() ]; $resultDomain[] = $domain; } $this->result = $resultDomain; } else { if ($result = $this->domainRepository->findByName(name: $this->uri[3])) { $domain = [ 'id' => $result->getId(), 'name' => $result->getName(), 'panel_id' => $result->getPanelId(), 'a' => $result->getA(), 'aaaa' => $result->getAaaa() ]; $this->result = $domain; } else { $this->header = "404 Not Found "; $this->status = "404 Not Found "; $this->message = "The specified domain was not found."; } } } /** * @return void */ public function handleDomainPostRequest(): void { $name = $_POST['name'] ?? ''; $panelID = intval(value: $_POST['panel_id'] ?? 0); $a = $_POST['a'] ?? ''; $aaaa = $_POST['aaaa'] ?? ''; if (empty($name)) { $this->header = "400 Bad Request"; $this->status = "400 Bad Request"; $this->message = "A name is required"; } else { if (empty($a) && empty($aaaa) && empty($panelID)) { $this->header = "400 Bad Request"; $this->status = "400 Bad Request"; $this->message = "At least one IP address or panel ID is required."; } else { if ($this->domainRepository->findByName(name: $name)) { $this->header = "400 Bad request"; $this->status = "400 Bad request"; $this->message = "Domain: $name already exists."; } else { $result = $this->domainRepository->insert(name: $name, panelID: $panelID, a: $a, aaaa: $aaaa); $this->status = "201 Created"; $this->message = $result; } } } } /** * @return void */ public function handleDomainPutRequest(): void { $putData = fopen(filename: 'php://input', mode: 'r'); $data = fread(stream: $putData, length: 512); $params = explode(separator: '&', string: $data); foreach ($params as $param) { [$key, $value] = explode(separator: '=', string: $param); $put[$key] = $value; } $id = $put['id'] ?? 0; $name = $put['name'] ?? ""; $panelID = $put['panel_id'] ?? ""; $a = $put['a'] ?? ""; $aaaa = $put['aaaa'] ?? ""; if ($id == 0) { $this->status = "400 Bad Request"; $this->message = "An ID is required"; } else { if (!$this->domainRepository->findByID(id: $id)) { $this->status = "404 Not Found"; $this->message = "Domain with ID : $id doesn't exist."; } else { // TODO not required, as we rely on the ID if (empty($name)) { $this->status = "400 Bad Request"; $this->message = "A name is required"; } else { if (empty($a) && empty($aaaa)) { $this->status = "400 Bad Request"; $this->message = "At least one IP address is required."; } else { $this->domainRepository->update(id: $id, name: $panelID, panelID: $name, a: $a, aaaa: $aaaa); $this->header = "201 Updated"; $this->status = "201 Updated"; $this->message = "201 Updated"; } } } } } /** * @return void */ public function handleDomainDeleteRequest(): void { $deleteData = fopen(filename: 'php://input', mode: 'r'); $data = fread(stream: $deleteData, length: 512); $params = explode(separator: '&', string: $data); foreach ($params as $param) { [$key, $value] = explode(separator: '=', string: $param); $delete[$key] = $value; } $id = $delete['id'] ?? 0; if ($id == 0) { $this->header = "400 Bad Request"; $this->status = "400 Bad Request"; $this->message = "You need to supply an ID."; } else { if (!$this->domainRepository->findByID(id: $id)) { $this->header = "400 Bad Request"; $this->status = "400 Bad Request"; $this->message = "There is no domain with ID $id."; } else { $this->domainRepository->delete(id: $id); $this->header = "204 No content."; $this->status = "204 No content."; $this->message = "The domain $id has been deleted."; } } } }