BxApiModule.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup API API to the UNA backend
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. class BxApiModule extends BxDolModule
  12. {
  13. function __construct(&$aModule)
  14. {
  15. parent::__construct($aModule);
  16. }
  17. public function serviceGetSafeServices()
  18. {
  19. $a = parent::serviceGetSafeServices();
  20. return array_merge($a, array (
  21. 'DeletePage' => '',
  22. 'ChangeAccountPassword' => '',
  23. 'SwitchProfile' => ''
  24. ));
  25. }
  26. public function serviceGetPublicServices()
  27. {
  28. $a = parent::serviceGetPublicServices();
  29. return array_merge($a, array (
  30. 'Test' => '',
  31. 'GetPage' => '',
  32. 'ResetPasswordSendRequest' => '',
  33. 'ResetPasswordCheckCode' => '',
  34. 'CreateAccount' => '',
  35. ));
  36. }
  37. /**
  38. * @page public_api API Public
  39. * @section public_api_api_test /m/oauth2/com/test
  40. *
  41. * Test method to check public API
  42. *
  43. * **HTTP Method:**
  44. * `GET`
  45. *
  46. * **Request params:**
  47. * n/a
  48. *
  49. * **Response (success):**
  50. * @code
  51. * {
  52. * "result": "Test passed."
  53. * }
  54. * @endcode
  55. */
  56. public function serviceTest()
  57. {
  58. return array('result' => 'Test passed.');
  59. }
  60. /**
  61. * @page public_api API Public
  62. * @section public_api_api_get_page /m/oauth2/com/get_page
  63. *
  64. * Get page with cells and blocks as array
  65. *
  66. * **HTTP Method:**
  67. * `GET`
  68. *
  69. * **Request params:**
  70. * - `uri` - page URI
  71. *
  72. * **Response (success):**
  73. * @code
  74. * {
  75. * "id": "123", // page ID
  76. * "layout": "5", // page layout, 5 is simplest page with one cell
  77. * "module": "system", // module which this page
  78. * "title": "Test page", // page title
  79. * "type": 1, // page type, 1 is for default page with header and footer
  80. * "uri": "test", // page URI, which is part of page URL
  81. * "elements": {
  82. * "cell_1": [
  83. * {
  84. * "content": "test content", // block content, it can be array as well
  85. * "designbox_id": "11", // block design, such as padding, border, title
  86. * "hidden_on": "", // not empty block need to be hidden on mobile, or desktop
  87. * "id": "321",
  88. * "module": "system", // module name this block is related to
  89. * "order": "1", // block order
  90. * "title": "Test block", // block title
  91. * "type": "raw" // block type
  92. * }
  93. * ]
  94. * }
  95. * @endcode
  96. *
  97. * **Response (error):**
  98. * @code
  99. * {
  100. * "error":"short error description here",
  101. * "error_description":"long error description here"
  102. * }
  103. * @endcode
  104. */
  105. public function serviceGetPage()
  106. {
  107. $sUri = bx_get('uri');
  108. $oPage = BxDolPage::getObjectInstanceByURI($sUri);
  109. if (!$oPage) {
  110. return array(
  111. 'code' => 404,
  112. 'error' => 'Not Found',
  113. 'desc' => 'This page doesn\'t exist',
  114. );
  115. }
  116. if (!$oPage->isVisiblePage()) {
  117. return array(
  118. 'code' => 403,
  119. 'error' => 'Forbidden',
  120. 'desc' => 'This page requires special right to be viewed',
  121. );
  122. }
  123. return $oPage->getPageAPI();
  124. }
  125. /**
  126. * @page private_api API Private
  127. * @section private_api_api_delete_page /m/oauth2/com/delete_page
  128. *
  129. * Delete page with all blocks
  130. *
  131. * **Scopes:**
  132. * `api`
  133. *
  134. * **HTTP Method:**
  135. * `POST`
  136. *
  137. * **Request params:**
  138. * - `uri` - page URI
  139. *
  140. * **Request header:**
  141. * @code
  142. * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
  143. * @endcode
  144. *
  145. * **Response (success):**
  146. * @code
  147. * {
  148. * "code": 200,
  149. * }
  150. * @endcode
  151. *
  152. * **Response (error):**
  153. * @code
  154. * {
  155. * "error":"short error description here",
  156. * "error_description":"long error description here"
  157. * }
  158. * @endcode
  159. */
  160. public function serviceDeletePage()
  161. {
  162. $sUri = bx_get('uri');
  163. $oPage = BxDolPage::getObjectInstanceByURI($sUri);
  164. if (!$oPage) {
  165. return array(
  166. 'code' => 404,
  167. 'error' => 'No Content',
  168. 'desc' => 'Such page doesn\'t exist',
  169. );
  170. }
  171. if (!$oPage->isDeleteAllowed()) {
  172. return array(
  173. 'code' => 403,
  174. 'error' => 'Forbidden',
  175. 'desc' => 'Not enough rights to delete this page',
  176. );
  177. }
  178. $oPageBuilder = new BxTemplStudioBuilderPage($oPage->getModule(), $oPage->getName());
  179. $mixed = $oPageBuilder->processAction('page_delete');
  180. if (is_array($mixed) && (isset($mixed['msg']) || isset($mixed['message']))) {
  181. return array(
  182. 'code' => 500,
  183. 'error' => 'Internal Error',
  184. 'desc' => isset($mixed['msg']) ? $mixed['msg'] : $mixed['message'],
  185. );
  186. }
  187. return array('code' => 200);
  188. }
  189. /**
  190. * @page private_api API Private
  191. * @section private_api_api_change_account_password /m/oauth2/com/change_account_password
  192. *
  193. * Change account password
  194. *
  195. * **Scopes:**
  196. * `api`
  197. *
  198. * **HTTP Method:**
  199. * `POST`
  200. *
  201. * **Request params:**
  202. * - `password` - new password
  203. *
  204. * **Request header:**
  205. * @code
  206. * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
  207. * @endcode
  208. *
  209. * **Response (success):**
  210. * @code
  211. * {
  212. * "code": 200,
  213. * }
  214. * @endcode
  215. *
  216. * **Response (error):**
  217. * @code
  218. * {
  219. * "error":"short error description here",
  220. * "error_description":"long error description here"
  221. * }
  222. * @endcode
  223. */
  224. public function serviceChangeAccountPassword()
  225. {
  226. $sPassword = bx_get('password');
  227. if ($sPassword == '') {
  228. return array(
  229. 'code' => 404,
  230. 'error' => 'No Content',
  231. 'desc' => 'Password can\'t be empty',
  232. );
  233. }
  234. $oAccount = BxDolAccount::getInstance();
  235. if (!$oAccount->updatePassword($sPassword)){
  236. return array(
  237. 'code' => 500,
  238. 'error' => 'Internal Error',
  239. );
  240. }
  241. return array('code' => 200);
  242. }
  243. /**
  244. * @page private_api API Private
  245. * @section private_api_api_switch_profile /m/oauth2/com/switch_profile
  246. *
  247. * Switch account active profile
  248. *
  249. * **Scopes:**
  250. * `api`
  251. *
  252. * **HTTP Method:**
  253. * `POST`
  254. *
  255. * **Request params:**
  256. * - `profile_id` - profile id
  257. *
  258. * **Request header:**
  259. * @code
  260. * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
  261. * @endcode
  262. *
  263. * **Response (success):**
  264. * @code
  265. * {
  266. * "code": 200,
  267. * }
  268. * @endcode
  269. *
  270. * **Response (error):**
  271. * @code
  272. * {
  273. * "error":"short error description here",
  274. * "error_description":"long error description here"
  275. * }
  276. * @endcode
  277. */
  278. public function serviceSwitchProfile()
  279. {
  280. $mixedProfileIdToSwitch = bx_get('profile_id');
  281. if ($mixedProfileIdToSwitch == '') {
  282. return array(
  283. 'code' => 404,
  284. 'error' => 'No Content',
  285. 'desc' => 'Profile_id can\'t be empty',
  286. );
  287. }
  288. if (bx_get_logged_profile_id() == (int)$mixedProfileIdToSwitch){
  289. return array(
  290. 'code' => 404,
  291. 'error' => 'Not Allowed',
  292. 'desc' => 'Requested profile_id equal with current profile_id',
  293. );
  294. }
  295. $mixedRes = bx_srv('system', 'switch_profile', [$mixedProfileIdToSwitch], 'TemplServiceAccount');
  296. if (true === $mixedRes) {
  297. return array('code' => 200);
  298. }
  299. else {
  300. return array(
  301. 'code' => 500,
  302. 'error' => 'Internal Error',
  303. 'desc' => $mixedRes,
  304. );
  305. }
  306. }
  307. /**
  308. * @page public_api API Public
  309. * @section public_api_api_reset_password_send_request /m/oauth2/com/reset_password_send_request
  310. *
  311. * Send email with reset password code
  312. *
  313. * **Scopes:**
  314. * `api`
  315. *
  316. * **HTTP Method:**
  317. * `POST`
  318. *
  319. * **Request params:**
  320. * - `email` - email address
  321. *
  322. * **Request header:**
  323. * @code
  324. * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
  325. * @endcode
  326. *
  327. * **Response (success):**
  328. * @code
  329. * {
  330. * "code": 200,
  331. * }
  332. * @endcode
  333. *
  334. * **Response (error):**
  335. * @code
  336. * {
  337. * "error":"short error description here",
  338. * "error_description":"long error description here"
  339. * }
  340. * @endcode
  341. */
  342. public function serviceResetPasswordSendRequest(){
  343. $sEmail = bx_get('email');
  344. if ($sEmail == ''){
  345. return array(
  346. 'code' => 404,
  347. 'error' => 'No Content',
  348. 'desc' => 'Email can\'t be empty',
  349. );
  350. }
  351. $oAccountQuery = BxDolAccountQuery::getInstance();
  352. $iAccountId = $oAccountQuery->getIdByEmail($sEmail);
  353. if (!$iAccountId){
  354. return array(
  355. 'code' => 404,
  356. 'error' => 'No Content',
  357. 'desc' => 'Email is not valid',
  358. );
  359. }
  360. $oKey = BxDolKey::getInstance();
  361. $aPlus['key'] = $oKey->getNewKey(array('email' => $sEmail));
  362. $aPlus['forgot_password_url'] = bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php?i=forgot-password', array('key' => $aPlus['key'])));
  363. $aTemplate = BxDolEmailTemplates::getInstance() -> parseTemplate('t_Forgot', $aPlus, $iAccountId);
  364. if ($aTemplate && sendMail($sEmail, $aTemplate['Subject'], $aTemplate['Body'], 0, $aPlus, BX_EMAIL_SYSTEM)){
  365. return array('code' => 200);
  366. }
  367. return array(
  368. 'code' => 500,
  369. 'error' => 'Internal Error'
  370. );
  371. }
  372. /**
  373. * @page public_api API Public
  374. * @section public_api_api_reset_password_check_code /m/oauth2/com/reset_password_check_code
  375. *
  376. * Check validation code & set new password
  377. *
  378. * **Scopes:**
  379. * `api`
  380. *
  381. * **HTTP Method:**
  382. * `POST`
  383. *
  384. * **Request params:**
  385. * - `code` - validation code
  386. * - `email` - email address
  387. *
  388. * **Request header:**
  389. * @code
  390. * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
  391. * @endcode
  392. *
  393. * **Response (success):**
  394. * @code
  395. * {
  396. * "code": 200,
  397. * "password" : "[NEW PASSWORD]"
  398. * }
  399. * @endcode
  400. *
  401. * **Response (error):**
  402. * @code
  403. * {
  404. * "error":"short error description here",
  405. * "error_description":"long error description here"
  406. * }
  407. * @endcode
  408. */
  409. public function serviceResetPasswordCheckCode() {
  410. $sKey = bx_get('code');
  411. if ($sKey == '') {
  412. return array(
  413. 'code' => 404,
  414. 'error' => 'No Content',
  415. 'desc' => 'Validation code can\'t be empty',
  416. );
  417. }
  418. $oKey = BxDolKey::getInstance();
  419. if (!$oKey || !$oKey->isKeyExists($sKey)) {
  420. return array(
  421. 'code' => 404,
  422. 'error' => 'Wrong code',
  423. 'desc' => 'Validation code is not exist or expired',
  424. );
  425. }
  426. $aData = $oKey->getKeyData($sKey);
  427. if (!isset($aData['email'])){
  428. return array(
  429. 'code' => 404,
  430. 'error' => 'Wrong code',
  431. 'desc' => 'Validation code is not exist or expired',
  432. );
  433. }
  434. $oAccountQuery = BxDolAccountQuery::getInstance();
  435. $iAccountId = $oAccountQuery->getIdByEmail($aData['email']);
  436. if (!$iAccountId) {
  437. return array(
  438. 'code' => 404,
  439. 'error' => 'Wrong code',
  440. 'desc' => 'Validation code is not exist or expired',
  441. );
  442. }
  443. $oBxTemplServiceAccount = new BxTemplServiceAccount();
  444. $sPassword = $oBxTemplServiceAccount->generateUserNewPwd($iAccountId);
  445. $oKey->removeKey($sKey);
  446. $aPlus = array ('password' => $sPassword);
  447. $aTemplate = BxDolEmailTemplates::getInstance() -> parseTemplate('bx_api_password_reset', $aPlus, $iAccountId);
  448. $oAccountQuery->unlockAccount($iAccountId);
  449. if ($aTemplate && sendMail($aData['email'], $aTemplate['Subject'], $aTemplate['Body'], 0, $aPlus, BX_EMAIL_SYSTEM)) {
  450. return array(
  451. 'code' => 200,
  452. 'password' => $sPassword,
  453. );
  454. }
  455. }
  456. /**
  457. * @page public_api API Public
  458. * @section public_api_api_create_account /m/oauth2/com/create_account
  459. *
  460. * Create account
  461. *
  462. * **Scopes:**
  463. * `api`
  464. *
  465. * **HTTP Method:**
  466. * `POST`
  467. *
  468. * **Request params:**
  469. * - `name` - account name
  470. * - `email` - email address
  471. * - `password` - password
  472. *
  473. * **Request header:**
  474. * @code
  475. * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
  476. * @endcode
  477. *
  478. * **Response (success):**
  479. * @code
  480. * {
  481. * "code": 200,
  482. * "profile_id" : "[PROFILE ID]"
  483. * }
  484. * @endcode
  485. *
  486. * **Response (error):**
  487. * @code
  488. * {
  489. * "error":"short error description here",
  490. * "error_description":"long error description here"
  491. * }
  492. * @endcode
  493. */
  494. public function serviceCreateAccount()
  495. {
  496. $sAccountName = bx_get('name');
  497. $sEmail = bx_get('email');
  498. $sPassword = bx_get('password');
  499. if (!($sAccountName && $sEmail && $sPassword)){
  500. return array(
  501. 'code' => 404,
  502. 'error' => 'No Content',
  503. 'desc' => 'Account name, email, password code can\'t be empty',
  504. );
  505. }
  506. $oAccQuery = BxDolAccountQuery::getInstance();;
  507. $iId = $oAccQuery->getIdByEmail($sEmail);
  508. if ($iId > 0){
  509. return array(
  510. 'code' => 404,
  511. 'error' => 'Already exists',
  512. 'desc' => 'Account with requested email already exists',
  513. );
  514. }
  515. $_POST['name'] = $sAccountName;
  516. $_POST['email'] = $sEmail;
  517. $_POST['password'] = $sPassword;
  518. $_POST['email_confirmed'] = false;
  519. $_POST['do_submit'] = 'Submit';
  520. $oForm = BxDolForm::getObjectInstance('bx_accounts_account', 'bx_accounts_account_create');
  521. $oForm->aParams['csrf']['disable'] = true;
  522. $oForm->initChecker();
  523. if($oForm->isSubmittedAndValid()) {
  524. $iAccountId = $oForm->insert();
  525. if (!$iAccountId) {
  526. return $this->_error(_t('_sg_wtv_error_account_creation_failed'), 150);
  527. }
  528. $oBxTemplAccountForms = new BxTemplAccountForms();
  529. $iProfileId = $oBxTemplAccountForms->onAccountCreated($iAccountId, $oForm->isSetPendingApproval(), BX_PROFILE_ACTION_MANUAL, false);
  530. $sProfileModule = getParam('sys_account_default_profile_type');
  531. if (getParam('sys_account_auto_profile_creation') && !empty($sProfileModule)) {
  532. $oAccount = BxDolAccount::getInstance($iAccountId);
  533. $aProfileInfo = BxDolService::call($sProfileModule, 'prepare_fields', array(array(
  534. 'author' => $iProfileId,
  535. 'name' => $oAccount->getDisplayName(),
  536. )));
  537. $a = BxDolService::call($sProfileModule, 'entity_add', array($iProfileId, $aProfileInfo));
  538. if ($a['code'] != 0)
  539. return $this->_error($a['message']);
  540. $iProfileId = $a['content']['profile_id'];
  541. }
  542. return array(
  543. 'code' => 200,
  544. 'profile_id' => $iProfileId
  545. );
  546. }
  547. else{
  548. $s = $oForm->getFormErrors();
  549. return array(
  550. 'code' => 500,
  551. 'error' => 'Internal Error',
  552. 'desc' => $s,
  553. );
  554. }
  555. }
  556. }
  557. /** @} */