order = $order; } public function getDisplayName(): string { return settings('virtfusionserv::display_name', 'VirtFusion'); } /** * Returns the meta data about this Server/Service * * @return object */ public static function metaData(): object { return (object) [ 'display_name' => 'VirtfusionService', 'author' => 'Shane C.', 'version' => '1.0.0', 'wemx_version' => ['dev', '>=1.8.0'], ]; } /** * Define the default configuration values required to setup this service * i.e host, api key, or other values. Use Laravel validation rules for * * Laravel validation rules: https://laravel.com/docs/10.x/validation * * @return array */ public static function setConfig(): array { $doesNotEndWithSlash = function ($attribute, $value, $fail) { if (preg_match('/\/$/', $value)) { return $fail('Panel URL must not end with a slash "/". It should be like https://panel.example.com'); } }; return [ [ "key" => "virtfusionserv::host", "name" => "VirtFusion Panel Host/URL", "description" => "The Host/URL of the VirtFusion panel i.e https://panel.example.com", "type" => "url", "rules" => ["required", "active_url", $doesNotEndWithSlash] ], [ "key" => "encrypted::virtfusionserv::apikey", "name" => "VirtFusion API Key", "description" => "API Key to manage VirtFusion panel.", "type" => "password", "rules" => ["required"], ] ]; } /** * Define the default package configuration values required when creatig * new packages. i.e maximum ram usage, allowed databases and backups etc. * * Laravel validation rules: https://laravel.com/docs/10.x/validation * * @return array */ public static function setPackageConfig(Package $package): array { $response = Service::api('get', '/packages'); if ($response->failed()) { if (isset($response['errors'])) { throw new Exception("[VirtFusion] " . json_encode($response['errors'])); } if (isset($response['message'])) { throw new Exception("[VirtFusion] " . $response['message']); } } $collectPackages = collect($response['data']); $packages = $collectPackages->mapWithKeys(function ($item) { if (!$item['enabled']) { return []; } return [$item['id'] => $item['name']]; }); return [ [ "col" => "col-12", "key" => "package", "name" => "Package", "description" => "Select the package to use for this service", "type" => "select", "options" => $packages->toArray(), "save_on_change" => true, "rules" => ['required'], ], [ "col" => "col-12", "key" => "hypervisor_group_id", "name" => "Hypervisor Group ID", "description" => "Enter the Hypervisor Group ID to use for this service", "type" => "number", "save_on_change" => true, "rules" => ['required', 'numeric'], ], [ "key" => "allowed_ips", "name" => "Number of Allowed IPv4 IPs", "description" => "Enter the number of allowed IPv4 IPs for this service", "type" => "number", "rules" => ['required', 'numeric'], ], ]; } /** * Define the checkout config that is required at checkout and is fillable by * the client. Its important to properly sanatize all inputted data with rules * * Laravel validation rules: https://laravel.com/docs/10.x/validation * * @return array */ public static function setCheckoutConfig(Package $package): array { return []; } /** * Define buttons shown at order management page * * @return array */ public static function setServiceButtons(Order $order): array { try { $response = Service::api('post', "/users/{$order->user->id}/serverAuthenticationTokens/{$order->data['id']}"); if ($response->failed()) { if (isset($response['errors'])) { return []; } if (isset($response['message'])) { return []; } } } catch (Exception $e) { return []; } $loginUrl = settings('virtfusionserv::host') . $response['data']['authentication']['endpoint_complete']; return [ [ "name" => "Panel Login", "color" => "primary", "href" => $loginUrl, "target" => "_blank", ] ]; } /** * This function is responsible for creating an instance of the * service. This can be anything such as a server, vps or any other instance. * * @return void */ public function create(array $data = []) { $order = $this->order; $user = $this->order->user; $package = $this->order->package; if (!$order->hasExternalUser()) { $response = Service::api('post', '/users', [ "name" => $user->first_name . ' ' . $user->last_name, "email" => $user->email, "extRelationId" => $user->id, "sendMail" => false, ]); if ($response->failed() && $response->status() != 409) { if (isset($response['errors'])) { throw new Exception("[VirtFusion] " . json_encode($response['errors'])); } if (isset($response['message'])) { throw new Exception("[VirtFusion] " . $response['message']); } } if ($response->status() == 409) { $getUserRes = Service::api('get', "/users/{$user->id}/byExtRelation"); $virtFusionUser = $getUserRes['data']; $order->createExternalUser([ 'external_id' => $virtFusionUser['id'], 'username' => $user->email, 'password' => Str::random(16), 'data' => $virtFusionUser ]); } else { $order->createExternalUser([ 'external_id' => $response['data']['id'], // optional 'username' => $user->email, 'password' => $response['data']['password'], 'data' => $response['data'], // Additional data about the user as an array (optional) ]); } $user->email([ 'subject' => 'Panel Account Created', 'content' => "Your account has been created on the vps panel. You can login using the following details:

Email: {$user->email}
Password: {$response['data']['password']}", 'button' => [ 'name' => 'VPS Panel', 'url' => settings('virtfusionserv::host'), ] ]); } // create the server $createSrvRes = Service::api('post', '/servers', [ "packageId" => $package->data('package'), "userId" => $order->getExternalUser()->external_id, "hypervisorId" => $package->data('hypervisor_group_id'), "ipv4" => $package->data('allowed_ips', 1), ]); if ($createSrvRes->failed()) { if (isset($response['errors'])) { throw new Exception("[VirtFusion] " . json_encode($response['errors'])); } if (isset($response['message'])) { throw new Exception("[VirtFusion] " . $response['message']); } } $order->external_id = $createSrvRes['data']['id']; $order->data = $createSrvRes['data']; $order->save(); return $createSrvRes; } /** * This function is responsible for upgrading or downgrading * an instance of this service. This method is optional * If your service doesn't support upgrading, remove this method. * * Optional * @return void */ public function upgrade(Package $oldPackage, Package $newPackage) { $order = $this->order; $response = Service::api('put', "/servers/{$order->data['id']}/package/{$newPackage->data('package')}"); if ($response->failed()) { if (isset($response['errors'])) { throw new Exception("[VirtFusion] " . json_encode($response['errors'])); } if (isset($response['message'])) { throw new Exception("[VirtFusion] " . $response['message']); } } } /** * This function is responsible for suspending an instance of the * service. This method is called when a order is expired or * suspended by an admin * * @return void */ public function suspend(array $data = []) { $order = $this->order; $response = Service::api('post', "/servers/{$order->data['id']}/suspend"); if ($response->failed()) { if (isset($response['errors'])) { throw new Exception("[VirtFusion] " . json_encode($response['errors'])); } if (isset($response['message'])) { throw new Exception("[VirtFusion] " . $response['message']); } } } /** * This function is responsible for unsuspending an instance of the * service. This method is called when a order is activated or * unsuspended by an admin * * @return void */ public function unsuspend(array $data = []) { $order = $this->order; $response = Service::api('post', "/servers/{$order->data['id']}/unsuspend"); if ($response->failed()) { if (isset($response['errors'])) { throw new Exception("[VirtFusion] " . json_encode($response['errors'])); } if (isset($response['message'])) { throw new Exception("[VirtFusion] " . $response['message']); } } } /** * This function is responsible for deleting an instance of the * service. This can be anything such as a server, vps or any other instance. * * @return void */ public function terminate(array $data = []) { $order = $this->order; Service::api('delete', "/servers/{$order->data['id']}?delay=5"); } /** * This function is responsible automatically logging in to the * panel when the user clicks the login button in the client area. * * @return redirect */ public function loginToPanel(Order $order) { try { $response = Service::api('post', "/users/{$order->user->id}/serverAuthenticationTokens/{$order->data['id']}"); if ($response->failed()) { if (isset($response['errors'])) { throw new Exception("[VirtFusion] " . json_encode($response['errors'])); } if (isset($response['message'])) { throw new Exception("[VirtFusion] " . $response['message']); } } return redirect(settings('virtfusionserv::host') . $response['data']['authentication']['endpoint_complete']); } catch (Exception $e) { return redirect()->back()->withError("Something went wrong, please try again later."); } } /** * Test API connection */ public static function testConnection() { try { // try to get list of packages through API request $response = Service::api('get', '/connect'); } catch (Exception $error) { // if try-catch fails, return the error with details return redirect()->back()->withError("Failed to connect to VirtFusion.

{$error->getMessage()}"); } // if no errors are logged, return a success message return redirect()->back()->withSuccess("Successfully connected with VirtFusion"); } public static function api($method, $endpoint, $data = []) { // validate the method if (!in_array($method, ['get', 'post', 'put', 'delete', 'patch', 'head'])) { throw new Exception("[VirtFusion] Invalid method: {$method}"); } // make the request $url = settings('virtfusionserv::host') . '/api/v1' . $endpoint; $response = Http::withHeaders([ 'Authorization' => 'Bearer ' . settings('encrypted::virtfusionserv::apikey'), 'Accept' => 'application/json', 'Content-Type' => 'application/json', ])->$method($url, $data); // dd($response, $response->json()); if ($response->failed()) { // dd($response, $response->json()); if ($response->unauthorized() or $response->forbidden()) { throw new Exception("[VirtFusion] This action is unauthorized! Confirm that API token has the right permissions"); } if ($response->serverError()) { throw new Exception("[VirtFusion] Internal Server Error: {$response->status()}"); } } return $response; } }