From 4e4807dbea2d1629b4af76c8fd9a60e9a53ec268 Mon Sep 17 00:00:00 2001 From: pbao9 Date: Mon, 9 Mar 2026 16:43:06 +0700 Subject: [PATCH] feat: Implement DNS management with dedicated models, repositories, requests, controllers, and services, while refactoring authentication by removing Passport and Sanctum. --- .agent/workflows/code-style-guide.md | 179 ---- app/Facades/BaseHelperFacade.php | 30 + .../Api/Admin/Auth/AuthController.php | 8 +- .../Api/Admin/Order/OrderController.php | 2 +- .../Controllers/Backend/DomainController.php | 377 ++++++++ .../Controllers/Backend/RecordController.php | 312 +++++++ .../Controllers/Backend/ServerController.php | 204 +++++ .../Controllers/admin/CustomerController.php | 6 +- .../Controllers/admin/LoginController.php | 2 +- .../Controllers/admin/OrderController.php | 2 +- .../Controllers/admin/SupportController.php | 2 +- app/Http/Controllers/admin/TaskController.php | 4 +- app/Http/Controllers/admin/package/Host.php | 2 +- app/Http/Helpers/function_helper.php | 4 +- app/Http/Middleware/IsLoginCheck.php | 2 +- .../Requests/Domain/DomainRemoveRequest.php | 21 + app/Http/Requests/Domain/DomainRequest.php | 23 + .../Requests/Record/RecordRemoveRequest.php | 21 + .../Requests/Server/ServerRemoveRequest.php | 21 + app/Http/Requests/Server/ServerRequest.php | 24 + app/Http/Services/VNPayService.php | 2 +- app/Models/Customer.php | 3 +- app/Models/DnsDomain.php | 41 + app/Models/DnsRecord.php | 33 + app/Models/DnsServer.php | 36 + app/Models/User.php | 4 +- app/Observers/CustomerObserver.php | 12 +- app/Observers/OrderObserver.php | 12 +- app/Providers/AuthServiceProvider.php | 10 +- app/Providers/RepositoryProvider.php | 11 + app/Providers/RouteServiceProvider.php | 7 +- .../DnsManager/Domain/DnsDomainRepository.php | 89 ++ .../Domain/DnsDomainRepositoryInterface.php | 16 + .../DnsManager/Record/DnsRecordRepository.php | 70 ++ .../Record/DnsRecordRepositoryInterface.php | 14 + .../DnsManager/Server/DnsServerRepository.php | 24 + .../Server/DnsServerRepositoryInterface.php | 12 + app/Services/ServerService.php | 341 ++++++++ composer.json | 4 +- composer.lock | 828 +----------------- config/auth.php | 31 +- config/passport.php | 75 -- config/sanctum.php | 83 -- ...03_09_000001_create_dns_manager_tables.php | 74 ++ routes/admin.php | 58 ++ routes/api.php | 2 +- routes/channels.php | 10 +- 47 files changed, 1905 insertions(+), 1243 deletions(-) delete mode 100644 .agent/workflows/code-style-guide.md create mode 100644 app/Facades/BaseHelperFacade.php create mode 100644 app/Http/Controllers/Backend/DomainController.php create mode 100644 app/Http/Controllers/Backend/RecordController.php create mode 100644 app/Http/Controllers/Backend/ServerController.php create mode 100644 app/Http/Requests/Domain/DomainRemoveRequest.php create mode 100644 app/Http/Requests/Domain/DomainRequest.php create mode 100644 app/Http/Requests/Record/RecordRemoveRequest.php create mode 100644 app/Http/Requests/Server/ServerRemoveRequest.php create mode 100644 app/Http/Requests/Server/ServerRequest.php create mode 100644 app/Models/DnsDomain.php create mode 100644 app/Models/DnsRecord.php create mode 100644 app/Models/DnsServer.php create mode 100644 app/Repositories/DnsManager/Domain/DnsDomainRepository.php create mode 100644 app/Repositories/DnsManager/Domain/DnsDomainRepositoryInterface.php create mode 100644 app/Repositories/DnsManager/Record/DnsRecordRepository.php create mode 100644 app/Repositories/DnsManager/Record/DnsRecordRepositoryInterface.php create mode 100644 app/Repositories/DnsManager/Server/DnsServerRepository.php create mode 100644 app/Repositories/DnsManager/Server/DnsServerRepositoryInterface.php create mode 100644 app/Services/ServerService.php delete mode 100644 config/passport.php delete mode 100644 config/sanctum.php create mode 100644 database/migrations/2026_03_09_000001_create_dns_manager_tables.php create mode 100644 routes/admin.php diff --git a/.agent/workflows/code-style-guide.md b/.agent/workflows/code-style-guide.md deleted file mode 100644 index 376b687..0000000 --- a/.agent/workflows/code-style-guide.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -description: Code Style Guide ---- - -# Laravel 10 – Repository Pattern -## Strict Coding Rules (Anti-Trash & Anti-Overengineering) - -This document defines mandatory rules to prevent meaningless files, useless comments, and over-engineered architecture. - ---- - -## 0. Core Principle - -Do not create code unless it introduces real behavior. -Do not write comments to compensate for bad code. - -Readable code replaces comments. -Behavior justifies files. - ---- - -## 1. Comment Rules (VERY STRICT) - -Forbidden: -- Comments repeating code meaning -- Comments describing method names -- Placeholder comments -- TODO without ticket reference - -Allowed only to explain WHY: -- Architectural decisions -- Non-obvious side effects -- Constraints or workarounds - ---- - -## 2. File Creation Rules - -Do NOT create files: -- For clean structure only -- For symmetry -- For future assumptions -- To wrap a single call - ---- - -## 3. When a New File Is Allowed - -At least ONE condition must be true: -1. Real business rules exist -2. Logic reused in 2+ places -3. Side effects exist (transaction, cache, events) - ---- - -## 4. Repository Rules - -Repositories MAY: -- Query data -- Filter -- Paginate -- Cache - -Repositories MUST NOT: -- Validate -- Apply business rules -- Format responses -- Check permissions - ---- - -## 5. Service Layer Rules - -Service allowed only if: -- Uses multiple repositories -- Manages transactions -- Coordinates caching -- Enforces domain rules - -Proxy-only services are forbidden. - ---- - -## 6. Controller Rules - -Controllers MAY: -- Accept Request -- Call Service or Repository -- Return Response - -Controllers MUST NOT: -- Contain business logic -- Query database directly - ---- - -## 7. Interface Rules - -Do NOT create interfaces if only one implementation exists. - -Interfaces allowed only when: -- Multiple implementations exist -- Cache on/off switching -- Required for testing - ---- - -## 8. Helper Rules - -Forbidden: -- Business logic in helpers - -Allowed: -- String -- Date -- Array utilities - ---- - -## 9. Naming Rules - -Forbidden: -handle, process, execute, run, doSomething - -Required: -publishCourse, syncStudentProgress, calculateFinalScore - ---- - -## 10. Exception Rules - -Forbidden: -throw new Exception() - -Required: -Explicit domain-specific exceptions - ---- - -## 11. Folder Structure Rules - -Avoid over-fragmentation. - -One concept = minimal files. - ---- - -## 12. File Count Sanity Check - -CRUD feature <= 5 files is acceptable. -More than 10 files indicates over-engineering. - ---- - -## 13. Code Review Rejection Checklist - -Reject if: -- File has no behavior -- Service only proxies calls -- Comment explains WHAT not WHY -- Interface has one implementation -- File exists for future use - ---- - -## 14. AI Enforcement Rules - -- Do not create files without behavior -- Do not generate meaningless comments -- Do not create proxy layers -- Prefer fewer, clearer files -- Reject over-engineering - ---- - -## 15. Final Rule - -Architecture serves behavior. -If code has no clear reason to exist, remove it. diff --git a/app/Facades/BaseHelperFacade.php b/app/Facades/BaseHelperFacade.php new file mode 100644 index 0000000..82adf14 --- /dev/null +++ b/app/Facades/BaseHelperFacade.php @@ -0,0 +1,30 @@ + 'required|string', ]); - $token = Auth::guard('admins-api')->attempt($request->only('username', 'password')); + $token = Auth::guard('admin')->attempt($request->only('username', 'password')); if (!$token) { return response()->json([ @@ -28,7 +28,7 @@ class AuthController extends Controller ], 401); } - $user = Auth::guard('admins-api')->user(); + $user = Auth::guard('admin')->user(); return response()->json([ 'error' => false, @@ -43,7 +43,7 @@ class AuthController extends Controller public function me(): JsonResponse { - $user = Auth::guard('admins-api')->user(); + $user = Auth::guard('admin')->user(); return response()->json([ 'error' => false, @@ -76,7 +76,7 @@ class AuthController extends Controller public function logout(): JsonResponse { - Auth::guard('admins-api')->logout(); + Auth::guard('admin')->logout(); return response()->json([ 'error' => false, diff --git a/app/Http/Controllers/Api/Admin/Order/OrderController.php b/app/Http/Controllers/Api/Admin/Order/OrderController.php index 276421c..c517eb2 100644 --- a/app/Http/Controllers/Api/Admin/Order/OrderController.php +++ b/app/Http/Controllers/Api/Admin/Order/OrderController.php @@ -165,7 +165,7 @@ class OrderController extends Controller 'discount_id' => $request->discount_id ?? 0, 'amount' => $total + ($total * (10 / 100)), 'payment_id' => $request->payment_id, - 'user_id' => Auth::guard('admins-api')->id(), + 'user_id' => Auth::guard('admin')->id(), 'status' => $request->status, 'client_ip' => $request->getClientIp() ]; diff --git a/app/Http/Controllers/Backend/DomainController.php b/app/Http/Controllers/Backend/DomainController.php new file mode 100644 index 0000000..fe4ee50 --- /dev/null +++ b/app/Http/Controllers/Backend/DomainController.php @@ -0,0 +1,377 @@ +domainRepository->filter([], ['users', 'server'])->map(function ($domain) { + return [ + 'id' => $domain->id, + 'name' => $domain->domain_name, + 'server' => $domain->server ? $domain->server->ip_address : '', + 'user' => $domain->users->pluck('name')->implode(', '), + 'checkbox' => '', + 'created_at' => Carbon::parse($domain->created_at)->format('Y-m-d H:i:s'), + 'action' => $this->domainActionButtons($domain), + ]; + }); + + return response()->json(['data' => $domains]); + } + + public function create() + { + $title = 'Add Domain'; + return view('Backend.domains.create', compact('title')); + } + + public function store(DomainRequest $request) + { + $validated = $request->validated(); + + $isCreated = $this->domainRepository->findDomain($validated['domain_name']); + if (!empty($isCreated)) { + return response()->json([ + 'success' => false, + 'message' => "Domain '{$validated['domain_name']}' đã tồn tại trong hệ thống!", + ]); + } + + DB::beginTransaction(); + try { + $userIds = $validated['user_id'] ?? []; + $domainData = collect($validated)->except('user_id')->toArray(); + + $domain = $this->domainRepository->create($domainData); + $domain->users()->attach($userIds); + $domain->save(); + + try { + $server = $this->serverService->findServerByID($domain->dns_manager_server_id); + + if (!$server) { + throw new Exception("Không tìm thấy server với ID: {$domain->dns_manager_server_id}"); + } + + $existingDomainInfo = $this->serverService->getDomainInfo($domain->domain_name); + + if ($existingDomainInfo) { + $this->domainRepository->update($domain->id, [ + 'is_created' => 1, + 'plesk_id' => $existingDomainInfo['id'], + ]); + } else { + $response = $this->serverService->createDomain($domain->toArray()); + + if (!$response || !isset($response['id'])) { + throw new Exception('Không thể tạo domain trên server. Vui lòng kiểm tra lại thông tin server.'); + } + + $this->domainRepository->update($domain->id, [ + 'is_created' => 1, + 'plesk_id' => $response['id'], + ]); + } + } catch (Exception $domainError) { + Log::error('Lỗi khi tạo domain: ' . $domainError->getMessage()); + } + + DB::commit(); + + $domain = $domain->refresh(); + $message = $domain->is_created == 1 && $domain->plesk_id + ? "Domain '{$domain->domain_name}' đã được xử lý thành công trên server!" + : "Domain '{$domain->domain_name}' đã được lưu vào database nhưng chưa thể xử lý trên server."; + + return response()->json(['success' => true, 'message' => $message, 'url' => route('admin.domain.index')]); + } catch (Exception $error) { + DB::rollBack(); + return response()->json(['success' => false, 'message' => 'Có lỗi xảy ra: ' . $error->getMessage()]); + } + } + + public function edit(int $id) + { + $domain = $this->domainRepository->find($id); + if (empty($domain)) { + return back()->withErrors("Không tìm thấy domain với ID: {$id}"); + } + + $title = 'Edit domain'; + return view('Backend.domains.edit', compact('title', 'domain')); + } + + public function update(DomainRequest $request, int $id) + { + $domain = $this->domainRepository->find($id); + + if (empty($domain)) { + return response()->json(['success' => false, 'message' => "Không tìm thấy domain với ID: {$id}"]); + } + + $validated = $request->validated(); + + DB::beginTransaction(); + try { + $userIds = $validated['user_id'] ?? []; + $domainData = collect($validated)->except('user_id')->toArray(); + + $this->domainRepository->update($id, $domainData); + $domain->users()->sync($userIds); + + try { + $updatedDomain = $this->domainRepository->find($id); + $server = $this->serverService->findServerByID($updatedDomain->dns_manager_server_id); + + if (!$server) { + throw new Exception("Không tìm thấy server với ID: {$updatedDomain->dns_manager_server_id}"); + } + + $existingDomainInfo = $this->serverService->getDomainInfo($updatedDomain->domain_name); + + if ($existingDomainInfo) { + $this->serverService->updateDomain($existingDomainInfo['id'], $updatedDomain->toArray()); + $this->domainRepository->update($updatedDomain->id, [ + 'is_created' => 1, + 'plesk_id' => $existingDomainInfo['id'], + ]); + } else { + $response = $this->serverService->createDomain($updatedDomain->toArray()); + + if (!$response || !isset($response['id'])) { + throw new Exception('Không thể tạo domain trên server.'); + } + + $this->domainRepository->update($updatedDomain->id, [ + 'is_created' => 1, + 'plesk_id' => $response['id'], + ]); + } + } catch (Exception $domainError) { + Log::error('Lỗi khi cập nhật domain: ' . $domainError->getMessage()); + } + + DB::commit(); + + $updatedDomain = $this->domainRepository->find($id); + $message = $updatedDomain->is_created == 1 && $updatedDomain->plesk_id + ? "Domain '{$updatedDomain->domain_name}' đã được cập nhật thành công trên server!" + : "Domain '{$updatedDomain->domain_name}' đã được cập nhật trong database nhưng chưa thể xử lý trên server."; + + return response()->json(['success' => true, 'message' => $message, 'url' => route('admin.domain.index')]); + } catch (Exception $error) { + DB::rollBack(); + return response()->json(['success' => false, 'message' => 'Có lỗi xảy ra: ' . $error->getMessage()]); + } + } + + public function record(int $id = 0) + { + $domain = $this->domainRepository->findWithRelations($id, ['record']); + + if (empty($domain)) { + return back()->withErrors("Không tìm thấy domain với ID: {$id}"); + } + + $title = strtoupper($domain->domain_name) . ' Records'; + return view('Backend.domains.view', compact('domain', 'title', 'id')); + } + + public function destroy(int $id) + { + $domain = $this->domainRepository->find($id); + if (!$domain) { + return response()->json(['success' => false, 'message' => "Không tìm thấy domain với ID: {$id}"]); + } + + try { + if ($domain->is_created !== 1 || !$domain->plesk_id) { + $this->domainRepository->delete($domain->id); + return response()->json([ + 'success' => true, + 'message' => "Domain '{$domain->domain_name}' đã được xóa khỏi database.", + 'url' => route('admin.domain.index'), + ]); + } + + $server = $this->serverService->findServerByID($domain->dns_manager_server_id); + + if (!$server) { + return response()->json(['success' => false, 'message' => "Không tìm thấy server với ID: {$domain->dns_manager_server_id}"]); + } + + $removed = $this->serverService->removeDomain($domain->plesk_id); + + if (!$removed) { + return response()->json(['success' => false, 'message' => "Không thể xóa domain '{$domain->domain_name}' trên server."]); + } + + $this->domainRepository->delete($domain->id); + $this->clearDomainCaches($domain); + + return response()->json([ + 'success' => true, + 'message' => "Domain '{$domain->domain_name}' đã được xóa thành công khỏi server và database!", + 'url' => route('admin.domain.index'), + ]); + } catch (Exception $error) { + return response()->json(['success' => false, 'message' => 'Có lỗi xảy ra khi xóa domain: ' . $error->getMessage()]); + } + } + + public function destroyCustom(DomainRemoveRequest $request) + { + $request->validated(); + + $domains = $this->domainRepository->findWhereIn('id', $request->get('ids')); + + if (!$domains || $domains->isEmpty()) { + return response()->json(['success' => false, 'message' => 'Không tìm thấy domain nào.']); + } + + $successCount = 0; + $errorCount = 0; + $errors = []; + + foreach ($domains as $domain) { + try { + if ($domain->is_created !== 1 || !$domain->plesk_id) { + $this->domainRepository->delete($domain->id); + $successCount++; + continue; + } + + $server = $this->serverService->findServerByID($domain->dns_manager_server_id); + + if (!$server) { + $errors[] = "Domain '{$domain->domain_name}': Không tìm thấy server"; + $errorCount++; + continue; + } + + $removed = $this->serverService->removeDomain($domain->plesk_id); + + if (!$removed) { + $errors[] = "Domain '{$domain->domain_name}': Không thể xóa trên server"; + $errorCount++; + continue; + } + + $this->domainRepository->delete($domain->id); + $this->clearDomainCaches($domain); + $successCount++; + } catch (Exception $error) { + $errors[] = "Domain '{$domain->domain_name}': " . $error->getMessage(); + $errorCount++; + } + } + + if ($successCount > 0 && $errorCount === 0) { + $message = "Đã xóa thành công {$successCount} domain!"; + } elseif ($successCount > 0) { + $message = "Đã xóa thành công {$successCount} domain, {$errorCount} domain gặp lỗi."; + } else { + $message = 'Không thể xóa domain nào. Vui lòng kiểm tra lại.'; + } + + return response()->json([ + 'success' => $errorCount === 0, + 'message' => $message, + 'details' => ['success_count' => $successCount, 'error_count' => $errorCount, 'errors' => $errors], + 'url' => route('admin.domain.index'), + ]); + } + + private function domainActionButtons($domain): string + { + $editUrl = route('admin.domain.edit', ['id' => $domain->id]); + $recordUrl = route('admin.domain.record', ['id' => $domain->id]); + $deleteUrl = route('admin.domain.destroy', ['id' => $domain->id]); + + return << + + + + + + + Edit + + + + + + + + + Records + + + + + + + + + Delete + + HTML; + } + + private function clearDomainCaches($domain): void + { + try { + Cache::forget("domain.{$domain->id}"); + Cache::forget("domain.{$domain->domain_name}"); + Cache::forget('domains.all'); + Cache::forget('domains.filtered'); + + if ($domain->users) { + foreach ($domain->users as $user) { + Cache::forget("user.{$user->id}.domains"); + } + } + + if ($domain->dns_manager_server_id) { + Cache::forget("server.{$domain->dns_manager_server_id}.domains"); + } + } catch (Exception $e) { + Log::warning('Failed to clear domain caches: ' . $e->getMessage()); + } + } +} diff --git a/app/Http/Controllers/Backend/RecordController.php b/app/Http/Controllers/Backend/RecordController.php new file mode 100644 index 0000000..a3f45a7 --- /dev/null +++ b/app/Http/Controllers/Backend/RecordController.php @@ -0,0 +1,312 @@ + [ + 'name' => 'required', + 'type' => 'required', + 'ttl' => 'required', + 'value' => 'required|ip|ipv4', + 'plesk_id' => 'nullable', + ], + 'AAAA' => [ + 'name' => 'required', + 'type' => 'required', + 'ttl' => 'required', + 'value' => 'required|ip|ipv6', + 'plesk_id' => 'nullable', + ], + 'CNAME' => [ + 'name' => 'required', + 'type' => 'required', + 'ttl' => 'required', + 'value' => 'required', + 'plesk_id' => 'nullable', + ], + 'MX' => [ + 'name' => 'required', + 'type' => 'required', + 'ttl' => 'required', + 'value' => 'required', + 'priority' => 'required', + 'plesk_id' => 'nullable', + ], + 'TXT' => [ + 'name' => 'required', + 'type' => 'required', + 'ttl' => 'required', + 'value' => 'required', + 'plesk_id' => 'nullable', + ], + 'CAA' => [ + 'name' => 'required', + 'type' => 'required', + 'ttl' => 'required', + 'value' => 'required', + 'plesk_id' => 'nullable', + ], + 'SRV' => [ + 'type' => 'required', + 'ttl' => 'required', + 'value' => 'required', + 'service_name' => 'required', + 'protocol' => 'required', + 'weight' => 'required', + 'port' => 'required', + 'priority' => 'required', + 'plesk_id' => 'nullable', + ], + ]; + + public function __construct( + public DnsDomainRepositoryInterface $domainRepository, + public DnsRecordRepositoryInterface $recordRepository, + public ServerService $serverService + ) {} + + public function index() + { + $title = 'All Records'; + return view('Backend.records.index', compact('title')); + } + + public function getAll() + { + $records = $this->recordRepository->filter([], ['domain'])->map(function ($record) { + return [ + 'id' => $record->id, + 'name' => Str::limit($record->name, 20, '...'), + 'type' => $record->type, + 'value' => Str::limit($record->value, 20, '...'), + 'domain' => $record->domain ? $record->domain->domain_name : '', + 'checkbox' => '', + 'created_at' => Carbon::parse($record->created_at)->format('Y-m-d H:i:s'), + 'action' => $this->recordActionButtons($record), + ]; + }); + + return response()->json(['data' => $records]); + } + + public function create(int $id) + { + $title = 'Add Records'; + return view('Backend.records.create', compact('title', 'id')); + } + + public function store(Request $request, int $id = 0) + { + $domain = $this->domainRepository->find($id); + if (empty($domain)) { + return response()->json(['success' => false, 'message' => 'These credentials do not match our records.']); + } + + $validated = Validator::make($request->all(), $this->rules[$request->get('type')] ?? []); + + if ($validated->fails()) { + return response()->json(['success' => false, 'message' => $validated->errors()->first()]); + } + + $request->merge(['dns_manager_domain_id' => $id, 'domain' => $domain->domain_name]); + + if (empty($request->get('plesk_id'))) { + $this->serverService->findServerByID($domain->dns_manager_server_id); + $this->serverService->handlePayload($request->all()); + $record = $this->serverService->addRecord(); + + if (!empty($record) && $record['error']) { + return response()->json(['success' => false, 'message' => $record['message'] ?? 'Failed to add record on server.']); + } + } + + DB::beginTransaction(); + try { + if (isset($record)) { + $request->merge(['plesk_id' => $record['data']['id'] ?? 0]); + } + + $this->recordRepository->create($request->all()); + DB::commit(); + } catch (Exception $error) { + DB::rollBack(); + return response()->json(['success' => false, 'message' => $error->getMessage()]); + } + + return response()->json([ + 'success' => true, + 'message' => 'Add record successfully', + 'url' => route('admin.domain.record', ['id' => $id]), + ]); + } + + public function edit(int $id = 0, int $record_id = 0) + { + $domain = $this->domainRepository->find($id); + if (empty($domain)) { + return back()->withErrors('These credentials do not match our records.'); + } + + $record = $this->recordRepository->find($record_id); + if (empty($record)) { + return back()->withErrors('These credentials do not match our records.'); + } + + $title = 'Edit Record'; + return view('Backend.records.edit', compact('title', 'record', 'id')); + } + + public function update(Request $request, int $id = 0, int $record_id = 0) + { + $domain = $this->domainRepository->find($id); + if (empty($domain)) { + return response()->json(['success' => false, 'message' => 'These credentials do not match our records.']); + } + + $record = $this->recordRepository->find($record_id); + if (empty($record)) { + return response()->json(['success' => false, 'message' => 'These credentials do not match our records.']); + } + + $validated = Validator::make($request->all(), $this->rules[$request->get('type')] ?? []); + + if ($validated->fails()) { + return response()->json(['success' => false, 'message' => $validated->errors()->first()]); + } + + $this->serverService->findServerByID($domain->dns_manager_server_id); + $this->serverService->handlePayload($request->all()); + $updatedRecord = $this->serverService->updateRecord($record->plesk_id); + + if (!empty($updatedRecord) && $updatedRecord['error']) { + return response()->json(['success' => false, 'message' => $updatedRecord['message'] ?? 'Failed to update record on server.']); + } + + DB::beginTransaction(); + try { + $this->recordRepository->update($record_id, $request->all()); + DB::commit(); + } catch (Exception $error) { + DB::rollBack(); + return response()->json(['success' => false, 'message' => $error->getMessage()]); + } + + return response()->json([ + 'success' => true, + 'message' => 'Update record successfully', + 'url' => route('admin.domain.record', ['id' => $id]), + ]); + } + + public function destroy(int $id = 0) + { + $record = $this->recordRepository->findWithRelations($id, ['domain']); + if (empty($record) || empty($record->domain)) { + return response()->json(['success' => false, 'message' => 'These credentials do not match our records.']); + } + + $this->serverService->findServerByID($record->domain->dns_manager_server_id); + $record_delete = $this->serverService->deleteRecord($record->plesk_id); + + if (!empty($record_delete) && $record_delete['error']) { + return response()->json(['success' => false, 'message' => $record_delete['message'] ?? 'Failed to delete record on server.']); + } + + DB::beginTransaction(); + try { + $domainId = $record->dns_manager_domain_id; + $this->recordRepository->delete($id); + DB::commit(); + } catch (Exception $error) { + DB::rollBack(); + return response()->json(['success' => false, 'message' => $error->getMessage()]); + } + + return response()->json([ + 'success' => true, + 'message' => 'Deleted record successfully', + 'url' => route('admin.domain.record', ['id' => $domainId]), + ]); + } + + public function destroyCustom(RecordRemoveRequest $request) + { + $request->validated(); + + $records = $this->recordRepository->findWhereIn('id', $request->get('ids'), ['domain']); + + if (!$records) { + return response()->json(['success' => false, 'message' => 'These credentials do not match our records.']); + } + + try { + foreach ($records->all() as $record) { + if (empty($record->domain)) continue; + + $this->serverService->findServerByID($record->domain->dns_manager_server_id); + $this->serverService->deleteRecord($record->plesk_id); + $this->recordRepository->delete($record->id); + } + } catch (Exception $error) { + return response()->json(['success' => false, 'message' => $error->getMessage()]); + } + + return response()->json([ + 'success' => true, + 'message' => 'Deleted successfully!', + 'url' => route('admin.record.index'), + ]); + } + + private function recordActionButtons($record): string + { + $domainId = $record->domain ? $record->domain->id : 0; + $editUrl = route('admin.record.edit', ['id' => $domainId, 'record_id' => $record->id]); + $deleteUrl = route('admin.record.destroy', ['id' => $record->id]); + + return << + + + + + + + Edit + + + + + + + + + Delete + + HTML; + } +} diff --git a/app/Http/Controllers/Backend/ServerController.php b/app/Http/Controllers/Backend/ServerController.php new file mode 100644 index 0000000..9069468 --- /dev/null +++ b/app/Http/Controllers/Backend/ServerController.php @@ -0,0 +1,204 @@ +serverRepository->getAll()->map(function ($server) { + return [ + 'id' => $server->id, + 'name' => $server->name, + 'ip' => $server->ip_address, + 'status' => $server->getStatus(), + 'checkbox' => '', + 'created_at' => Carbon::parse($server->created_at)->format('Y-m-d H:i:s'), + 'action' => $this->serverActionButtons($server), + ]; + }); + + return response()->json(['data' => $servers]); + } + + public function create() + { + $title = 'Add New Server Hosting'; + return view('Backend.servers.create', compact('title')); + } + + public function connect(ServerRequest $request) + { + $request->validated(); + + if (!$request->ajax()) { + return response()->json(['success' => false, 'message' => 'Method not support']); + } + + $status = $this->serverService->checkConnection($request->all()); + + if ($status) { + return response()->json(['success' => true, 'message' => 'Connection established successfully.']); + } + + return response()->json([ + 'success' => false, + 'message' => 'Connection attempt failed. Please check your credentials or server settings.', + ]); + } + + public function store(ServerRequest $request) + { + $request->validated(); + + DB::beginTransaction(); + try { + $data = $request->all(); + $data['password'] = Crypt::encryptString($request->password); + + $this->serverRepository->create($data); + DB::commit(); + } catch (Exception $error) { + DB::rollBack(); + return response()->json(['success' => false, 'message' => $error->getMessage()]); + } + + return response()->json([ + 'success' => true, + 'message' => 'Created successfully!', + 'url' => route('admin.server.index'), + ]); + } + + public function edit(int $id) + { + $server = $this->serverRepository->find($id); + if (!$server) { + return back()->withErrors('Invalid Request'); + } + + $title = 'Update Server Hosting'; + return view('Backend.servers.edit', compact('title', 'server')); + } + + public function update(ServerRequest $request, int $id) + { + $request->validated(); + + DB::beginTransaction(); + try { + $data = $request->all(); + $data['password'] = Crypt::encryptString($request->password); + + $this->serverRepository->update($id, $data); + DB::commit(); + } catch (Exception $error) { + DB::rollBack(); + return response()->json(['success' => false, 'message' => $error->getMessage()]); + } + + return response()->json([ + 'success' => true, + 'message' => 'Updated successfully!', + 'url' => route('admin.server.index'), + ]); + } + + public function destroy(int $id) + { + $server = $this->serverRepository->find($id); + if (!$server) { + return response()->json(['success' => false, 'message' => 'Invalid Request']); + } + + $this->serverRepository->delete($id); + + return response()->json([ + 'success' => true, + 'message' => 'Deleted successfully!', + 'url' => route('admin.server.index'), + ]); + } + + public function destroyCustom(ServerRemoveRequest $request) + { + $request->validated(); + + $servers = $this->serverRepository->findWhereIn('id', $request->get('ids')); + + if (!$servers) { + return response()->json(['success' => false, 'message' => 'Invalid Request']); + } + + foreach ($servers->all() as $server) { + $this->serverRepository->delete($server->id); + } + + return response()->json([ + 'success' => true, + 'message' => 'Deleted successfully!', + 'url' => route('admin.server.index'), + ]); + } + + private function serverActionButtons($server): string + { + $editUrl = route('admin.server.edit', ['id' => $server->id]); + $deleteUrl = route('admin.server.destroy', ['id' => $server->id]); + + return << + + + + + + + Edit + + + + + + + + + + + Delete + + HTML; + } +} diff --git a/app/Http/Controllers/admin/CustomerController.php b/app/Http/Controllers/admin/CustomerController.php index 39d49c3..17a367f 100644 --- a/app/Http/Controllers/admin/CustomerController.php +++ b/app/Http/Controllers/admin/CustomerController.php @@ -720,7 +720,9 @@ class CustomerController extends Controller if (!$customer) { return back()->withErrors('Invalid request'); } - Auth::guard('users')->login($customer); + // TODO: impersonation feature needs redesign for JWT — session login does not work with JWT guard + // This is a legacy Livewire admin feature; will be removed when portal-admin migration is complete + Auth::guard('client')->login($customer); session()->put('admin_login_for_customer', true); @@ -728,7 +730,7 @@ class CustomerController extends Controller } public function LogoutWithCustomer() { - Auth::guard('users')->logout(); + Auth::guard('client')->logout(); return redirect()->route('customer.index'); } diff --git a/app/Http/Controllers/admin/LoginController.php b/app/Http/Controllers/admin/LoginController.php index 9705a34..1c77248 100644 --- a/app/Http/Controllers/admin/LoginController.php +++ b/app/Http/Controllers/admin/LoginController.php @@ -27,7 +27,7 @@ class LoginController extends Controller if (!$user) return back()->withErrors('Không tìm thấy thông tin người dùng'); - if (Auth::guard('admins')->attempt(['username' => $request->username, 'password' => $request->password], $request->remember)) { + if (Auth::guard('admin')->attempt(['username' => $request->username, 'password' => $request->password], $request->remember)) { if (\auth()->user()->status) { $token = \auth()->user()->createToken('access_token', ['*'], Carbon::now()->addDay())->plainTextToken; Cookie::queue('accessToken', $token, 24 * 60); diff --git a/app/Http/Controllers/admin/OrderController.php b/app/Http/Controllers/admin/OrderController.php index 748b3c6..bf9444d 100644 --- a/app/Http/Controllers/admin/OrderController.php +++ b/app/Http/Controllers/admin/OrderController.php @@ -172,7 +172,7 @@ class OrderController extends Controller 'discount_id' => $request->discount_id ?? 0, 'amount' => $total + ($total * (10 / 100)), 'payment_id' => $request->payment_id, - 'user_id' => auth()->guard('admins')->user()->id, + 'user_id' => auth()->guard('admin')->user()->id, 'status' => $request->status, 'client_ip' => $request->getClientIp() ]; diff --git a/app/Http/Controllers/admin/SupportController.php b/app/Http/Controllers/admin/SupportController.php index d2da05b..823e585 100644 --- a/app/Http/Controllers/admin/SupportController.php +++ b/app/Http/Controllers/admin/SupportController.php @@ -52,7 +52,7 @@ class SupportController extends Controller } $request->validated(); - $request->merge(['user_id' => auth()->guard('admins')->id()]); + $request->merge(['user_id' => auth()->guard('admin')->id()]); DB::beginTransaction(); try { diff --git a/app/Http/Controllers/admin/TaskController.php b/app/Http/Controllers/admin/TaskController.php index c87cf6e..c524471 100644 --- a/app/Http/Controllers/admin/TaskController.php +++ b/app/Http/Controllers/admin/TaskController.php @@ -177,8 +177,8 @@ class TaskController extends Controller Log::create([ 'agent' => $request->userAgent(), 'client_ip' => $request->getClientIp(), - 'username' => auth()->guard('admins')->user()->username, - 'description' => auth()->guard('admins')->user()->username . ": $request->action for VirtualMachine $request->product", + 'username' => auth()->guard('admin')->user()->username, + 'description' => auth()->guard('admin')->user()->username . ": $request->action for VirtualMachine $request->product", 'customer_id' => $request->userid ]); diff --git a/app/Http/Controllers/admin/package/Host.php b/app/Http/Controllers/admin/package/Host.php index d35f868..a0c436e 100644 --- a/app/Http/Controllers/admin/package/Host.php +++ b/app/Http/Controllers/admin/package/Host.php @@ -51,7 +51,7 @@ class Host extends Controller $editUrl = route('package.host.edit', ['id' => $d->id]); $deleteBtn = ''; - if (auth()->guard('admins')->user()->can("delete module vcenter")) { + if (auth()->guard('admin')->user()->can("delete module vcenter")) { $deleteUrl = route('package.host.destroy', ['id' => $d->id]); $csrf = csrf_field(); $method = method_field('delete'); diff --git a/app/Http/Helpers/function_helper.php b/app/Http/Helpers/function_helper.php index 843e71c..e168019 100644 --- a/app/Http/Helpers/function_helper.php +++ b/app/Http/Helpers/function_helper.php @@ -61,14 +61,14 @@ if (!function_exists('format_day')) { if (!function_exists('customer')) { function customer() { - return Auth::guard('users')->user(); + return Auth::guard('client')->user(); } } if (!function_exists('user')) { function user() { - return Auth::guard('users')->user(); + return Auth::guard('client')->user(); } } diff --git a/app/Http/Middleware/IsLoginCheck.php b/app/Http/Middleware/IsLoginCheck.php index 40dc360..092f5e7 100644 --- a/app/Http/Middleware/IsLoginCheck.php +++ b/app/Http/Middleware/IsLoginCheck.php @@ -16,7 +16,7 @@ class IsLoginCheck */ public function handle(Request $request, Closure $next) { - if (! auth()->guard('users')->check()) { + if (! auth()->guard('client')->check()) { return $next($request); } return redirect()->route('home'); diff --git a/app/Http/Requests/Domain/DomainRemoveRequest.php b/app/Http/Requests/Domain/DomainRemoveRequest.php new file mode 100644 index 0000000..a5cf00e --- /dev/null +++ b/app/Http/Requests/Domain/DomainRemoveRequest.php @@ -0,0 +1,21 @@ + 'required|array|min:1', + 'ids.*' => 'required|integer|exists:dns_manager_domain,id', + ]; + } +} diff --git a/app/Http/Requests/Domain/DomainRequest.php b/app/Http/Requests/Domain/DomainRequest.php new file mode 100644 index 0000000..7a0a793 --- /dev/null +++ b/app/Http/Requests/Domain/DomainRequest.php @@ -0,0 +1,23 @@ + 'required|string|max:255', + 'dns_manager_server_id' => 'required|integer|exists:dns_manager_servers,id', + 'user_id' => 'nullable|array', + 'user_id.*' => 'integer|exists:users,id', + ]; + } +} diff --git a/app/Http/Requests/Record/RecordRemoveRequest.php b/app/Http/Requests/Record/RecordRemoveRequest.php new file mode 100644 index 0000000..a167e5d --- /dev/null +++ b/app/Http/Requests/Record/RecordRemoveRequest.php @@ -0,0 +1,21 @@ + 'required|array|min:1', + 'ids.*' => 'required|integer|exists:dns_manager_ns,id', + ]; + } +} diff --git a/app/Http/Requests/Server/ServerRemoveRequest.php b/app/Http/Requests/Server/ServerRemoveRequest.php new file mode 100644 index 0000000..45c6a80 --- /dev/null +++ b/app/Http/Requests/Server/ServerRemoveRequest.php @@ -0,0 +1,21 @@ + 'required|array|min:1', + 'ids.*' => 'required|integer|exists:dns_manager_servers,id', + ]; + } +} diff --git a/app/Http/Requests/Server/ServerRequest.php b/app/Http/Requests/Server/ServerRequest.php new file mode 100644 index 0000000..1ea0f76 --- /dev/null +++ b/app/Http/Requests/Server/ServerRequest.php @@ -0,0 +1,24 @@ + 'required|string|max:255', + 'ip_address' => 'required|string|max:255', + 'username' => 'required|string|max:255', + 'password' => 'required|string|max:255', + 'status' => 'nullable|string|in:activated,Stopped', + ]; + } +} diff --git a/app/Http/Services/VNPayService.php b/app/Http/Services/VNPayService.php index 8fccd82..c1fe1de 100644 --- a/app/Http/Services/VNPayService.php +++ b/app/Http/Services/VNPayService.php @@ -26,7 +26,7 @@ class VNPayService $vnp_BankCode = $data['bankCode'] ?? ''; $vnp_IpAddr = request()->ip(); - $user = Auth::guard('client')->user() ?? Auth::guard('users')->user(); + $user = Auth::guard('client')->user(); $userName = $user ? $user->fullname : 'Khách'; $isDeposit = isset($data['transaction_ref']); diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 32185c2..d6627f2 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -6,12 +6,11 @@ use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Auth\User as Authenticatable; -use Laravel\Sanctum\HasApiTokens; use Tymon\JWTAuth\Contracts\JWTSubject; class Customer extends Authenticatable implements JWTSubject { - use HasFactory, HasApiTokens, HasUuids, SoftDeletes; + use HasFactory, HasUuids, SoftDeletes; protected $table = 'customers'; diff --git a/app/Models/DnsDomain.php b/app/Models/DnsDomain.php new file mode 100644 index 0000000..73f5e24 --- /dev/null +++ b/app/Models/DnsDomain.php @@ -0,0 +1,41 @@ +belongsTo(User::class); + } + + public function customer() + { + return $this->belongsToMany(Customer::class, 'dns_domain_user', 'domain_id', 'customer_id')->withTimestamps(); + } + + public function server() + { + return $this->belongsTo(DnsServer::class, 'dns_manager_server_id', 'id'); + } + + public function record() + { + return $this->hasMany(DnsRecord::class, 'dns_manager_domain_id', 'id'); + } +} diff --git a/app/Models/DnsRecord.php b/app/Models/DnsRecord.php new file mode 100644 index 0000000..2be4402 --- /dev/null +++ b/app/Models/DnsRecord.php @@ -0,0 +1,33 @@ +belongsTo(DnsDomain::class, 'dns_manager_domain_id', 'id'); + } +} diff --git a/app/Models/DnsServer.php b/app/Models/DnsServer.php new file mode 100644 index 0000000..f4836b4 --- /dev/null +++ b/app/Models/DnsServer.php @@ -0,0 +1,36 @@ +attributes['status']) { + 'activated' => 'Activated', + 'Stopped' => 'Stopped', + default => 'Unknown', + }; + } + + protected function scopeIsActive($query) + { + return $query->where('status', 'activated'); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index c4b177a..a6774fa 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,17 +2,15 @@ namespace App\Models; -use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; -use Laravel\Sanctum\HasApiTokens; use Spatie\Permission\Traits\HasRoles; use Tymon\JWTAuth\Contracts\JWTSubject; class User extends Authenticatable implements JWTSubject { - use HasApiTokens, HasFactory, Notifiable; + use HasFactory, Notifiable; use HasRoles; protected $table = 'user'; diff --git a/app/Observers/CustomerObserver.php b/app/Observers/CustomerObserver.php index a2aab30..2878b8b 100644 --- a/app/Observers/CustomerObserver.php +++ b/app/Observers/CustomerObserver.php @@ -24,8 +24,8 @@ class CustomerObserver $this->logRepository->create([ 'agent' => request()->userAgent(), 'client_ip' => request()->getClientIp(), - 'username' => auth()->guard('admins')->user()->username ?? 'System', - 'description' => (auth()->guard('admins')->user()->username ?? 'System') . " created new Customer with id: " . $customer->id, + 'username' => auth()->guard('admin')->user()->username ?? 'System', + 'description' => (auth()->guard('admin')->user()->username ?? 'System') . " created new Customer with id: " . $customer->id, 'customer_id' => $customer->id ]); } @@ -43,8 +43,8 @@ class CustomerObserver $this->logRepository->create([ 'agent' => request()->userAgent(), 'client_ip' => request()->getClientIp(), - 'username' => auth()->guard('admins')->user()->username ?? 'System', - 'description' => (auth()->guard('admins')->user()->username ?? 'System') . " Modified Customer ID#" . $customer->id . " - #$attribute from $old_value to $value", + 'username' => auth()->guard('admin')->user()->username ?? 'System', + 'description' => (auth()->guard('admin')->user()->username ?? 'System') . " Modified Customer ID#" . $customer->id . " - #$attribute from $old_value to $value", 'customer_id' => $customer->id ]); } @@ -61,8 +61,8 @@ class CustomerObserver $this->logRepository->create([ 'agent' => request()->userAgent(), 'client_ip' => request()->getClientIp(), - 'username' => auth()->guard('admins')->user()->username ?? 'System', - 'description' => (auth()->guard('admins')->user()->username ?? 'System') . " Deleted Customer ID#" . $customer->getOriginal('id'), + 'username' => auth()->guard('admin')->user()->username ?? 'System', + 'description' => (auth()->guard('admin')->user()->username ?? 'System') . " Deleted Customer ID#" . $customer->getOriginal('id'), 'customer_id' => $customer->getOriginal('id') ]); } diff --git a/app/Observers/OrderObserver.php b/app/Observers/OrderObserver.php index ec3d11a..b8a0438 100644 --- a/app/Observers/OrderObserver.php +++ b/app/Observers/OrderObserver.php @@ -19,8 +19,8 @@ class OrderObserver $this->logRepository->create([ 'agent' => request()->userAgent(), 'client_ip' => request()->getClientIp(), - 'username' => auth()->guard('admins')->user()->username ?? 'System', - 'description' => (auth()->guard('admins')->user()->username ?? 'System') . " created new Order with Order id: " . $order->id, + 'username' => auth()->guard('admin')->user()->username ?? 'System', + 'description' => (auth()->guard('admin')->user()->username ?? 'System') . " created new Order with Order id: " . $order->id, 'customer_id' => $order->customer_id ]); } @@ -38,8 +38,8 @@ class OrderObserver $this->logRepository->create([ 'agent' => request()->userAgent(), 'client_ip' => request()->getClientIp(), - 'username' => auth()->guard('admins')->user()->username ?? 'System', - 'description' => (auth()->guard('admins')->user()->username ?? 'System') . " Modified Order ID#" . $order->id . " - #$attribute from $old_value to $value", + 'username' => auth()->guard('admin')->user()->username ?? 'System', + 'description' => (auth()->guard('admin')->user()->username ?? 'System') . " Modified Order ID#" . $order->id . " - #$attribute from $old_value to $value", 'customer_id' => $order->customer_id ]); } @@ -56,8 +56,8 @@ class OrderObserver $this->logRepository->create([ 'agent' => request()->userAgent(), 'client_ip' => request()->getClientIp(), - 'username' => auth()->guard('admins')->user()->username ?? 'System', - 'description' => (auth()->guard('admins')->user()->username ?? 'System') . " Deleted Order ID#" . $order->getOriginal('id'), + 'username' => auth()->guard('admin')->user()->username ?? 'System', + 'description' => (auth()->guard('admin')->user()->username ?? 'System') . " Deleted Order ID#" . $order->getOriginal('id'), 'customer_id' => $order->getOriginal('customer_id') ]); } diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index e56100c..afb0cf8 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -3,8 +3,6 @@ namespace App\Providers; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; -use Illuminate\Support\Facades\Gate; -use Laravel\Passport\Passport; class AuthServiceProvider extends ServiceProvider { @@ -13,9 +11,7 @@ class AuthServiceProvider extends ServiceProvider * * @var array */ - protected $policies = [ -// 'App\Models\Customer' => 'App\Policies\ModelPolicy', - ]; + protected $policies = []; /** * Register any authentication / authorization services. @@ -25,9 +21,5 @@ class AuthServiceProvider extends ServiceProvider public function boot() { $this->registerPolicies(); - - Passport::tokensExpireIn(now()->addDays(15)); - Passport::refreshTokensExpireIn(now()->addDays(30)); - Passport::personalAccessTokensExpireIn(now()->addDays(30)); } } diff --git a/app/Providers/RepositoryProvider.php b/app/Providers/RepositoryProvider.php index ae8577e..934ac36 100644 --- a/app/Providers/RepositoryProvider.php +++ b/app/Providers/RepositoryProvider.php @@ -98,6 +98,12 @@ use App\Repositories\VPS\VPSCachedRepository; use App\Repositories\VPS\VPSRepositoryInterface; use App\Repositories\Module\VirtualMachine\VirtualMachineRepository; use App\Repositories\Module\VirtualMachine\VirtualMachineRepositoryInterface; +use App\Repositories\DnsManager\Domain\DnsDomainRepository; +use App\Repositories\DnsManager\Domain\DnsDomainRepositoryInterface; +use App\Repositories\DnsManager\Server\DnsServerRepository as DnsManagerServerRepository; +use App\Repositories\DnsManager\Server\DnsServerRepositoryInterface as DnsManagerServerRepositoryInterface; +use App\Repositories\DnsManager\Record\DnsRecordRepository; +use App\Repositories\DnsManager\Record\DnsRecordRepositoryInterface; class RepositoryProvider extends ServiceProvider { @@ -364,6 +370,11 @@ class RepositoryProvider extends ServiceProvider \App\Repositories\Api\Service\ServiceRepositoryInterface::class, \App\Repositories\Api\Service\ServiceRepository::class ); + + // DNS Manager + $this->app->bind(DnsManagerServerRepositoryInterface::class, DnsManagerServerRepository::class); + $this->app->bind(DnsDomainRepositoryInterface::class, DnsDomainRepository::class); + $this->app->bind(DnsRecordRepositoryInterface::class, DnsRecordRepository::class); } /** diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 0ba6606..a45fbaa 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -50,7 +50,12 @@ class RouteServiceProvider extends ServiceProvider ->namespace($this->namespace) ->group(base_path('routes/api.php')); - // 3. Web & Admin routes + // 3. Admin Backend routes (DNS Manager) + Route::middleware('web') + ->namespace($this->namespace) + ->group(base_path('routes/admin.php')); + + // 4. Web routes Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); diff --git a/app/Repositories/DnsManager/Domain/DnsDomainRepository.php b/app/Repositories/DnsManager/Domain/DnsDomainRepository.php new file mode 100644 index 0000000..6d9599d --- /dev/null +++ b/app/Repositories/DnsManager/Domain/DnsDomainRepository.php @@ -0,0 +1,89 @@ +model->where('domain_name', $domain)->first(); + } + + public function filter(array $data = [], array $relationships = [], string $order = 'id', array $select = ['*']) + { + $model = $this->model; + + if (count($relationships)) { + $model = $model->with($relationships); + } + + if (isset($data['q']) && $data['q']) { + $model = $model->where('domain_name', 'like', '%' . $data['q'] . '%'); + } + + if (isset($data['search']['value']) && $data['search']['value']) { + $model = $model->where('domain_name', 'like', '%' . $data['search']['value'] . '%'); + } + + if (isset($data['user_id']) && $data['user_id']) { + $model = $model->whereHas('users', function ($query) use ($data) { + $query->where('users.id', $data['user_id']); + }); + } + + if (isset($data['limit']) && !isset($data['page']) && $data['limit']) { + $model = $model->take($data['limit']); + } + + if (isset($data['relations'])) { + foreach ($data['relations'] as $key => $value) { + $model = $model->whereHas($key, function ($query) use ($value) { + if (isset($value['condition'])) { + switch (strtoupper($value['condition'])) { + case 'IN': + $query->whereIn($value['key'], $value['value']); + break; + case 'NOTIN': + $query->whereNotIn($value['key'], $value['value']); + break; + default: + $query->where($value['key'], $value['condition'], $value['value']); + } + } else { + $query->where($value['key'], $value['value']); + } + }); + } + } + + $model = $model->select($select)->orderByDesc($order); + + if (isset($data['start'])) { + return $model->offset($data['start'])->limit($data['length'] ?? 10)->get(); + } + + if (isset($data['page'])) { + return $model->paginate($data['length'] ?? 12); + } + + return $model->get(); + } + + public function findWhereIn(string $key, array $value = []) + { + return $this->model->whereIn($key, $value)->get(); + } + + public function findWithRelations(int $id, array $relationships = []) + { + return $this->model->with($relationships)->find($id); + } +} diff --git a/app/Repositories/DnsManager/Domain/DnsDomainRepositoryInterface.php b/app/Repositories/DnsManager/Domain/DnsDomainRepositoryInterface.php new file mode 100644 index 0000000..52b20ea --- /dev/null +++ b/app/Repositories/DnsManager/Domain/DnsDomainRepositoryInterface.php @@ -0,0 +1,16 @@ +model->with($relationships)->find($id); + } + + public function findWhereIn(string $key, array $value = [], array $relationships = []) + { + return $this->model->with($relationships)->whereIn($key, $value)->get(); + } + + public function filter(array $data = [], array $relationships = [], string $order = 'id', array $select = ['*']) + { + $model = $this->model; + + if (count($relationships)) { + $model = $model->with($relationships); + } + + if (isset($data['q']) && $data['q']) { + $model = $model->where('name', 'like', '%' . $data['q'] . '%'); + } + + if (isset($data['limit']) && !isset($data['page']) && $data['limit']) { + $model = $model->take($data['limit']); + } + + if (isset($data['relations'])) { + foreach ($data['relations'] as $key => $value) { + $model = $model->whereHas($key, function ($query) use ($value) { + if (isset($value['condition'])) { + switch (strtoupper($value['condition'])) { + case 'IN': + $query->whereIn($value['key'], $value['value']); + break; + case 'NOTIN': + $query->whereNotIn($value['key'], $value['value']); + break; + default: + $query->where($value['key'], $value['condition'], $value['value']); + } + } else { + $query->where($value['key'], $value['value']); + } + }); + } + } + + $model = $model->select($select)->orderByDesc($order); + + if (isset($data['page'])) { + return $model->paginate(12); + } + + return $model->get(); + } +} diff --git a/app/Repositories/DnsManager/Record/DnsRecordRepositoryInterface.php b/app/Repositories/DnsManager/Record/DnsRecordRepositoryInterface.php new file mode 100644 index 0000000..9aeb580 --- /dev/null +++ b/app/Repositories/DnsManager/Record/DnsRecordRepositoryInterface.php @@ -0,0 +1,14 @@ +model->isActive()->get(); + } + + public function findWhereIn(string $key, array $value = []) + { + return $this->model->whereIn($key, $value)->get(); + } +} diff --git a/app/Repositories/DnsManager/Server/DnsServerRepositoryInterface.php b/app/Repositories/DnsManager/Server/DnsServerRepositoryInterface.php new file mode 100644 index 0000000..9b8a283 --- /dev/null +++ b/app/Repositories/DnsManager/Server/DnsServerRepositoryInterface.php @@ -0,0 +1,12 @@ + '', + 'type' => 'A', + 'value' => '', + 'opt' => '', + 'ttl' => 300, + ]; + + protected string $domain = ''; + + protected array $entry_points = [ + 'auth' => ':8443/api/v2/auth/keys', + 'server' => ':8443/api/v2/server', + 'domain' => ':8443/api/v2/domains', + 'record' => ':8443/api/v2/dns/records', + ]; + + public function __construct( + public DnsServerRepositoryInterface $serverRepository + ) { + $this->server = $this->getServer(); + } + + public function findServerByID(int $id): ?DnsServer + { + return $this->server = $this->serverRepository->find($id); + } + + public function handlePayload(array $data = []): static + { + $this->domain = $data['domain'] ?? ''; + $name = $data['name'] ?? ''; + + $this->payload = [ + 'type' => $data['type'] ?? 'A', + 'host' => $name === '@' ? $this->domain : ($name . '.' . $this->domain), + 'value' => str_replace(["\r", "\n"], ' ', $data['value'] ?? ''), + 'ttl' => $data['ttl'] ?? 300, + ]; + + switch (strtoupper($this->payload['type'])) { + case 'MX': + $this->payload['opt'] = $data['priority'] ?? 0; + break; + + case 'SRV': + $this->payload['host'] = sprintf('_%s._%s.%s', $data['service_name'], $data['protocol'], $this->domain); + $this->payload['opt'] = sprintf('%d %d %d', $data['priority'] ?? 0, $data['weight'] ?? 50, $data['port'] ?? 21); + break; + } + + return $this; + } + + public function addRecord(): array + { + if (empty($this->domain)) { + return ['error' => true, 'message' => 'Invalid domain']; + } + + try { + $response = Http::withoutVerifying() + ->withBasicAuth($this->server->username, Crypt::decryptString($this->server->password)) + ->timeout(10) + ->post( + BaseHelper::url($this->server->ip_address) . $this->entry_points['record'] . '?' . http_build_query(['domain' => $this->domain]), + $this->payload + )->throw(); + + $this->resetServer(); + + return $response->successful() && count($response->json()) + ? ['error' => false, 'data' => $response->json()] + : ['error' => true]; + } catch (RequestException $e) { + Log::error($e->getMessage()); + return ['error' => true, 'message' => $e->getMessage()]; + } + } + + public function updateRecord(int $record_id = 0): array + { + if (empty($record_id)) { + return ['error' => true, 'message' => 'Invalid request']; + } + + try { + $response = Http::withoutVerifying() + ->withBasicAuth($this->server->username, Crypt::decryptString($this->server->password)) + ->timeout(10) + ->put( + BaseHelper::url($this->server->ip_address) . $this->entry_points['record'] . "/$record_id", + $this->payload + )->throw(); + + $this->resetServer(); + + return $response->successful() && count($response->json()) + ? ['error' => false, 'data' => $response->json()] + : ['error' => true]; + } catch (RequestException $e) { + Log::error($e->getMessage()); + return ['error' => true, 'message' => $e->getMessage()]; + } + } + + public function deleteRecord(int $record_id = 0): array + { + if (empty($record_id)) { + return ['error' => true, 'message' => 'Invalid request']; + } + + try { + $response = Http::withoutVerifying() + ->withBasicAuth($this->server->username, Crypt::decryptString($this->server->password)) + ->timeout(30) + ->delete( + BaseHelper::url($this->server->ip_address) . $this->entry_points['record'] . "/$record_id" + )->throw(); + + $this->resetServer(); + + return $response->successful() && count($response->json()) + ? ['error' => false, 'data' => $response->json()] + : ['error' => true]; + } catch (RequestException $e) { + Log::error($e->getMessage()); + return ['error' => true, 'message' => $e->getMessage()]; + } + } + + public function checkConnection(array $data = []): bool + { + if (empty($data['username']) || empty($data['password']) || empty($data['ip_address'])) { + return false; + } + + try { + $response = Http::withoutVerifying() + ->withBasicAuth($data['username'], $data['password']) + ->timeout(10) + ->get(BaseHelper::url($data['ip_address']) . $this->entry_points['server']); + + return $response->successful(); + } catch (RequestException $e) { + Log::error($e->getMessage()); + return false; + } + } + + public function getDomainInfo(string $domain = ''): array|false + { + if (empty($domain)) { + return false; + } + + try { + $response = Http::withoutVerifying() + ->withBasicAuth($this->server->username, Crypt::decryptString($this->server->password)) + ->timeout(10) + ->get(BaseHelper::url($this->server->ip_address) . $this->entry_points['domain'], ['name' => $domain]); + + $this->resetServer(); + + if ($response->successful()) { + $domains = $response->json(); + foreach ($domains as $domainInfo) { + if (isset($domainInfo['name']) && $domainInfo['name'] === $domain) { + return $domainInfo; + } + } + } + + return false; + } catch (RequestException $e) { + Log::error($e->getMessage()); + return false; + } + } + + public function createDomain(array $data = []): array|false + { + if (empty($data)) { + return false; + } + + if (!$this->server) { + $this->server = $this->serverRepository->find($data['dns_manager_server_id']); + } + + $param = [ + 'name' => $data['domain_name'], + 'description' => '', + 'hosting_type' => 'virtual', + 'hosting_settings' => [ + 'ftp_login' => str_replace('.', '_', $data['domain_name']), + 'ftp_password' => Str::random(12), + ], + 'ip_addresses' => ['103.42.58.124'], + 'ipv4' => ['103.42.58.124'], + 'plan' => ['name' => 'Default Domain'], + ]; + + try { + $response = Http::withoutVerifying() + ->withBasicAuth($this->server->username, Crypt::decryptString($this->server->password)) + ->timeout(30) + ->post(BaseHelper::url($this->server->ip_address) . $this->entry_points['domain'], $param); + + $this->resetServer(); + $responseData = $response->json(); + + Log::info('Response Plesk API Created', ['data' => $responseData]); + + if ($response->successful() && isset($responseData['id'], $responseData['guid'])) { + return $responseData; + } + } catch (RequestException $e) { + Log::error('Plesk domain creation failed', [ + 'error' => $e->getMessage(), + 'response' => $e->response?->body(), + 'data' => $param, + ]); + } + + return false; + } + + public function updateDomain(int $pleskDomainId, array $data = []): array|false + { + if (empty($pleskDomainId) || empty($data)) { + return false; + } + + if (!$this->server) { + $this->server = $this->serverRepository->find($data['dns_manager_server_id']); + } + + $param = [ + 'name' => $data['domain_name'], + 'description' => '', + 'hosting_type' => 'virtual', + 'hosting_settings' => [ + 'ftp_login' => str_replace('.', '_', $data['domain_name']), + 'ftp_password' => Str::random(12), + ], + 'ip_addresses' => ['103.42.58.124'], + 'ipv4' => ['103.42.58.124'], + 'plan' => ['name' => 'Default Domain'], + ]; + + try { + $response = Http::withoutVerifying() + ->withBasicAuth($this->server->username, Crypt::decryptString($this->server->password)) + ->timeout(30) + ->put(BaseHelper::url($this->server->ip_address) . $this->entry_points['domain'] . "/{$pleskDomainId}", $param); + + $this->resetServer(); + $responseData = $response->json(); + + Log::info('Response Plesk API Updated', ['data' => $responseData]); + + if ($response->successful() && isset($responseData['id'], $responseData['guid'])) { + return $responseData; + } + } catch (RequestException $e) { + Log::error('Plesk domain update failed', [ + 'error' => $e->getMessage(), + 'response' => $e->response?->body(), + 'data' => $param, + ]); + } + + return false; + } + + public function removeDomain(int $pleskDomainId): bool + { + if (empty($this->server)) { + return false; + } + + try { + $response = Http::withoutVerifying() + ->withBasicAuth($this->server->username, Crypt::decryptString($this->server->password)) + ->timeout(30) + ->delete(BaseHelper::url($this->server->ip_address) . $this->entry_points['domain'] . "/{$pleskDomainId}"); + + $this->resetServer(); + + if ($response->successful()) { + Log::info('Xoá domain thành công', ['plesk_id' => $pleskDomainId, 'status' => $response->status()]); + return true; + } + + Log::error('Xoá domain thất bại', [ + 'plesk_id' => $pleskDomainId, + 'status' => $response->status(), + 'response' => $response->body(), + ]); + + return false; + } catch (\Exception $e) { + Log::error('Exception khi xoá domain', ['plesk_id' => $pleskDomainId, 'error' => $e->getMessage()]); + return false; + } + } + + public function addServerById(int $serverId): bool + { + $this->server = $this->serverRepository->find($serverId); + return !empty($this->server); + } + + private function getServer(): ?DnsServer + { + return $this->serverRepository->getActived()->first(); + } + + private function resetServer(): void + { + $this->server = null; + } +} diff --git a/composer.json b/composer.json index d9170d4..8936081 100644 --- a/composer.json +++ b/composer.json @@ -17,8 +17,6 @@ "kalnoy/nestedset": "^6.0", "laravel/framework": "^10.0", "laravel/horizon": "^5.4.0", - "laravel/passport": "^12.2", - "laravel/sanctum": "^3.3", "laravel/tinker": "^2.7", "maatwebsite/excel": "^3.1", "opcodesio/log-viewer": "^3.18", @@ -79,4 +77,4 @@ }, "minimum-stability": "dev", "prefer-stable": true -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index ef08eb2..306f5df 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f75a70ad418e7eb8399eb29cd86b0496", + "content-hash": "7e08cc0cca2ccc80fd345626dc3adef8", "packages": [ { "name": "blade-ui-kit/blade-heroicons", @@ -521,73 +521,6 @@ ], "time": "2025-02-06T14:54:32+00:00" }, - { - "name": "defuse/php-encryption", - "version": "v2.4.0", - "source": { - "type": "git", - "url": "https://github.com/defuse/php-encryption.git", - "reference": "f53396c2d34225064647a05ca76c1da9d99e5828" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/defuse/php-encryption/zipball/f53396c2d34225064647a05ca76c1da9d99e5828", - "reference": "f53396c2d34225064647a05ca76c1da9d99e5828", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "paragonie/random_compat": ">= 2", - "php": ">=5.6.0" - }, - "require-dev": { - "phpunit/phpunit": "^5|^6|^7|^8|^9|^10", - "yoast/phpunit-polyfills": "^2.0.0" - }, - "bin": [ - "bin/generate-defuse-key" - ], - "type": "library", - "autoload": { - "psr-4": { - "Defuse\\Crypto\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Hornby", - "email": "taylor@defuse.ca", - "homepage": "https://defuse.ca/" - }, - { - "name": "Scott Arciszewski", - "email": "info@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "Secure PHP Encryption Library", - "keywords": [ - "aes", - "authenticated encryption", - "cipher", - "crypto", - "cryptography", - "encrypt", - "encryption", - "openssl", - "security", - "symmetric key cryptography" - ], - "support": { - "issues": "https://github.com/defuse/php-encryption/issues", - "source": "https://github.com/defuse/php-encryption/tree/v2.4.0" - }, - "time": "2023-06-19T06:10:36+00:00" - }, { "name": "developermithu/tallcraftui", "version": "v2.1.1", @@ -1171,69 +1104,6 @@ }, "time": "2025-10-17T16:34:55+00:00" }, - { - "name": "firebase/php-jwt", - "version": "v7.0.3", - "source": { - "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/28aa0694bcfdfa5e2959c394d5a1ee7a5083629e", - "reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e", - "shasum": "" - }, - "require": { - "php": "^8.0" - }, - "require-dev": { - "guzzlehttp/guzzle": "^7.4", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5", - "psr/cache": "^2.0||^3.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0" - }, - "suggest": { - "ext-sodium": "Support EdDSA (Ed25519) signatures", - "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" - }, - "type": "library", - "autoload": { - "psr-4": { - "Firebase\\JWT\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Neuman Vong", - "email": "neuman+pear@twilio.com", - "role": "Developer" - }, - { - "name": "Anant Narayanan", - "email": "anant@php.net", - "role": "Developer" - } - ], - "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", - "homepage": "https://github.com/firebase/php-jwt", - "keywords": [ - "jwt", - "php" - ], - "support": { - "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v7.0.3" - }, - "time": "2026-02-25T22:16:40+00:00" - }, { "name": "fruitcake/php-cors", "version": "v1.4.0", @@ -2272,82 +2142,6 @@ }, "time": "2026-03-06T15:31:27+00:00" }, - { - "name": "laravel/passport", - "version": "v12.4.3", - "source": { - "type": "git", - "url": "https://github.com/laravel/passport.git", - "reference": "1d2e0170a52f150d5c35c9a6fc1f7ccebcde7626" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/passport/zipball/1d2e0170a52f150d5c35c9a6fc1f7ccebcde7626", - "reference": "1d2e0170a52f150d5c35c9a6fc1f7ccebcde7626", - "shasum": "" - }, - "require": { - "ext-json": "*", - "firebase/php-jwt": "^6.4|^7.0", - "illuminate/auth": "^9.21|^10.0|^11.0|^12.0", - "illuminate/console": "^9.21|^10.0|^11.0|^12.0", - "illuminate/container": "^9.21|^10.0|^11.0|^12.0", - "illuminate/contracts": "^9.21|^10.0|^11.0|^12.0", - "illuminate/cookie": "^9.21|^10.0|^11.0|^12.0", - "illuminate/database": "^9.21|^10.0|^11.0|^12.0", - "illuminate/encryption": "^9.21|^10.0|^11.0|^12.0", - "illuminate/http": "^9.21|^10.0|^11.0|^12.0", - "illuminate/support": "^9.21|^10.0|^11.0|^12.0", - "lcobucci/jwt": "^4.3|^5.0", - "league/oauth2-server": "^8.5.3", - "nyholm/psr7": "^1.5", - "php": "^8.0", - "phpseclib/phpseclib": "^2.0|^3.0", - "symfony/console": "^6.0|^7.0", - "symfony/psr-http-message-bridge": "^2.1|^6.0|^7.0" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "orchestra/testbench": "^7.35|^8.14|^9.0|^10.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.3|^10.5|^11.5" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Laravel\\Passport\\PassportServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Laravel\\Passport\\": "src/", - "Laravel\\Passport\\Database\\Factories\\": "database/factories/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Laravel Passport provides OAuth2 server support to Laravel.", - "keywords": [ - "laravel", - "oauth", - "passport" - ], - "support": { - "issues": "https://github.com/laravel/passport/issues", - "source": "https://github.com/laravel/passport" - }, - "time": "2026-02-19T14:14:05+00:00" - }, { "name": "laravel/prompts", "version": "v0.1.25", @@ -2406,72 +2200,6 @@ }, "time": "2024-08-12T22:06:33+00:00" }, - { - "name": "laravel/sanctum", - "version": "v3.3.3", - "source": { - "type": "git", - "url": "https://github.com/laravel/sanctum.git", - "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/8c104366459739f3ada0e994bcd3e6fd681ce3d5", - "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5", - "shasum": "" - }, - "require": { - "ext-json": "*", - "illuminate/console": "^9.21|^10.0", - "illuminate/contracts": "^9.21|^10.0", - "illuminate/database": "^9.21|^10.0", - "illuminate/support": "^9.21|^10.0", - "php": "^8.0.2" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "orchestra/testbench": "^7.28.2|^8.8.3", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.6" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Laravel\\Sanctum\\SanctumServiceProvider" - ] - }, - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Laravel\\Sanctum\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.", - "keywords": [ - "auth", - "laravel", - "sanctum" - ], - "support": { - "issues": "https://github.com/laravel/sanctum/issues", - "source": "https://github.com/laravel/sanctum" - }, - "time": "2023-12-19T18:44:48+00:00" - }, { "name": "laravel/sentinel", "version": "v1.0.1", @@ -2658,70 +2386,6 @@ }, "time": "2026-02-06T14:12:35+00:00" }, - { - "name": "lcobucci/clock", - "version": "3.3.1", - "source": { - "type": "git", - "url": "https://github.com/lcobucci/clock.git", - "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/db3713a61addfffd615b79bf0bc22f0ccc61b86b", - "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b", - "shasum": "" - }, - "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0", - "psr/clock": "^1.0" - }, - "provide": { - "psr/clock-implementation": "1.0" - }, - "require-dev": { - "infection/infection": "^0.29", - "lcobucci/coding-standard": "^11.1.0", - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^1.10.25", - "phpstan/phpstan-deprecation-rules": "^1.1.3", - "phpstan/phpstan-phpunit": "^1.3.13", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^11.3.6" - }, - "type": "library", - "autoload": { - "psr-4": { - "Lcobucci\\Clock\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Luís Cobucci", - "email": "lcobucci@gmail.com" - } - ], - "description": "Yet another clock abstraction", - "support": { - "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/3.3.1" - }, - "funding": [ - { - "url": "https://github.com/lcobucci", - "type": "github" - }, - { - "url": "https://www.patreon.com/lcobucci", - "type": "patreon" - } - ], - "time": "2024-09-24T20:45:14+00:00" - }, { "name": "lcobucci/jwt", "version": "5.6.0", @@ -2984,60 +2648,6 @@ ], "time": "2022-12-11T20:36:23+00:00" }, - { - "name": "league/event", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/event.git", - "reference": "062ebb450efbe9a09bc2478e89b7c933875b0935" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/event/zipball/062ebb450efbe9a09bc2478e89b7c933875b0935", - "reference": "062ebb450efbe9a09bc2478e89b7c933875b0935", - "shasum": "" - }, - "require": { - "php": ">=7.1.0" - }, - "require-dev": { - "henrikbjorn/phpspec-code-coverage": "~1.0.1", - "phpspec/phpspec": "^2.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2-dev" - } - }, - "autoload": { - "psr-4": { - "League\\Event\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Frank de Jonge", - "email": "info@frenky.net" - } - ], - "description": "Event package", - "keywords": [ - "emitter", - "event", - "listener" - ], - "support": { - "issues": "https://github.com/thephpleague/event/issues", - "source": "https://github.com/thephpleague/event/tree/2.3.0" - }, - "time": "2025-03-14T19:51:10+00:00" - }, { "name": "league/flysystem", "version": "3.32.0", @@ -3226,276 +2836,6 @@ ], "time": "2024-09-21T08:32:55+00:00" }, - { - "name": "league/oauth2-server", - "version": "8.5.5", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/oauth2-server.git", - "reference": "cc8778350f905667e796b3c2364a9d3bd7a73518" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/cc8778350f905667e796b3c2364a9d3bd7a73518", - "reference": "cc8778350f905667e796b3c2364a9d3bd7a73518", - "shasum": "" - }, - "require": { - "defuse/php-encryption": "^2.3", - "ext-openssl": "*", - "lcobucci/clock": "^2.2 || ^3.0", - "lcobucci/jwt": "^4.3 || ^5.0", - "league/event": "^2.2", - "league/uri": "^6.7 || ^7.0", - "php": "^8.0", - "psr/http-message": "^1.0.1 || ^2.0" - }, - "replace": { - "league/oauth2server": "*", - "lncd/oauth2": "*" - }, - "require-dev": { - "laminas/laminas-diactoros": "^3.0.0", - "phpstan/phpstan": "^0.12.57", - "phpstan/phpstan-phpunit": "^0.12.16", - "phpunit/phpunit": "^9.6.6", - "roave/security-advisories": "dev-master" - }, - "type": "library", - "autoload": { - "psr-4": { - "League\\OAuth2\\Server\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alex Bilbie", - "email": "hello@alexbilbie.com", - "homepage": "http://www.alexbilbie.com", - "role": "Developer" - }, - { - "name": "Andy Millington", - "email": "andrew@noexceptions.io", - "homepage": "https://www.noexceptions.io", - "role": "Developer" - } - ], - "description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.", - "homepage": "https://oauth2.thephpleague.com/", - "keywords": [ - "Authentication", - "api", - "auth", - "authorisation", - "authorization", - "oauth", - "oauth 2", - "oauth 2.0", - "oauth2", - "protect", - "resource", - "secure", - "server" - ], - "support": { - "issues": "https://github.com/thephpleague/oauth2-server/issues", - "source": "https://github.com/thephpleague/oauth2-server/tree/8.5.5" - }, - "funding": [ - { - "url": "https://github.com/sephster", - "type": "github" - } - ], - "time": "2024-12-20T23:06:10+00:00" - }, - { - "name": "league/uri", - "version": "7.8.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/uri.git", - "reference": "4436c6ec8d458e4244448b069cc572d088230b76" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76", - "reference": "4436c6ec8d458e4244448b069cc572d088230b76", - "shasum": "" - }, - "require": { - "league/uri-interfaces": "^7.8", - "php": "^8.1", - "psr/http-factory": "^1" - }, - "conflict": { - "league/uri-schemes": "^1.0" - }, - "suggest": { - "ext-bcmath": "to improve IPV4 host parsing", - "ext-dom": "to convert the URI into an HTML anchor tag", - "ext-fileinfo": "to create Data URI from file contennts", - "ext-gmp": "to improve IPV4 host parsing", - "ext-intl": "to handle IDN host with the best performance", - "ext-uri": "to use the PHP native URI class", - "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain", - "league/uri-components": "to provide additional tools to manipulate URI objects components", - "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP", - "php-64bit": "to improve IPV4 host parsing", - "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", - "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "7.x-dev" - } - }, - "autoload": { - "psr-4": { - "League\\Uri\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ignace Nyamagana Butera", - "email": "nyamsprod@gmail.com", - "homepage": "https://nyamsprod.com" - } - ], - "description": "URI manipulation library", - "homepage": "https://uri.thephpleague.com", - "keywords": [ - "URN", - "data-uri", - "file-uri", - "ftp", - "hostname", - "http", - "https", - "middleware", - "parse_str", - "parse_url", - "psr-7", - "query-string", - "querystring", - "rfc2141", - "rfc3986", - "rfc3987", - "rfc6570", - "rfc8141", - "uri", - "uri-template", - "url", - "ws" - ], - "support": { - "docs": "https://uri.thephpleague.com", - "forum": "https://thephpleague.slack.com", - "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri/tree/7.8.0" - }, - "funding": [ - { - "url": "https://github.com/sponsors/nyamsprod", - "type": "github" - } - ], - "time": "2026-01-14T17:24:56+00:00" - }, - { - "name": "league/uri-interfaces", - "version": "7.8.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4", - "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^8.1", - "psr/http-message": "^1.1 || ^2.0" - }, - "suggest": { - "ext-bcmath": "to improve IPV4 host parsing", - "ext-gmp": "to improve IPV4 host parsing", - "ext-intl": "to handle IDN host with the best performance", - "php-64bit": "to improve IPV4 host parsing", - "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", - "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "7.x-dev" - } - }, - "autoload": { - "psr-4": { - "League\\Uri\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ignace Nyamagana Butera", - "email": "nyamsprod@gmail.com", - "homepage": "https://nyamsprod.com" - } - ], - "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI", - "homepage": "https://uri.thephpleague.com", - "keywords": [ - "data-uri", - "file-uri", - "ftp", - "hostname", - "http", - "https", - "parse_str", - "parse_url", - "psr-7", - "query-string", - "querystring", - "rfc3986", - "rfc3987", - "rfc6570", - "uri", - "url", - "ws" - ], - "support": { - "docs": "https://uri.thephpleague.com", - "forum": "https://thephpleague.slack.com", - "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0" - }, - "funding": [ - { - "url": "https://github.com/sponsors/nyamsprod", - "type": "github" - } - ], - "time": "2026-01-15T06:54:53+00:00" - }, { "name": "maatwebsite/excel", "version": "3.1.67", @@ -4273,84 +3613,6 @@ ], "time": "2024-11-21T10:36:35+00:00" }, - { - "name": "nyholm/psr7", - "version": "1.8.2", - "source": { - "type": "git", - "url": "https://github.com/Nyholm/psr7.git", - "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Nyholm/psr7/zipball/a71f2b11690f4b24d099d6b16690a90ae14fc6f3", - "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3", - "shasum": "" - }, - "require": { - "php": ">=7.2", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1 || ^2.0" - }, - "provide": { - "php-http/message-factory-implementation": "1.0", - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "http-interop/http-factory-tests": "^0.9", - "php-http/message-factory": "^1.0", - "php-http/psr7-integration-tests": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4", - "symfony/error-handler": "^4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, - "autoload": { - "psr-4": { - "Nyholm\\Psr7\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com" - }, - { - "name": "Martijn van der Ven", - "email": "martijn@vanderven.se" - } - ], - "description": "A fast PHP7 implementation of PSR-7", - "homepage": "https://tnyholm.se", - "keywords": [ - "psr-17", - "psr-7" - ], - "support": { - "issues": "https://github.com/Nyholm/psr7/issues", - "source": "https://github.com/Nyholm/psr7/tree/1.8.2" - }, - "funding": [ - { - "url": "https://github.com/Zegnat", - "type": "github" - }, - { - "url": "https://github.com/nyholm", - "type": "github" - } - ], - "time": "2024-09-09T07:06:30+00:00" - }, { "name": "opcodesio/log-viewer", "version": "v3.23.0", @@ -7712,94 +6974,6 @@ ], "time": "2026-01-23T16:02:12+00:00" }, - { - "name": "symfony/psr-http-message-bridge", - "version": "v7.4.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "929ffe10bbfbb92e711ac3818d416f9daffee067" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/929ffe10bbfbb92e711ac3818d416f9daffee067", - "reference": "929ffe10bbfbb92e711ac3818d416f9daffee067", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/http-message": "^1.0|^2.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0" - }, - "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-kernel": "<6.4" - }, - "require-dev": { - "nyholm/psr7": "^1.1", - "php-http/discovery": "^1.15", - "psr/log": "^1.1.4|^2|^3", - "symfony/browser-kit": "^6.4|^7.0|^8.0", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/event-dispatcher": "^6.4|^7.0|^8.0", - "symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0", - "symfony/http-kernel": "^6.4.13|^7.1.6|^8.0", - "symfony/runtime": "^6.4.13|^7.1.6|^8.0" - }, - "type": "symfony-bridge", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\PsrHttpMessage\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "PSR HTTP message bridge", - "homepage": "https://symfony.com", - "keywords": [ - "http", - "http-message", - "psr-17", - "psr-7" - ], - "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.4.4" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-01-03T23:30:35+00:00" - }, { "name": "symfony/routing", "version": "v6.4.34", diff --git a/config/auth.php b/config/auth.php index d53b4af..446747d 100644 --- a/config/auth.php +++ b/config/auth.php @@ -14,7 +14,7 @@ return [ */ 'defaults' => [ - 'guard' => 'admins', + 'guard' => 'admin', 'passwords' => 'admins', ], @@ -36,35 +36,14 @@ return [ */ 'guards' => [ - 'web' => [ - 'driver' => 'session', - 'provider' => 'users', - ], - 'admins' => [ - 'driver' => 'session', - 'provider' => 'admins', - ], - 'users' => [ - 'driver' => 'session', - 'provider' => 'users', - ], - 'users-api' => [ - 'driver' => 'passport', - 'provider' => 'users', - ], + // JWT guard for customer API (/v1/client/*) 'client' => [ 'driver' => 'jwt', 'provider' => 'users', ], - 'client-api' => [ - 'driver' => 'jwt', - 'provider' => 'users', - ], - 'client-sanctum' => [ - 'driver' => 'sanctum', - 'provider' => 'users', - ], - 'admins-api' => [ + + // JWT guard for admin API (/v1/administrator/*) + 'admin' => [ 'driver' => 'jwt', 'provider' => 'admins', ], diff --git a/config/passport.php b/config/passport.php deleted file mode 100644 index 62e8bcc..0000000 --- a/config/passport.php +++ /dev/null @@ -1,75 +0,0 @@ - 'users', - - /* - |-------------------------------------------------------------------------- - | Encryption Keys - |-------------------------------------------------------------------------- - | - | Passport uses encryption keys while generating secure access tokens for - | your application. By default, the keys are stored as local files but - | can be set via environment variables when that is more convenient. - | - */ - - 'private_key' => env('PASSPORT_PRIVATE_KEY'), - - 'public_key' => env('PASSPORT_PUBLIC_KEY'), - - /* - |-------------------------------------------------------------------------- - | Passport Database Connection - |-------------------------------------------------------------------------- - | - | By default, Passport's models will utilize your application's default - | database connection. If you wish to use a different connection you - | may specify the configured name of the database connection here. - | - */ - - 'connection' => env('PASSPORT_CONNECTION'), - - /* - |-------------------------------------------------------------------------- - | Client UUIDs - |-------------------------------------------------------------------------- - | - | By default, Passport uses auto-incrementing primary keys when assigning - | IDs to clients. However, if Passport is installed using the provided - | --uuids switch, this will be set to "true" and UUIDs will be used. - | - */ - - 'client_uuids' => true, - - /* - |-------------------------------------------------------------------------- - | Personal Access Client - |-------------------------------------------------------------------------- - | - | If you enable client hashing, you should set the personal access client - | ID and unhashed secret within your environment file. The values will - | get used while issuing fresh personal access tokens to your users. - | - */ - - 'personal_access_client' => [ - 'id' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_ID'), - 'secret' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET'), - ], - -]; diff --git a/config/sanctum.php b/config/sanctum.php deleted file mode 100644 index 0d07a41..0000000 --- a/config/sanctum.php +++ /dev/null @@ -1,83 +0,0 @@ - explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( - '%s%s', - 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', - Sanctum::currentApplicationUrlWithPort() - ))), - - /* - |-------------------------------------------------------------------------- - | Sanctum Guards - |-------------------------------------------------------------------------- - | - | This array contains the authentication guards that will be checked when - | Sanctum is trying to authenticate a request. If none of these guards - | are able to authenticate the request, Sanctum will use the bearer - | token that's present on an incoming request for authentication. - | - */ - - 'guard' => ['admins', 'users'], - - /* - |-------------------------------------------------------------------------- - | Expiration Minutes - |-------------------------------------------------------------------------- - | - | This value controls the number of minutes until an issued token will be - | considered expired. This will override any values set in the token's - | "expires_at" attribute, but first-party sessions are not affected. - | - */ - - 'expiration' => 86400, - - /* - |-------------------------------------------------------------------------- - | Token Prefix - |-------------------------------------------------------------------------- - | - | Sanctum can prefix new tokens in order to take advantage of numerous - | security scanning initiatives maintained by open source platforms - | that notify developers if they commit tokens into repositories. - | - | See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning - | - */ - - 'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''), - - /* - |-------------------------------------------------------------------------- - | Sanctum Middleware - |-------------------------------------------------------------------------- - | - | When authenticating your first-party SPA with Sanctum you may need to - | customize some of the middleware Sanctum uses while processing the - | request. You may change the middleware listed below as required. - | - */ - - 'middleware' => [ - 'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class, - 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class, - 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class, - ], - -]; diff --git a/database/migrations/2026_03_09_000001_create_dns_manager_tables.php b/database/migrations/2026_03_09_000001_create_dns_manager_tables.php new file mode 100644 index 0000000..4f96e9b --- /dev/null +++ b/database/migrations/2026_03_09_000001_create_dns_manager_tables.php @@ -0,0 +1,74 @@ +id(); + $table->string('name')->nullable(); + $table->string('ip_address')->index(); + $table->string('username')->default('root'); + $table->string('password', 255); + $table->string('api_key')->nullable(); + $table->string('status')->default('activated'); + $table->timestamps(); + }); + } + + if (!Schema::hasTable('dns_manager_domain')) { + Schema::create('dns_manager_domain', function (Blueprint $table) { + $table->id(); + $table->string('domain_name')->nullable(); + $table->tinyInteger('user_id')->index()->default(0); + $table->integer('dns_manager_server_id')->default(0)->index(); + $table->integer('is_created')->default(0); + $table->integer('plesk_id')->nullable(); + $table->timestamps(); + }); + } + + if (!Schema::hasTable('dns_domain_user')) { + Schema::create('dns_domain_user', function (Blueprint $table) { + $table->id(); + $table->unsignedBigInteger('domain_id')->index(); + $table->unsignedBigInteger('user_id')->index(); + $table->timestamps(); + + $table->unique(['domain_id', 'user_id']); + }); + } + + if (!Schema::hasTable('dns_manager_ns')) { + Schema::create('dns_manager_ns', function (Blueprint $table) { + $table->id(); + $table->integer('dns_manager_domain_id')->index(); + $table->string('name')->default(''); + $table->string('type')->default('A'); + $table->string('type_valid')->nullable(); + $table->string('priority')->nullable()->default(0); + $table->string('weight')->nullable()->default(0); + $table->string('port')->nullable()->default(0); + $table->string('service_name')->nullable(); + $table->string('protocol')->nullable(); + $table->longText('value')->nullable(); + $table->integer('plesk_id')->nullable(); + $table->integer('ttl')->default(300); + $table->timestamps(); + }); + } + } + + public function down(): void + { + Schema::dropIfExists('dns_manager_ns'); + Schema::dropIfExists('dns_domain_user'); + Schema::dropIfExists('dns_manager_domain'); + Schema::dropIfExists('dns_manager_servers'); + } +}; diff --git a/routes/admin.php b/routes/admin.php new file mode 100644 index 0000000..5f19665 --- /dev/null +++ b/routes/admin.php @@ -0,0 +1,58 @@ +as('admin.')->group(function () { + + // Server + Route::group(['prefix' => 'server', 'as' => 'server.', 'controller' => ServerController::class], function () { + Route::get('/', 'index')->name('index'); + Route::get('get-all', 'getAll')->name('getAll'); + Route::get('create', 'create')->name('create'); + Route::post('create', 'store')->name('store'); + Route::post('check-connect', 'connect')->name('connect'); + Route::get('edit/{id}', 'edit')->name('edit'); + Route::put('edit/{id}', 'update')->name('update'); + Route::delete('remove/{id}', 'destroy')->name('destroy'); + Route::delete('remove-all', 'destroyCustom')->name('destroyCustom'); + }); + + // Domain + Route::group(['prefix' => 'domain', 'as' => 'domain.', 'controller' => DomainController::class], function () { + Route::get('/', 'index')->name('index'); + Route::get('get-all', 'getAll')->name('getAll'); + Route::get('{id}/records', 'record')->name('record'); + Route::get('create', 'create')->name('create'); + Route::post('create', 'store')->name('store'); + Route::get('edit/{id}', 'edit')->name('edit'); + Route::put('edit/{id}', 'update')->name('update'); + Route::delete('remove/{id}', 'destroy')->name('destroy'); + Route::delete('remove-all', 'destroyCustom')->name('destroyCustom'); + }); + + // Record + Route::group(['prefix' => 'record', 'as' => 'record.', 'controller' => RecordController::class], function () { + Route::get('/', 'index')->name('index'); + Route::get('get-all', 'getAll')->name('getAll'); + Route::get('domain/{id}/record/create', 'create')->name('create'); + Route::post('domain/{id}/record/create', 'store')->name('store'); + Route::get('domain/{id}/record/edit/{record_id}', 'edit')->name('edit'); + Route::put('domain/{id}/record/edit/{record_id}', 'update')->name('update'); + Route::delete('remove/{id}', 'destroy')->name('destroy'); + Route::delete('remove-all', 'destroyCustom')->name('destroyCustom'); + }); + +}); diff --git a/routes/api.php b/routes/api.php index a8ff8d2..f2358d8 100644 --- a/routes/api.php +++ b/routes/api.php @@ -33,7 +33,7 @@ Route::prefix('v1') Route::prefix('administrator')->group(function () { Route::post('login', [AuthController::class, 'login']); - Route::middleware('api.auth:admins-api')->group(function () { + Route::middleware('api.auth:admin')->group(function () { Route::post('logout', [AuthController::class, 'logout']); Route::post('refresh', [AuthController::class, 'refresh']); Route::get('me', [AuthController::class, 'me']); diff --git a/routes/channels.php b/routes/channels.php index 369f607..60e88b4 100644 --- a/routes/channels.php +++ b/routes/channels.php @@ -18,20 +18,20 @@ use Illuminate\Support\Facades\Broadcast; //}); Broadcast::channel('Payment-Success.{id}', function ($user, $id) { return (int)$user->id === (int)$id; -}, ['guards' => ['users', 'customer']]); +}, ['guards' => ['client']]); Broadcast::channel('Expiry-Time.{id}', function ($user, $id) { return (int)$user->id === (int)$id; -}, ['guards' => ['users', 'customer']]); +}, ['guards' => ['client']]); Broadcast::channel('Created.Success.{id}', function ($user, $id) { return (int)$user->id === (int)$id; -}, ['guards' => ['users', 'customer']]); +}, ['guards' => ['client']]); Broadcast::channel('Panel.Status.{id}', function ($user, $id) { return (int)$user->id === (int)$id; -}, ['guards' => ['users', 'customer']]); +}, ['guards' => ['client']]); Broadcast::channel('user.{id}', function ($user, $id) { return (int) $user->id === (int) $id; -}, ['guards' => ['users', 'customer']]); +}, ['guards' => ['client']]);