src/Controller/ConfigureHelpdesk.php line 56

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Console\Wizard\ConfigureHelpdesk as Helpdesk;
  4. use Doctrine\DBAL\DriverManager;
  5. use Doctrine\ORM\Tools\Setup;
  6. use Doctrine\ORM\EntityManager;
  7. use Symfony\Bundle\FrameworkBundle\Console\Application;
  8. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  9. use Symfony\Component\Yaml\Yaml;
  10. use Symfony\Component\HttpFoundation\Request;
  11. use Symfony\Component\HttpFoundation\Response;
  12. use Symfony\Component\Console\Input\ArrayInput;
  13. use Symfony\Component\Console\Output\NullOutput;
  14. use Symfony\Component\HttpKernel\KernelInterface;
  15. use Symfony\Component\HttpFoundation\JsonResponse;
  16. use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  17. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportRole;
  18. use Webkul\UVDesk\CoreFrameworkBundle\Entity\User;
  19. use Webkul\UVDesk\CoreFrameworkBundle\Entity\UserInstance;
  20. use Webkul\UVDesk\CoreFrameworkBundle\Services\UVDeskService;
  21. class ConfigureHelpdesk extends AbstractController
  22. {
  23. const DB_URL_TEMPLATE = "mysql://[user]:[password]@[host]:[port]";
  24. const DB_ENV_PATH_TEMPLATE = "DATABASE_URL=DB_DRIVER://DB_USER:DB_PASSWORD@DB_HOST/DB_NAME\n";
  25. const DB_ENV_PATH_PARAM_TEMPLATE = "env(DATABASE_URL): 'DB_DRIVER://DB_USER:DB_PASSWORD@DB_HOST/DB_NAME'\n";
  26. const DEFAULT_JSON_HEADERS = [
  27. 'Content-Type' => 'application/json',
  28. ];
  29. private static $requiredExtensions = [
  30. [
  31. 'name' => 'imap',
  32. ],
  33. [
  34. 'name' => 'mailparse',
  35. ],
  36. [
  37. 'name' => 'mysqli',
  38. ],
  39. ];
  40. private static $requiredConfigfiles = [
  41. [
  42. 'name' => 'uvdesk',
  43. ],
  44. [
  45. 'name' => 'uvdesk_mailbox',
  46. ],
  47. ];
  48. public function load()
  49. {
  50. return $this->render('installation-wizard/index.html.twig');
  51. }
  52. public function evaluateSystemRequirements(Request $request, KernelInterface $kernel)
  53. {
  54. $max_execution_time = ini_get('max_execution_time');
  55. // Evaluate system specification requirements
  56. switch (strtolower($request->request->get('specification'))) {
  57. case 'php-version':
  58. $response = [
  59. 'status' => version_compare(phpversion(), '7.0.0', '<') ? false : true,
  60. 'version' => sprintf('%s.%s.%s', PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION),
  61. ];
  62. if ($response['status']) {
  63. $response['message'] = sprintf('Using PHP v%s', $response['version']);
  64. } else {
  65. $response['message'] = sprintf('Currently using PHP v%s. Please use PHP 7 or greater.', $response['version']);
  66. }
  67. break;
  68. case 'php-extensions':
  69. $extensions_status = array_map(function ($extension) {
  70. return [
  71. $extension['name'] => extension_loaded($extension['name']),
  72. ];
  73. }, self::$requiredExtensions);
  74. $response = [
  75. 'extensions' => $extensions_status,
  76. ];
  77. break;
  78. case 'php-maximum-execution':
  79. $response['status' ] = $max_execution_time >= 30 ? true : false;
  80. if ($response['status']) {
  81. $response['message'] = sprintf('Maximum execution time is %s', ini_get('max_execution_time').' sec');
  82. } else {
  83. $response['message'] = sprintf('Please increase your max execution time.' );
  84. $response['description'] = '</span>Issue can be resolved by simply<p><a href="https://www.simplified.guide/php/increase-max-execution-time" target="_blank"> increasing your maximum execution time</a> make it 60 or more and restart your server after making this change, refresh the browser and try again.</p>';
  85. }
  86. break;
  87. case 'php-envfile-permission':
  88. $filename = $kernel->getProjectDir().'/.env';
  89. if (!is_writable($filename)) {
  90. @chmod($filename, 0666);
  91. }
  92. $response['status'] = is_writable($filename) ? true : false;
  93. if ($response['status']) {
  94. $response['message'] = sprintf('Read/Write permission enabled for .env file.');
  95. } else {
  96. $response['message'] = sprintf('Please enable read/write permission for <b>.env</b> file of your project.');
  97. $response['description'] = '</span> Issue can be resolved by simply <a href="https://www.uvdesk.com/en/blog/open-source-helpdesk-installation-on-ubuntu-uvdesk/" target="_blank"><p> enabling your <b>.env</b> file read/write permission</a> refresh the browser and try again.</p>';
  98. }
  99. break;
  100. case 'php-configfiles-permission':
  101. $configfiles_status = array_map(function ($configfile) use ($kernel) {
  102. $filename = $kernel->getProjectDir().'/config/packages/'.$configfile['name'].'.yaml';
  103. if (!is_writable($filename)) {
  104. @chmod($filename, 0666);
  105. }
  106. return [
  107. $configfile['name'] => is_writable($filename) ,
  108. ];
  109. }, self::$requiredConfigfiles);
  110. $response = [
  111. 'configfiles' => $configfiles_status,
  112. 'description' => '</span> <br><p> Issue can be resolved by simply <a href="https://www.uvdesk.com/en/blog/open-source-helpdesk-installation-on-ubuntu-uvdesk/" target="_blank"> enabling read/write permissions for your files under config/packages folder of your project.</a></p>',
  113. ];
  114. break;
  115. case 'redis-status':
  116. if (extension_loaded('redis')) {
  117. return new JsonResponse([
  118. 'status' => false,
  119. 'message' => "Redis extension is installed on your server follow the details",
  120. 'description' =>'<span>Please check the <a href="https://github.com/uvdesk/community-skeleton/issues/364#issuecomment-780486976" target="_blank">Redis host</a> specified in the <span style="font-weight:600;">setup.php</span> file. If your Redis server host is different, you can either update it with your Redis host or follow the steps in the <a href="https://github.com/uvdesk/community-skeleton/issues/364#issuecomment-780486976" target="_blank">URL</a>. After making the changes, reload the page and try again.</span>'
  121. ]);
  122. }
  123. break;
  124. default:
  125. $code = 404;
  126. break;
  127. }
  128. return new Response(json_encode($response ?? []), $code ?? 200, self::DEFAULT_JSON_HEADERS);
  129. }
  130. public function verifyDatabaseCredentials(Request $request)
  131. {
  132. if (session_status() == PHP_SESSION_NONE) {
  133. session_start();
  134. }
  135. try {
  136. $connectionUrl = strtr(self::DB_URL_TEMPLATE, [
  137. '[host]' => $request->request->get('serverName'),
  138. '[port]' => $request->request->get('serverPort'),
  139. '[user]' => $request->request->get('username'),
  140. '[password]' => $request->request->get('password'),
  141. ]);
  142. if ($request->request->get('serverVersion') != null) {
  143. $connectionUrl .= "?serverVersion=" . $request->request->get('serverVersion');
  144. }
  145. $databaseConnection = DriverManager::getConnection([
  146. 'url' => $connectionUrl,
  147. ]);
  148. $entityManager = EntityManager::create($databaseConnection, Setup::createAnnotationMetadataConfiguration(['src/Entity'], false));
  149. // Establish a connection if not active
  150. if (false == $databaseConnection->isConnected()) {
  151. $databaseConnection->connect();
  152. }
  153. // Check if database exists
  154. $createDatabase = (bool) $request->request->get('createDatabase');
  155. if (
  156. ! in_array($request->request->get('database'), $databaseConnection->getSchemaManager()->listDatabases())
  157. && false == $createDatabase
  158. ) {
  159. return new JsonResponse([
  160. 'status' => false,
  161. 'message' => "The requested database was not found."
  162. ]);
  163. }
  164. // Storing database configuration to session.
  165. $_SESSION['DB_CONFIG'] = [
  166. 'host' => $request->request->get('serverName'),
  167. 'port' => $request->request->get('serverPort'),
  168. 'version' => $request->request->get('serverVersion'),
  169. 'username' => $request->request->get('username'),
  170. 'password' => $request->request->get('password'),
  171. 'database' => $request->request->get('database'),
  172. 'createDatabase' => $createDatabase,
  173. ];
  174. } catch (\Exception $e) {
  175. return new JsonResponse([
  176. 'status' => false,
  177. 'message' => "Failed to establish a connection with database server."
  178. ]);
  179. }
  180. return new JsonResponse(['status' => true]);
  181. }
  182. public function prepareSuperUserDetailsXHR(Request $request)
  183. {
  184. if (session_status() == PHP_SESSION_NONE) {
  185. session_start();
  186. }
  187. // unset($_SESSION['USER_DETAILS']);
  188. $_SESSION['USER_DETAILS'] = [
  189. 'name' => $request->request->get('name'),
  190. 'email' => $request->request->get('email'),
  191. 'password' => $request->request->get('password'),
  192. ];
  193. return new Response(json_encode(['status' => true]), 200, self::DEFAULT_JSON_HEADERS);
  194. }
  195. public function updateConfigurationsXHR(Request $request, KernelInterface $kernel)
  196. {
  197. if (session_status() == PHP_SESSION_NONE) {
  198. session_start();
  199. }
  200. $database_host = $_SESSION['DB_CONFIG']['host'];
  201. $database_port = $_SESSION['DB_CONFIG']['port'];
  202. $database_version = $_SESSION['DB_CONFIG']['version'];
  203. $database_user = $_SESSION['DB_CONFIG']['username'];
  204. $database_pass = $_SESSION['DB_CONFIG']['password'];
  205. $database_name = $_SESSION['DB_CONFIG']['database'];
  206. $create_database = $_SESSION['DB_CONFIG']['createDatabase'];
  207. try {
  208. $connectionUrl = strtr(self::DB_URL_TEMPLATE, [
  209. '[host]' => $database_host,
  210. '[port]' => $database_port,
  211. '[user]' => $database_user,
  212. '[password]' => $database_pass,
  213. ]);
  214. if (! empty($database_version)) {
  215. $connectionUrl .= "?serverVersion=$database_version";
  216. }
  217. $databaseConnection = DriverManager::getConnection([
  218. 'url' => $connectionUrl,
  219. ]);
  220. $entityManager = EntityManager::create($databaseConnection, Setup::createAnnotationMetadataConfiguration(['src/Entity'], false));
  221. // Establish an active connection with database server
  222. if (false == $databaseConnection->isConnected()) {
  223. $databaseConnection->connect();
  224. }
  225. // Check if database exists
  226. if (! in_array($database_name, $databaseConnection->getSchemaManager()->listDatabases())) {
  227. if (false == $create_database) {
  228. throw new \Exception('Database does not exist.');
  229. }
  230. // Create database
  231. $databaseConnection->getSchemaManager()->createDatabase($databaseConnection->getDatabasePlatform()->quoteSingleIdentifier($database_name));
  232. }
  233. $connectionUrl = strtr(self::DB_URL_TEMPLATE . "/[database]", [
  234. '[host]' => $database_host,
  235. '[port]' => $database_port,
  236. '[user]' => $database_user,
  237. '[password]' => $database_pass,
  238. '[database]' => $database_name,
  239. ]);
  240. if (!empty($database_version)) {
  241. $connectionUrl .= "?serverVersion=$database_version";
  242. }
  243. // Update .env
  244. $application = new Application($kernel);
  245. $application->setAutoExit(false);
  246. $returnCode = $application->run(new ArrayInput([
  247. 'command' => 'uvdesk_wizard:env:update',
  248. 'name' => 'DATABASE_URL',
  249. 'value' => $connectionUrl
  250. ]), new NullOutput());
  251. if (0 === $returnCode) {
  252. return new JsonResponse(['success' => true]);
  253. }
  254. } catch (\Exception $e) {
  255. return new JsonResponse([
  256. 'status' => false,
  257. 'message' => "An unexpected error occurred: " . $e->getMessage(),
  258. ]);
  259. }
  260. return new JsonResponse(['success' => false], 500);
  261. }
  262. public function migrateDatabaseSchemaXHR(Request $request, KernelInterface $kernel)
  263. {
  264. $application = new Application($kernel);
  265. $application->setAutoExit(false);
  266. $resultCode = $application->run(new ArrayInput([
  267. 'command' => 'uvdesk_wizard:database:migrate'
  268. ]), new NullOutput());
  269. return new Response(json_encode([]), 200, self::DEFAULT_JSON_HEADERS);
  270. }
  271. public function populateDatabaseEntitiesXHR(Request $request, KernelInterface $kernel)
  272. {
  273. $application = new Application($kernel);
  274. $application->setAutoExit(false);
  275. $resultCode = $application->run(new ArrayInput([
  276. 'command' => 'doctrine:fixtures:load',
  277. '--append' => true,
  278. ]), new NullOutput());
  279. return new Response(json_encode([]), 200, self::DEFAULT_JSON_HEADERS);
  280. }
  281. public function createDefaultSuperUserXHR(Request $request, UserPasswordEncoderInterface $encoder)
  282. {
  283. if (session_status() == PHP_SESSION_NONE) {
  284. session_start();
  285. }
  286. // $entityManager = $this->getDoctrine()->getEntityManager();
  287. $entityManager = $this->getDoctrine()->getManager();
  288. $role = $entityManager->getRepository(SupportRole::class)->findOneByCode('ROLE_SUPER_ADMIN');
  289. $userInstance = $entityManager->getRepository(UserInstance::class)->findOneBy([
  290. 'isActive' => true,
  291. 'supportRole' => $role,
  292. ]);
  293. if (empty($userInstance)) {
  294. list($name, $email, $password) = array_values($_SESSION['USER_DETAILS']);
  295. // Retrieve existing user or generate new empty user
  296. $accountExistsFlag = false;
  297. $user = $entityManager->getRepository(User::class)->findOneByEmail($email) ?: (new User())->setEmail($email);
  298. if ($user->getId() != null) {
  299. $userInstance = $user->getAgentInstance();
  300. if (!empty($userInstance)) {
  301. $accountExistsFlag = true;
  302. if ($userInstance->getSupportRole()->getId() != $role->getId()) {
  303. $userInstance->setSupportRole($role);
  304. $entityManager->persist($userInstance);
  305. $entityManager->flush();
  306. }
  307. }
  308. } else {
  309. $username = explode(' ', $name, 2);
  310. $encodedPassword = $encoder->encodePassword($user, $password);
  311. $user
  312. ->setFirstName($username[0])
  313. ->setLastName(! empty($username[1]) ? $username[1] : '')
  314. ->setPassword($encodedPassword)
  315. ->setIsEnabled(true);
  316. $entityManager->persist($user);
  317. $entityManager->flush();
  318. }
  319. if (false == $accountExistsFlag) {
  320. $userInstance = new UserInstance();
  321. $userInstance->setSource('website');
  322. $userInstance->setIsActive(true);
  323. $userInstance->setIsVerified(true);
  324. $userInstance->setUser($user);
  325. $userInstance->setSupportRole($role);
  326. $entityManager->persist($userInstance);
  327. $entityManager->flush();
  328. }
  329. }
  330. return new Response(json_encode([]), 200, self::DEFAULT_JSON_HEADERS);
  331. }
  332. public function websiteConfigurationXHR(Request $request, UVDeskService $uvdesk)
  333. {
  334. switch ($request->getMethod()) {
  335. case "GET":
  336. $currentWebsitePrefixCollection = $uvdesk->getCurrentWebsitePrefixes();
  337. if ($currentWebsitePrefixCollection) {
  338. $result = $currentWebsitePrefixCollection;
  339. $result['status'] = true;
  340. } else {
  341. $result['status'] = false;
  342. }
  343. break;
  344. case "POST":
  345. if (session_status() == PHP_SESSION_NONE) {
  346. session_start();
  347. }
  348. $_SESSION['PREFIXES_DETAILS'] = [
  349. 'member' => $request->request->get('member-prefix'),
  350. 'customer' => $request->request->get('customer-prefix'),
  351. ];
  352. $result = ['status' => true];
  353. break;
  354. default:
  355. break;
  356. }
  357. return new Response(json_encode($result ?? []), 200, self::DEFAULT_JSON_HEADERS);
  358. }
  359. public function updateWebsiteConfigurationXHR(Request $request, UVDeskService $uvdesk)
  360. {
  361. if (session_status() == PHP_SESSION_NONE) {
  362. session_start();
  363. }
  364. $collectionURL= $uvdesk->updateWebsitePrefixes(
  365. $_SESSION['PREFIXES_DETAILS']['member'],
  366. $_SESSION['PREFIXES_DETAILS']['customer']
  367. );
  368. // uvdesk tracker
  369. $userDetails =[
  370. 'name' => $_SESSION['USER_DETAILS']['name'],
  371. 'email' => $_SESSION['USER_DETAILS']['email'],
  372. 'domain' => $this->getParameter('uvdesk.site_url'),
  373. ];
  374. Helpdesk::addUserDetailsInTracker($userDetails);
  375. return new Response(json_encode($collectionURL), 200, self::DEFAULT_JSON_HEADERS);
  376. }
  377. }