feat: Add DNS management resources and importer

- Implemented DomainCollection, DomainDetailResource, DomainNSCollection, DomainNSResource, and DomainResource for handling DNS domain and record data.
- Created VpsServiceCollection and VpsServiceResource for VPS service management.
- Added DnsManagerNS and DnsManagerUser models to represent DNS records and user associations.
- Developed AdminZoneDnsSqlImporter for importing DNS data from SQL dumps, including customer and DNS domain records.
- Added migration scripts to update the customers table with new fields and sync foreign key references for DNS tables.
- Created a migration preview document outlining the mapping and schema changes for the admin zone DNS import.
This commit is contained in:
baodev0
2026-05-26 13:54:33 +07:00
parent 520f21cb11
commit fccb0c353a
30 changed files with 4030 additions and 105 deletions
@@ -0,0 +1,138 @@
<?php
namespace App\Http\Controllers\Api\Admin\DnsManager;
use App\Http\Controllers\Controller;
use App\Repositories\DnsManager\Record\DnsRecordRepositoryInterface;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class RecordController extends Controller
{
public function __construct(
private readonly DnsRecordRepositoryInterface $recordRepository,
) {}
public function index(Request $request): JsonResponse
{
$perPage = min((int) $request->get('per_page', 15), 500);
$filter = trim((string) $request->get('filter', ''));
$type = trim((string) $request->get('type', ''));
$query = $this->recordRepository->model
->with(['domain.server'])
->newQuery();
if ($filter !== '') {
$query->where(function ($subQuery) use ($filter) {
$subQuery->where('name', 'like', "%{$filter}%")
->orWhere('value', 'like', "%{$filter}%")
->orWhereHas('domain', function ($domainQuery) use ($filter) {
$domainQuery->where('domain_name', 'like', "%{$filter}%")
->orWhereHas('server', function ($serverQuery) use ($filter) {
$serverQuery->where('name', 'like', "%{$filter}%")
->orWhere('ip_address', 'like', "%{$filter}%");
});
});
});
}
if ($type !== '') {
$query->where('type', $type);
}
$paginator = $query->orderByDesc('id')->paginate($perPage);
return response()->json([
'error' => false,
'data' => [
'items' => $paginator->getCollection()->map(fn($record) => $this->formatRecord($record)),
'total' => $paginator->total(),
'per_page' => $paginator->perPage(),
'current_page' => $paginator->currentPage(),
'last_page' => $paginator->lastPage(),
],
]);
}
public function show(int $id): JsonResponse
{
$record = $this->recordRepository->model
->with(['domain.server'])
->find($id);
if (! $record) {
return response()->json(['error' => true, 'message' => "Không tìm thấy bản ghi DNS #$id"], 404);
}
return response()->json([
'error' => false,
'data' => $this->formatRecord($record),
]);
}
public function update(int $id, Request $request): JsonResponse
{
$record = $this->recordRepository->model
->with(['domain.server'])
->find($id);
if (! $record) {
return response()->json(['error' => true, 'message' => "Không tìm thấy bản ghi DNS #$id"], 404);
}
$validated = $request->validate([
'type' => 'required|string|in:A,AAAA,CNAME,TXT,MX,NS,SRV',
'name' => 'required|string|max:255',
'value' => 'required|string',
'ttl' => 'nullable|integer|min:60',
'priority' => 'nullable|integer|min:0',
'weight' => 'nullable|integer|min:0',
'port' => 'nullable|integer|min:0',
'service_name' => 'nullable|string|max:255',
'protocol' => 'nullable|string|max:50',
]);
$payload = [
'type' => $validated['type'],
'type_valid' => $validated['type'],
'name' => $validated['name'],
'value' => $validated['value'],
'ttl' => $validated['ttl'] ?? 300,
'priority' => array_key_exists('priority', $validated) ? (string) ($validated['priority'] ?? 0) : $record->priority,
'weight' => array_key_exists('weight', $validated) ? (string) ($validated['weight'] ?? 0) : $record->weight,
'port' => array_key_exists('port', $validated) ? (string) ($validated['port'] ?? 0) : $record->port,
'service_name' => $validated['service_name'] ?? null,
'protocol' => $validated['protocol'] ?? null,
];
$this->recordRepository->update($id, $payload);
return $this->show($id);
}
private function formatRecord($record): array
{
return [
'id' => $record->id,
'dns_manager_domain_id' => $record->dns_manager_domain_id,
'domain_name' => $record->domain?->domain_name,
'dns_manager_server_id' => $record->domain?->dns_manager_server_id,
'server_name' => $record->domain?->server?->name,
'server_ip_address' => $record->domain?->server?->ip_address,
'type' => $record->type,
'type_valid' => $record->type_valid,
'name' => $record->name,
'value' => $record->value,
'priority' => $record->priority !== null ? (int) $record->priority : null,
'weight' => $record->weight !== null ? (int) $record->weight : null,
'port' => $record->port !== null ? (int) $record->port : null,
'service_name' => $record->service_name,
'protocol' => $record->protocol,
'plesk_id' => $record->plesk_id,
'ttl' => (int) $record->ttl,
'created_at' => $record->created_at,
'updated_at' => $record->updated_at,
];
}
}
@@ -4,46 +4,48 @@ namespace App\Http\Controllers\Api\Admin\DnsManager;
use App\Http\Controllers\Controller;
use App\Repositories\DnsManager\Server\DnsServerRepositoryInterface;
use App\Services\ServerService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
class ServerController extends Controller
{
public function __construct(
private readonly DnsServerRepositoryInterface $serverRepository,
private readonly ServerService $serverService,
) {}
public function index(Request $request): JsonResponse
{
$perPage = min((int) $request->get('per_page', 15), 500);
$filter = $request->get('filter');
$status = $request->get('status');
$filter = $request->get('filter');
$status = $request->get('status');
$query = $this->serverRepository->model->newQuery();
if ($filter) {
$query->where(function ($q) use ($filter) {
$q->where('name', 'like', "%{$filter}%")
->orWhere('ip_address', 'like', "%{$filter}%");
$query->where(function ($subQuery) use ($filter) {
$subQuery->where('name', 'like', "%{$filter}%")
->orWhere('ip_address', 'like', "%{$filter}%")
->orWhere('username', 'like', "%{$filter}%");
});
}
if ($status) {
if ($status !== null && $status !== '') {
$query->where('status', $status);
}
$paginator = $query->paginate($perPage);
$paginator = $query->orderByDesc('id')->paginate($perPage);
return response()->json([
'error' => false,
'data' => [
'items' => $paginator->items(),
'total' => $paginator->total(),
'per_page' => $paginator->perPage(),
'data' => [
'items' => $paginator->getCollection()->map(fn($server) => $this->formatServer($server)),
'total' => $paginator->total(),
'per_page' => $paginator->perPage(),
'current_page' => $paginator->currentPage(),
'last_page' => $paginator->lastPage(),
'last_page' => $paginator->lastPage(),
],
]);
}
@@ -56,30 +58,44 @@ class ServerController extends Controller
return response()->json(['error' => true, 'message' => "Không tìm thấy server #$id"], 404);
}
return response()->json(['error' => false, 'data' => $server]);
return response()->json([
'error' => false,
'data' => $this->formatServer($server),
]);
}
public function store(Request $request): JsonResponse
{
$request->validate([
'name' => 'required|string|max:255',
$validated = $request->validate([
'name' => 'required|string|max:255',
'ip_address' => 'required|string|max:255',
'username' => 'required|string|max:255',
'password' => 'required|string|max:255',
'api_key' => 'nullable|string',
'status' => 'nullable|string|in:activated,Stopped',
'username' => 'required|string|max:255',
'password' => 'required|string|max:255',
'api_key' => 'nullable|string',
'status' => 'nullable|string|in:activated,Stopped',
]);
DB::beginTransaction();
try {
$data = $request->all();
$data['password'] = Crypt::encryptString($request->password);
$server = $this->serverRepository->create($data);
$server = $this->serverRepository->create([
'name' => $validated['name'],
'ip_address' => $validated['ip_address'],
'username' => $validated['username'],
'password' => encrypt($validated['password']),
'api_key' => $validated['api_key'] ?? null,
'status' => $validated['status'] ?? 'activated',
]);
DB::commit();
return response()->json(['error' => false, 'data' => $server], 201);
return response()->json([
'error' => false,
'data' => $this->formatServer($server),
], 201);
} catch (\Exception $e) {
DB::rollBack();
return response()->json(['error' => true, 'message' => $e->getMessage()], 500);
}
}
@@ -92,29 +108,34 @@ class ServerController extends Controller
return response()->json(['error' => true, 'message' => "Không tìm thấy server #$id"], 404);
}
$request->validate([
'name' => 'required|string|max:255',
'ip_address' => 'required|string|max:255',
'username' => 'required|string|max:255',
'password' => 'nullable|string|max:255',
'api_key' => 'nullable|string',
'status' => 'nullable|string|in:activated,Stopped',
$validated = $request->validate([
'name' => 'sometimes|required|string|max:255',
'ip_address' => 'sometimes|required|string|max:255',
'username' => 'sometimes|required|string|max:255',
'password' => 'nullable|string|max:255',
'api_key' => 'nullable|string',
'status' => 'nullable|string|in:activated,Stopped',
]);
DB::beginTransaction();
try {
$data = $request->except(['password']);
if (!empty($request->password)) {
$data['password'] = Crypt::encryptString($request->password);
try {
$payload = collect($validated)
->except('password')
->toArray();
if ($request->filled('password')) {
$payload['password'] = encrypt((string) $request->password);
}
$this->serverRepository->update($id, $data);
$this->serverRepository->update($id, $payload);
DB::commit();
return response()->json(['error' => false, 'data' => $this->serverRepository->find($id)]);
return $this->show($id);
} catch (\Exception $e) {
DB::rollBack();
return response()->json(['error' => true, 'message' => $e->getMessage()], 500);
}
}
@@ -131,4 +152,37 @@ class ServerController extends Controller
return response()->json(['error' => false, 'message' => 'Đã xoá server thành công']);
}
public function checkConnection(int $id): JsonResponse
{
$server = $this->serverRepository->find($id);
if (!$server) {
return response()->json(['error' => true, 'message' => "Không tìm thấy server #$id"], 404);
}
$connected = $this->serverService->checkConnectionByServer($server);
return response()->json([
'error' => !$connected,
'data' => ['connected' => $connected],
'message' => $connected
? 'Kết nối server thành công.'
: 'Không thể kết nối tới server. Vui lòng kiểm tra lại IP hoặc tài khoản.',
]);
}
private function formatServer($server): array
{
return [
'id' => $server->id,
'name' => $server->name,
'ip_address' => $server->ip_address,
'username' => $server->username,
'api_key' => $server->api_key,
'status' => $server->status,
'created_at' => $server->created_at,
'updated_at' => $server->updated_at,
];
}
}
@@ -0,0 +1,284 @@
<?php
namespace App\Http\Controllers\Api\Client\Service;
use App\Http\Controllers\Controller;
use App\Http\Resources\Api\Service\DomainCollection;
use App\Http\Resources\Api\Service\DomainDetailResource;
use App\Http\Resources\Api\Service\DomainNSResource;
use App\Models\DnsDomain;
use App\Models\DnsManagerNS;
use App\Services\ActivityLogger;
use App\Services\ServerService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class DomainController extends Controller
{
public function __construct(
protected ActivityLogger $activityLogger,
protected ServerService $serverService,
) {}
public function index(Request $request): JsonResponse
{
$customer = $request->user();
$perPage = min((int) $request->get('per_page', 15), 100);
$domains = DnsDomain::query()
->with('server')
->withCount('record')
->whereHas('customer', fn ($query) => $query->where('customers.id', $customer->id))
->orderByDesc('id')
->paginate($perPage);
return (new DomainCollection($domains))
->additional([
'error' => false,
'message' => 'Lấy dữ liệu thành công',
'page_type' => 'service_domain',
])
->response();
}
public function show(Request $request, int $domainId): JsonResponse
{
$domain = $this->resolveCustomerDomain($request, $domainId);
if (! $domain) {
return response()->json(['error' => true, 'message' => 'Không tìm thấy domain'], 404);
}
$perPage = min((int) $request->get('per_page', 15), 100);
$domain->load('server')->loadCount('record');
$records = DnsManagerNS::query()
->where('dns_manager_domain_id', $domain->id)
->orderBy('type')
->orderBy('name')
->paginate($perPage);
return response()->json([
'error' => false,
'message' => 'Lấy dữ liệu thành công',
'page_type' => 'service_domain_detail',
'data' => new DomainDetailResource($domain, $records),
]);
}
public function storeRecord(Request $request, int $domainId): JsonResponse
{
$domain = $this->resolveCustomerDomain($request, $domainId);
if (! $domain) {
return response()->json(['error' => true, 'message' => 'Không tìm thấy domain'], 404);
}
$payload = $this->validateDomainRecordPayload($request);
$this->serverService->findServerByID($domain->dns_manager_server_id);
$serverPayload = $this->serverService->handlePayload([
...$payload,
'domain' => $domain->domain_name,
])->addRecord();
if (! empty($serverPayload['error'])) {
return response()->json([
'error' => true,
'message' => $serverPayload['message'] ?? 'Không thể tạo DNS record trên server',
], 422);
}
DB::beginTransaction();
try {
$record = DnsManagerNS::query()->create([
'dns_manager_domain_id' => $domain->id,
'type' => $payload['type'],
'type_valid' => $payload['type'],
'name' => $payload['name'],
'value' => $payload['value'],
'ttl' => $payload['ttl'] ?? 300,
'priority' => (string) ($payload['priority'] ?? 0),
'weight' => (string) ($payload['weight'] ?? 0),
'port' => (string) ($payload['port'] ?? 0),
'service_name' => $payload['service_name'] ?? null,
'protocol' => $payload['protocol'] ?? null,
'plesk_id' => $serverPayload['data']['id'] ?? null,
]);
DB::commit();
} catch (\Throwable $e) {
DB::rollBack();
return response()->json(['error' => true, 'message' => $e->getMessage()], 500);
}
$customer = $request->user();
$this->activityLogger->log(
event: 'created',
logName: 'DNS',
description: "Customer {$customer->email} tạo DNS record #{$record->id} của domain {$domain->domain_name}",
subject: $record,
newValues: [
'domain_id' => $domain->id,
'domain_name' => $domain->domain_name,
'type' => $record->type,
'name' => $record->name,
'value' => $record->value,
],
);
return response()->json([
'error' => false,
'message' => 'Tạo DNS record thành công',
'data' => new DomainNSResource($record),
], 201);
}
public function updateRecord(Request $request, int $domainId, int $recordId): JsonResponse
{
$domain = $this->resolveCustomerDomain($request, $domainId);
if (! $domain) {
return response()->json(['error' => true, 'message' => 'Không tìm thấy domain'], 404);
}
$record = DnsManagerNS::query()
->where('dns_manager_domain_id', $domain->id)
->find($recordId);
if (! $record) {
return response()->json(['error' => true, 'message' => 'Không tìm thấy bản ghi DNS'], 404);
}
$payload = $this->validateDomainRecordPayload($request);
if (! empty($record->plesk_id)) {
$this->serverService->findServerByID($domain->dns_manager_server_id);
$serverPayload = $this->serverService->handlePayload([
...$payload,
'domain' => $domain->domain_name,
])->updateRecord((int) $record->plesk_id);
if (! empty($serverPayload['error'])) {
return response()->json([
'error' => true,
'message' => $serverPayload['message'] ?? 'Không thể cập nhật DNS record trên server',
], 422);
}
}
$record->update([
'type' => $payload['type'],
'type_valid' => $record->type_valid ?: $payload['type'],
'name' => $payload['name'],
'value' => $payload['value'],
'ttl' => $payload['ttl'] ?? $record->ttl,
'priority' => isset($payload['priority']) ? (string) $payload['priority'] : $record->priority,
'weight' => isset($payload['weight']) ? (string) $payload['weight'] : $record->weight,
'port' => isset($payload['port']) ? (string) $payload['port'] : $record->port,
'service_name' => $payload['service_name'] ?? $record->service_name,
'protocol' => $payload['protocol'] ?? $record->protocol,
]);
$customer = $request->user();
$this->activityLogger->log(
event: 'updated',
logName: 'DNS',
description: "Customer {$customer->email} cập nhật DNS record #{$record->id} của domain {$domain->domain_name}",
subject: $record,
newValues: [
'domain_id' => $domain->id,
'domain_name' => $domain->domain_name,
'type' => $record->type,
'name' => $record->name,
'value' => $record->value,
],
);
return response()->json([
'error' => false,
'message' => 'Cập nhật DNS record thành công',
'data' => new DomainNSResource($record),
]);
}
public function destroyRecord(Request $request, int $domainId, int $recordId): JsonResponse
{
$domain = $this->resolveCustomerDomain($request, $domainId);
if (! $domain) {
return response()->json(['error' => true, 'message' => 'Không tìm thấy domain'], 404);
}
$record = DnsManagerNS::query()
->where('dns_manager_domain_id', $domain->id)
->find($recordId);
if (! $record) {
return response()->json(['error' => true, 'message' => 'Không tìm thấy bản ghi DNS'], 404);
}
if (! empty($record->plesk_id)) {
$this->serverService->findServerByID($domain->dns_manager_server_id);
$serverPayload = $this->serverService->deleteRecord((int) $record->plesk_id);
if (! empty($serverPayload['error'])) {
return response()->json([
'error' => true,
'message' => $serverPayload['message'] ?? 'Không thể xóa DNS record trên server',
], 422);
}
}
$snapshot = new DomainNSResource($record);
$record->delete();
$customer = $request->user();
$this->activityLogger->log(
event: 'deleted',
logName: 'DNS',
description: "Customer {$customer->email} xóa DNS record #{$recordId} của domain {$domain->domain_name}",
subject: $domain,
newValues: [
'domain_id' => $domain->id,
'domain_name' => $domain->domain_name,
'record_id' => $recordId,
],
);
return response()->json([
'error' => false,
'message' => 'Xóa DNS record thành công',
'data' => $snapshot,
]);
}
private function resolveCustomerDomain(Request $request, int $domainId): ?DnsDomain
{
$customer = $request->user();
return DnsDomain::query()
->with('server')
->where('id', $domainId)
->whereHas('customer', fn ($query) => $query->where('customers.id', $customer->id))
->first();
}
private function validateDomainRecordPayload(Request $request): array
{
return $request->validate([
'type' => ['required', 'string', 'in:A,AAAA,CNAME,TXT,MX,NS,SRV'],
'name' => ['required', 'string', 'max:255'],
'value' => ['required', 'string'],
'ttl' => ['nullable', 'integer', 'min:60', 'max:86400'],
'priority' => ['nullable', 'integer', 'min:0', 'max:65535'],
'weight' => ['nullable', 'integer', 'min:0', 'max:65535'],
'port' => ['nullable', 'integer', 'min:0', 'max:65535'],
'service_name' => ['nullable', 'string', 'max:255'],
'protocol' => ['nullable', 'string', 'max:255'],
]);
}
}
@@ -3,8 +3,8 @@
namespace App\Http\Controllers\Api\Client\Service;
use App\Http\Controllers\Controller;
use App\Http\Resources\Api\Service\VpsServiceCollection;
use App\Http\Resources\Api\Client\Service\ServiceClientDetailResource;
use \App\Http\Resources\Api\Client\Service\ServiceClientResource;
use App\Http\Services\vCenter;
use App\Models\Order;
use App\Models\Service;
@@ -31,22 +31,75 @@ class ServiceController extends Controller
$this->activityLogger = $activityLogger;
}
public function getService(Request $request)
public function indexVps(Request $request): JsonResponse
{
$limit = $request->get('limit', 10);
$services = $this->serviceClientService->getActiveServices($limit);
$perPage = min((int) $request->get('per_page', 15), 100);
$customer = $request->user();
return ServiceClientResource::collection($services)->additional([
$services = $this->serviceClientService->getActiveServices($customer->id, 'vps', $perPage);
return (new VpsServiceCollection($services))
->additional([
'error' => false,
'message' => 'Lấy dữ liệu thành công',
'page_type' => 'service_vps',
])
->response();
}
public function indexHosting(Request $request): JsonResponse
{
$perPage = min((int) $request->get('per_page', 15), 100);
return response()->json([
'error' => false,
'message' => 'Lấy dữ liệu thành công',
'page_type' => 'service',
'page_type' => 'service_hosting',
'data' => [
'items' => [],
'pagination' => [
'total' => 0,
'per_page' => $perPage,
'current_page' => 1,
'last_page' => 1,
],
],
]);
}
public function indexWebDesign(Request $request): JsonResponse
{
$perPage = min((int) $request->get('per_page', 15), 100);
return response()->json([
'error' => false,
'message' => 'Lấy dữ liệu thành công',
'page_type' => 'service_web_design',
'data' => [
'items' => [],
'pagination' => [
'total' => 0,
'per_page' => $perPage,
'current_page' => 1,
'last_page' => 1,
],
],
]);
}
public function getDetail(Request $request, string $uuid)
{
$service = $this->serviceClientService->getDetailService($uuid);
$service = $this->serviceClientService->getDetailService($uuid, $request->user()->id);
if (!$service) {
return response()->json(
[
'error' => true,
'message' => 'Không tìm thấy dịch vụ',
],
404,
);
}
return (new ServiceClientDetailResource($service))->additional([
'error' => false,
@@ -113,7 +166,7 @@ class ServiceController extends Controller
);
return response()->json([
'error' => false,
'error' => false,
'message' => $ticket,
]);
}
@@ -188,7 +241,7 @@ class ServiceController extends Controller
$customer = $request->user();
$service = Service::with([
'product.osVersions' => fn ($q) => $q->where('status', 1)->with('osGroup'),
'product.osVersions' => fn($q) => $q->where('status', 1)->with('osGroup'),
])
->where('uuid', $uuid)
->where('customer_id', $customer->id)
@@ -199,7 +252,10 @@ class ServiceController extends Controller
}
if (!in_array($service->status, ['active', 'suspended'], true)) {
return response()->json(['success' => false, 'message' => 'Dịch vụ không ở trạng thái hợp lệ để xem OS'], 422);
return response()->json(
['success' => false, 'message' => 'Dịch vụ không ở trạng thái hợp lệ để xem OS'],
422,
);
}
if (!$service->product) {
@@ -207,32 +263,38 @@ class ServiceController extends Controller
}
$grouped = $service->product->osVersions
->groupBy(fn ($os) => $os->osGroup?->id ?? 0)
->map(fn ($items) => [
'group' => [
'id' => $items->first()->osGroup?->id,
'name' => $items->first()->osGroup?->name,
'thumbnail' => $items->first()->osGroup?->thumbnail,
->groupBy(fn($os) => $os->osGroup?->id ?? 0)
->map(
fn($items) => [
'group' => [
'id' => $items->first()->osGroup?->id,
'name' => $items->first()->osGroup?->name,
'thumbnail' => $items->first()->osGroup?->thumbnail,
],
'items' => $items
->map(
fn($os) => [
'id' => $os->id,
'version' => $os->version,
'template_id' => $os->template_id,
],
)
->values(),
],
'items' => $items->map(fn ($os) => [
'id' => $os->id,
'version' => $os->version,
'template_id' => $os->template_id,
])->values(),
])
)
->values();
return response()->json([
'success' => true,
'data' => $grouped,
'data' => $grouped,
]);
}
public function rebuild(Request $request, string $uuid, vCenter $serviceVCenter): JsonResponse
{
$customer = $request->user();
$payload = $request->validate([
'os_id' => ['required', 'integer', 'exists:os,id'],
$payload = $request->validate([
'os_id' => ['required', 'integer', 'exists:os,id'],
'password' => ['nullable', 'string', 'max:255'],
]);
@@ -246,18 +308,18 @@ class ServiceController extends Controller
}
if ($service->status === 'suspended') {
return response()->json(['success' => false, 'message' => 'Dịch vụ đang bị tạm ngưng, không thể rebuild'], 422);
return response()->json(
['success' => false, 'message' => 'Dịch vụ đang bị tạm ngưng, không thể rebuild'],
422,
);
}
if (!$service->isActive()) {
return response()->json(['success' => false, 'message' => 'Dịch vụ không ở trạng thái active'], 422);
}
$allowedOsIds = $service->product?->osVersions()
->where('status', 1)
->pluck('os.id')
->map('intval')
->toArray() ?? [];
$allowedOsIds =
$service->product?->osVersions()->where('status', 1)->pluck('os.id')->map('intval')->toArray() ?? [];
if (!in_array((int) $payload['os_id'], $allowedOsIds, true)) {
return response()->json(['success' => false, 'message' => 'OS không hợp lệ cho sản phẩm hiện tại'], 422);
@@ -269,31 +331,34 @@ class ServiceController extends Controller
}
DB::table('reinstall_logs')->insert([
'product_id' => $vm->id,
'product_id' => $vm->id,
'product_type' => 4,
'custome_id' => $customer->id,
'os_id' => $payload['os_id'],
'status' => 'pending',
'initiator' => 'client',
'note' => 'Client rebuild via service UUID: ' . $uuid,
'created_at' => now(),
'updated_at' => now(),
'custome_id' => $customer->id,
'os_id' => $payload['os_id'],
'status' => 'pending',
'initiator' => 'client',
'note' => 'Client rebuild via service UUID: ' . $uuid,
'created_at' => now(),
'updated_at' => now(),
]);
$result = $serviceVCenter->reBuildVPS((string) $vm->name);
if (is_string($result) || ($result['error'] ?? false)) {
return response()->json([
'success' => false,
'message' => is_string($result) ? $result : ($result['message'] ?? 'Không thể rebuild VM'),
], 400);
return response()->json(
[
'success' => false,
'message' => is_string($result) ? $result : $result['message'] ?? 'Không thể rebuild VM',
],
400,
);
}
$this->activityLogger->log(
event: 'rebuild',
logName: 'VM',
event: 'rebuild',
logName: 'VM',
description: "Customer {$customer->email} rebuild VM: {$vm->name} với OS ID: {$payload['os_id']} qua service UUID: {$uuid}",
subject: $vm,
newValues: ['os_id' => $payload['os_id'], 'service_uuid' => $uuid],
subject: $vm,
newValues: ['os_id' => $payload['os_id'], 'service_uuid' => $uuid],
);
return response()->json([
@@ -301,5 +366,4 @@ class ServiceController extends Controller
'message' => 'Đã gửi yêu cầu rebuild VM',
]);
}
}
}