Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 98250f2f4c | |||
| 2691013cc4 | |||
| 24e79eed31 | |||
| db3afee99e | |||
| fb0cffc844 | |||
| c6012fa63c | |||
| b25530f063 | |||
| bb2e8ac538 | |||
| 07f3c69977 | |||
| e5570785db | |||
| b25535ba5f | |||
| 00ccd2c902 | |||
| 33f466af04 |
22
.github/workflows/linter.yml
vendored
22
.github/workflows/linter.yml
vendored
@@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
name: Lint Code Base
|
|
||||||
on: [ workflow_call ]
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Lint Code Base
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: read
|
|
||||||
statuses: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout Code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Lint Code Base
|
|
||||||
uses: super-linter/super-linter@v5
|
|
||||||
env:
|
|
||||||
VALIDATE_ALL_CODEBASE: false
|
|
||||||
DEFAULT_BRANCH: main
|
|
||||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
|
||||||
3
.github/workflows/publish-release.yml
vendored
3
.github/workflows/publish-release.yml
vendored
@@ -5,11 +5,8 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
jobs:
|
jobs:
|
||||||
linter:
|
|
||||||
uses: ./.github/workflows/linter.yml
|
|
||||||
publish-release:
|
publish-release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: linter
|
|
||||||
steps:
|
steps:
|
||||||
- name: Publish Release
|
- name: Publish Release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
|
|||||||
83
README.md
83
README.md
@@ -1,33 +1,90 @@
|
|||||||
[](https://github.com/marketplace/actions/super-linter)
|
# VirtFusion Direct Provisioning Module for WHMCS
|
||||||
|
|
||||||
|
[](https://github.com/EZSCALE/virtfusion-whmcs-module/actions)
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
# VirtFusion Direct Provisioning Module for WHMCS
|
This module requires VirtFusion v1.7.3 or higher as this is what it's based on. Please refer to the
|
||||||
|
official [documentation](https://docs.virtfusion.com/integrations/whmcs).
|
||||||
This module requires VirtFusion v1.7.3 or higher as this is what it's based on. Please refer to the official [documenataion](https://docs.virtfusion.com/integrations/whmcs).
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Download the latest release from the [releases](https://github.com/EZSCALE/virtfusion-whmcs-module/releases) page.
|
1. Download the latest release from the [releases](https://github.com/EZSCALE/virtfusion-whmcs-module/releases) page.
|
||||||
2. Extract the contents of the archive and upload the modules folder to your WHMCS installation directory.
|
2. Extract the contents of the archive and upload the modules folder to your WHMCS installation directory.
|
||||||
|
|
||||||
## Configuration
|
## :heavy_exclamation_mark: Important Notes :heavy_exclamation_mark:
|
||||||
|
|
||||||
You'll need to configure the following constraints in your `configuration.php` file.
|
You must create two custom fields in WHMCS for this module to work. You need to configure the following custom fields on
|
||||||
This is only temporary and will be replaced with pulling the token from the database in the future.
|
each product you want to use this module with.
|
||||||
|
|
||||||
```php
|
| Field Name | Field Type | Description | Validation | Select Options | Admin Only | Required Field | Show on Order Form | Show on Invoice |
|
||||||
// VirtFusion API URL
|
|--------------------------|------------|--------------------------|-------------|----------------|------------|----------------|--------------------|-----------------|
|
||||||
const VIRTFUSION_API_URL = "https://your-virtfusion-url.com/api/v1";
|
| Initial Operating System | Text Box | Set to whatever you want | Leave Blank | Leave Blank | :x: | :x: | :white_check_mark: | :x: |
|
||||||
|
| Initial SSH Key | Text Box | Set to whatever you want | Leave Blank | Leave Blank | :x: | :x: | :white_check_mark: | :x: |
|
||||||
|
|
||||||
// VirtFusion API Token
|
You can run this SQL query to create the custom fields:
|
||||||
const VIRT_TOKEN = "your-virtfusion-token";
|
|
||||||
|
```sql
|
||||||
|
-- Insert records for Initial Operating System if they don't already exist
|
||||||
|
INSERT INTO tblcustomfields
|
||||||
|
(type, relid, fieldname, fieldtype, description, fieldoptions, regexpr, adminonly, required, showorder, showinvoice,
|
||||||
|
sortorder, created_at, updated_at)
|
||||||
|
SELECT 'product',
|
||||||
|
id,
|
||||||
|
'Initial Operating System',
|
||||||
|
'text',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'on',
|
||||||
|
'',
|
||||||
|
0,
|
||||||
|
UTC_TIMESTAMP(),
|
||||||
|
UTC_TIMESTAMP()
|
||||||
|
FROM tblproducts
|
||||||
|
WHERE servertype = 'VirtFusionDirect'
|
||||||
|
AND NOT EXISTS (SELECT 1
|
||||||
|
FROM tblcustomfields
|
||||||
|
WHERE fieldname = 'Initial Operating System'
|
||||||
|
AND relid = tblproducts.id);
|
||||||
|
|
||||||
|
-- Insert records for Initial SSH Key if they don't already exist
|
||||||
|
INSERT INTO tblcustomfields
|
||||||
|
(type, relid, fieldname, fieldtype, description, fieldoptions, regexpr, adminonly, required, showorder, showinvoice,
|
||||||
|
sortorder, created_at, updated_at)
|
||||||
|
SELECT 'product',
|
||||||
|
id,
|
||||||
|
'Initial SSH Key',
|
||||||
|
'text',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'on',
|
||||||
|
'',
|
||||||
|
0,
|
||||||
|
UTC_TIMESTAMP(),
|
||||||
|
UTC_TIMESTAMP()
|
||||||
|
FROM tblproducts
|
||||||
|
WHERE servertype = 'VirtFusionDirect'
|
||||||
|
AND NOT EXISTS (SELECT 1
|
||||||
|
FROM tblcustomfields
|
||||||
|
WHERE fieldname = 'Initial SSH Key'
|
||||||
|
AND relid = tblproducts.id);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## What does this module change?
|
## What does this module change?
|
||||||
|
|
||||||
This module changes the following things:
|
This module changes the following things:
|
||||||
|
|
||||||
- Adds configurable options to the product configuration page to allow the user to select the operating system and add
|
- Adds configurable options to the product configuration page to allow the user to select the operating system and add
|
||||||
a ssh key to the initial deployment.
|
an ssh key to the initial deployment.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- [ ] Add post checkout checks to ensure the user has selected an operating system and added a ssh key.
|
||||||
@@ -83,9 +83,16 @@ function VirtFusionDirect_updateServerObject(array $params)
|
|||||||
return (new ModuleFunctions())->updateServerObject($params);
|
return (new ModuleFunctions())->updateServerObject($params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows changing of the package of a server
|
||||||
|
*
|
||||||
|
* @author https://github.com/BlinkohHost/virtfusion-whmcs-module
|
||||||
|
* @param array $params
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
function VirtFusionDirect_ChangePackage(array $params)
|
function VirtFusionDirect_ChangePackage(array $params)
|
||||||
{
|
{
|
||||||
return 'success';
|
return (new ModuleFunctions())->changePackage($params);
|
||||||
}
|
}
|
||||||
|
|
||||||
function VirtFusionDirect_AdminServicesTabFields(array $params)
|
function VirtFusionDirect_AdminServicesTabFields(array $params)
|
||||||
|
|||||||
@@ -1,232 +1,123 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use WHMCS\Module\Server\VirtFusionDirect\ConfigureService;
|
||||||
use WHMCS\User\User;
|
use WHMCS\User\User;
|
||||||
|
|
||||||
if (!defined("WHMCS")) {
|
if (!defined("WHMCS")) {
|
||||||
die("This file cannot be accessed directly");
|
die("This file cannot be accessed directly");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
add_hook('ClientAreaFooterOutput', 1, function ($vars) {
|
||||||
* You'll need to configure the following constrants in your configuration.php file.
|
if (!isset($vars['productinfo']['module']) || $vars['productinfo']['module'] !== 'VirtFusionDirect') {
|
||||||
* This is only temporary and will be replaced with pulling the token from the database in the future.
|
|
||||||
*
|
|
||||||
* const VIRTFUSION_API_URL = "https://your-virtfusion-url.com/api/v1";
|
|
||||||
*
|
|
||||||
* You can create a token in the VirtFusion control panel under System > API.
|
|
||||||
*
|
|
||||||
* const VIRT_TOKEN = "your-virtfusion-token";
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the constants are not defined, return null to prevent errors.
|
|
||||||
*/
|
|
||||||
if (!defined("VIRTFUSION_API_URL") || !defined("VIRT_TOKEN")) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('fetchPackageId')) {
|
|
||||||
/**
|
|
||||||
* @param string $packageName
|
|
||||||
* @return int|null
|
|
||||||
* @throws JsonException
|
|
||||||
*/
|
|
||||||
function fetchPackageId(string $packageName): ?int
|
|
||||||
{
|
|
||||||
$url = sprintf("%s/packages", VIRTFUSION_API_URL);
|
|
||||||
|
|
||||||
$packages = makeRequest($url);
|
|
||||||
|
|
||||||
foreach ($packages['data'] as $package) {
|
|
||||||
if ($package['name'] === $packageName && $package['enabled'] === true) {
|
|
||||||
return $package['id'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('fetchTemplates')) {
|
$cs = new ConfigureService();
|
||||||
/**
|
|
||||||
* @param int $serverPackageId
|
|
||||||
* @return array|null
|
|
||||||
* @throws JsonException
|
|
||||||
*/
|
|
||||||
function fetchTemplates(int $serverPackageId): ?array
|
|
||||||
{
|
|
||||||
$url = sprintf("%s/media/templates/fromServerPackageSpec/%d", VIRTFUSION_API_URL, $serverPackageId);
|
|
||||||
|
|
||||||
return makeRequest($url);
|
$templates_data = $cs->fetchTemplates(
|
||||||
|
$cs->fetchPackageByDbId($vars['productinfo']['pid']) ?? $cs->fetchPackageId($vars['productinfo']['name'])
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($templates_data)) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('custom_os_templates_hook')) {
|
$dropdownOptions = [];
|
||||||
/**
|
|
||||||
* @param array $vars
|
|
||||||
* @return array|null[]
|
|
||||||
*/
|
|
||||||
function custom_os_templates_hook(array $vars): array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$serverPackageId = fetchPackageId($vars['productinfo']['name']); // Replace with the appropriate server package ID
|
|
||||||
|
|
||||||
if ($serverPackageId === null) {
|
foreach ($templates_data['data'] as $osCategory) {
|
||||||
return [
|
foreach ($osCategory['templates'] as $template) {
|
||||||
'templates' => null,
|
$optionValue = $template['id'];
|
||||||
];
|
$optionLabel = $template['name'] . " " . $template['version'] . " " . $template['variant'];
|
||||||
}
|
$dropdownOptions[] = ['id' => $optionValue, 'name' => $optionLabel];
|
||||||
|
|
||||||
$templates = fetchTemplates($serverPackageId);
|
|
||||||
|
|
||||||
// Assign the generated dropdown menu to a Smarty template variable
|
|
||||||
return [
|
|
||||||
'templates' => $templates,
|
|
||||||
];
|
|
||||||
} catch (JsonException $e) {
|
|
||||||
return [
|
|
||||||
'templates' => null,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('get_vf_user_details')) {
|
// Sort dropdownOptions alphabetically by the 'name' key
|
||||||
/**
|
usort($dropdownOptions, function ($a, $b) {
|
||||||
* @param int $id
|
return strcmp($a['name'], $b['name']);
|
||||||
* @return array
|
});
|
||||||
* @throws JsonException
|
|
||||||
*/
|
|
||||||
function get_vf_user_details(int $id): ?array {
|
|
||||||
$url = sprintf("%s/users/%s/byExtRelation", VIRTFUSION_API_URL, $id);
|
|
||||||
$response = makeRequest($url);
|
|
||||||
|
|
||||||
if (isset($response['msg']) && $response['msg'] === "ext_relation_id not found") {
|
$sshKeys = $cs->getUserSshKeys($vars['loggedinuser']);
|
||||||
|
$sshKeysOptions = array_map(function ($sshKey) {
|
||||||
|
if ($sshKey['enabled'] === false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $response['data'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('makeRequest')) {
|
|
||||||
/**
|
|
||||||
* @param string $url
|
|
||||||
* @return mixed
|
|
||||||
* @throws JsonException
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
function makeRequest(string $url): array
|
|
||||||
{
|
|
||||||
$curl = curl_init();
|
|
||||||
curl_setopt_array($curl, array(
|
|
||||||
CURLOPT_URL => $url,
|
|
||||||
CURLOPT_RETURNTRANSFER => true,
|
|
||||||
CURLOPT_HTTPHEADER => array(
|
|
||||||
sprintf("Authorization: Bearer %s", VIRT_TOKEN)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
|
|
||||||
$response = curl_exec($curl);
|
|
||||||
$err = curl_error($curl);
|
|
||||||
curl_close($curl);
|
|
||||||
|
|
||||||
if ($err) {
|
|
||||||
throw new Exception("cURL Error: " . $err);
|
|
||||||
}
|
|
||||||
|
|
||||||
return json_decode($response, true, 512, JSON_THROW_ON_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('get_users_ssh_keys')) {
|
|
||||||
/**
|
|
||||||
* @throws JsonException
|
|
||||||
*/
|
|
||||||
function get_users_ssh_keys(?User $user): ?array {
|
|
||||||
if (is_null($user)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$vfUser = get_vf_user_details($user['id']);
|
|
||||||
|
|
||||||
$url = sprintf("%s/ssh_keys/user/%s", VIRTFUSION_API_URL, $vfUser['id']);
|
|
||||||
|
|
||||||
$response = makeRequest($url);
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('add_hook_os_templates')) {
|
|
||||||
/**
|
|
||||||
* @param array $vars
|
|
||||||
* @return array|null
|
|
||||||
* @throws JsonException
|
|
||||||
*/
|
|
||||||
function add_hook_os_templates(array $vars): ?array
|
|
||||||
{
|
|
||||||
if (!isset($vars['productinfo']['module']) || $vars['productinfo']['module'] !== 'VirtFusionDirect') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$templates_data = custom_os_templates_hook($vars)['templates'];
|
|
||||||
|
|
||||||
if (empty($templates_data)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$dropdownOptions = [];
|
|
||||||
foreach ($templates_data['data'] as $osCategory) {
|
|
||||||
foreach ($osCategory['templates'] as $template) {
|
|
||||||
$optionValue = $template['id'];
|
|
||||||
$optionLabel = $template['name'] . " " . $template['version'] . " " . $template['variant'];
|
|
||||||
$dropdownOptions[] = ['id' => $optionValue, 'name' => $optionLabel];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort dropdownOptions alphabetically by the 'name' key
|
|
||||||
usort($dropdownOptions, function ($a, $b) {
|
|
||||||
return strcmp($a['name'], $b['name']);
|
|
||||||
});
|
|
||||||
|
|
||||||
$osTemplates = [
|
|
||||||
'id' => 'os_template',
|
|
||||||
'optionname' => 'Initial Operating System',
|
|
||||||
'optiontype' => 1,
|
|
||||||
'options' => $dropdownOptions,
|
|
||||||
'selectedvalue' => ''
|
|
||||||
];
|
|
||||||
|
|
||||||
$sshKeys = get_users_ssh_keys($vars['loggedinuser']);
|
|
||||||
|
|
||||||
$sshKeysOptions = [
|
|
||||||
'id' => 'ssh_key',
|
|
||||||
'optionname' => 'Initial SSH Key',
|
|
||||||
'optiontype' => 1,
|
|
||||||
'options' => array_map(function ($sshKey) {
|
|
||||||
if ($sshKey['enabled'] === false) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'id' => $sshKey['id'],
|
|
||||||
'name' => $sshKey['name']
|
|
||||||
];
|
|
||||||
}, $sshKeys['data'] ?? []),
|
|
||||||
'selectedvalue' => ''
|
|
||||||
];
|
|
||||||
|
|
||||||
$configurableoptions = $vars['configurableoptions'];
|
|
||||||
array_push(
|
|
||||||
$configurableoptions,
|
|
||||||
$osTemplates,
|
|
||||||
$sshKeysOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'configurableoptions' => $configurableoptions,
|
'id' => $sshKey['id'],
|
||||||
|
'name' => $sshKey['name']
|
||||||
];
|
];
|
||||||
}
|
}, $sshKeys['data'] ?? []);
|
||||||
|
|
||||||
add_hook('ClientAreaPageCart', 1, 'add_hook_os_templates');
|
$osID = array_values(array_filter(array_map(function ($option) {
|
||||||
}
|
if ($option['textid'] === 'initialoperatingsystem') {
|
||||||
|
return $option['id'];
|
||||||
|
}
|
||||||
|
}, $vars['customfields'])));
|
||||||
|
|
||||||
|
$sshID = array_values(array_filter(array_map(function ($option) {
|
||||||
|
if ($option['textid'] === 'initialsshkey') {
|
||||||
|
return $option['id'];
|
||||||
|
}
|
||||||
|
}, $vars['customfields'])));
|
||||||
|
|
||||||
|
// Construct the JavaScript code
|
||||||
|
return "
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var osTemplates = " . json_encode($dropdownOptions) . ";
|
||||||
|
var sshKeys = " . json_encode($sshKeysOptions) . ";
|
||||||
|
|
||||||
|
var osInputField = document.querySelector('[name=\"customfield[" . ($osID[0] ?? null) . "]\"]');
|
||||||
|
var sshInputField = document.querySelector('[name=\"customfield[" . ($sshID[0] ?? null) . "]\"]');
|
||||||
|
|
||||||
|
// Create dropdown options menu, then add it to the DOM then on change, update the regular input.
|
||||||
|
var osSelect = document.createElement('select');
|
||||||
|
osSelect.className = 'form-control';
|
||||||
|
|
||||||
|
osTemplates.forEach(function(template) {
|
||||||
|
var option = document.createElement('option');
|
||||||
|
option.value = template.id;
|
||||||
|
option.text = template.name;
|
||||||
|
osSelect.appendChild(option);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set the default value of the input field to the first option in the dropdown.
|
||||||
|
osInputField.value = osSelect.options[0].value;
|
||||||
|
|
||||||
|
osSelect.addEventListener('change', function() {
|
||||||
|
osInputField.value = this.value;
|
||||||
|
console.log(this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
osInputField.parentNode.insertBefore(osSelect, osInputField.nextSibling);
|
||||||
|
osInputField.style.display = 'none';
|
||||||
|
|
||||||
|
if (sshKeys.length > 0) {
|
||||||
|
// Create dropdown options menu, then add it to the DOM then on change, update the regular input.
|
||||||
|
var sshSelect = document.createElement('select');
|
||||||
|
sshSelect.className = 'form-control';
|
||||||
|
|
||||||
|
sshKeys.forEach(function(sshkey) {
|
||||||
|
var option = document.createElement('option');
|
||||||
|
option.value = sshkey.id;
|
||||||
|
option.text = sshkey.name;
|
||||||
|
sshSelect.appendChild(option);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set the default value of the input field to the first option in the dropdown.
|
||||||
|
sshInputField.value = sshSelect.options[0].value;
|
||||||
|
|
||||||
|
sshSelect.addEventListener('change', function() {
|
||||||
|
sshInputField.value = this.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
sshInputField.parentNode.insertBefore(sshSelect, sshInputField.nextSibling);
|
||||||
|
sshInputField.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
sshInputField.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
";
|
||||||
|
});
|
||||||
153
modules/servers/VirtFusionDirect/lib/ConfigureService.php
Normal file
153
modules/servers/VirtFusionDirect/lib/ConfigureService.php
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace WHMCS\Module\Server\VirtFusionDirect;
|
||||||
|
|
||||||
|
use JsonException;
|
||||||
|
use WHMCS\Database\Capsule as DB;
|
||||||
|
use WHMCS\User\User;
|
||||||
|
|
||||||
|
class ConfigureService extends Module
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array|false $cp
|
||||||
|
*/
|
||||||
|
private array|bool $cp;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
$this->cp = $this->getCP(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return int|null
|
||||||
|
* @throws JsonException
|
||||||
|
*/
|
||||||
|
public function fetchPackageId(string $packageName): ?int
|
||||||
|
{
|
||||||
|
$request = $this->initCurl($this->cp['token']);
|
||||||
|
|
||||||
|
$response = $request->get(
|
||||||
|
sprintf("%s/packages", $this->cp['url'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$packages = $this->decodeResponseFromJson($response);
|
||||||
|
|
||||||
|
foreach ($packages['data'] as $package) {
|
||||||
|
if ($package['name'] === $packageName && $package['enabled'] === true) {
|
||||||
|
return $package['id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $productId
|
||||||
|
* @return int|null
|
||||||
|
*/
|
||||||
|
public function fetchPackageByDbId(int $productId): ?int
|
||||||
|
{
|
||||||
|
$product = DB::table('tblproducts')->where('id', $productId)->first();
|
||||||
|
|
||||||
|
if (is_null($product)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)$product->configoption2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $serverPackageId
|
||||||
|
* @return array|null
|
||||||
|
* @throws JsonException
|
||||||
|
*/
|
||||||
|
public function fetchTemplates(?int $serverPackageId): ?array
|
||||||
|
{
|
||||||
|
if (is_null($serverPackageId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = $this->initCurl($this->cp['token']);
|
||||||
|
|
||||||
|
$response = $request->get(
|
||||||
|
sprintf("%s/media/templates/fromServerPackageSpec/%d", $this->cp['url'], $serverPackageId)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->decodeResponseFromJson($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User|null $user
|
||||||
|
* @return array|null
|
||||||
|
* @throws JsonException
|
||||||
|
*/
|
||||||
|
public function getUserSshKeys(?User $user): ?array
|
||||||
|
{
|
||||||
|
if (is_null($user)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = $this->initCurl($this->cp['token']);
|
||||||
|
|
||||||
|
$vfUser = $this->getVFUserDetails($user['id']);
|
||||||
|
|
||||||
|
$response = $request->get(
|
||||||
|
sprintf("%s/ssh_keys/user/%d", $this->cp['url'], $vfUser['id'])
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->decodeResponseFromJson($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
* @return array|null
|
||||||
|
* @throws JsonException
|
||||||
|
*/
|
||||||
|
public function getVFUserDetails(int $id): ?array
|
||||||
|
{
|
||||||
|
$request = $this->initCurl($this->cp['token']);
|
||||||
|
|
||||||
|
$response = $this->decodeResponseFromJson($request->get(
|
||||||
|
sprintf("%s/users/%d/byExtRelation", $this->cp['url'], $id)
|
||||||
|
));
|
||||||
|
|
||||||
|
return isset($response['msg']) && $response['msg'] === "ext_relation_id not found" ? null : $response['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
* @param array $vars
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function initServerBuild(int $id, array $vars): bool
|
||||||
|
{
|
||||||
|
$request = $this->initCurl($this->cp['token']);
|
||||||
|
|
||||||
|
// Generate a random 8 character hostname
|
||||||
|
$hostname = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 8);
|
||||||
|
|
||||||
|
$inputData = [
|
||||||
|
"operatingSystemId" => $vars['customfields']['Initial Operating System'],
|
||||||
|
"name" => $hostname,
|
||||||
|
"sshKeys" => [
|
||||||
|
$vars['customfields']['Initial SSH Key']
|
||||||
|
],
|
||||||
|
'email' => true
|
||||||
|
];
|
||||||
|
|
||||||
|
if (empty($vars['customfields']['Initial SSH Key'])) {
|
||||||
|
unset($inputData['sshKeys']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$request->addOption(CURLOPT_POSTFIELDS, json_encode($inputData));
|
||||||
|
|
||||||
|
$request->post(
|
||||||
|
sprintf("%s/servers/%d/build", $this->cp['url'], $id)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -232,4 +232,17 @@ class Module
|
|||||||
|
|
||||||
return $curl;
|
return $curl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a response from JSON into an associative array.
|
||||||
|
*
|
||||||
|
* @param string $response
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* @throws \JsonException
|
||||||
|
*/
|
||||||
|
public function decodeResponseFromJson(string $response): array
|
||||||
|
{
|
||||||
|
return json_decode($response, true, 512, JSON_THROW_ON_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,6 +163,10 @@ class ModuleFunctions extends Module
|
|||||||
Database::systemOnServerCreate($params['serviceid'], $data);
|
Database::systemOnServerCreate($params['serviceid'], $data);
|
||||||
$this->updateWhmcsServiceParamsOnServerObject($params['serviceid'], $data);
|
$this->updateWhmcsServiceParamsOnServerObject($params['serviceid'], $data);
|
||||||
|
|
||||||
|
// If the server is created successfully, we can initialize the server build.
|
||||||
|
$cs = new ConfigureService();
|
||||||
|
$cs->initServerBuild($data->data->id, $params);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Server was created successfully.
|
* Server was created successfully.
|
||||||
@@ -181,6 +185,46 @@ class ModuleFunctions extends Module
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function was implemented by Zander Scott / awildboop of Blinkoh, LLC
|
||||||
|
// Please read this function thoroughly before use to ensure security & integrity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows changing of the package of a server
|
||||||
|
*
|
||||||
|
* @author https://github.com/BlinkohHost/virtfusion-whmcs-module
|
||||||
|
* @param $params
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function changePackage($params)
|
||||||
|
{
|
||||||
|
$service = Database::getSystemService($params['serviceid']);
|
||||||
|
|
||||||
|
if ($service) {
|
||||||
|
$whmcsService = Database::getWhmcsService($params['serviceid']);
|
||||||
|
$cp = $this->getCP($whmcsService->server);
|
||||||
|
$request = $this->initCurl($cp['token']);
|
||||||
|
$data = $request->put($cp['url'] . '/servers/' . $service->server_id . '/package/' . $params['configoption2']);
|
||||||
|
$data = json_decode($data);
|
||||||
|
|
||||||
|
Log::insert(__FUNCTION__, $request->getRequestInfo(), $data);
|
||||||
|
|
||||||
|
switch ($request->getRequestInfo('http_code')) {
|
||||||
|
|
||||||
|
case 204:
|
||||||
|
return 'success';
|
||||||
|
case 404:
|
||||||
|
return '404 was returned from the web service without the msg property. The service may be currently unavailable.';
|
||||||
|
case 423:
|
||||||
|
if (property_exists($data, 'msg')) {
|
||||||
|
return $data->msg;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 'Update package request failed. The web service reported HTTP code ' . $request->getRequestInfo('http_code');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 'Service not found.';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* TERMINATE SERVER
|
* TERMINATE SERVER
|
||||||
|
|||||||
Reference in New Issue
Block a user