siteBuilder.php 35 KB

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