ApiController.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <?php
  2. namespace Opentalent\OtAdmin\Http;
  3. use Opentalent\OtAdmin\Controller\ScanController;
  4. use Opentalent\OtAdmin\Controller\SiteController;
  5. use Psr\Log\LoggerAwareInterface;
  6. use Psr\Log\LoggerAwareTrait;
  7. use TYPO3\CMS\Core\Http\JsonResponse;
  8. use TYPO3\CMS\Core\Http\ServerRequest;
  9. use TYPO3\CMS\Core\Utility\GeneralUtility;
  10. use TYPO3\CMS\Extbase\Object\ObjectManager;
  11. /**
  12. * Actions for Http API calls
  13. *
  14. * @package Opentalent\OtAdmin\Http
  15. */
  16. class ApiController implements LoggerAwareInterface
  17. {
  18. use LoggerAwareTrait;
  19. const ALLOWED_IPS = [
  20. '/^127\.0\.0\.[0-1]$/',
  21. '/^localhost$/',
  22. '/^10\.8\.0\.\d{1,3}$/',
  23. '/^141\.94\.117\.38$/', // prod-front
  24. '/^141\.94\.117\.40$/', // prod-back
  25. '/^141\.94\.117\.42$/', // test
  26. '/^141\.94\.117\.44$/', // preprod
  27. '/^172\.1[6-9]\.\d{1,3}\.\d{1,3}$/', // local (docker)
  28. '/^172\.2[0-9]\.\d{1,3}\.\d{1,3}$/', // local (docker)
  29. '/^172\.3[0-1]\.\d{1,3}\.\d{1,3}$/' // local (docker)
  30. ];
  31. /**
  32. * Returns true if the client Ip is allowed
  33. *
  34. * @param string $clientIp
  35. * @return bool
  36. */
  37. public static function isIpAllowed(string $clientIp): bool
  38. {
  39. foreach (self::ALLOWED_IPS as $ipRule) {
  40. if (preg_match($ipRule, $clientIp)) {
  41. return true;
  42. }
  43. }
  44. return false;
  45. }
  46. /**
  47. * Check that the client Ip is allowed, else throw a Runtime error
  48. *
  49. * @return bool
  50. */
  51. private function assertIpAllowed(): bool
  52. {
  53. $clientIp = $_SERVER['REMOTE_ADDR'];
  54. if (!self::isIpAllowed($clientIp)){
  55. $route = $_REQUEST['route'];
  56. $this->logger->error(sprintf(
  57. "OtAdmin API: an attempt was made to call the route " .
  58. $route . " from an non-allowed IP (" . $clientIp . ")"));
  59. throw new \RuntimeException("Not allowed");
  60. }
  61. return true;
  62. }
  63. /**
  64. * Retrieve the organization's id from the given request parameters
  65. *
  66. * @param ServerRequest $request
  67. * @return int
  68. */
  69. private function getOrganizationId(ServerRequest $request): int
  70. {
  71. $params = $request->getQueryParams();
  72. $organizationId = $params['organization-id'];
  73. if (!$organizationId) {
  74. throw new \RuntimeException("Missing parameter: 'organization-id'");
  75. }
  76. return (int)$organizationId;
  77. }
  78. /**
  79. * -- Target of the route 'site_infos' --
  80. *
  81. * Return the main informations about the organization's website
  82. *
  83. * @param ServerRequest $request
  84. * @return JsonResponse
  85. * @throws \Exception
  86. */
  87. public function getSiteInfosAction(ServerRequest $request): JsonResponse
  88. {
  89. $this->assertIpAllowed();
  90. $organizationId = $this->getOrganizationId($request);
  91. $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
  92. $infos = $controller->getSiteInfosAction($organizationId);
  93. return new JsonResponse($infos);
  94. }
  95. /**
  96. * -- Target of the route 'site_create' --
  97. * >> Requires a query param named 'organization-id' (int)
  98. *
  99. * Create the organization's website
  100. *
  101. * @param ServerRequest $request
  102. * @return JsonResponse
  103. * @throws \Exception
  104. */
  105. public function createSiteAction(ServerRequest $request): JsonResponse
  106. {
  107. $this->assertIpAllowed();
  108. $organizationId = $this->getOrganizationId($request);
  109. $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
  110. $rootUid = $controller->createSiteAction($organizationId);
  111. $this->logger->info(sprintf(
  112. "OtAdmin API: A new website has been created with root page uid=" . $rootUid .
  113. " for the organization " . $organizationId));
  114. return new JsonResponse(
  115. [
  116. 'organization_id' => $organizationId,
  117. 'msg' => "A new website has been created with root page uid=" . $rootUid,
  118. 'root_uid' => $rootUid
  119. ]
  120. );
  121. }
  122. /**
  123. * -- Target of the route 'site_update' --
  124. * >> Requires a query param named 'organization-id' (int)
  125. *
  126. * Update the settings of the organization's website
  127. *
  128. * @param ServerRequest $request
  129. * @return JsonResponse
  130. * @throws \Exception
  131. */
  132. public function updateSiteConstantsAction(ServerRequest $request): JsonResponse
  133. {
  134. $this->assertIpAllowed();
  135. $organizationId = $this->getOrganizationId($request);
  136. $deep = (isset($queryParams['deep']) && $queryParams['deep']);
  137. $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
  138. $rootUid = $controller->updateSiteAction($organizationId, $deep);
  139. $this->logger->info(sprintf(
  140. "OtAdmin API: The website with root uid " . $rootUid . " has been updated " .
  141. " (organization: " . $organizationId . ")"));
  142. return new JsonResponse(
  143. [
  144. 'organization_id' => $organizationId,
  145. 'msg' => "The website with root uid " . $rootUid . " has been updated",
  146. 'root_uid' => $rootUid
  147. ]
  148. );
  149. }
  150. /**
  151. * -- Target of the route 'redirect_add' --
  152. * >> Requires query params named 'from-domain' (string) and 'to-domain' (string)
  153. *
  154. * Add or update a redirection from 'from-domain' to 'to-domain'
  155. *
  156. * @param ServerRequest $request
  157. * @return JsonResponse
  158. * @throws \Exception
  159. */
  160. public function addRedirectionAction(ServerRequest $request): JsonResponse
  161. {
  162. $this->assertIpAllowed();
  163. $fromDomain = (isset($queryParams['from-domain']) && $queryParams['from-domain']);
  164. $toDomain = (isset($queryParams['to-domain']) && $queryParams['to-domain']);
  165. $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
  166. $res = $controller->addRedirection($fromDomain, $toDomain);
  167. if ($res === SiteController::REDIRECTION_UPDATED) {
  168. $msg = "An existing redirection has been updated ";
  169. } elseif ($res === SiteController::REDIRECTION_CREATED) {
  170. $msg = "A redirection has been added ";
  171. }
  172. $this->logger->info(sprintf(
  173. "OtAdmin API: " . $msg . " from " . $fromDomain . " to " . $toDomain
  174. ));
  175. return new JsonResponse(
  176. [
  177. 'msg' => $msg . " from " . $fromDomain . " to " . $toDomain,
  178. ]
  179. );
  180. }
  181. /**
  182. * -- Target of the route 'site_delete' --
  183. * >> Requires a query param named 'organization-id' (int)
  184. *
  185. * Proceeds to a soft-deletion of the organization's website
  186. *
  187. * @param ServerRequest $request
  188. * @return JsonResponse
  189. * @throws \Exception
  190. */
  191. public function deleteSiteAction(ServerRequest $request): JsonResponse
  192. {
  193. $this->assertIpAllowed();
  194. $organizationId = $this->getOrganizationId($request);
  195. $params = $request->getQueryParams();
  196. $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
  197. $rootUid = $controller->deleteSiteAction($organizationId);
  198. $this->logger->info(sprintf(
  199. "OtAdmin API: The website with root uid " . $rootUid . " has been soft-deleted " .
  200. " (organization: " . $organizationId . ")"));
  201. return new JsonResponse(
  202. [
  203. 'organization_id' => $organizationId,
  204. 'msg' => "The website with root uid " . $rootUid . " has been soft-deleted. Use the /site/undelete route to restore it.",
  205. 'root_uid' => $rootUid
  206. ]
  207. );
  208. }
  209. /**
  210. * -- Target of the route 'site_undelete' --
  211. * >> Requires a query param named 'organization-id' (int)
  212. *
  213. * Restore a soft-deleted organization's website
  214. *
  215. * @param ServerRequest $request
  216. * @return JsonResponse
  217. * @throws \Exception
  218. */
  219. public function undeleteSiteAction(ServerRequest $request): JsonResponse
  220. {
  221. $this->assertIpAllowed();
  222. $organizationId = $this->getOrganizationId($request);
  223. $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
  224. $rootUid = $controller->undeleteSiteAction($organizationId);
  225. $this->logger->info(sprintf(
  226. "OtAdmin API: The website with root uid " . $rootUid . " has been restored " .
  227. " (organization: " . $organizationId . ")"));
  228. return new JsonResponse(
  229. [
  230. 'organization_id' => $organizationId,
  231. 'msg' => "The website with root uid " . $rootUid . " has been restored",
  232. 'root_uid' => $rootUid
  233. ]
  234. );
  235. }
  236. /**
  237. * -- Target of the route 'site_clearcache' --
  238. * >> Requires a query param named 'organization-id' (int)
  239. *
  240. * Clear the cache of the organization's website
  241. *
  242. * @param ServerRequest $request
  243. * @return JsonResponse
  244. * @throws \Exception
  245. */
  246. public function clearSiteCacheAction(ServerRequest $request): JsonResponse
  247. {
  248. $this->assertIpAllowed();
  249. $organizationId = $this->getOrganizationId($request);
  250. $queryParams = $request->getQueryParams();
  251. $clearAll = (isset($queryParams['all']) && $queryParams['all']);;
  252. $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
  253. $rootUid = $controller->clearSiteCacheAction($organizationId, $clearAll);
  254. return new JsonResponse(
  255. [
  256. 'organization_id' => $organizationId,
  257. 'msg' => "The cache has been cleared for the website with root uid " . $rootUid . "",
  258. 'root_uid' => $rootUid
  259. ]
  260. );
  261. }
  262. /**
  263. * -- Target of the route 'site_setdomain' --
  264. * >> Requires a query param named 'organization-id' (int)
  265. * and a parameter named 'domain' (string)
  266. *
  267. * Set a new domain for the organization website
  268. *
  269. * @param ServerRequest $request
  270. * @return JsonResponse
  271. * @throws \Exception
  272. */
  273. public function setSiteCustomDomainAction(ServerRequest $request): JsonResponse
  274. {
  275. $this->assertIpAllowed();
  276. $organizationId = $this->getOrganizationId($request);
  277. $queryParams = $request->getQueryParams();
  278. $domain = $queryParams['domain'];
  279. if (!$domain) {
  280. throw new \RuntimeException("Missing 'domain' parameter");
  281. }
  282. $redirect = (isset($queryParams['redirect']) && $queryParams['redirect']);
  283. $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
  284. $rootUid = $controller->setSiteCustomDomainAction($organizationId, $domain, $redirect);
  285. return new JsonResponse(
  286. [
  287. 'organization_id' => $organizationId,
  288. 'msg' => "The cache has been cleared for the website with root uid " . $rootUid . "",
  289. 'root_uid' => $rootUid
  290. ]
  291. );
  292. }
  293. /**
  294. * -- Target of the route 'site_resetperms' --
  295. * >> Requires a query param named 'organization-id' (int)
  296. *
  297. * Reset the permissions of the website be users (admin, editors...)
  298. *
  299. * @param ServerRequest $request
  300. * @return JsonResponse
  301. * @throws \Exception
  302. */
  303. public function resetBeUserPermsAction(ServerRequest $request): JsonResponse
  304. {
  305. $this->assertIpAllowed();
  306. $organizationId = $this->getOrganizationId($request);
  307. $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
  308. $rootUid = $controller->resetBeUserPermsAction($organizationId);
  309. return new JsonResponse(
  310. [
  311. 'organization_id' => $organizationId,
  312. 'msg' => "The website with root uid " . $rootUid . " had its be users permissions reset",
  313. 'root_uid' => $rootUid
  314. ]
  315. );
  316. }
  317. /**
  318. * -- Target of the route 'site_status' --
  319. * >> Requires a query param named 'organization-id' (int)
  320. *
  321. * Returns the current status of the website
  322. *
  323. * @param ServerRequest $request
  324. * @return JsonResponse
  325. * @throws \Exception
  326. */
  327. public function getSiteStatusAction(ServerRequest $request): JsonResponse
  328. {
  329. $this->assertIpAllowed();
  330. $organizationId = $this->getOrganizationId($request);
  331. $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
  332. $queryParams = $request->getQueryParams();
  333. $full = (isset($queryParams['full']) && $queryParams['full']);
  334. $status = $controller->getSiteStatusAction($organizationId, $full);
  335. return new JsonResponse($status->toArray());
  336. }
  337. /**
  338. * -- Target of the route 'scan' --
  339. *
  340. * Scan the whole Typo3 database and return the results
  341. *
  342. * @param ServerRequest $request
  343. * @return JsonResponse
  344. * @throws \Exception
  345. */
  346. public function scanAllAction(ServerRequest $request): JsonResponse
  347. {
  348. $this->assertIpAllowed();
  349. $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(ScanController::class);
  350. $queryParams = $request->getQueryParams();
  351. $full = (isset($queryParams['full']) && $queryParams['full']);
  352. $results = $controller->scanAllAction($full);
  353. return new JsonResponse($results);
  354. }
  355. }