initial commit
This commit is contained in:
162
app/Http/Controllers/Api/WhmcsServiceController.php
Normal file
162
app/Http/Controllers/Api/WhmcsServiceController.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Enums\UserRole;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Whmcs\ProvisionServiceRequest;
|
||||
use App\Jobs\ProvisionCustomerJob;
|
||||
use App\Models\Customer;
|
||||
use App\Models\HostingPlan;
|
||||
use App\Models\User;
|
||||
use App\Models\WhmcsService;
|
||||
use App\Services\Hosting\Provisioning\DeprovisionService;
|
||||
use App\Services\Hosting\Provisioning\VmidReservationService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class WhmcsServiceController extends Controller
|
||||
{
|
||||
public function provision(ProvisionServiceRequest $request): JsonResponse
|
||||
{
|
||||
$plan = HostingPlan::query()->where('slug', $request->validated('plan_slug'))->firstOrFail();
|
||||
$domain = $request->domain();
|
||||
|
||||
if ($domain && Customer::query()->where('domain', $domain)->exists()) {
|
||||
return response()->json(['error' => 'Domain already taken.'], 422);
|
||||
}
|
||||
|
||||
$result = DB::transaction(function () use ($request, $plan, $domain) {
|
||||
$user = User::query()->updateOrCreate(
|
||||
['whmcs_client_id' => $request->integer('whmcs_client_id')],
|
||||
[
|
||||
'name' => $request->validated('client_name'),
|
||||
'email' => $request->validated('client_email'),
|
||||
'password' => Hash::make(Str::random(32)),
|
||||
'role' => UserRole::Customer,
|
||||
'is_active' => true,
|
||||
],
|
||||
);
|
||||
|
||||
$customer = Customer::query()->create([
|
||||
'user_id' => $user->id,
|
||||
'hosting_plan_id' => $plan->id,
|
||||
'name' => $request->validated('hostname'),
|
||||
'domain' => $domain ?? 'direct-'.Str::slug($request->validated('hostname')).'-'.Str::lower(Str::random(6)).'.internal',
|
||||
'behind_traefik' => $request->boolean('behind_traefik', true),
|
||||
'provision_mode' => $request->validated('provision_mode'),
|
||||
'attached_iso' => $request->validated('iso_volid'),
|
||||
'cpu' => $plan->cpu,
|
||||
'ram' => $plan->ram,
|
||||
'disk' => $plan->disk,
|
||||
'status' => 'pending',
|
||||
'provisioning_step' => 'queued',
|
||||
]);
|
||||
|
||||
$whmcsService = WhmcsService::query()->create([
|
||||
'whmcs_service_id' => $request->integer('whmcs_service_id'),
|
||||
'whmcs_client_id' => $request->integer('whmcs_client_id'),
|
||||
'whmcs_order_id' => $request->input('whmcs_order_id'),
|
||||
'customer_id' => $customer->id,
|
||||
'user_id' => $user->id,
|
||||
'hosting_plan_id' => $plan->id,
|
||||
'status' => 'provisioning',
|
||||
'config' => $request->only([
|
||||
'provision_mode', 'template_slug', 'iso_volid', 'behind_traefik', 'subdomain',
|
||||
]),
|
||||
]);
|
||||
|
||||
$customer->update(['whmcs_service_id' => $whmcsService->id]);
|
||||
|
||||
$vmid = app(VmidReservationService::class)->reserveForCustomer($customer);
|
||||
$customer->update(['vmid' => $vmid]);
|
||||
|
||||
ProvisionCustomerJob::dispatch($customer->id);
|
||||
|
||||
return compact('customer', 'user', 'whmcsService', 'vmid');
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Provisioning queued.',
|
||||
'customer_id' => $result['customer']->id,
|
||||
'vmid' => $result['vmid'],
|
||||
'panel_url' => config('hosting.panel.url'),
|
||||
], 202);
|
||||
}
|
||||
|
||||
public function suspend(Request $request, int $whmcsServiceId): JsonResponse
|
||||
{
|
||||
$service = $this->resolveService($whmcsServiceId);
|
||||
$customer = $service->customer;
|
||||
|
||||
if ($customer?->vmid) {
|
||||
app(\App\Services\Hosting\Proxmox\ProxmoxClient::class)->stopVM((int) $customer->vmid);
|
||||
}
|
||||
|
||||
$service->update(['status' => 'suspended']);
|
||||
$customer?->update(['status' => 'failed', 'provisioning_step' => 'suspended']);
|
||||
|
||||
return response()->json(['message' => 'Service suspended.']);
|
||||
}
|
||||
|
||||
public function unsuspend(Request $request, int $whmcsServiceId): JsonResponse
|
||||
{
|
||||
$service = $this->resolveService($whmcsServiceId);
|
||||
$customer = $service->customer;
|
||||
|
||||
if ($customer?->vmid) {
|
||||
app(\App\Services\Hosting\Proxmox\ProxmoxClient::class)->startVM((int) $customer->vmid);
|
||||
$customer->update(['status' => 'active', 'provisioning_step' => 'completed']);
|
||||
}
|
||||
|
||||
$service->update(['status' => 'active']);
|
||||
|
||||
return response()->json(['message' => 'Service unsuspended.']);
|
||||
}
|
||||
|
||||
public function terminate(Request $request, int $whmcsServiceId, DeprovisionService $deprovision): JsonResponse
|
||||
{
|
||||
$service = $this->resolveService($whmcsServiceId);
|
||||
$customer = $service->customer;
|
||||
|
||||
if ($customer) {
|
||||
$deprovision->terminatePermanently($customer);
|
||||
}
|
||||
|
||||
$service->update(['status' => 'terminated', 'customer_id' => null]);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Service terminated. VMID will be released after configured retention.',
|
||||
]);
|
||||
}
|
||||
|
||||
public function status(int $whmcsServiceId): JsonResponse
|
||||
{
|
||||
$service = $this->resolveService($whmcsServiceId);
|
||||
$service->load('customer');
|
||||
|
||||
return response()->json([
|
||||
'whmcs_service_id' => $service->whmcs_service_id,
|
||||
'status' => $service->status,
|
||||
'customer' => $service->customer ? [
|
||||
'id' => $service->customer->id,
|
||||
'name' => $service->customer->name,
|
||||
'vmid' => $service->customer->vmid,
|
||||
'status' => $service->customer->status,
|
||||
'provisioning_step' => $service->customer->provisioning_step,
|
||||
'ip_address' => $service->customer->ip_address,
|
||||
'domain' => $service->customer->domain,
|
||||
] : null,
|
||||
]);
|
||||
}
|
||||
|
||||
private function resolveService(int $whmcsServiceId): WhmcsService
|
||||
{
|
||||
return WhmcsService::query()
|
||||
->where('whmcs_service_id', $whmcsServiceId)
|
||||
->firstOrFail();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user