UserThemeController.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2018 John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
  5. * @copyright Copyright (c) 2019 Janis Köhr <janiskoehr@icloud.com>
  6. *
  7. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  8. * @author Daniel Kesselberg <mail@danielkesselberg.de>
  9. * @author Janis Köhr <janis.koehr@novatec-gmbh.de>
  10. * @author John Molakvoæ <skjnldsv@protonmail.com>
  11. * @author Roeland Jago Douma <roeland@famdouma.nl>
  12. *
  13. * @license GNU AGPL version 3 or any later version
  14. *
  15. * This program is free software: you can redistribute it and/or modify
  16. * it under the terms of the GNU Affero General Public License as
  17. * published by the Free Software Foundation, either version 3 of the
  18. * License, or (at your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU Affero General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU Affero General Public License
  26. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  27. *
  28. */
  29. namespace OCA\Theming\Controller;
  30. use OCA\Theming\AppInfo\Application;
  31. use OCA\Theming\ITheme;
  32. use OCA\Theming\Service\BackgroundService;
  33. use OCA\Theming\Service\ThemesService;
  34. use OCA\Theming\ThemingDefaults;
  35. use OCP\AppFramework\Http;
  36. use OCP\AppFramework\Http\DataResponse;
  37. use OCP\AppFramework\Http\FileDisplayResponse;
  38. use OCP\AppFramework\Http\JSONResponse;
  39. use OCP\AppFramework\Http\NotFoundResponse;
  40. use OCP\AppFramework\OCS\OCSBadRequestException;
  41. use OCP\AppFramework\OCS\OCSForbiddenException;
  42. use OCP\AppFramework\OCSController;
  43. use OCP\IConfig;
  44. use OCP\IRequest;
  45. use OCP\IUserSession;
  46. use OCP\PreConditionNotMetException;
  47. class UserThemeController extends OCSController {
  48. protected ?string $userId = null;
  49. private IConfig $config;
  50. private IUserSession $userSession;
  51. private ThemesService $themesService;
  52. private ThemingDefaults $themingDefaults;
  53. private BackgroundService $backgroundService;
  54. public function __construct(string $appName,
  55. IRequest $request,
  56. IConfig $config,
  57. IUserSession $userSession,
  58. ThemesService $themesService,
  59. ThemingDefaults $themingDefaults,
  60. BackgroundService $backgroundService) {
  61. parent::__construct($appName, $request);
  62. $this->config = $config;
  63. $this->userSession = $userSession;
  64. $this->themesService = $themesService;
  65. $this->themingDefaults = $themingDefaults;
  66. $this->backgroundService = $backgroundService;
  67. $user = $userSession->getUser();
  68. if ($user !== null) {
  69. $this->userId = $user->getUID();
  70. }
  71. }
  72. /**
  73. * @NoAdminRequired
  74. *
  75. * Enable theme
  76. *
  77. * @param string $themeId the theme ID
  78. * @return DataResponse
  79. * @throws OCSBadRequestException|PreConditionNotMetException
  80. */
  81. public function enableTheme(string $themeId): DataResponse {
  82. $theme = $this->validateTheme($themeId);
  83. // Enable selected theme
  84. $this->themesService->enableTheme($theme);
  85. return new DataResponse();
  86. }
  87. /**
  88. * @NoAdminRequired
  89. *
  90. * Disable theme
  91. *
  92. * @param string $themeId the theme ID
  93. * @return DataResponse
  94. * @throws OCSBadRequestException|PreConditionNotMetException
  95. */
  96. public function disableTheme(string $themeId): DataResponse {
  97. $theme = $this->validateTheme($themeId);
  98. // Enable selected theme
  99. $this->themesService->disableTheme($theme);
  100. return new DataResponse();
  101. }
  102. /**
  103. * Validate and return the matching ITheme
  104. *
  105. * Disable theme
  106. *
  107. * @param string $themeId the theme ID
  108. * @return ITheme
  109. * @throws OCSBadRequestException|PreConditionNotMetException
  110. */
  111. private function validateTheme(string $themeId): ITheme {
  112. if ($themeId === '' || !$themeId) {
  113. throw new OCSBadRequestException('Invalid theme id: ' . $themeId);
  114. }
  115. $themes = $this->themesService->getThemes();
  116. if (!isset($themes[$themeId])) {
  117. throw new OCSBadRequestException('Invalid theme id: ' . $themeId);
  118. }
  119. // If trying to toggle another theme but this is enforced
  120. if ($this->config->getSystemValueString('enforce_theme', '') !== ''
  121. && $themes[$themeId]->getType() === ITheme::TYPE_THEME) {
  122. throw new OCSForbiddenException('Theme switching is disabled');
  123. }
  124. return $themes[$themeId];
  125. }
  126. /**
  127. * @NoAdminRequired
  128. * @NoCSRFRequired
  129. */
  130. public function getBackground(): Http\Response {
  131. $file = $this->backgroundService->getBackground();
  132. if ($file !== null) {
  133. $response = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => $file->getMimeType()]);
  134. $response->cacheFor(24 * 60 * 60, false, true);
  135. return $response;
  136. }
  137. return new NotFoundResponse();
  138. }
  139. /**
  140. * @NoAdminRequired
  141. */
  142. public function deleteBackground(): JSONResponse {
  143. $currentVersion = (int)$this->config->getUserValue($this->userId, Application::APP_ID, 'userCacheBuster', '0');
  144. $this->backgroundService->deleteBackgroundImage();
  145. return new JSONResponse([
  146. 'backgroundImage' => null,
  147. 'backgroundColor' => $this->themingDefaults->getColorPrimary(),
  148. 'version' => $currentVersion,
  149. ]);
  150. }
  151. /**
  152. * @NoAdminRequired
  153. */
  154. public function setBackground(string $type = BackgroundService::BACKGROUND_DEFAULT, string $value = '', string $color = null): JSONResponse {
  155. $currentVersion = (int)$this->config->getUserValue($this->userId, Application::APP_ID, 'userCacheBuster', '0');
  156. // Set color if provided
  157. if ($color) {
  158. $this->backgroundService->setColorBackground($color);
  159. }
  160. // Set background image if provided
  161. try {
  162. switch ($type) {
  163. case BackgroundService::BACKGROUND_SHIPPED:
  164. $this->backgroundService->setShippedBackground($value);
  165. break;
  166. case BackgroundService::BACKGROUND_CUSTOM:
  167. $this->backgroundService->setFileBackground($value);
  168. break;
  169. case BackgroundService::BACKGROUND_DEFAULT:
  170. // Delete both background and color keys
  171. $this->backgroundService->setDefaultBackground();
  172. break;
  173. default:
  174. if (!$color) {
  175. return new JSONResponse(['error' => 'Invalid type provided'], Http::STATUS_BAD_REQUEST);
  176. }
  177. }
  178. } catch (\InvalidArgumentException $e) {
  179. return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
  180. } catch (\Throwable $e) {
  181. return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
  182. }
  183. $currentVersion++;
  184. $this->config->setUserValue($this->userId, Application::APP_ID, 'userCacheBuster', (string)$currentVersion);
  185. return new JSONResponse([
  186. 'backgroundImage' => $this->config->getUserValue($this->userId, Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT),
  187. 'backgroundColor' => $this->themingDefaults->getColorPrimary(),
  188. 'version' => $currentVersion,
  189. ]);
  190. }
  191. }