PluginProbe
WebTotem Security / 2.4.12
WebTotem Security v2.4.12
3.0.1 3.0.0 trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.3.3 2.0 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.1 2.2.2 2.2.3 2.2.4 All 109 releases
wt-security / lib / API.php

API.php in WebTotem Security 2.4.12, at lib/API.php

950 lines 34.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('WEBTOTEM_INIT') || WEBTOTEM_INIT !== true) {
4 if (!headers_sent()) {
5 header('HTTP/1.1 403 Forbidden');
6 }
7 die("Protected By WebTotem!");
8 }
9
10 /**
11 * WebTotem API class.
12 *
13 * Mostly contains wrappers for API methods. Check and send methods.
14 *
15 * @version 1.0
16 * @copyright (C) 2022 WebTotem team (http://wtotem.com)
17 * @license GNU/GPL: http://www.gnu.org/copyleft/gpl.html
18 */
19 class WebTotemAPI extends WebTotem {
20
21 /**
22 * Method for getting a auth token.
23 *
24 * @param string $api_key
25 * Application programming interface key.
26 *
27 * @return bool|string
28 * Returns auth status
29 */
30 public static function auth($api_key) {
31 $domain = WEBTOTEM_SITE_DOMAIN;
32
33 $payload = '{"query":"mutation{ guest{ apiKeys{ auth(apiKey:\"' . $api_key . '\", source:\"' . $domain . '\"),{ token{ value, refreshToken, expiresIn } } } } }"}';
34 $result = self::sendRequest($payload, FALSE, TRUE);
35
36 if (isset($result['data']['guest']['apiKeys']['auth']['token']['value'])) {
37 $auth_token = $result['data']['guest']['apiKeys']['auth']['token'];
38 WebTotemOption::login(['token' => $auth_token, 'api_key' => $api_key]);
39 return 'success';
40 } elseif($result['errors'][0]['message'] == 'INVALID_API_KEY') {
41 WebTotemOption::logout();
42 }
43
44 return FALSE;
45 }
46
47 /**
48 * Get site info from API server.
49 *
50 * @param string $attempt
51 * Is the request an attempt to get host data.
52 *
53 * @return array
54 * Returns host data.
55 */
56 public static function siteInfo($attempt = FALSE) {
57
58 if(self::isMultiSite()){
59 $host['id'] = WebTotemOption::getSessionOption('host_id');
60
61 if ($host['id']) {
62 return $host;
63 }
64 }
65
66 $host = WebTotemOption::getHost();
67
68 if ($host['id']) {
69 return $host;
70 }
71
72 $all_sites = self::getSites(null, 0);
73 if($all_sites){
74 if(self::isMultiSite()) {
75 $sites = get_sites();
76 foreach ($sites as $site){
77 $domain = untrailingslashit($site->domain . $site->path);
78 self::addSite($domain, $all_sites);
79 }
80
81 if (!$attempt) {
82 return self::siteInfo(TRUE);
83 }
84 }
85 else {
86 $domain = WEBTOTEM_SITE_DOMAIN;
87 return self::addSite($domain, $all_sites);
88 }
89 }
90
91 return [];
92 }
93
94 /**
95 * Method for adding a site to the WebTotem platform.
96 *
97 * @param string $domain
98 * Domain to add.
99 * @param array $all_sites
100 * Array with site data on the WebTotem platform.
101 *
102 * @return array
103 * Returns host data.
104 */
105 public static function addSite( $domain, $all_sites) {
106
107 if(function_exists('idn_to_utf8')){
108 $domain = idn_to_utf8($domain);
109 }
110
111 // Checking if the site has been added to the WebTotem.
112 if(array_key_exists('edges', $all_sites)){
113
114 foreach ($all_sites['edges'] as $site){
115 $site = $site['node'];
116 $hostname = untrailingslashit($site['hostname']);
117 // If it added, save site data to DB.
118 if($hostname == $domain or $hostname == 'www.' . $domain){
119 WebTotemOption::setHost($site['hostname'], $site['id']);
120 return [
121 'id' => $site['id'],
122 'name' => $site['hostname'],
123 ];
124 }
125 }
126
127 }
128
129 // If the site is not added then try to add.
130 $payload = '{"variables":{"input":{"title":"' . $domain . '","hostname":"' . $domain . '","configs":{"scheme":"http","port":80,"wa":{},"dec":{},"ps":{}}}},"query":"mutation ($input: CreateSiteInput) { auth { sites { create(input: $input) { id hostname title } } } }"}';
131 $add_site = self::sendRequest($payload, TRUE);
132 if (isset($add_site['errors'])) {
133 WebTotemOption::setNotification('error', __('Failed to add the site to the WebTotem platform.', 'wtotem'));
134 }
135 else {
136 if($host = $add_site['data']['auth']['sites']['create']) {
137 // If it added, save site ID.
138 WebTotemOption::setHost($host['title'], $host['id']);
139 return [
140 'id' => $host['id'],
141 'name' => $host['title'],
142 ];
143 }
144 }
145 return [];
146 }
147
148 /**
149 * Get all sites from API.
150 *
151 * @param string $cursor
152 * Mark for loading data.
153 * @param string $limit
154 * Limit of sites to loading.
155 *
156 * @return array
157 * Returns host data.
158 */
159 public static function getSites($cursor = null, $limit = 15, $filter = false) {
160 $cursor = ($cursor == null) ? 'null' : '\"' . $cursor . '\"';
161 if(!$filter) {
162 $filter = ($limit === 0) ? '' : 'pagination:{ first: ' . $limit . ', cursor: ' . $cursor . ' }';
163 }
164
165 $payload = '{"query":"query getSites { auth { viewer { sites { ...sites } } } } fragment sites on SiteQueries { list(filter: { ' . $filter . ' }) { pageInfo{ hasNextPage endCursor } edges { node { id hostname title createdAt ssl { status } availability { status } reputation { status } ports { status } deface { status } domain { status } antivirus { status } firewall { status } maliciousScript { stack { name } } } } } }"}';
166 $result = self::sendRequest($payload, true);
167
168 if (isset($result['data']['auth']['viewer']['sites']['list']['edges'])) {
169 return $result['data']['auth']['viewer']['sites']['list'];
170 }
171
172 return [];
173 }
174
175 /**
176 * Method to get the agents file names and AM file link.
177 *
178 * @param string $host_id
179 * Host id on WebTotem.
180 *
181 * @return array
182 * Returns agents files data.
183 */
184 public static function getAgentsFiles($host_id) {
185
186 if(WebTotem::isMultiSite()){
187 $all_hosts = WebTotemOption::getOption('all_hosts') ?: [];
188 $siteIdsArray = $all_hosts ? array_values($all_hosts) : [];
189 $siteIds = $siteIdsArray ? addslashes(WebTotem::convertArrayToString($siteIdsArray)) : '';
190
191 $payload = '{"query":"mutation { auth { am { installMultisite(mainSiteId: \"' . $host_id . '\", siteIds: [' . $siteIds . ']){ downloadLink, amFilename, wafFilename, avFilename } } } }"}';
192 $response = self::sendRequest($payload, TRUE);
193
194 return $response['data']['auth']['am']['installMultisite'];
195 }
196 else {
197 $payload = '{"query":"mutation { auth { am { install(siteId: \"' . $host_id . '\"){ downloadLink, amFilename, wafFilename, avFilename } } } }"}';
198 $response = self::sendRequest($payload, TRUE);
199 return $response['data']['auth']['am']['install'];
200 }
201 }
202
203 /**
204 * Add secondary MultiSite host.
205 *
206 * @param $new_sites
207 * An array with sites to add.
208 *
209 * @return void.
210 */
211 public static function addMultiSiteNewSites($new_sites){
212 // Host id of the main site in MultiSite network.
213 $main_host = WebTotemOption::getMainHost();
214
215 foreach ($new_sites as $site){
216 $all_sites = self::getSites(null, 0);
217 $host = self::addSite($site, $all_sites);
218 if(key_exists('id', $host)){
219 $payload = '{"query":"mutation { auth { am { addMultisiteHost(mainSiteId: \"' . $main_host['id'] . '\", siteId: \"' . $host['id'] . '\") } } }"}';
220
221 $result = self::sendRequest($payload, TRUE);
222 if(!$result['errors'][0]['message']){
223 WebTotemOption::setNotification( 'info', __('A new website has been added: ', 'wtotem') . $site);
224 }
225 }
226 }
227 }
228
229 /**
230 * Remove secondary MultiSite host.
231 *
232 * @param $host_id
233 * Host id on WebTotem.
234 *
235 * @return bool
236 * Returns result removing host.
237 */
238 public static function removeMultiSiteHost($host_id){
239 $payload = '{"query":"mutation { auth { am { removeMultisiteHost(siteId: \"' . $host_id . '\") } } }"}';
240 $response = self::sendRequest($payload, TRUE);
241 return $response['data']['auth']['am']['removeSecondaryMultisiteHost'];
242 }
243
244 /**
245 * Method to get agents (AM, WAF, AV) statuses.
246 *
247 * @param string $host_id
248 * Host id on WebTotem.
249 *
250 * @return array
251 * Returns agents statuses data.
252 */
253 public static function getAgentsStatusesFromAPI($host_id) {
254 $payload = '{"query":"query ($id: ID!) { auth { viewer { sites { one(id: $id) { agentManager { statuses { am { status } av { status } waf { status } } } } } } } }", "variables":{"id":"' . $host_id . '"}}';
255 $response = self::sendRequest($payload, TRUE);
256
257 if (isset($response['data']['auth']['viewer']['sites']['one']['agentManager']['statuses'])) {
258 return $response['data']['auth']['viewer']['sites']['one']['agentManager']['statuses'];
259 }
260
261 return [];
262 }
263
264 /**
265 * Method to get user time zone.
266 *
267 * @return string|bool
268 * Returns time zone data.
269 */
270 public static function getTimeZone() {
271 $payload = '{"query":"query { auth { viewer{ timezone } } } "}';
272 $response = self::sendRequest($payload, TRUE);
273
274 if (isset($response['data']['auth']['viewer']['timezone'])) {
275 return $response['data']['auth']['viewer']['timezone'];
276 }
277 return FALSE;
278 }
279
280 /**
281 * Method for get all the site security data.
282 *
283 * @param string $host_id
284 * Host id on WebTotem.
285 * @param int|array $days
286 * For what period data is needed.
287 *
288 * @return array
289 * Returns all data.
290 */
291 public static function getAllData($host_id, $days = 7) {
292 $language = WebTotem::getLanguage();
293 $period = WebTotem::getPeriod($days);
294
295 $payload = '{"query":"query($id: ID!, $dateRange: DateRangeInput!, $language: Language!, $dateRangeWeek: DateRangeInput!, $wafLogFilter: WafLogFilter!) { auth { viewer { sites { one(id: $id) { ports { status ip tcp ignorePorts lastTest { time } } availability { status lastTest { time } responseTime downTime(dateRange: $dateRange) percent(dateRange: $dateRange) } deface { status lastTest { time } words count } domain { status registrar owner email createdDate expiredDate } ports { status lastTest { time } ip tcp country } ssl { status daysLeft expiryDate issueDate } reputation { status lastTest { time } virusList { virus{ type path } antiVirus } } firewall { lastTest { time } logs(wafLogFilter: $wafLogFilter){ edges{ node{ type blocked payload ip location{ country{ nameEn } } time request status country category } } } map(dateRange: $dateRange) { attacks, country } status chart(dateRange: $dateRange) { time attacks blocked } report(dateRange: $dateRange) { time attacks ip } } serverStatus { info { phpVersion phpServerUser phpServerSoftware phpGatewayInterface phpServerProtocol osInfo cpuCount cpuModel CpuFreq cpuFamily lsCpu maxExecTime mathLibraries } ramChart(dateRange: $dateRangeWeek){ total value time } cpuChart(dateRange: $dateRangeWeek){ value time } discUsage{ total free } status } maliciousScript { lastTest { time } status } scoring( language: $language ){ score lastTest{ time } result{ ip country isHigherThan }} agentManager{ createdAt } antivirus { status stats { changed deleted scanned infected error } lastTest { time } isFirstCheck } } } } } }","variables":{"id":"' . $host_id . '","dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '}, "dateRangeWeek":{"to":' . $period['to'] . ',"from":' . $period['from'] . '}, "wafLogFilter": {"dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '},"order":{"direction":"DESC","field":"time"},"pagination":{"first": 10,"cursor":null}}, "language":"' . $language . '"}}';
296 $response = self::sendRequest($payload, TRUE);
297
298 if (isset($response['data']['auth']['viewer']['sites']['one'])) {
299 return $response['data']['auth']['viewer']['sites']['one'];
300 }
301
302 return [];
303 }
304
305 /**
306 * Method to get firewall data.
307 *
308 * @param string $host_id
309 * Host id on WebTotem.
310 * @param int $limit
311 * Limit on the number of records.
312 * @param string $cursor
313 * Mark for loading data.
314 * @param int|array $days
315 * For what period data is needed.
316 *
317 * @return array
318 * Returns firewall data.
319 */
320 public static function getFirewall($host_id, $limit = 20, $cursor = NULL, $days = 365) {
321 $period = WebTotem::getPeriod($days);
322 $cursor = ($cursor == NULL) ? 'null' : '"' . $cursor . '"';
323
324 $payload = '{"query":"query($id: ID!, $wafLogFilter: WafLogFilter!, $dateRange: DateRangeInput!) { auth { viewer { sites { one(id: $id) { firewall { lastTest { time } status map(dateRange: $dateRange) { attacks, country, location { country { nameEn } } } chart(dateRange: $dateRange) { time attacks blocked } ...FirewallLogFragment } agentManager { createdAt } } } } } } fragment FirewallLogFragment on Waf { logs(wafLogFilter: $wafLogFilter) { edges { cursor node { type blocked payload ip location { country { nameEn } } time request status country category } } pageInfo { endCursor hasNextPage } } }", "variables":{"dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '},"id":"' . $host_id . '","wafLogFilter":{"dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '},"order":{"direction":"DESC","field":"time"},"pagination":{"first":' . $limit . ',"cursor":' . $cursor . '}}} }';
325 $response = self::sendRequest($payload, TRUE);
326
327 if (isset($response['data']['auth']['viewer']['sites']['one'])) {
328 return $response['data']['auth']['viewer']['sites']['one'];
329 }
330
331 return [];
332 }
333
334 /**
335 * Method to get firewall chart data.
336 *
337 * @param string $host_id
338 * Host id on WebTotem.
339 * @param int $days
340 * For what period data is needed.
341 *
342 * @return array
343 * Returns firewall chart data.
344 */
345 public static function getFirewallChart($host_id, $days = 7) {
346 $period = WebTotem::getPeriod($days);
347
348 $payload = '{ "query":"query($id: ID!, $dateRange: DateRangeInput!) { auth { viewer { sites { one(id: $id) { firewall { lastTest { time } status map(dateRange: $dateRange) { attacks, country, location { country { nameEn } } } chart(dateRange: $dateRange) { time attacks blocked } } } } } } }", "operationName":null,"variables":{"id":"' . $host_id . '","dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '} } }';
349 $response = self::sendRequest($payload, TRUE);
350
351 if (isset($response['data']['auth']['viewer']['sites']['one']['firewall'])) {
352 return $response['data']['auth']['viewer']['sites']['one']['firewall'];
353 }
354
355 return [];
356 }
357
358 /**
359 * Method to set firewall settings.
360 *
361 * @param string $host_id
362 * Host id on WebTotem.
363 * @param array $settings
364 * User-specified settings.
365 *
366 * @return array
367 * Returns information whether the request was successful.
368 */
369 public static function setFirewallSettings($host_id, array $settings) {
370 $payload = '{"variables":{"input": {"siteId": "' . $host_id . '", "gdn": ' . $settings['gdn'] . ', "dosProtection": ' . $settings['dosProtection'] . ', "dosLimit": ' . $settings['dosLimit'] . ', "loginAttemptsProtection": ' . $settings['loginAttemptsProtection'] . ', "loginAttemptsLimit": ' . $settings['loginAttemptsLimit'] . '}},"query":"mutation WafSettings($input: WafSettingsInput!) { auth { sites { waf{ settings(input: $input) { gdn dosProtection loginAttemptsProtection dosLimit loginAttemptsLimit } } } } }"}';
371 return self::sendRequest($payload, TRUE);
372 }
373
374 /**
375 * Method to get antivirus data.
376 *
377 * @param array $params
378 * Parameters for filtering data.
379 *
380 * @return array
381 * Returns antivirus data.
382 */
383 public static function getAntivirus(array $params) {
384
385 $cursor = ($params['cursor']) ? '"' . $params['cursor'] . '"' : 'null';
386 $event = ($params['event']) ? '"' . $params['event'] . '"' : '"new"';
387 $permissions = ($params['permissions']) ? ' "permissionsChanged":true, ' : '';
388 $period = WebTotem::getPeriod($params['days']);
389
390 $payload = '{"operationName":null,"variables":{"id":"' . $params['host_id'] . '","avLogFilter":{' . $permissions . '"event":' . $event . ', "dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '},"order":{"direction":"DESC","field":"time"},"pagination":{"first":' . $params['limit'] . ',"cursor":' . $cursor . '}}},"query":"query ($id: ID!, $avLogFilter: AvLogFilter!) { auth { viewer { sites { one(id: $id) { id ... on Site { configs { ... on AvConfig { isActive id } } } antivirus { quarantine{ id path date } status log(avLogFilter: $avLogFilter) { edges { node { filePath event signatures time permissions permissionsChanged } } pageInfo { endCursor hasNextPage __typename } } lastTest { time } stats { changed deleted scanned infected } } } } } } }"}';
391 $response = self::sendRequest($payload, TRUE);
392
393 if (isset($response['data']['auth']['viewer']['sites']['one']['antivirus'])) {
394 return $response['data']['auth']['viewer']['sites']['one']['antivirus'];
395 }
396 return [];
397 }
398
399 /**
400 * Method to get antivirus last test.
401 *
402 * @param string $host_id
403 * Host id on WebTotem.
404 *
405 * @return array
406 * Returns antivirus last test data.
407 */
408 public static function getAntivirusLastTest($host_id) {
409
410 $payload = '{"variables":{"id":"' . $host_id . '"},"query":"query ($id: ID!) { auth { viewer { sites { one(id: $id) { antivirus { status lastTest { time } } } } } } }"}';
411 $response = self::sendRequest($payload, TRUE);
412
413 if (isset($response['data']['auth']['viewer']['sites']['one']['antivirus'])) {
414 return $response['data']['auth']['viewer']['sites']['one']['antivirus'];
415 }
416 return [];
417 }
418
419 /**
420 * Method to force check services.
421 *
422 * @param string $host_id
423 * Host id on WebTotem.
424 * @param string $service
425 * Service that needs to be checked.
426 *
427 * @return array
428 * Returns information whether the request was successful.
429 */
430 public static function forceCheck($host_id, $service) {
431 $payload = '{"variables":{"id":"' . $host_id . '","service":"' . $service . '"},"query":"mutation ($id: ID!, $service: ForceCheckService!) { auth { sites { forceCheck(siteId: $id, service: $service) } } }"} ';
432 return self::sendRequest($payload, TRUE);
433 }
434
435 /**
436 * Method to export antivirus report.
437 *
438 * @param string $host_id
439 * Host id on WebTotem.
440 * @param int|array $days
441 * For what period data is needed.
442 *
443 * @return array
444 * Returns information whether the request was successful.
445 */
446 public static function avExport($host_id, $days = 30) {
447 $period = WebTotem::getPeriod($days);
448 $payload = '{"variables":{ "input":{"siteId":"' . $host_id . '", "dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '} }},"query":"mutation ($input: AvLogExportInput!) { auth { sites { av { export(input: $input) } } } }"} ';
449 return self::sendRequest($payload, TRUE);
450 }
451
452 /**
453 * Method to get quarantine data.
454 *
455 * @param string $host_id
456 * Host id on WebTotem.
457 *
458 * @return array
459 * Returns quarantine data.
460 */
461 public static function getQuarantineList($host_id) {
462 $payload = '{"query":"query{ auth{ viewer{ sites{ one(id:\"' . $host_id . '\"){ antivirus{ quarantine{ id path date } } } } } } } "}';
463 $response = self::sendRequest($payload, TRUE);
464
465 if (isset($response['data']['auth']['viewer']['sites']['one']['antivirus']['quarantine'])) {
466 return $response['data']['auth']['viewer']['sites']['one']['antivirus']['quarantine'];
467 }
468 return [];
469 }
470
471 /**
472 * Method to move file to quarantine.
473 *
474 * @param string $host_id
475 * Host id on WebTotem.
476 * @param string $path
477 * Path to the file.
478 *
479 * @return array
480 * Returns information whether the request was successful.
481 */
482 public static function moveToQuarantine($host_id, $path) {
483 $payload = '{"query":"mutation{ auth{ sites{ av{ moveToQuarantine(input:{ siteId:\"' . $host_id . '\", path:\"' . $path . '\" }) } } } } "}';
484 return self::sendRequest($payload, TRUE);
485 }
486
487 /**
488 * Method to move file from quarantine.
489 *
490 * @param string $id
491 * Id assigned to the file.
492 *
493 * @return array
494 * Returns information whether the request was successful.
495 */
496 public static function moveFromQuarantine($id) {
497 $payload = '{"query":"mutation{ auth{ sites{ av{ moveFromQuarantine(id: \"' . $id . '\") } } } } "}';
498 return self::sendRequest($payload, TRUE);
499 }
500
501 /**
502 * Method to get server status data.
503 *
504 * @param string $host_id
505 * Host id on WebTotem.
506 * @param int|array $days
507 * For what period data is needed.
508 *
509 * @return array
510 * Returns server status data.
511 */
512 public static function getServerStatusData($host_id, $days = 7) {
513 $period = WebTotem::getPeriod($days);
514 $payload = '{ "query":"query($id: ID!, $dateRange: DateRangeInput!) { auth { viewer { sites { one(id: $id) { serverStatus { ramChart(dateRange: $dateRange){ total value time } cpuChart(dateRange: $dateRange){ value time } } } } } } }", "variables":{"id":"' . $host_id . '","dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '} } }';
515
516 $response = self::sendRequest($payload, TRUE);
517
518 if (isset($response['data']['auth']['viewer']['sites']['one']['serverStatus'])) {
519 return $response['data']['auth']['viewer']['sites']['one']['serverStatus'];
520 }
521
522 return [];
523 }
524
525 /**
526 * Method to remove port from ignore list.
527 *
528 * @param string $host_id
529 * Host id on WebTotem.
530 * @param string $port
531 * User specified port.
532 *
533 * @return array
534 * Returns information whether the request was successful.
535 */
536 public static function removeIgnorePort($host_id, $port) {
537 $payload = '{"variables":{ "input": { "siteId": "' . $host_id . '", "port":' . $port . '} },"query":"mutation($input: IgnorePortInput!) { auth { sites { ps { removeIgnorePort(input: $input) } } } }"} ';
538 return self::sendRequest($payload, TRUE);
539 }
540
541 /**
542 * Method to add port to ignore list.
543 *
544 * @param string $host_id
545 * Host id on WebTotem.
546 * @param string $port
547 * User specified port.
548 *
549 * @return array
550 * Returns information whether the request was successful.
551 */
552 public static function addIgnorePort($host_id, $port) {
553 $payload = '{"variables":{ "input": { "siteId": "' . $host_id . '", "port":' . (int) $port . '} },"query":"mutation($input: IgnorePortInput!) { auth { sites { ps { addIgnorePort(input: $input) } } } }"} ';
554 return self::sendRequest($payload, TRUE);
555 }
556
557 /**
558 * Method to get all ports list.
559 *
560 * @param string $host_id
561 * Host id on WebTotem.
562 *
563 * @return array
564 * Returns ports data.
565 */
566 public static function getAllPortsList($host_id) {
567 $payload = '{"query":"query($id: ID!) { auth { viewer { sites { one(id: $id) { ports { status ip tcp ignorePorts lastTest { time } } } } } } } ","variables":{"id":"' . $host_id . '"}}';
568
569 $response = self::sendRequest($payload, TRUE);
570
571 if (isset($response['data']['auth']['viewer']['sites']['one']['ports'])) {
572 return $response['data']['auth']['viewer']['sites']['one']['ports'];
573 }
574
575 return [];
576 }
577
578 /**
579 * Method to get all reports.
580 *
581 * @param string $host_id
582 * Host id on WebTotem.
583 * @param int $limit
584 * Limit on the number of records.
585 * @param string $cursor
586 * Mark for loading data.
587 *
588 * @return array
589 * Returns reports data.
590 */
591 public static function getAllReports($host_id, $limit = 10, $cursor = NULL) {
592 $cursor = ($cursor == NULL) ? 'null' : '"' . $cursor . '"';
593 $payload = '{"variables":{"filter": { "order": { "direction": "DESC", "field": "created_at"}, "siteId":"' . $host_id . '", "pagination":{"first":' . $limit . ', "cursor":' . $cursor . '} } },"query":"query ReportsQuery($filter: ReportListFilter!) { auth { viewer { reports { list(filter: $filter) { edges { node { id site { hostname } createdAt wa dc ps rc sc av waf } cursor } pageInfo { endCursor hasNextPage } } } } } }"}';
594 $response = self::sendRequest($payload, TRUE);
595
596 if (isset($response['data']['auth']['viewer']['reports']['list']['edges'])) {
597 return $response['data']['auth']['viewer']['reports']['list'];
598 }
599
600 return [];
601 }
602
603 /**
604 * Method to generate report.
605 *
606 * @param string $host_id
607 * Host id on WebTotem.
608 * @param int|array $days
609 * For what period data is needed.
610 * @param array $services
611 * User-specified module settings.
612 *
613 * @return string|bool
614 * Returns report download link.
615 */
616 public static function generateReport($host_id, $days, array $services) {
617 $period = WebTotem::getPeriod($days);
618 $language = WebTotem::getLanguage();
619
620 $payload = '{"query":"query ($input: GenerateReportInput) { auth { viewer { reports { generate(input: $input) } } } }", "variables":{ "input": { "siteId": "' . $host_id . '", "from": ' . $period['from'] . ', "to": ' . $period['to'] . ', "wa": ' . $services['wa'] . ', "dc": ' . $services['dc'] . ', "ps": ' . $services['ps'] . ', "rc": ' . $services['rc'] . ', "sc": ' . $services['sc'] . ', "av": ' . $services['av'] . ', "waf": ' . $services['waf'] . ', "language": "' . $language . '" } } }';
621 $response = self::sendRequest($payload, TRUE);
622
623 if (isset($response['data']['auth']['viewer']['reports']['generate'])) {
624 return $response['data']['auth']['viewer']['reports']['generate'];
625 }
626
627 return FALSE;
628 }
629
630 /**
631 * Method to download report.
632 *
633 * @param string $id
634 * Assigned to the report.
635 *
636 * @return string|bool
637 * Returns report download link.
638 */
639 public static function downloadReport($id) {
640 $payload = '{"query": "query { auth { viewer { reports { download(id: \"' . $id . '\") } } } }"}';
641 $response = self::sendRequest($payload, TRUE);
642
643 if (isset($response['data']['auth']['viewer']['reports']['download'])) {
644 return $response['data']['auth']['viewer']['reports']['download'];
645 }
646
647 return FALSE;
648 }
649
650 /**
651 * Method to get configs data.
652 *
653 * @param string $host_id
654 * Host id on WebTotem.
655 *
656 * @return array|bool
657 * Returns configs data.
658 */
659 public static function getConfigs($host_id) {
660 $payload = '{"query":"query{ auth{ viewer{ sites{ one(id:\"' . $host_id . '\"){ configs{ ... on WaConfig { id service isActive notifications } ... on WafConfig { id service isActive notifications } ... on AvConfig { id service isActive notifications } ... on DcConfig { id service isActive notifications } ... on DecConfig { id service isActive } ... on RcConfig { id service isActive notifications} ... on CmsConfig { id service isActive } ... on PsConfig { id service isActive notifications } ... on SsConfig { id service isActive } ... on ScConfig { id service isActive } } } } } } } "}';
661 $response = self::sendRequest($payload, TRUE);
662
663 if (isset($response['data']['auth']['viewer']['sites']['one']['configs'])) {
664 return $response['data']['auth']['viewer']['sites']['one']['configs'];
665 }
666
667 return FALSE;
668 }
669
670 /**
671 * Method to toggle modules config.
672 *
673 * @param string $service_id
674 * Service id that we enable or disable.
675 *
676 * @return string|bool
677 * Returns information whether the request was successful.
678 */
679 public static function toggleConfigs($service_id) {
680 $payload = '{"query":"mutation{ auth{ configs{ toggle(id: \"' . $service_id . '\"){ ... on WaConfig { service isActive } ... on AvConfig { service isActive } ... on DcConfig { service isActive } ... on DecConfig { service isActive } ... on RcConfig { service isActive } ... on CmsConfig { service isActive } ... on PsConfig { service isActive } ... on WafConfig { service isActive } } } } } "}';
681 $response = self::sendRequest($payload, TRUE);
682
683 if (isset($response['data']['auth']['configs']['toggle'])) {
684 return $response['data']['auth']['configs']['toggle'];
685 }
686
687 return FALSE;
688 }
689
690 /**
691 * Method to toggle modules notification.
692 *
693 * @param string $host_id
694 * Host id on WebTotem.
695 * @param string $service
696 * Service id in which we enable or disable notifications.
697 *
698 * @return string|bool
699 * Returns information whether the request was successful.
700 */
701 public static function toggleNotifications($host_id, $service) {
702 $payload = '{"query":"mutation{ auth{ sites{ toggleNotifications(siteId: \"' . $host_id . '\", service: ' . $service . ') } } }"}';
703 $response = self::sendRequest($payload, TRUE);
704
705 if (isset($response['data']['auth']['sites']['toggleNotifications'])) {
706 return $response;//['data']['auth']['sites']['toggleNotifications'];
707 }
708
709 return FALSE;
710 }
711
712 /**
713 * Method to get allow/deny ip list.
714 *
715 * @param string $host_id
716 * Host id on WebTotem.
717 *
718 * @return array|bool
719 * Returns ip allow/deny lists.
720 */
721 public static function getIpLists($host_id) {
722 $payload = '{"variables":{ "id": "' . $host_id . '" },"query":"query($id: ID!) { auth { viewer { sites{ one(id: $id){ firewall{ blackList{ id ip createdAt } whiteList{ id ip createdAt } settings{ gdn dosProtection dosLimit loginAttemptsProtection loginAttemptsLimit } } } } } } }"} ';
723 $response = self::sendRequest($payload, TRUE);
724
725 if (isset($response['data']['auth']['viewer']['sites']['one']['firewall'])) {
726 return $response['data']['auth']['viewer']['sites']['one']['firewall'];
727 }
728
729 return [];
730 }
731
732 /**
733 * Method to add ip to allow/deny list.
734 *
735 * @param string $host_id
736 * Host id on WebTotem.
737 * @param string $ips
738 * Ip address list.
739 * @param string $list
740 * Allow or deny list.
741 *
742 * @return bool
743 * Returns information whether the request was successful.
744 */
745 public static function addIpToList($host_id, $ips, $list) {
746
747 if ($ips) {
748 $ips = WebTotem::convertIpListForApi($ips);
749 $payload = '{"variables":{ "input": { "siteId": "' . $host_id . '", "ips": ' . $ips . ', "color": "' . $list . '" } }, "query":"mutation($input: WafListInput!) { auth { sites { waf { addToList(input: $input){ status invalidIPs} } } } }"} ';
750 $response = self::sendRequest($payload, TRUE);
751
752 if (isset($response['data']['auth']['sites']['waf']['addToList'])) {
753 return $response['data']['auth']['sites']['waf']['addToList'];
754 }
755 }
756
757 return FALSE;
758 }
759
760 /**
761 * Method to remove ip from allow/deny list by id.
762 *
763 * @param string $id
764 * Id assignment to ip address.
765 *
766 * @return bool
767 * Returns information whether the request was successful.
768 */
769 public static function removeIpFromList($id) {
770 $payload = '{"variables":{ "id": "' . $id . '" },"query":"mutation($id: ID!) { auth { sites { waf { removeFromList(id: $id) } } } }"} ';
771 $response = self::sendRequest($payload, TRUE);
772
773 if (isset($response['data']['auth']['sites']['waf']['removeFromList'])) {
774 return $response['data']['auth']['sites']['waf']['removeFromList'];
775 }
776
777 return FALSE;
778 }
779
780 /**
781 * Method to get allow url list.
782 *
783 * @param string $host_id
784 * Host id on WebTotem.
785 *
786 * @return array
787 * Returns url allow lists.
788 */
789 public static function getAllowUrlList($host_id) {
790 $payload = '{"query":"query { auth { viewer { sites { one(id: \"' . $host_id . '\"){ firewall{ urlWhiteList{ id url createdAt } } } } } } }"} ';
791 $response = self::sendRequest($payload, TRUE);
792
793 if (isset($response['data']['auth']['viewer']['sites']['one']['firewall']['urlWhiteList'])) {
794 return $response['data']['auth']['viewer']['sites']['one']['firewall']['urlWhiteList'];
795 }
796
797 return [];
798 }
799
800 /**
801 * Method to add url to allow list.
802 *
803 * @param string $host_id
804 * Host id on WebTotem.
805 * @param string $url
806 * User-specified url.
807 *
808 * @return bool|string
809 * Returns information whether the request was successful.
810 */
811 public static function addUrlToAllowList($host_id, $url) {
812 $payload = '{"variables":{ "input": { "siteId": "' . $host_id . '", "url": "' . $url . '" } }, "query":"mutation($input: WafUrlWhiteListInput!) { auth { sites { waf { addToUrlWhiteList(input: $input) } } } }"} ';
813 $response = self::sendRequest($payload, TRUE);
814
815 if (isset($response['data']['auth']['sites']['waf']['addToUrlWhiteList'])) {
816 return $response['data']['auth']['sites']['waf']['addToUrlWhiteList'];
817 }
818
819 return FALSE;
820 }
821
822 /**
823 * Method to remove url from allow list.
824 *
825 * @param string $id
826 * Id assignment to url address.
827 *
828 * @return bool|string
829 * Returns information whether the request was successful.
830 */
831 public static function removeUrlFromAllowList($id) {
832 $payload = '{"variables":{ "id": "' . $id . '" }, "query":"mutation($id: ID!) { auth { sites { waf { removeFromUrlWhiteList(id: $id) } } } }"} ';
833 $response = self::sendRequest($payload, TRUE);
834
835 if (isset($response['data']['auth']['sites']['waf']['removeFromUrlWhiteList'])) {
836 return $response['data']['auth']['sites']['waf']['removeFromUrlWhiteList'];
837 }
838
839 return FALSE;
840 }
841
842 /**
843 * Method to get user's email.
844 *
845 * @return string
846 * Returns user's email.
847 */
848 public static function getEmail(){
849 $payload = '{"query":"query { auth { viewer { email __typename } __typename } }"}';
850 $response = self::sendRequest($payload, true);
851
852 return $response['data']['auth']['viewer']['email'];
853 }
854
855 /**
856 * Function sends GraphQL request to API server.
857 *
858 * @param string $payload
859 * Payload to be sent to API server.
860 * @param bool $token
861 * Whether a token is needed when sending a request.
862 * @param bool $repeat
863 * Required to avoid recursion.
864 *
865 * @return array
866 * Returns response from WebTotem API.
867 */
868 protected static function sendRequest($payload, $token = FALSE, $repeat = FALSE) {
869
870 $api_key = WebTotemOption::getOption('api_key');
871
872 // Checking whether a token is needed.
873 if ($token) {
874 $auth_token = WebTotemOption::getOption('auth_token');
875 $auth_token_expired = WebTotemOption::getOption('auth_token_expired');
876
877 // Checking whether the token has expired.
878 if ($auth_token_expired <= time() && !$repeat) {
879 $result = self::auth($api_key);
880 if ($result === 'success') {
881 return self::sendRequest($payload, $token, TRUE);
882 }
883 else {
884 if(isset($result['errors'])){
885 $message = WebTotem::messageForHuman($result['errors'][0]['message']);
886 WebTotemOption::setNotification('error', $message);
887 }
888 }
889 }
890 }
891
892 if (function_exists('wp_remote_post')) {
893
894 $args = [
895 'body' => $payload,
896 'timeout' => '60',
897 'sslverify' => false,
898 'headers' => [
899 'Content-Type:application/json',
900 'Content-Type' => 'application/json',
901 'Accept: application/json',
902 'source: WORDPRESS',
903 ],
904 ];
905
906 if (isset($auth_token)) {
907 $auth = "Bearer " . $auth_token;
908 $args['headers'] = array_merge($args['headers'], ["Authorization" => $auth]);
909 }
910
911 $response = wp_remote_post(WEBTOTEM_API_URL, $args);
912 $response = wp_remote_retrieve_body($response);
913 $response = json_decode($response, true);
914
915 }
916 else {
917 $error = 'WP_REMOTE_POST_NOT_EXIST';
918 }
919
920 // Checking if there are errors in the response.
921 if (isset($response['errors'][0]['message'])) {
922 $message = WebTotem::messageForHuman($response['errors'][0]['message']);
923 if (stripos($response['errors'][0]['message'], "INVALID_TOKEN") !== FALSE && !$repeat) {
924 $response = self::auth($api_key);
925 if ($response === 'success') {
926 return self::sendRequest($payload, $token, TRUE);
927 }
928 }
929 elseif(stripos($response['errors'][0]['message'], "USERHOST_NOT_BELONG_TO_USER") !== FALSE){
930 if(WebTotem::isMultiSite()){
931 WebTotemOption::clearAllHosts();
932 WebTotemOption::clearOptions([ 'host_id', 'host_name' ]);
933 } else {
934 WebTotemOption::clearOptions([ 'host_id', 'host_name' ]);
935 }
936 }
937 else {
938 WebTotemOption::setNotification('error', $message); // for debug json_encode($payload).' '.
939 }
940 }
941
942 if (!empty($error)) {
943 WebTotemOption::setNotification('error', $error);
944 }
945
946 return $response;
947 }
948
949 }
950