siteBuilder.php 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205
  1. <?php
  2. /**
  3. * WHMCS siteBuilder Provisioning Module
  4. *
  5. * Provisioning User Accounts & manage Websites on the siteBuilder Server
  6. *
  7. * @see https://centos-webpanel.com/
  8. * @copyright Copyright (c) Thurdata GmbH 2022
  9. * @license GPL
  10. */
  11. use WHMCS\Database\Capsule;
  12. require_once 'Net/DNS2.php';
  13. require_once(__DIR__ . '/api/sitebuilder.php');
  14. require_once(__DIR__ . '/api/SiteProApiClient.php');
  15. if (!defined('WHMCS')) {
  16. die('This file cannot be accessed directly');
  17. }
  18. /**
  19. * Define siteBuilder product metadata parameters.
  20. *
  21. * @see https://developers.whmcs.com/provisioning-modules/meta-data-params/
  22. *
  23. * @return array
  24. */
  25. function siteBuilder_MetaData() {
  26. return array(
  27. 'DisplayName' => 'ThurData SiteBuilder Provisioning',
  28. 'DefaultSSLPort' => '2443',
  29. 'RequiresServer' => true
  30. );
  31. }
  32. /**
  33. * Create tables if neccessary
  34. * Define siteBuilder product configuration options.
  35. *
  36. * @see https://developers.whmcs.com/provisioning-modules/config-options/
  37. *
  38. * @return array
  39. */
  40. function siteBuilder_ConfigOptions() {
  41. // check for tables and create if neccessary
  42. siteBuilderCreateTables();
  43. // return ConfigOptions
  44. return ["BuilderURL" => [
  45. "FriendlyName" => "Builder URL", # Full Builder URL (prefix//hostname:port/)
  46. "Type" => "text", # Text Box
  47. "Size" => "25", # Defines the Field Width
  48. "Description" => "Full Builder URL (prefix//hostname:port/)",
  49. "Default" => "https://builder.thurdata.ch/",
  50. ], [
  51. "FriendlyName" => "Hosting Plan ID",
  52. "Type" => "text", # Text Box
  53. "Size" => "25", # Defines the Field Width
  54. "Description" => "Set the hostingPlan ID for this Product",
  55. "Default" => "Free",
  56. ], [
  57. "FriendlyName" => "Quota in MB",
  58. "Type" => "text", # Text Box
  59. "Size" => "25", # Defines the Field Width
  60. "Description" => "Set the Quoat matching Your HostingPlan (MB)",
  61. "Default" => "512",
  62. ]
  63. ];
  64. }
  65. /**
  66. * Test connection to a siteBuilder server with the given server parameters.
  67. *
  68. * Allows an admin user to verify that an API connection can be
  69. * successfully made with the given configuration parameters for a
  70. * server.
  71. *
  72. * When defined in a module, a test connection button will appear
  73. * alongside the server type dropdown when adding or editing an
  74. * existing server.
  75. *
  76. * @param array $params common module parameters
  77. *
  78. * @see https://developers.whmcs.com/provisioning-modules/module-parameters/
  79. *
  80. * @return array
  81. */
  82. function siteBuilder_Testconnection($params) {
  83. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  84. // ping remota API
  85. $response = $siteBuilder->ping($params['serverusername'], $params['serverpassword']);
  86. if($response['response']['answer'] == 'pong') {
  87. return array(
  88. 'success' => true,
  89. 'error' => '',
  90. );
  91. }
  92. return array(
  93. 'success' => false,
  94. 'error' => $response,
  95. );
  96. }
  97. /**
  98. * Provision a new siteBuilder account
  99. *
  100. * Attempt to provision a new siteBuilder account. This is
  101. * called any time provisioning is requested inside of WHMCS. Depending upon the
  102. * configuration, this can be any of:
  103. * * When a new order is placed
  104. * * When an invoice for a new order is paid
  105. * * Upon manual request by an admin user
  106. *
  107. * @param array $params common module parameters
  108. *
  109. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  110. *
  111. * @return string 'success' or an error message
  112. */
  113. function siteBuilder_CreateAccount($params) {
  114. $username = strtolower(substr($params['clientsdetails']['firstname'],0,2) . substr($params['clientsdetails']['lastname'],0,3)) . $params['serviceid'];
  115. $userdomain = $params['domain'];
  116. // set DNS
  117. /* disabled on dev, has to be already set in test env
  118. $response = siteBuildersetDNS($params, $userdomain);
  119. if($response != 'success') {
  120. return $response;
  121. }
  122. */
  123. // update service
  124. try {
  125. Capsule::table('tblhosting')
  126. ->where('id', '=', $params['serviceid'])
  127. ->update(
  128. array(
  129. 'username' => $username,
  130. 'domain' => $userdomain,
  131. )
  132. );
  133. } catch (\Exception $e) {
  134. logModuleCall(
  135. 'siteBuilder',
  136. __FUNCTION__,
  137. $params,
  138. 'Error: could save username & domain in database',
  139. $e->getMessage()
  140. );
  141. return 'Error: could save username & password in database';
  142. }
  143. // add account to database
  144. try {
  145. Capsule::table('sitePro_acc')
  146. ->insert(
  147. array(
  148. 'account' => $username,
  149. 'pid' => $params['serviceid'],
  150. 'enabled' => true,
  151. )
  152. );
  153. } catch (\Exception $e) {
  154. logModuleCall(
  155. 'siteBuilder',
  156. __FUNCTION__,
  157. $params,
  158. 'Error: could save username & serviceid in database',
  159. $e->getMessage()
  160. );
  161. return 'Error: could save username & serviceid in database';
  162. }
  163. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  164. // create siteBuilder account
  165. $response = $siteBuilder->create($username, $params['domain'], $params['serverusername'], $params['serverpassword']);
  166. if($response['status'] != '200') {
  167. return 'Error: ' . $response['response']['error'];
  168. }
  169. // set quota for new account
  170. $response = $siteBuilder->setQuota($username, $params['configoption3'], $params['serverusername'], $params['serverpassword']);
  171. if($response['status'] != '200') {
  172. return 'Error: ' . $response['response']['error'];
  173. }
  174. /* enable this block to get a default domain website without hostname (otherwise the customer is able to do that)
  175. // create default domain site
  176. $response = $siteBuilder->init($username, $params['domain'], $params['serverusername'], $params['serverpassword']);
  177. if($response['status'] != '200') {
  178. return 'Error: ' . $response['response']['error'];
  179. }
  180. // add default site to database
  181. try {
  182. Capsule::table('sitePro_site')
  183. ->insert(
  184. array(
  185. 'relid' => $params['serviceid'],
  186. 'name' => $params['domain'],
  187. 'enabled' => true,
  188. )
  189. );
  190. } catch (\Exception $e) {
  191. logModuleCall(
  192. 'siteBuilder',
  193. __FUNCTION__,
  194. $params,
  195. 'Error: could save site & serviceid in database',
  196. $e->getMessage()
  197. );
  198. return 'Error: could save site & serviceid in database';
  199. }
  200. */
  201. return 'success';
  202. }
  203. /**
  204. * Removes a siteBuilder account and undeploy all related sites
  205. *
  206. * Called when a termination is requested. This can be invoked automatically for
  207. * overdue products if enabled, or requested manually by an admin user.
  208. *
  209. * @param array $params common module parameters
  210. *
  211. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  212. *
  213. * @return string 'success' or an error message
  214. */
  215. function siteBuilder_TerminateAccount($params) {
  216. // check if account is suspended
  217. try {
  218. $active = Capsule::table('sitePro_acc')
  219. ->where('account',$params['username'])
  220. ->value('enabled');
  221. } catch (\Exception $e) {
  222. logModuleCall(
  223. 'siteBuilder',
  224. __FUNCTION__,
  225. $params,
  226. 'Error: could fetch account from database',
  227. $e->getMessage()
  228. );
  229. return 'Error: could fetch account from database';
  230. }
  231. if($active == true) {
  232. return 'Error: Account is active, please suspend account first';
  233. }
  234. // undeploy all related sites
  235. $sites = getSites($params['serviceid']);
  236. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  237. if(!empty($sites)) {
  238. foreach($sites as $site) {
  239. $response = $siteBuilder->undeploy($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  240. if($response['status'] != '200') {
  241. return 'Error: ' . $response['response'];
  242. }
  243. // remove sitebuilder session
  244. $response = siteBuilderRemoveSession($params,$site);
  245. if($response != 'success') {
  246. return 'Error: ' . $response;
  247. }
  248. }
  249. }
  250. // cleanup database
  251. try {
  252. Capsule::table('sitePro_site')
  253. ->where('relid',$params['serviceid'])
  254. ->delete();
  255. } catch (\Exception $e) {
  256. logModuleCall(
  257. 'siteBuilder',
  258. __FUNCTION__,
  259. $params,
  260. 'Error: could remove site from database',
  261. $e->getMessage()
  262. );
  263. return 'Error: could remove site from database';
  264. }
  265. // terminate account
  266. $response = $siteBuilder->terminate($params['username'], $params['domain']);
  267. if($response['status'] != '200') {
  268. return 'Error: ' . $response['response']['error'];
  269. }
  270. try {
  271. Capsule::table('sitePro_acc')
  272. ->where('account',$params['username'])
  273. ->delete();
  274. } catch (\Exception $e) {
  275. logModuleCall(
  276. 'siteBuilder',
  277. __FUNCTION__,
  278. $params,
  279. 'Error: could remove account from database',
  280. $e->getMessage()
  281. );
  282. return 'Error: could remove account from database';
  283. }
  284. return 'success';
  285. }
  286. /**
  287. * Set a siteBuilder account to status inactive.
  288. *
  289. * Called when a suspension is requested. This is invoked automatically by WHMCS
  290. * when a product becomes overdue on payment or can be called manually by admin
  291. * user.
  292. *
  293. * @param array $params common module parameters
  294. *
  295. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  296. *
  297. * @return string 'success' or an error message
  298. */
  299. function siteBuilder_SuspendAccount($params) {
  300. // set account to disabled in database
  301. try {
  302. Capsule::table('sitePro_acc')
  303. ->where('account',$params['username'])
  304. ->update(array(
  305. 'enabled' => false,
  306. ));
  307. } catch (\Exception $e) {
  308. logModuleCall(
  309. 'siteBuilder',
  310. __FUNCTION__,
  311. $params,
  312. 'Error: could not disable account in database',
  313. $e->getMessage()
  314. );
  315. return 'Error: could not disable account in database';
  316. }
  317. // disable all sites but not change status in DB for unsuspend restoring
  318. $sites = getSites($params['serviceid']);
  319. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  320. if(!empty($sites)) {
  321. foreach($sites as $site) {
  322. $response = $siteBuilder->disable($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  323. if($response['status'] != '200') {
  324. return 'Error: ' . $response['response']['error'];
  325. }
  326. }
  327. }
  328. return 'success';
  329. }
  330. /**
  331. * Set a siteBuilder account to status active and enable active sites
  332. *
  333. * Called when an un-suspension is requested. This is invoked
  334. * automatically upon payment of an overdue invoice for a product, or
  335. * can be called manually by admin user.
  336. *
  337. * @param array $params common module parameters
  338. *
  339. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  340. *
  341. * @return string 'success' or an error message
  342. */
  343. function siteBuilder_UnsuspendAccount($params) {
  344. // set account to enabled in database
  345. try {
  346. Capsule::table('sitePro_acc')
  347. ->where('account',$params['username'])
  348. ->update(array(
  349. 'enabled' => true,
  350. ));
  351. } catch (\Exception $e) {
  352. logModuleCall(
  353. 'siteBuilder',
  354. __FUNCTION__,
  355. $params,
  356. 'Error: could update account in database',
  357. $e->getMessage()
  358. );
  359. return 'Error: could update account in database';
  360. }
  361. // enable active sites
  362. $sites = getSitesEnabled($params['serviceid']);
  363. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  364. if(!empty($sites)) {
  365. foreach($sites as $site) {
  366. $response = $siteBuilder->enable($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  367. if($response['status'] != '200') {
  368. return 'Error: ' . $response['response']['error'];
  369. }
  370. }
  371. }
  372. return 'success';
  373. }
  374. /**
  375. * Client area output logic handling.
  376. *
  377. * This function is used to define module specific client area output. It should
  378. * return an array consisting of a template file and optional additional
  379. * template variables to make available to that template.
  380. *
  381. * @param array $params common module parameters
  382. *
  383. * @see https://developers.whmcs.com/provisioning-modules/client-area-output/
  384. *
  385. * @return array
  386. */
  387. function siteBuilder_ClientArea($params) {
  388. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  389. $clientInfo = array('moduleclientarea' => '1');
  390. $clientInfo['domain'] = $params['domain'];
  391. // Client status
  392. $accEnabled = Capsule::table('sitePro_acc')
  393. ->where('pid', $params['serviceid'])
  394. ->value('enabled');
  395. $clientInfo['account'] = ['enabled' => $accEnabled];
  396. $clientInfo['sites'] = [];
  397. // Client sites
  398. $sites = getSites($params['serviceid']);
  399. foreach($sites as $site){
  400. $response = $siteBuilder->getSSLDays($params['username'], $site);
  401. if($response['status'] == '200') {
  402. $sslSite = $response['response']['ssl_remaining'];
  403. }
  404. $response = $siteBuilder->isenabled($params['username'], $site);
  405. if($response['status'] == '200') {
  406. $enabled = $response['response']['isenabled'];
  407. }
  408. array_push($clientInfo['sites'],['name' => $site, 'sslSite' => $sslSite, 'enabled' => $enabled]);
  409. }
  410. // Client Quota
  411. $response = $siteBuilder->getQuota($params['username']);
  412. if($response['status'] != '200') {
  413. logModuleCall(
  414. 'siteBuilder',
  415. __FUNCTION__,
  416. $params,
  417. 'Error getting Quota',
  418. $response
  419. );
  420. }
  421. $clientInfo['quota'] = round($response['response']['quota'][0]['blocks']/1024);
  422. $clientInfo['limit'] = round($response['response']['quota'][0]['hard']/1024);
  423. // return template vars
  424. return array(
  425. 'tabOverviewReplacementTemplate' => 'clientarea',
  426. 'vars' => $clientInfo,
  427. );
  428. }
  429. /**
  430. * Upgrade or downgrade a siteBuilder account by package.
  431. *
  432. * Called to apply any change in product assignment or parameters. It
  433. * is called to provision upgrade or downgrade orders, as well as being
  434. * able to be invoked manually by an admin user.
  435. *
  436. * This same function is called for upgrades and downgrades of both
  437. * products and configurable options.
  438. *
  439. * @param array $params common module parameters
  440. *
  441. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  442. *
  443. * @return string "success" or an error message
  444. */
  445. function siteBuilder_ChangePackage($params) {
  446. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  447. // configoption3 contains quota in MB
  448. $response = $siteBuilder->setQuota($params['username'], $params['configoption3'], $params['serverusername'], $params['serverpassword']);
  449. if($response['status'] != '200') {
  450. return 'Error: ' . $response['response']['error'];
  451. }
  452. return 'success';
  453. }
  454. /**
  455. * Usage Update
  456. *
  457. * Important: Runs daily per server not per product
  458. * Run Manually: /admin/reports.php?report=disk_usage_summary&action=updatestats
  459. * @param array $params common module parameters
  460. *
  461. * @see https://developers.whmcs.com/provisioning-modules/usage-update/
  462. */
  463. function siteBuilder_UsageUpdate($params) {
  464. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  465. $response = $siteBuilder->getStats();
  466. if($response['status'] != '200') {
  467. logActivity('ERROR: Unable to update sitebuilder server usage: ' . implode('#',[$response]));
  468. }
  469. $stats = $response['response']['quota'];
  470. foreach($stats as $stat){
  471. try {
  472. Capsule::table('tblhosting')
  473. ->where('server', $params['serverid'])
  474. ->where('username', $stat['user'])
  475. ->update([
  476. 'diskusage' => $stat['used']/1024,
  477. 'disklimit' => $stat['hard']/1024,
  478. 'lastupdate' => Capsule::raw('now()'),
  479. ]);
  480. } catch (\Exception $e) {
  481. logActivity('ERROR: Unable to update sitebuilder server usage: ' . $e->getMessage());
  482. }
  483. logModuleCall(
  484. 'siteBuilder',
  485. __FUNCTION__,
  486. $stat,
  487. 'debug',
  488. $params
  489. );
  490. }
  491. }
  492. /**
  493. * Additional actions a client user can invoke.
  494. *
  495. * Define additional actions a client user can perform for an instance of a
  496. * product/service.
  497. *
  498. * Any actions you define here will be automatically displayed in the available
  499. * list of actions within the client area.
  500. *
  501. * @return array
  502. */
  503. function siteBuilder_ClientAreaCustomButtonArray ($params) {
  504. return array(
  505. 'Neue Webseite' => 'newSite',
  506. );
  507. }
  508. /**
  509. * Additional actions a client user can invoke.
  510. *
  511. * Define additional actions a client user is allowed to perform for an instance of a
  512. * product/service.
  513. *
  514. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  515. *
  516. * @return array
  517. */
  518. function siteBuilder_ClientAreaAllowedFunctions() {
  519. return array(
  520. 'Add Site' => 'addSite',
  521. 'New Site' => 'newSite',
  522. 'Confirm Delete Site' => 'delSiteConfirm',
  523. 'Delete Site' => 'delSite',
  524. 'Edit Site' => 'editSite',
  525. 'Conform Revert Site' => 'revSiteConfirm',
  526. 'Revert Site' => 'revSite',
  527. 'Disable Site' => 'disableSite',
  528. 'Enable Site' => 'enableSite'
  529. );
  530. }
  531. /**
  532. * Opens a form to add a new domain.
  533. *
  534. * @param array $params common module parameters
  535. *
  536. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  537. *
  538. * @return array template information
  539. */
  540. function siteBuilder_newSite($params) {
  541. return array(
  542. 'breadcrumb' => array(
  543. 'clientarea.php?action=productdetails&id=' . $params['serviceid'] . '&modop=custom&a=newSite' => 'Neue Webseite',
  544. ),
  545. 'templatefile' => 'siteBuilder_new_site',
  546. );
  547. }
  548. /**
  549. * Adds a new domain to a siteBuilder account.
  550. *
  551. * @param array $params common module parameters
  552. *
  553. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  554. *
  555. * @return string "success" or an error message
  556. */
  557. function siteBuilder_addSite($params) {
  558. if(empty($_POST['d'])) {
  559. $site = $params['domain'];
  560. } else {
  561. if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  562. return 'Error: invalid site name';
  563. }
  564. $site = $_POST['d'] . '.' . $params['domain'];
  565. }
  566. // check OSI-8
  567. if(in_array($site,getSites($params['serviceid']))) {
  568. return 'Error: OSI-8 (Seite existiert bereits)';
  569. }
  570. // set DNS
  571. /* disabled on dev, has to be already set in test env
  572. $response = siteBuildersetDNS($params, $site);
  573. if($response != 'success') {
  574. return $response;
  575. }
  576. */
  577. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  578. // set up webconfig
  579. $response = $siteBuilder->init($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  580. if($response['status'] != '200') {
  581. return 'Error: ' . $response['response']['error'];
  582. }
  583. // update DB
  584. try {
  585. Capsule::table('sitePro_site')
  586. ->insert(
  587. array(
  588. 'relid' => $params['serviceid'],
  589. 'name' => $site,
  590. 'enabled' => true,
  591. )
  592. );
  593. } catch (\Exception $e) {
  594. logModuleCall(
  595. 'siteBuilder',
  596. __FUNCTION__,
  597. $params,
  598. 'Error: could save site & serviceid in database',
  599. $e->getMessage()
  600. );
  601. return 'Error: could save site & serviceid in database';
  602. }
  603. return 'success';
  604. }
  605. /**
  606. * Creates a sitePro editor session and redirect on success
  607. *
  608. * @param array $params common module parameters
  609. *
  610. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  611. *
  612. * @return string "success" or an error message
  613. */
  614. function siteBuilder_editSite($params) {
  615. if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  616. return 'Error: invalid site name';
  617. }
  618. $site = $_POST['s'];
  619. $api = new SiteProApiClient('https://builder.thurdata.ch/api/', 'apikey0', '993yVHwC05TLsx2JI2XFlAhkkPUxR6JbQUYbI.a5HiRtmNV9');
  620. // use this for enterprise licenses and change 'your-bulder-domain.com' to your builder domain
  621. //$api = new SiteProApiClient('http://your-bulder-domain.com/api/', 'your_api_username', 'your_api_password');
  622. try {
  623. // this call is used to open builder, so you need to set correct parameters to represent users website you want to open
  624. // this data usually comes from your user/hosting manager system
  625. $res = $api->remoteCall('requestLogin', array(
  626. 'type' => 'internal', // (required) 'internal'
  627. 'domain' => $site, // (required) domain of the user website you want to edit
  628. 'lang' => 'de', // (optional) 2-letter language code, set language code you whant builder to open in
  629. 'apiUrl' => getSiteBuilderApiURL($params) . 'deploy/' . $params['username'] . '/' . $site, // (required) API endpoint URL
  630. 'resellerClientAccountId' => $params['serviceid'], // (required) ID of website/user in your system
  631. 'username' => $params['serverusername'], // (optional) authorization username to be used with API endpoint
  632. 'password' => 'your-secure-password', // (optional) authorization password to be used with API endpoint
  633. 'hostingPlan' => $params['configoption2'],
  634. ));
  635. if (!$res || !is_object($res)) {
  636. logModuleCall(
  637. 'siteBuilder',
  638. __FUNCTION__,
  639. $params,
  640. 'Error: Response format error',
  641. $res
  642. );
  643. return 'Error: Response format error';
  644. } else if (isset($res->url) && $res->url) {
  645. logModuleCall(
  646. 'siteBuilder',
  647. __FUNCTION__,
  648. $params,
  649. 'Debug',
  650. $res
  651. );
  652. // on success redirect to builder URL
  653. header('Location: '.$res->url, true);
  654. exit();
  655. } else {
  656. logModuleCall(
  657. 'siteBuilder',
  658. __FUNCTION__,
  659. $params,
  660. 'Error: Unknown error',
  661. $res
  662. );
  663. return 'Error: Unknown error';
  664. }
  665. } catch (\Exception $e) {
  666. logModuleCall(
  667. 'siteBuilder',
  668. __FUNCTION__,
  669. $params,
  670. 'Error: Request error',
  671. $e->getMessage()
  672. );
  673. return 'Error: Request error';
  674. }
  675. return 'success';
  676. }
  677. /**
  678. * Opens a form to delete a domain from a siteBuilder account.
  679. *
  680. * @param array $params common module parameters
  681. *
  682. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  683. *
  684. * @return array template information
  685. */
  686. function siteBuilder_delSiteConfirm() {
  687. return array(
  688. 'templatefile' => 'siteBuilder_del_site_confirm',
  689. 'vars' => array(
  690. 'delsite' => $_POST['s'],
  691. ),
  692. );
  693. }
  694. /**
  695. * Removes a site from a siteBuilder account.
  696. *
  697. * @param array $params common module parameters
  698. *
  699. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  700. *
  701. * @return string "success" or an error message
  702. */
  703. function siteBuilder_delSite($params) {
  704. if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  705. return 'Error: invalid domain name';
  706. }
  707. $site = $_POST['s'];
  708. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  709. // undeploy
  710. $response = $siteBuilder->undeploy($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  711. if($response['status'] != '200') {
  712. return 'Error: ' . $response['response']['error'];
  713. }
  714. // update DB
  715. try {
  716. Capsule::table('sitePro_site')
  717. ->where('name', $site)
  718. ->delete();
  719. } catch (\Exception $e) {
  720. logModuleCall(
  721. 'siteBuilder',
  722. __FUNCTION__,
  723. $params,
  724. 'Error: could not remove site from database',
  725. $e->getMessage()
  726. );
  727. return 'Error: could not remove site from database';
  728. }
  729. // unset DNS
  730. /* disabled on dev, has to be already set in test env
  731. $response = siteBuilderunsetDNS($params, $site);
  732. if($response != 'success') {
  733. return $response;
  734. }
  735. */
  736. $response = siteBuilderRemoveSession($params,$site);
  737. if($response != 'success') {
  738. return 'Error: ' . $response;
  739. }
  740. return 'success';
  741. }
  742. /**
  743. * Opens a form to re-init a website.
  744. *
  745. * @param array $params common module parameters
  746. *
  747. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  748. *
  749. * @return array template information
  750. */
  751. function siteBuilder_revSiteConfirm($params) {
  752. return array(
  753. 'templatefile' => 'siteBuilder_rev_site_confirm',
  754. 'vars' => array(
  755. 'revSite' => $_POST['s'],
  756. ),
  757. );
  758. }
  759. /**
  760. * Revert all Changes (re-init) of the Site.
  761. *
  762. * @param array $params common module parameters
  763. *
  764. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  765. *
  766. * @return string "success" or an error message
  767. */
  768. function siteBuilder_revSite($params) {
  769. if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  770. return 'Error: invalid site name';
  771. }
  772. $site = $_POST['s'];
  773. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  774. // re-init site on webhost
  775. $response = $siteBuilder->revert($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  776. if($response['status'] != '200') {
  777. return 'Error: ' . $response['response']['error'];
  778. }
  779. // remove builder session
  780. $api = new SiteProApiClient('https://builder.thurdata.ch/api/', 'apikey0', '993yVHwC05TLsx2JI2XFlAhkkPUxR6JbQUYbI.a5HiRtmNV9');
  781. try {
  782. // this call is used to open builder, so you need to set correct parameters to represent users website you want to open
  783. // this data usually comes from your user/hosting manager system
  784. $res = $api->remoteCall('requestLogin', array(
  785. 'type' => 'internal', // (required) 'internal'
  786. 'domain' => $site, // (required) domain of the user website you want to edit
  787. 'lang' => 'de', // (optional) 2-letter language code, set language code you whant builder to open in
  788. 'apiUrl' => getSiteBuilderApiURL($params) . 'deploy/' . $params['username'] . '/' . $site, // (required) API endpoint URL
  789. 'resellerClientAccountId' => $params['serviceid'], // (required) ID of website/user in your system
  790. 'username' => $params['serverusername'], // (optional) authorization username to be used with API endpoint
  791. 'password' => 'your-secure-password', // (optional) authorization password to be used with API endpoint
  792. ));
  793. if (!$res || !is_object($res)) {
  794. logModuleCall(
  795. 'siteBuilder',
  796. __FUNCTION__,
  797. $params,
  798. 'Error: Response format error',
  799. $res
  800. );
  801. return 'Error: Response format error';
  802. } else if (isset($res->url) && $res->url) {
  803. $result = $api->remoteCall('delete-site', array(
  804. 'domain' => $site
  805. ));
  806. if (!$result || !is_object($result)) {
  807. logModuleCall(
  808. 'siteBuilder',
  809. __FUNCTION__,
  810. $params,
  811. 'Error: Response format error',
  812. $result
  813. );
  814. return 'Error: Response format error';
  815. } else if (isset($result->ok) && $res->ok) {
  816. return 'success';
  817. }
  818. } else {
  819. logModuleCall(
  820. 'siteBuilder',
  821. __FUNCTION__,
  822. $params,
  823. 'Error: Unknown error',
  824. $res
  825. );
  826. return 'Error: Unknown error';
  827. }
  828. } catch (\Exception $e) {
  829. logModuleCall(
  830. 'siteBuilder',
  831. __FUNCTION__,
  832. $params,
  833. 'Error: Request error',
  834. $e->getMessage()
  835. );
  836. return 'Error: Request error';
  837. }
  838. return 'success';
  839. }
  840. /**
  841. * Enables a website.
  842. *
  843. * @param array $params common module parameters
  844. *
  845. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  846. *
  847. * @return string "success" or an error message
  848. */
  849. function siteBuilder_enableSite($params) {
  850. if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  851. return 'Error: invalid site name';
  852. }
  853. $site = $_POST['s'];
  854. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  855. // enable
  856. $response = $siteBuilder->enable($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  857. if($response['status'] != '200') {
  858. return 'Error: ' . $response['response']['error'];
  859. }
  860. // update DB
  861. try {
  862. Capsule::table('sitePro_site')
  863. ->where('relid',$params['serviceid'])
  864. ->where('name',$site)
  865. ->update(array(
  866. 'enabled' => true,
  867. ));
  868. } catch (\Exception $e) {
  869. logModuleCall(
  870. 'siteBuilder',
  871. __FUNCTION__,
  872. $params,
  873. 'Error: could save site status in database',
  874. $e->getMessage()
  875. );
  876. return 'Error: could save site status in database';
  877. }
  878. return 'success';
  879. }
  880. /**
  881. * Disables a website.
  882. *
  883. * @param array $params common module parameters
  884. *
  885. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  886. *
  887. * @return string "success" or an error message
  888. */
  889. function siteBuilder_disableSite($params) {
  890. if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  891. return 'Error: invalid site name';
  892. }
  893. $site = $_POST['s'];
  894. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  895. // disable
  896. $response = $siteBuilder->disable($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  897. if($response['status'] != '200') {
  898. return 'Error: ' . $response['response']['error'];
  899. }
  900. // update DB
  901. try {
  902. Capsule::table('sitePro_site')
  903. ->where('relid',$params['serviceid'])
  904. ->where('name',$site)
  905. ->update(array(
  906. 'enabled' => false,
  907. ));
  908. } catch (\Exception $e) {
  909. logModuleCall(
  910. 'siteBuilder',
  911. __FUNCTION__,
  912. $params,
  913. 'Error: could save site status in database',
  914. $e->getMessage()
  915. );
  916. return 'Error: could save site status in database';
  917. }
  918. return 'success';
  919. }
  920. // Helpers
  921. /**
  922. * Removes the sitePro builder session for a site
  923. *
  924. * @param array $params common module parameters
  925. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  926. * @param string $site sitename
  927. *
  928. * @return string "success" or an error message
  929. */
  930. function siteBuilderRemoveSession($params, $site) {
  931. // remove builder session
  932. $api = new SiteProApiClient('https://builder.thurdata.ch/api/', 'apikey0', '993yVHwC05TLsx2JI2XFlAhkkPUxR6JbQUYbI.a5HiRtmNV9');
  933. try {
  934. // this call is used to open builder, so you need to set correct parameters to represent users website you want to open
  935. // this data usually comes from your user/hosting manager system
  936. $res = $api->remoteCall('requestLogin', array(
  937. 'type' => 'internal', // (required) 'internal'
  938. 'domain' => $site, // (required) domain of the user website you want to edit
  939. 'lang' => 'de', // (optional) 2-letter language code, set language code you whant builder to open in
  940. 'apiUrl' => getSiteBuilderApiURL($params) . 'deploy/' . $params['username'] . '/' . $site, // (required) API endpoint URL
  941. 'resellerClientAccountId' => $params['serviceid'], // (required) ID of website/user in your system
  942. 'username' => $params['serverusername'], // (optional) authorization username to be used with API endpoint
  943. 'password' => 'your-secure-password', // (optional) authorization password to be used with API endpoint
  944. ));
  945. if (!$res || !is_object($res)) {
  946. logModuleCall(
  947. 'siteBuilder',
  948. __FUNCTION__,
  949. $params,
  950. 'Error: Response format error',
  951. $res
  952. );
  953. return 'Error: Response format error';
  954. } else if (isset($res->url) && $res->url) {
  955. $result = $api->remoteCall('delete-site', array(
  956. 'domain' => $site
  957. ));
  958. if (!$result || !is_object($result)) {
  959. logModuleCall(
  960. 'siteBuilder',
  961. __FUNCTION__,
  962. $params,
  963. 'Error: Response format error',
  964. $result
  965. );
  966. return 'Error: Response format error';
  967. } else if (isset($result->ok) && $res->ok) {
  968. return 'success';
  969. }
  970. } else {
  971. logModuleCall(
  972. 'siteBuilder',
  973. __FUNCTION__,
  974. $params,
  975. 'Error: Unknown error',
  976. $res
  977. );
  978. return 'Error: Unknown error';
  979. }
  980. } catch (\Exception $e) {
  981. logModuleCall(
  982. 'siteBuilder',
  983. __FUNCTION__,
  984. $params,
  985. 'Error: Request error',
  986. $e->getMessage()
  987. );
  988. return 'Error: Request error';
  989. }
  990. return 'success';
  991. }
  992. /**
  993. * Update a DNS zone for a domain setting a new record for a domain or subdomain of a CWP7 account.
  994. *
  995. * @param array $params common module parameters
  996. *
  997. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  998. *
  999. * @return string "success" or an error message
  1000. */
  1001. function siteBuildersetDNS($params, $site) {
  1002. $siteName = $site . '.';
  1003. $zoneRecords = array();
  1004. $domainRecord = array(
  1005. 'line' => $siteName.'|A|0',
  1006. 'name' => $siteName,
  1007. 'type' => 'A',
  1008. 'class' => 'IN',
  1009. 'data' => array(
  1010. 'address' => $params['serverip'],
  1011. ),
  1012. );
  1013. array_push($zoneRecords, $domainRecord);
  1014. $zoneIDcollection = Capsule::table('dns_manager2_zone')
  1015. ->select('id')
  1016. ->where('name', '=', $params['domain'])
  1017. ->where('clientid', '=', $params['userid'])
  1018. ->get();
  1019. $zoneIDobj = $zoneIDcollection[0];
  1020. $zoneID = $zoneIDobj->{'id'};
  1021. if(!isset($zoneID)) {
  1022. return 'Error: Zone for domain ' . $params['domain'] . ' or not owned by client';
  1023. }
  1024. $dnsZone = localAPI('dnsmanager', array( 'dnsaction' => 'getZone', 'zone_id' => $zoneID));
  1025. foreach($dnsZone['data']->records as $record) {
  1026. if(($record->name != $siteName) || ($record->type != 'A' && $record->type != 'CNAME')) {
  1027. array_push($zoneRecords, $record);
  1028. };
  1029. }
  1030. $result = localAPI('dnsmanager' ,
  1031. array(
  1032. 'dnsaction' => 'updateZone',
  1033. 'zone_id' => $zoneID,
  1034. 'records' => $zoneRecords,
  1035. )
  1036. );
  1037. if($result['result'] != 'success') {
  1038. return 'Error: ' . $result['message'];
  1039. }
  1040. return 'success';
  1041. }
  1042. /**
  1043. * Removing a DNS record for a site of a siteBuilder account.
  1044. *
  1045. * @param array $params common module parameters
  1046. *
  1047. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  1048. *
  1049. * @return string "success" or an error message
  1050. */
  1051. function siteBuilderunsetDNS($params, $site) {
  1052. $siteName = $site . '.';
  1053. $zoneRecords = array();
  1054. $zoneIDcollection = Capsule::table('dns_manager2_zone')
  1055. ->select('id')
  1056. ->where('name', '=', $params['domain'])
  1057. ->where('clientid', '=', $params['userid'])
  1058. ->get();
  1059. $zoneIDobj = $zoneIDcollection[0];
  1060. $zoneID = $zoneIDobj->{'id'};
  1061. if(!isset($zoneID)) {
  1062. return 'Error: Zone for domain ' . $params['domain'] . ' or not owned by client';
  1063. }
  1064. $dnsZone = localAPI('dnsmanager', array( 'dnsaction' => 'getZone', 'zone_id' => $zoneID));
  1065. foreach($dnsZone['data']->records as $record) {
  1066. if(($record->name != $siteName) || ($record->type != 'A' && $record->type != 'CNAME')) {
  1067. array_push($zoneRecords, $record);
  1068. };
  1069. }
  1070. $result = localAPI('dnsmanager' ,
  1071. array(
  1072. 'dnsaction' => 'updateZone',
  1073. 'zone_id' => $zoneID,
  1074. 'records' => $zoneRecords,
  1075. )
  1076. );
  1077. if($result['result'] != 'success') {
  1078. return 'Error: ' . $result['message'];
  1079. }
  1080. return 'success';
  1081. }
  1082. /**
  1083. * Returns API Url .
  1084. *
  1085. * @param string $params common module parameters
  1086. *
  1087. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  1088. *
  1089. * @return string $apiUrl
  1090. */
  1091. function getSiteBuilderApiURL($params) {
  1092. $httpPrefix = $params['serversecure'] ? 'https://' : 'http://';
  1093. $serverPort = $params['serverport'] ? ':' . $params['serverport'] . '/' : '/';
  1094. return $httpPrefix . $params['serverhostname'] . $serverPort;
  1095. }
  1096. /**
  1097. * Returns all sitenames of an account.
  1098. *
  1099. * @param string $params common module parameters
  1100. *
  1101. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  1102. *
  1103. * @return array $sites array of sitenames
  1104. */
  1105. function getSites($serviceID) {
  1106. $sitesObj = Capsule::table('sitePro_site')
  1107. ->where('relid', $serviceID)
  1108. ->get();
  1109. $sites = [];
  1110. foreach($sitesObj as $site){
  1111. array_push($sites, $site->name);
  1112. }
  1113. return $sites;
  1114. }
  1115. /**
  1116. * Returns all names of enabled sites of an account.
  1117. *
  1118. * @param string $params common module parameters
  1119. *
  1120. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  1121. *
  1122. * @return array $sites array of sitenames
  1123. */
  1124. function getSitesEnabled($serviceID) {
  1125. $sitesObj = Capsule::table('sitePro_site')
  1126. ->where('relid', $serviceID)
  1127. ->where('enabled', 1)
  1128. ->get();
  1129. $sites = [];
  1130. foreach($sitesObj as $site){
  1131. array_push($sites, $site->name);
  1132. }
  1133. return $sites;
  1134. }
  1135. /**
  1136. * Creates tables for account & site management if not exists
  1137. */
  1138. function siteBuilderCreateTables() {
  1139. // Create a new table.
  1140. if (!Capsule::schema()->hasTable('sitePro_acc')) {
  1141. try {
  1142. Capsule::schema()->create(
  1143. 'sitePro_acc',
  1144. function ($table) {
  1145. /** @var \Illuminate\Database\Schema\Blueprint $table */
  1146. $table->increments('id');
  1147. $table->string('account');
  1148. $table->integer('pid');
  1149. $table->boolean('enabled');
  1150. }
  1151. );
  1152. } catch (\Exception $e) {
  1153. echo "Unable to create sitePro_acc: {$e->getMessage()}";
  1154. }
  1155. }
  1156. if (!Capsule::schema()->hasTable('sitePro_site')) {
  1157. try {
  1158. Capsule::schema()->create(
  1159. 'sitePro_site',
  1160. function ($table) {
  1161. /** @var \Illuminate\Database\Schema\Blueprint $table */
  1162. $table->increments('id');
  1163. $table->integer('relid');
  1164. $table->string('name');
  1165. $table->boolean('enabled');
  1166. }
  1167. );
  1168. } catch (\Exception $e) {
  1169. echo "Unable to create sitePro_site: {$e->getMessage()}";
  1170. }
  1171. }
  1172. }