From 4a4dc5ea6da55485babd8b46a251ab0c0970ed15 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Thu, 30 May 2019 12:42:20 -0100 Subject: [PATCH] adding command to manage access rights Signed-off-by: Maxence Lange --- appinfo/info.xml | 1 + lib/Command/Fediverse.php | 232 +++++++++++++++ .../UnauthorizedFediverseException.php | 40 +++ lib/Service/ConfigService.php | 17 +- lib/Service/FediverseService.php | 266 ++++++++++++++++++ 5 files changed, 553 insertions(+), 3 deletions(-) create mode 100644 lib/Command/Fediverse.php create mode 100644 lib/Exceptions/UnauthorizedFediverseException.php create mode 100644 lib/Service/FediverseService.php diff --git a/appinfo/info.xml b/appinfo/info.xml index 939b29a6..f761d219 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -48,6 +48,7 @@ OCA\Social\Command\CacheRefresh OCA\Social\Command\CheckInstall + OCA\Social\Command\Fediverse OCA\Social\Command\NoteCreate OCA\Social\Command\NoteBoost OCA\Social\Command\Reset diff --git a/lib/Command/Fediverse.php b/lib/Command/Fediverse.php new file mode 100644 index 00000000..0a2dbf6e --- /dev/null +++ b/lib/Command/Fediverse.php @@ -0,0 +1,232 @@ + + * @copyright 2018, Maxence Lange + * @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 . + * + */ + + +namespace OCA\Social\Command; + + +use Exception; +use OC\Core\Command\Base; +use OCA\Social\Exceptions\UnauthorizedFediverseException; +use OCA\Social\Service\ConfigService; +use OCA\Social\Service\FediverseService; +use OCA\Social\Service\MiscService; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + + +/** + * Class Fediverse + * + * @package OCA\Social\Command + */ +class Fediverse extends Base { + + + /** @var FediverseService */ + private $fediverseService; + + /** @var ConfigService */ + private $configService; + + /** @var MiscService */ + private $miscService; + + + /** @var OutputInterface */ + private $output; + + + /** + * CacheUpdate constructor. + * + * @param FediverseService $fediverseService + * @param ConfigService $configService + * @param MiscService $miscService + */ + public function __construct( + FediverseService $fediverseService, ConfigService $configService, + MiscService $miscService + ) { + parent::__construct(); + + $this->fediverseService = $fediverseService; + $this->configService = $configService; + $this->miscService = $miscService; + } + + + /** + * + */ + protected function configure() { + parent::configure(); + $this->setName('social:fediverse') + ->addOption( + 'type', 't', InputArgument::OPTIONAL, + 'Change the type of access management', '' + ) + ->addArgument('action', InputArgument::OPTIONAL, 'add/remove/test address', '') + ->addArgument('address', InputArgument::OPTIONAL, 'address/host', '') + ->setDescription('Allow or deny access to the fediverse'); + } + + + /** + * @param InputInterface $input + * @param OutputInterface $output + * + * @throws Exception + */ + protected function execute(InputInterface $input, OutputInterface $output) { + $this->output = $output; + + if ($this->typeAccess($input->getOption('type'))) { + return; + } + + $this->output->writeln( + 'Current access type: ' . $this->fediverseService->getAccessType() . '' + ); + + switch ($input->getArgument('action')) { + case '': + $this->listAddresses(false); + break; + + case 'list': + $this->listAddresses(true); + break; + + case 'add': + $this->addAddress($input->getArgument('address')); + break; + + case 'remove': + $this->removeAddress($input->getArgument('address')); + break; + + case 'test': + $this->testAddress($input->getArgument('address')); + break; + + case 'reset': + $this->resetAddresses(); + break; + + default: + throw new Exception('specify action: add, remove, list, reset'); + } + } + + + /** + * @param string $type + * + * @return bool + * @throws Exception + */ + private function typeAccess(string $type) { + if ($type === '') { + return false; + } + + $this->fediverseService->setAccessType($type); + + return true; + } + + + /** + * @param bool $allKnownAddress + */ + private function listAddresses(bool $allKnownAddress = false) { + + if ($allKnownAddress) { + $this->output->writeln('- Known address:'); + foreach ($this->fediverseService->getKnownAddresses() as $address) { + $this->output->writeln(' ' . $address . ''); + } + } + + $this->output->writeln('- List:'); + foreach ($this->fediverseService->getListedAddresses() as $address) { + $this->output->writeln(' ' . $address . ''); + } + + } + + + /** + * @param string $address + * + * @throws Exception + */ + private function addAddress(string $address) { + $this->fediverseService->addAddress($address); + $this->output->writeln('' . $address . ' added to the list'); + } + + + /** + * @param string $address + * + * @throws Exception + */ + private function removeAddress(string $address) { + $this->fediverseService->removeAddress($address); + $this->output->writeln('' . $address . ' removed from the list'); + } + + + /** + * @param string $address + */ + private function testAddress(string $address) { + try { + $this->fediverseService->authorized($address); + $this->output->writeln('Authorized'); + } catch (UnauthorizedFediverseException $e) { + $this->output->writeln('Unauthorized'); + } + } + + + /** + * + */ + private function resetAddresses() { + $this->fediverseService->resetAddresses(); + $this->output->writeln('list is now empty'); + } + + +} + diff --git a/lib/Exceptions/UnauthorizedFediverseException.php b/lib/Exceptions/UnauthorizedFediverseException.php new file mode 100644 index 00000000..22d7ba5c --- /dev/null +++ b/lib/Exceptions/UnauthorizedFediverseException.php @@ -0,0 +1,40 @@ + + * @copyright 2018, Maxence Lange + * @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 . + * + */ + + +namespace OCA\Social\Exceptions; + + +use Exception; + + +class UnauthorizedFediverseException extends Exception { + +} + diff --git a/lib/Service/ConfigService.php b/lib/Service/ConfigService.php index cdfee8e3..cf747f6f 100644 --- a/lib/Service/ConfigService.php +++ b/lib/Service/ConfigService.php @@ -54,6 +54,8 @@ class ConfigService { const SOCIAL_ADDRESS = 'address'; const SOCIAL_SERVICE = 'service'; const SOCIAL_MAX_SIZE = 'max_size'; + const SOCIAL_ACCESS_TYPE = 'access_type'; + const SOCIAL_ACCESS_LIST = 'access_list'; const BACKGROUND_CRON = 1; const BACKGROUND_ASYNC = 2; @@ -62,11 +64,20 @@ class ConfigService { /** @var array */ public $defaults = [ - self::SOCIAL_ADDRESS => '', - self::SOCIAL_SERVICE => 1, - self::SOCIAL_MAX_SIZE => 10 + self::SOCIAL_ADDRESS => '', + self::SOCIAL_SERVICE => 1, + self::SOCIAL_MAX_SIZE => 10, + self::SOCIAL_ACCESS_TYPE => 'all_but', + self::SOCIAL_ACCESS_LIST => '[]' ]; + /** @var array */ + public $accessTypeList = [ + 'BLACKLIST' => 'all_but', + 'WHITELIST' => 'none_but' + ]; + + /** @var string */ private $userId; diff --git a/lib/Service/FediverseService.php b/lib/Service/FediverseService.php new file mode 100644 index 00000000..19f6e5e9 --- /dev/null +++ b/lib/Service/FediverseService.php @@ -0,0 +1,266 @@ + + * @copyright 2018, Maxence Lange + * @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 . + * + */ + + +namespace OCA\Social\Service; + +use Exception; +use OCA\Social\Exceptions\UnauthorizedFediverseException; + + +/** + * Class FediverseService + * + * @package OCA\Social\Service + */ +class FediverseService { + + + /** @var ConfigService */ + private $configService; + + /** @var MiscService */ + private $miscService; + + + /** + * FediverseService constructor. + * + * @param ConfigService $configService + * @param MiscService $miscService + */ + public function __construct( + ConfigService $configService, MiscService $miscService + ) { + $this->configService = $configService; + $this->miscService = $miscService; + } + + + /** + * @param string $address + * + * @return bool + * @throws UnauthorizedFediverseException + */ + public function authorized(string $address): bool { + if ($this->getAccessType() === + $this->configService->accessTypeList['BLACKLIST'] + && !$this->isListed($address)) { + return true; + } + + if ($this->getAccessType() === + $this->configService->accessTypeList['WHITELIST'] + && $this->isListed($address)) { + return true; + } + + throw new UnauthorizedFediverseException(); + } + + + /** + * @throws UnauthorizedFediverseException + */ + public function jailed() { + if ($this->getAccessType() !== $this->configService->accessTypeList['WHITELIST'] + || !empty($this->getListedAddresses())) { + return; + } + + throw new UnauthorizedFediverseException(); + } + + + /** + * @return string + */ + public function getAccessType(): string { + return $this->configService->getAppValue(ConfigService::SOCIAL_ACCESS_TYPE); + } + + + /** + * @param string $type + * + * @throws Exception + */ + public function setAccessType(string $type) { + $accepted = array_values($this->configService->accessTypeList); + if (!in_array($type, $accepted)) { + throw new Exception('invalid type: ' . json_encode($accepted)); + } + + $this->configService->setAppValue(ConfigService::SOCIAL_ACCESS_TYPE, $type); + } + + + /** + * @return array + */ + public function getKnownAddresses(): array { + return []; + } + + + /** + * @return array + */ + public function getListedAddresses(): array { + return json_decode($this->configService->getAppValue(ConfigService::SOCIAL_ACCESS_LIST)); + } + + /** + * @param string $address + * + * @return bool + */ + public function isListed(string $address): bool { + $list = $this->getListedAddresses(); + + return (in_array($address, $list)); + } + + /** + * + */ + public function resetAddresses() { + $this->configService->setAppValue(ConfigService::SOCIAL_ACCESS_LIST, '[]'); + } + + /** + * @param string $address + */ + public function addAddress(string $address) { + if ($this->isListed($address)) { + return; + } + + $list = $this->getListedAddresses(); + array_push($list, $address); + + $this->configService->setAppValue(ConfigService::SOCIAL_ACCESS_LIST, json_encode($list)); + } + + /** + * @param string $address + * + * @return void + * @throws Exception + */ + public function removeAddress(string $address) { + $list = $this->getListedAddresses(); + $list = array_diff($list, [$address]); + $this->configService->setAppValue(ConfigService::SOCIAL_ACCESS_LIST, json_encode($list)); + } + + +// +// /** +// * @param string $address +// * +// * @throws Exception +// */ +// public function blockAddress(string $address) { +// if ($this->isBlocked($address)) { +// return; +// } +// +// if ($this->isAllowed($address)) { +// throw new Exception($address . ' is already in the whitelist'); +// } +// +// $blackList = $this->getBlockedAddresses(); +// array_push($blackList, $address); +// +// $this->configService->setAppValue(ConfigService::SOCIAL_BLACKLIST, json_encode($blackList)); +// } +// +// /** +// * @return array +// */ +// public function getBlockedAddresses(): array { +// return json_decode($this->configService->getAppValue(ConfigService::SOCIAL_BLACKLIST)); +// } +// +// /** +// * @param string $address +// * +// * @return bool +// */ +// public function isBlocked(string $address): bool { +// return (in_array('ALL', $this->getBlockedAddresses()) +// || in_array($address, $this->getBlockedAddresses())); +// } +// +// +// /** +// * @param string $address +// * +// * @return void +// * @throws Exception +// */ +// public function allowAddress(string $address) { +// if ($this->isAllowed($address)) { +// return; +// } +// +// if ($this->isBlocked($address)) { +// throw new Exception($address . ' is already in the blacklist'); +// } +// +// $whiteList = $this->getAllowedAddresses(); +// array_push($whiteList, $address); +// +// $this->configService->setAppValue(ConfigService::SOCIAL_WHITELIST, json_encode($whiteList)); +// } +// +// /** +// * @return array +// */ +// public function getAllowedAddresses(): array { +// return json_decode($this->configService->getAppValue(ConfigService::SOCIAL_WHITELIST)); +// +// } +// +// /** +// * @param string $address +// * +// * @return bool +// */ +// public function isAllowed(string $address): bool { +// return (in_array('ALL', $this->getAllowedAddresses()) +// || in_array($address, $this->getAllowedAddresses())); +// } +// +// + +} +