-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathService.php
326 lines (292 loc) · 11 KB
/
Service.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
<?php
namespace App\Services\Virtfusion;
use Illuminate\Support\Facades\Http;
use App\Services\ServiceInterface;
use App\Models\Package;
use App\Models\Order;
class Service implements ServiceInterface
{
/**
* Unique key used to store settings
* for this service.
*
* @return string
*/
public static $key = 'virtfusion';
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* Returns the meta data about this Server/Service
*
* @return object
*/
public static function metaData(): object
{
return (object)
[
'display_name' => 'VirtFusion',
'author' => 'WemX',
'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
{
// Check if the URL ends with a slash
$doesNotEndWithSlash = function ($attribute, $value, $fail) {
if (preg_match('/\/$/', $value)) {
return $fail('AMP Panel URL must not end with a slash "/". It should be like https://panel.example.com');
}
};
return [
[
"key" => "virtfusion::host",
"name" => "Host",
"description" => "The host / url of the VirtFusion Panel i.e https://panel.example.com",
"type" => "url",
"rules" => ['required', 'active_url', $doesNotEndWithSlash], // laravel validation rules
],
[
"key" => "encrypted::virtfusion::api_key",
"name" => "API Key",
"description" => "The API Key of the VirtFusion Panel",
"type" => "password",
"rules" => ['required'], // laravel validation rules
],
];
}
/**
* 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
{
// collect the data then map with keus
$collectPackages = collect(Service::api('get', '/packages')['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" => "Hyporvisor Group ID",
"description" => "Enter the Hyporvisor 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 [];
}
/**
* 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 = $order->user;
$package = $order->package;
// check if external user exists
if(!$order->hasExternalUser()) {
try {
$externalUser = Service::api('post', '/users', [
"name" => $user->first_name . ' ' . $user->last_name,
'email' => $user->email,
'extRelationId' => $user->id,
'sendMail' => false, // set to true if you want virtfusion to send the credentials alongside wemx via email
])['data'];
$order->createExternalUser([
'external_id' => $externalUser['id'], // optional
'username' => $user->email,
'password' => $externalUser['password'],
'data' => $externalUser, // Additional data about the user as an array (optional)
]);
// Email the user their password
$user->email([
'subject' => 'Panel Account Created',
'content' => "Your account has been created on the vps panel. You can login using the following details: <br><br> Email: {$user->email} <br> Password: {$externalUser['password']}",
'button' => [
'name' => 'VPS Panel',
'url' => settings('virtfusion::host'),
]
]);
} catch (\Exception $e) {
throw new \Exception("Failed to create user on the panel, please make sure the email isn't already in use or that your name is longer than 10 chars");
}
}
// create the server
$response = 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),
]);
$order->external_id = $response['data']['id'];
$order->data = $response['data'];
$order->save();
return $response;
}
/**
* 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;
Service::api('put', "/servers/{$order->external_id}/package/{$newPackage->data('package')}");
}
/**
* 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;
Service::api('post', "/servers/{$order->external_id}/suspend");
}
/**
* 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;
Service::api('post', "/servers/{$order->external_id}/unsuspend");
}
/**
* 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->external_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->external_id}");
return redirect(settings('virtfusion::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. <br><br>{$error->getMessage()}");
}
// if no errors are logged, return a success message
return redirect()->back()->withSuccess("Successfully connected with VirtFusion");
}
/**
* Init connection with API
*/
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('virtfusion::host') . '/api/v1' . $endpoint;
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . settings('encrypted::virtfusion::api_key'),
'Accept' => 'application/json',
'Content-Type' => 'application/json',
])->$method($url, $data);
// dd($response, $response->json());
if($response->failed())
{
// dd($response, $response->json());
if(isset($response['errors'])) {
throw new \Exception("[VirtFusion] " . json_encode($response['errors']));
}
if(isset($response['message'])) {
throw new \Exception("[VirtFusion] " . $response['message']);
}
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()}");
}
throw new \Exception("[VirtFusion] Failed to connect to the API. Ensure the API details and hostname are valid.");
}
return $response;
}
}