From 1b16dbacf5acb7046ae0478c34be2643ec9b13da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Tue, 15 Sep 2020 08:45:22 +0200 Subject: [PATCH] Add calendar setting and move to more generic config ocs routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- appinfo/routes.php | 9 +- lib/Controller/ConfigController.php | 72 ++--------- lib/Controller/PageController.php | 10 +- lib/DAV/CalendarPlugin.php | 18 ++- lib/Service/ConfigService.php | 129 ++++++++++++++++++++ src/components/navigation/AppNavigation.vue | 68 +++++++---- src/store/main.js | 21 ++++ 7 files changed, 228 insertions(+), 99 deletions(-) create mode 100644 lib/Service/ConfigService.php diff --git a/appinfo/routes.php b/appinfo/routes.php index 6a1482cd8..4b273c464 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -26,9 +26,6 @@ 'routes' => [ ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], - ['name' => 'Config#get', 'url' => '/config', 'verb' => 'GET'], - ['name' => 'Config#setValue', 'url' => '/config/{key}', 'verb' => 'POST'], - // boards ['name' => 'board#index', 'url' => '/boards', 'verb' => 'GET'], ['name' => 'board#create', 'url' => '/boards', 'verb' => 'POST'], @@ -125,17 +122,17 @@ ['name' => 'attachment_api#delete', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}', 'verb' => 'DELETE'], ['name' => 'attachment_api#restore', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}/restore', 'verb' => 'PUT'], - - ['name' => 'board_api#preflighted_cors', 'url' => '/api/v1.0/{path}','verb' => 'OPTIONS', 'requirements' => ['path' => '.+']], ], 'ocs' => [ + ['name' => 'Config#get', 'url' => '/api/v1.0/config', 'verb' => 'GET'], + ['name' => 'Config#setValue', 'url' => '/api/v1.0/config/{key}', 'verb' => 'POST'], + ['name' => 'comments_api#list', 'url' => '/api/v1.0/cards/{cardId}/comments', 'verb' => 'GET'], ['name' => 'comments_api#create', 'url' => '/api/v1.0/cards/{cardId}/comments', 'verb' => 'POST'], ['name' => 'comments_api#update', 'url' => '/api/v1.0/cards/{cardId}/comments/{commentId}', 'verb' => 'PUT'], ['name' => 'comments_api#delete', 'url' => '/api/v1.0/cards/{cardId}/comments/{commentId}', 'verb' => 'DELETE'], - // dashboard ['name' => 'overview_api#upcomingCards', 'url' => '/api/v1.0/overview/upcoming', 'verb' => 'GET'], ] ]; diff --git a/lib/Controller/ConfigController.php b/lib/Controller/ConfigController.php index 342ac3fea..b64e23106 100644 --- a/lib/Controller/ConfigController.php +++ b/lib/Controller/ConfigController.php @@ -23,90 +23,42 @@ namespace OCA\Deck\Controller; +use OCA\Deck\Service\ConfigService; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\NotFoundResponse; -use OCP\IConfig; -use OCP\IGroup; -use OCP\IGroupManager; +use OCP\AppFramework\OCSController; use OCP\IRequest; -use OCP\AppFramework\Controller; -class ConfigController extends Controller { - private $config; - private $userId; - private $groupManager; +class ConfigController extends OCSController { + private $configService; public function __construct( $AppName, IRequest $request, - IConfig $config, - IGroupManager $groupManager, - $userId + ConfigService $configService ) { parent::__construct($AppName, $request); - $this->userId = $userId; - $this->groupManager = $groupManager; - $this->config = $config; + $this->configService = $configService; } /** * @NoCSRFRequired + * @NoAdminRequired */ - public function get() { - $data = [ - 'groupLimit' => $this->getGroupLimit(), - ]; - return new DataResponse($data); + public function get(): DataResponse { + return new DataResponse($this->configService->getAll()); } /** * @NoCSRFRequired + * @NoAdminRequired */ - public function setValue($key, $value) { - switch ($key) { - case 'groupLimit': - $result = $this->setGroupLimit($value); - break; - } + public function setValue(string $key, $value) { + $result = $this->configService->set($key, $value); if ($result === null) { return new NotFoundResponse(); } return new DataResponse($result); } - - private function setGroupLimit($value) { - $groups = []; - foreach ($value as $group) { - $groups[] = $group['id']; - } - $data = implode(',', $groups); - $this->config->setAppValue($this->appName, 'groupLimit', $data); - return $groups; - } - - private function getGroupLimitList() { - $value = $this->config->getAppValue($this->appName, 'groupLimit', ''); - $groups = explode(',', $value); - if ($value === '') { - return []; - } - return $groups; - } - - private function getGroupLimit() { - $groups = $this->getGroupLimitList(); - $groups = array_map(function ($groupId) { - /** @var IGroup $groups */ - $group = $this->groupManager->get($groupId); - if ($group === null) { - return null; - } - return [ - 'id' => $group->getGID(), - 'displayname' => $group->getDisplayName(), - ]; - }, $groups); - return array_filter($groups); - } } diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 2e6a32e6e..68b603d10 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -24,34 +24,33 @@ namespace OCA\Deck\Controller; use OCA\Deck\AppInfo\Application; +use OCA\Deck\Service\ConfigService; use OCA\Deck\Service\PermissionService; use OCP\AppFramework\Http\ContentSecurityPolicy; use OCP\IInitialStateService; use OCP\IRequest; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Controller; -use OCP\IL10N; class PageController extends Controller { private $permissionService; private $userId; private $l10n; private $initialState; + private $configService; public function __construct( $AppName, IRequest $request, PermissionService $permissionService, IInitialStateService $initialStateService, - IL10N $l10n, - $userId + ConfigService $configService ) { parent::__construct($AppName, $request); - $this->userId = $userId; $this->permissionService = $permissionService; $this->initialState = $initialStateService; - $this->l10n = $l10n; + $this->configService = $configService; } /** @@ -64,6 +63,7 @@ public function __construct( public function index() { $this->initialState->provideInitialState(Application::APP_ID, 'maxUploadSize', (int)\OCP\Util::uploadLimit()); $this->initialState->provideInitialState(Application::APP_ID, 'canCreate', $this->permissionService->canCreate()); + $this->initialState->provideInitialState(Application::APP_ID, 'config', $this->configService->getAll()); $response = new TemplateResponse('deck', 'main'); diff --git a/lib/DAV/CalendarPlugin.php b/lib/DAV/CalendarPlugin.php index 7e24fc1f3..76da1929a 100644 --- a/lib/DAV/CalendarPlugin.php +++ b/lib/DAV/CalendarPlugin.php @@ -26,15 +26,19 @@ use OCA\DAV\CalDAV\Integration\ExternalCalendar; use OCA\DAV\CalDAV\Integration\ICalendarProvider; use OCA\Deck\Db\Board; +use OCA\Deck\Service\ConfigService; use Sabre\DAV\Exception\NotFound; class CalendarPlugin implements ICalendarProvider { /** @var DeckCalendarBackend */ private $backend; + /** @var bool */ + private $calendarIntegrationEnabled; - public function __construct(DeckCalendarBackend $backend) { + public function __construct(DeckCalendarBackend $backend, ConfigService $configService) { $this->backend = $backend; + $this->calendarIntegrationEnabled = $configService->get('calendar'); } public function getAppId(): string { @@ -42,12 +46,20 @@ public function getAppId(): string { } public function fetchAllForCalendarHome(string $principalUri): array { + if (!$this->calendarIntegrationEnabled) { + return []; + } + return array_map(function (Board $board) use ($principalUri) { return new Calendar($principalUri, 'board-' . $board->getId(), $board, $this->backend); }, $this->backend->getBoards()); } public function hasCalendarInCalendarHome(string $principalUri, string $calendarUri): bool { + if (!$this->calendarIntegrationEnabled) { + return false; + } + $boards = array_map(static function (Board $board) { return 'board-' . $board->getId(); }, $this->backend->getBoards()); @@ -55,6 +67,10 @@ public function hasCalendarInCalendarHome(string $principalUri, string $calendar } public function getCalendarInCalendarHome(string $principalUri, string $calendarUri): ?ExternalCalendar { + if (!$this->calendarIntegrationEnabled) { + return null; + } + if ($this->hasCalendarInCalendarHome($principalUri, $calendarUri)) { try { $board = $this->backend->getBoard((int)str_replace('board-', '', $calendarUri)); diff --git a/lib/Service/ConfigService.php b/lib/Service/ConfigService.php new file mode 100644 index 000000000..baf1e4b8f --- /dev/null +++ b/lib/Service/ConfigService.php @@ -0,0 +1,129 @@ + + * + * @author Julius Härtl + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +declare(strict_types=1); + + +namespace OCA\Deck\Service; + +use OCA\Deck\AppInfo\Application; +use OCA\Deck\NoPermissionException; +use OCP\IConfig; +use OCP\IGroup; +use OCP\IGroupManager; + +class ConfigService { + private $config; + private $userId; + private $groupManager; + + public function __construct( + IConfig $config, + IGroupManager $groupManager, + $userId + ) { + $this->userId = $userId; + $this->groupManager = $groupManager; + $this->config = $config; + } + + public function getAll(): array { + $data = [ + 'calendar' => $this->get('calendar') + ]; + if ($this->groupManager->isAdmin($this->userId)) { + $data = [ + 'groupLimit' => $this->get('groupLimit'), + ]; + } + return $data; + } + + public function get($key) { + $result = null; + switch ($key) { + case 'groupLimit': + if (!$this->groupManager->isAdmin($this->userId)) { + throw new NoPermissionException('You must be admin to get the group limit'); + } + $result = $this->getGroupLimit(); + break; + case 'calendar': + $result = (bool)$this->config->getUserValue($this->userId, Application::APP_ID, 'calendar', true); + break; + } + return $result; + } + + public function set($key, $value) { + $result = null; + switch ($key) { + case 'groupLimit': + if (!$this->groupManager->isAdmin($this->userId)) { + throw new NoPermissionException('You must be admin to set the group limit'); + } + $result = $this->setGroupLimit($value); + break; + case 'calendar': + $this->config->setUserValue($this->userId, Application::APP_ID, 'calendar', (int)$value); + $result = $value; + break; + } + return $result; + } + + private function setGroupLimit($value) { + $groups = []; + foreach ($value as $group) { + $groups[] = $group['id']; + } + $data = implode(',', $groups); + $this->config->setAppValue(Application::APP_ID, 'groupLimit', $data); + return $groups; + } + + private function getGroupLimitList() { + $value = $this->config->getAppValue(Application::APP_ID, 'groupLimit', ''); + $groups = explode(',', $value); + if ($value === '') { + return []; + } + return $groups; + } + + private function getGroupLimit() { + $groups = $this->getGroupLimitList(); + $groups = array_map(function ($groupId) { + /** @var IGroup $groups */ + $group = $this->groupManager->get($groupId); + if ($group === null) { + return null; + } + return [ + 'id' => $group->getGID(), + 'displayname' => $group->getDisplayName(), + ]; + }, $groups); + return array_filter($groups); + } +} diff --git a/src/components/navigation/AppNavigation.vue b/src/components/navigation/AppNavigation.vue index 99f85f15b..8d7cd47ea 100644 --- a/src/components/navigation/AppNavigation.vue +++ b/src/components/navigation/AppNavigation.vue @@ -52,14 +52,28 @@ @@ -84,7 +100,8 @@ import { AppNavigation as AppNavigationVue, AppNavigationItem, AppNavigationSett import AppNavigationAddBoard from './AppNavigationAddBoard' import AppNavigationBoardCategory from './AppNavigationBoardCategory' import { loadState } from '@nextcloud/initial-state' -import { generateUrl, generateOcsUrl } from '@nextcloud/router' +import { generateOcsUrl } from '@nextcloud/router' +import { getCurrentUser } from '@nextcloud/auth' const canCreateState = loadState('deck', 'canCreate') @@ -123,8 +140,7 @@ export default { 'sharedBoards', ]), isAdmin() { - // eslint-disable-next-line - return OC.isUserAdmin() + return !!getCurrentUser()?.isAdmin }, cardDetailsInModal: { get() { @@ -134,15 +150,19 @@ export default { this.$store.dispatch('setCardDetailsInModal', newValue) }, }, + configCalendar: { + get() { + return this.$store.getters.config('calendar') + }, + set(newValue) { + this.$store.dispatch('setConfig', { calendar: newValue }) + }, + }, }, beforeMount() { if (this.isAdmin) { - axios.get(generateUrl('apps/deck/config')).then((response) => { - this.groupLimit = response.data.groupLimit - this.groupLimitDisabled = false - }, (error) => { - console.error('Error while loading groupLimit', error.response) - }) + this.groupLimit = this.$store.getters.config('groupLimit') + this.groupLimitDisabled = false axios.get(generateOcsUrl('cloud', 2) + 'groups').then((response) => { this.groups = response.data.ocs.data.groups.reduce((obj, item) => { obj.push({ @@ -157,15 +177,9 @@ export default { } }, methods: { - updateConfig() { - this.groupLimitDisabled = true - axios.post(generateUrl('apps/deck/config/groupLimit'), { - value: this.groupLimit, - }).then(() => { - this.groupLimitDisabled = false - }, (error) => { - console.error('Error while saving groupLimit', error.response) - }) + async updateConfig() { + await this.$store.dispatch('setConfig', { groupLimit: this.groupLimit }) + this.groupLimitDisabled = false }, }, } diff --git a/src/store/main.js b/src/store/main.js index 99b313e05..dc25160ab 100644 --- a/src/store/main.js +++ b/src/store/main.js @@ -22,6 +22,7 @@ import 'url-search-params-polyfill' +import { loadState } from '@nextcloud/initial-state' import Vue from 'vue' import Vuex from 'vuex' import axios from '@nextcloud/axios' @@ -56,6 +57,7 @@ export default new Vuex.Store({ }, strict: debug, state: { + config: loadState('deck', 'config', {}), showArchived: false, navShown: true, compactMode: localStorage.getItem('deck.compactMode') === 'true', @@ -73,6 +75,9 @@ export default new Vuex.Store({ filter: { tags: [], users: [], due: '' }, }, getters: { + config: state => (key) => { + return state.config[key] + }, cardDetailsInModal: state => { return state.cardDetailsInModal }, @@ -133,6 +138,9 @@ export default new Vuex.Store({ }, }, mutations: { + SET_CONFIG(state, { key, value }) { + Vue.set(state.config, key, value) + }, setSearchQuery(state, searchQuery) { state.searchQuery = searchQuery }, @@ -287,6 +295,19 @@ export default new Vuex.Store({ }, actions: { + async setConfig({ commit }, config) { + for (const key in config) { + try { + await axios.post(generateOcsUrl(`apps/deck/api/v1.0/config`) + key, { + value: config[key], + }) + commit('SET_CONFIG', { key, value: config[key] }) + } catch (e) { + console.error(`Error while saving ${key}`, e.response) + throw e + } + } + }, setFilter({ commit }, filter) { commit('SET_FILTER', filter) },