7 Commits

Author SHA1 Message Date
7b87fdcc3f Updated github action 2025-10-01 13:06:43 -04:00
a2275f4444 Moved SQL to a file 2025-10-01 13:02:52 -04:00
798d3fcdb5 Small tweaks 2025-10-01 13:02:42 -04:00
Andrew
9aa8378599 Merge pull request #2 from EZSCALE/Prophet731-patch-1
Update hooks.php
2024-01-16 12:13:15 -05:00
Andrew
f0c28a4961 Update hooks.php
Hide the SSH key field if the user isn't logged in to see them or is a new user.
2024-01-16 12:11:26 -05:00
Prophet731
a46223e5ac Update issue templates 2023-09-11 00:31:03 -04:00
98250f2f4c Ahh typos 2023-09-10 23:58:17 -04:00
7 changed files with 161 additions and 91 deletions

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1,19 +1,38 @@
--- # .github/workflows/semantic-versioning-release.yml
name: Publish Release name: Automated Semantic Versioning Release
on: on:
push: push:
branches: branches:
- main - main
jobs: jobs:
publish-release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: write # for creating tags and releases
issues: write # for commenting on issues
pull-requests: write # for commenting on PRs
steps: steps:
- name: Publish Release - name: Checkout code
uses: ncipollo/release-action@v1 uses: actions/checkout@v4
with: with:
token: ${{secrets.GITHUB_TOKEN}} # This is required to analyze the full commit history
draft: false fetch-depth: 0
prerelease: false
name: "0.0.${{ github.run_number }}" - name: Automated Semantic Release
tag: "0.0.${{ github.run_number }}" # This action wraps the popular semantic-release tool
body: "Release 0.0.${{ github.run_number }}" uses: cycjimmy/semantic-release-action@v4
with:
# You can specify the branches to release from
branch: main
env:
# GITHUB_TOKEN is required for authentication
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# To make this work, you must follow the Conventional Commits specification.
# Examples:
# - fix: correct a typo in the documentation
# - feat: add a new user authentication endpoint
# - feat(api): add rate limiting
# BREAKING CHANGE: The API now returns 429 when rate limit is exceeded.

View File

@@ -5,7 +5,8 @@
![GitHub issues](https://img.shields.io/github/issues/EZSCALE/virtfusion-whmcs-module) ![GitHub issues](https://img.shields.io/github/issues/EZSCALE/virtfusion-whmcs-module)
![GitHub pull requests](https://img.shields.io/github/issues-pr/EZSCALE/virtfusion-whmcs-module) ![GitHub pull requests](https://img.shields.io/github/issues-pr/EZSCALE/virtfusion-whmcs-module)
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). 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).
## Installation ## Installation
@@ -22,60 +23,8 @@ each product you want to use this module with.
| Initial Operating System | Text Box | Set to whatever you want | Leave Blank | Leave Blank | :x: | :x: | :white_check_mark: | :x: | | 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: | | Initial SSH Key | Text Box | Set to whatever you want | Leave Blank | Leave Blank | :x: | :x: | :white_check_mark: | :x: |
You can run this SQL query to create the custom fields: You can run this SQL query to create the custom fields. Run the SQL from this [file](modify.sql) or copy the contents
from it.
```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?

49
modify.sql Normal file
View File

@@ -0,0 +1,49 @@
-- 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);

View File

@@ -27,7 +27,7 @@ add_hook('ClientAreaFooterOutput', 1, function ($vars) {
foreach ($templates_data['data'] as $osCategory) { foreach ($templates_data['data'] as $osCategory) {
foreach ($osCategory['templates'] as $template) { foreach ($osCategory['templates'] as $template) {
$optionValue = $template['id']; $optionValue = $template['id'];
$optionLabel = $template['name'] . " " . $template['version'] . " " . $template['variant']; $optionLabel = $template['name']." ".$template['version']." ".$template['variant'];
$dropdownOptions[] = ['id' => $optionValue, 'name' => $optionLabel]; $dropdownOptions[] = ['id' => $optionValue, 'name' => $optionLabel];
} }
} }
@@ -65,18 +65,20 @@ add_hook('ClientAreaFooterOutput', 1, function ($vars) {
return " return "
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
var osTemplates = " . json_encode($dropdownOptions) . "; let osTemplates = ".json_encode($dropdownOptions, JSON_THROW_ON_ERROR).";
var sshKeys = " . json_encode($sshKeysOptions) . "; let sshKeys = ".json_encode($sshKeysOptions, JSON_THROW_ON_ERROR).";
var osInputField = document.querySelector('[name=\"customfield[" . ($osID[0] ?? null) . "]\"]'); const osInputField = document.querySelector('[name=\"customfield[".($osID[0] ?? null)."]\"]');
var sshInputField = document.querySelector('[name=\"customfield[" . ($sshID[0] ?? null) . "]\"]'); const osInputLabel = document.querySelector('[for=\"customfield".($osID[0] ?? null)."\"]');
const sshInputField = document.querySelector('[name=\"customfield[".($sshID[0] ?? null)."]\"]');
const sshInputLabel = document.querySelector('[for=\"customfield".($sshID[0] ?? null)."\"]');
// Create dropdown options menu, then add it to the DOM then on change, update the regular input. // Create dropdown options menu, then add it to the DOM then on change, update the regular input.
var osSelect = document.createElement('select'); let osSelect = document.createElement('select');
osSelect.className = 'form-control'; osSelect.className = 'form-control';
osTemplates.forEach(function(template) { osTemplates.forEach(function(template) {
var option = document.createElement('option'); let option = document.createElement('option');
option.value = template.id; option.value = template.id;
option.text = template.name; option.text = template.name;
osSelect.appendChild(option); osSelect.appendChild(option);
@@ -95,11 +97,11 @@ add_hook('ClientAreaFooterOutput', 1, function ($vars) {
if (sshKeys.length > 0) { if (sshKeys.length > 0) {
// Create dropdown options menu, then add it to the DOM then on change, update the regular input. // Create dropdown options menu, then add it to the DOM then on change, update the regular input.
var sshSelect = document.createElement('select'); let sshSelect = document.createElement('select');
sshSelect.className = 'form-control'; sshSelect.className = 'form-control';
sshKeys.forEach(function(sshkey) { sshKeys.forEach(function(sshkey) {
var option = document.createElement('option'); let option = document.createElement('option');
option.value = sshkey.id; option.value = sshkey.id;
option.text = sshkey.name; option.text = sshkey.name;
sshSelect.appendChild(option); sshSelect.appendChild(option);
@@ -116,6 +118,7 @@ add_hook('ClientAreaFooterOutput', 1, function ($vars) {
sshInputField.style.display = 'none'; sshInputField.style.display = 'none';
} else { } else {
sshInputField.style.display = 'none'; sshInputField.style.display = 'none';
sshInputLabel.style.display = 'none';
} }
}); });
</script> </script>

View File

@@ -39,7 +39,7 @@ class ModuleFunctions extends Module
*/ */
$server = $params['serverid'] ?: false; $server = $params['serverid'] ?: false;
$cp = $this->getCP($server, $server ? false : true); $cp = $this->getCP($server, !$server);
if (!$cp) { if (!$cp) {
return 'No Control server found.'; return 'No Control server found.';
@@ -82,7 +82,7 @@ class ModuleFunctions extends Module
[ [
"name" => $user->firstname . ' ' . $user->lastname, "name" => $user->firstname . ' ' . $user->lastname,
"email" => $user->email, "email" => $user->email,
"extRelationId" => $user->id "extRelationId" => $user->id,
] ]
)); ));
@@ -96,7 +96,6 @@ class ModuleFunctions extends Module
break; break;
default: default:
return 'Error processing user account.'; return 'Error processing user account.';
break;
} }
$data = json_decode($data); $data = json_decode($data);
@@ -192,7 +191,9 @@ class ModuleFunctions extends Module
* Allows changing of the package of a server * Allows changing of the package of a server
* *
* @author https://github.com/BlinkohHost/virtfusion-whmcs-module * @author https://github.com/BlinkohHost/virtfusion-whmcs-module
*
* @param $params * @param $params
*
* @return string * @return string
*/ */
public function changePackage($params) public function changePackage($params)
@@ -218,6 +219,7 @@ class ModuleFunctions extends Module
if (property_exists($data, 'msg')) { if (property_exists($data, 'msg')) {
return $data->msg; return $data->msg;
} }
break;
default: default:
return 'Update package request failed. The web service reported HTTP code ' . $request->getRequestInfo('http_code'); return 'Update package request failed. The web service reported HTTP code ' . $request->getRequestInfo('http_code');
} }
@@ -256,7 +258,6 @@ class ModuleFunctions extends Module
Database::deleteSystemService($params['serviceid']); Database::deleteSystemService($params['serviceid']);
$this->updateWhmcsServiceParamsOnDestroy($params['serviceid']); $this->updateWhmcsServiceParamsOnDestroy($params['serviceid']);
return 'success'; return 'success';
break;
case 404: case 404:
if (property_exists($data, 'msg')) { if (property_exists($data, 'msg')) {
@@ -269,11 +270,9 @@ class ModuleFunctions extends Module
} else { } else {
return '404 was returned from the web service without the msg property. The service may be currently unavailable.'; return '404 was returned from the web service without the msg property. The service may be currently unavailable.';
} }
break;
default: default:
return 'Termination request failed. The web service reported HTTP code ' . $request->getRequestInfo('http_code'); return 'Termination request failed. The web service reported HTTP code ' . $request->getRequestInfo('http_code');
break;
} }
} }
return 'Service not found. Termination routine has already been run?'; return 'Service not found. Termination routine has already been run?';
@@ -307,7 +306,6 @@ class ModuleFunctions extends Module
case 204: case 204:
return 'success'; return 'success';
break;
case 404: case 404:
if (property_exists($data, 'msg')) { if (property_exists($data, 'msg')) {
@@ -321,7 +319,6 @@ class ModuleFunctions extends Module
} else { } else {
return '404 was returned from the web service without the msg property. The service may be currently unavailable.'; return '404 was returned from the web service without the msg property. The service may be currently unavailable.';
} }
break;
case 423: case 423:
if (property_exists($data, 'msg')) { if (property_exists($data, 'msg')) {
return $data->msg; return $data->msg;
@@ -329,7 +326,6 @@ class ModuleFunctions extends Module
default: default:
return 'Suspend request failed. The web service reported HTTP code ' . $request->getRequestInfo('http_code'); return 'Suspend request failed. The web service reported HTTP code ' . $request->getRequestInfo('http_code');
break;
} }
} }
return 'Service not found.'; return 'Service not found.';
@@ -358,10 +354,8 @@ class ModuleFunctions extends Module
$this->updateWhmcsServiceParamsOnServerObject($params['serviceid'], $data); $this->updateWhmcsServiceParamsOnServerObject($params['serviceid'], $data);
return 'success'; return 'success';
break;
default: default:
return 'Request failed. The web service reported HTTP code ' . $request->getRequestInfo('http_code'); return 'Request failed. The web service reported HTTP code ' . $request->getRequestInfo('http_code');
break;
} }
} }
return 'Service not found.'; return 'Service not found.';
@@ -386,7 +380,6 @@ class ModuleFunctions extends Module
case 204: case 204:
return 'success'; return 'success';
break;
case 404: case 404:
if (property_exists($data, 'msg')) { if (property_exists($data, 'msg')) {
@@ -399,15 +392,14 @@ class ModuleFunctions extends Module
} else { } else {
return '404 was returned from the web service without the msg property. The service may be currently unavailable.'; return '404 was returned from the web service without the msg property. The service may be currently unavailable.';
} }
break;
case 423: case 423:
if (property_exists($data, 'msg')) { if (property_exists($data, 'msg')) {
return $data->msg; return $data->msg;
} }
break;
default: default:
return 'Unsuspend request failed. The web service reported HTTP code ' . $request->getRequestInfo('http_code'); return 'Unsuspend request failed. The web service reported HTTP code ' . $request->getRequestInfo('http_code');
break;
} }
} }
return 'Service not found'; return 'Service not found';