From de89a9e3b4f6fd10e2d821c793fc10b0e98e3e39 Mon Sep 17 00:00:00 2001 From: Pinga <121483313+getpinga@users.noreply.github.com> Date: Tue, 1 Apr 2025 11:59:10 +0300 Subject: [PATCH] Added ability to manage custom registrar pricing from panel; fixed #163 --- cp/app/Controllers/RegistrarsController.php | 116 ++++++- cp/bootstrap/app.php | 3 + cp/bootstrap/helper.php | 5 + .../views/admin/registrars/customPricing.twig | 284 ++++++++++++------ cp/routes/web.php | 3 +- 5 files changed, 314 insertions(+), 97 deletions(-) diff --git a/cp/app/Controllers/RegistrarsController.php b/cp/app/Controllers/RegistrarsController.php index 6cf7496..ea5c184 100644 --- a/cp/app/Controllers/RegistrarsController.php +++ b/cp/app/Controllers/RegistrarsController.php @@ -1245,24 +1245,16 @@ class RegistrarsController extends Controller } } - public function updateCustomPricing(Request $request, Response $response, $args) + public function customPricingView(Request $request, Response $response, $args) { if ($_SESSION["auth_roles"] != 0) { return $response->withHeader('Location', '/dashboard')->withStatus(302); } - //TODO - if ($request->getMethod() === 'POST') { - // Retrieve POST data - $data = $request->getParsedBody(); - $db = $this->container->get('db'); - - var_dump ($data);die(); - } - + $db = $this->container->get('db'); // Get the current URI $uri = $request->getUri()->getPath(); - + if ($args) { $args = trim($args); @@ -1300,6 +1292,108 @@ class RegistrarsController extends Controller } } + public function updateCustomPricing(Request $request, Response $response, $args) + { + if ($_SESSION["auth_roles"] != 0) { + return $response->withHeader('Location', '/dashboard')->withStatus(302); + } + + if (!$args) { + return $response->withHeader('Location', '/registrars')->withStatus(302); + } + + $method = $request->getMethod(); + $body = $request->getBody()->__toString(); + $data = json_decode($body, true); + $db = $this->container->get('db'); + $clid = getClid($db, $args); + + $tld = $data['tld'] ?? null; + $action = $data['action'] ?? null; + + if (!$tld || !$action || !in_array($action, ['create', 'renew', 'transfer', 'restore'])) { + $response->getBody()->write(json_encode(['error' => 'Invalid input'])); + return $response->withHeader('Content-Type', 'application/json')->withStatus(400); + } + + $tldId = $db->selectValue('SELECT id FROM domain_tld WHERE tld = ?', [$tld]); + if (!$tldId) { + $response->getBody()->write(json_encode(['error' => 'TLD not found'])); + return $response->withHeader('Content-Type', 'application/json')->withStatus(404); + } + + if ($method === 'POST') { + $prices = $data['prices'] ?? []; + + if ($action === 'restore') { + $price = $prices['restore'] ?? null; + if ($price === null) { + $response->getBody()->write(json_encode(['error' => 'Missing restore price'])); + return $response->withHeader('Content-Type', 'application/json')->withStatus(400); + } + + $db->exec(' + INSERT INTO domain_restore_price (tldid, registrar_id, price) + VALUES (?, ?, ?) + ON DUPLICATE KEY UPDATE price = VALUES(price) + ', [$tldId, $clid, $price]); + + } else { + $columns = []; + foreach ($prices as $key => $val) { + if (preg_match('/^y(\d{1,2})$/', $key, $matches)) { + $year = (int)$matches[1]; + $months = $year * 12; + $col = 'm' . $months; + $columns[$col] = $val; + } + } + + if (!empty($columns)) { + $columns['tldid'] = $tldId; + $columns['registrar_id'] = $clid; + $columns['command'] = $action; + + $colNames = array_keys($columns); + $placeholders = array_fill(0, count($columns), '?'); + $values = array_values($columns); + + $updateClause = implode(', ', array_map(function ($col) { + return "$col = VALUES($col)"; + }, $colNames)); + + $sql = 'INSERT INTO domain_price (' . implode(', ', $colNames) . ') + VALUES (' . implode(', ', $placeholders) . ') + ON DUPLICATE KEY UPDATE ' . $updateClause; + + $db->exec($sql, $values); + } + } + + $response->getBody()->write(json_encode(['success' => true])); + return $response->withHeader('Content-Type', 'application/json')->withStatus(200); + } + + elseif ($method === 'DELETE') { + if ($action === 'restore') { + $db->delete('domain_restore_price', [ + 'tldid' => $tldId, + 'registrar_id' => $clid + ]); + } else { + $db->exec('DELETE FROM domain_price WHERE tldid = ? AND registrar_id = ? AND command = ?', [ + $tldId, $clid, $action + ]); + } + + $response->getBody()->write(json_encode(['success' => true])); + return $response->withHeader('Content-Type', 'application/json')->withStatus(200); + } + + $response->getBody()->write(json_encode(['error' => 'Method not allowed'])); + return $response->withHeader('Content-Type', 'application/json')->withStatus(405); + } + public function transferRegistrar(Request $request, Response $response) { if ($_SESSION["auth_roles"] != 0) { diff --git a/cp/bootstrap/app.php b/cp/bootstrap/app.php index 021b0fc..ea1d936 100644 --- a/cp/bootstrap/app.php +++ b/cp/bootstrap/app.php @@ -304,6 +304,9 @@ $csrfMiddleware = function ($request, $handler) use ($container) { if ($path && $path === '/clear-cache') { return $handler->handle($request); } + if (str_starts_with($path, '/registrar/updatepricing/')) { + return $handler->handle($request); + } if ($path && $path === '/token-well') { $csrf->generateToken(); return $handler->handle($request); diff --git a/cp/bootstrap/helper.php b/cp/bootstrap/helper.php index ad28100..be1c655 100644 --- a/cp/bootstrap/helper.php +++ b/cp/bootstrap/helper.php @@ -1154,4 +1154,9 @@ function isValidHostname($hostname) { function sign($ts, $method, $path, $body, $secret_key) { $stringToSign = $ts . strtoupper($method) . $path . $body; return hash_hmac('sha256', $stringToSign, $secret_key); +} + +function getClid($db, string $clid): ?int { + $result = $db->selectValue('SELECT id FROM registrar WHERE clid = ? LIMIT 1', [$clid]); + return $result !== false ? (int)$result : null; } \ No newline at end of file diff --git a/cp/resources/views/admin/registrars/customPricing.twig b/cp/resources/views/admin/registrars/customPricing.twig index ece320f..3cd3345 100644 --- a/cp/resources/views/admin/registrars/customPricing.twig +++ b/cp/resources/views/admin/registrars/customPricing.twig @@ -25,107 +25,221 @@