diff --git a/appinfo/routes.php b/appinfo/routes.php index 32e9f01..5f2a963 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -34,7 +34,6 @@ return [ ['name' => 'page#goto_form', 'url' => '/{hash}', 'verb' => 'GET'], ['name' => 'page#insert_submission', 'url' => '/insert/submission', 'verb' => 'POST'], - ['name' => 'page#search', 'url' => '/search', 'verb' => 'POST'], ['name' => 'page#get_display_name', 'url' => '/get/displayname', 'verb' => 'POST'], ['name' => 'api#write_form', 'url' => '/write/form', 'verb' => 'POST'], diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php index 0dc4874..c4a2c93 100644 --- a/lib/Controller/ApiController.php +++ b/lib/Controller/ApiController.php @@ -94,108 +94,6 @@ class ApiController extends Controller { $this->logger = $logger; } - /** - * Transforms a string with user and group names to an array - * of nextcloud users and groups - * @param string $item - * @return Array - */ - private function convertAccessList($item) : array { - $split = []; - if (strpos($item, 'user_') === 0) { - $user = $this->userManager->get(substr($item, 5)); - $split = [ - 'id' => $user->getUID(), - 'user' => $user->getUID(), - 'type' => 'user', - 'desc' => 'user', - 'icon' => 'icon-user', - 'displayName' => $user->getDisplayName(), - 'avatarURL' => '', - 'lastLogin' => $user->getLastLogin(), - 'cloudId' => $user->getCloudId() - ]; - } elseif (strpos($item, 'group_') === 0) { - $group = substr($item, 6); - $group = $this->groupManager->get($group); - $split = [ - 'id' => $group->getGID(), - 'user' => $group->getGID(), - 'type' => 'group', - 'desc' => 'group', - 'icon' => 'icon-group', - 'displayName' => $group->getDisplayName(), - 'avatarURL' => '', - ]; - } - - return($split); - } - - /** - * Check if current user is in the access list - * @param Array $accessList - * @return Boolean - */ - private function checkUserAccess($accessList) { - foreach ($accessList as $accessItem ) { - if ($accessItem['type'] === 'user' && $accessItem['id'] === \OC::$server->getUserSession()->getUser()->getUID()) { - return true; - } - } - - return false; - } - - /** - * Check If current user is member of a group in the access list - * @param Array $accessList - * @return Boolean - */ - private function checkGroupAccess($accessList) { - foreach ($accessList as $accessItem ) { - if ($accessItem['type'] === 'group' && $this->groupManager->isInGroup(\OC::$server->getUserSession()->getUser()->getUID(),$accessItem['id'])) { - return true; - } - } - - return false; - } - - /** - * Set the access right of the current user for the form - * @param Array $form - * @param Array $shares - * @return String - */ - private function grantAccessAs($form, $shares) { - if (!\OC::$server->getUserSession()->getUser() instanceof IUser) { - $currentUser = ''; - } else { - $currentUser = \OC::$server->getUserSession()->getUser()->getUID(); - } - - $grantAccessAs = 'none'; - - if ($form['ownerId'] === $currentUser) { - $grantAccessAs = 'owner'; - } elseif ($form['access'] === 'public') { - $grantAccessAs = 'public'; - } elseif ($form['access'] === 'registered' && \OC::$server->getUserSession()->getUser() instanceof IUser) { - $grantAccessAs = 'registered'; - } elseif ($form['access'] === 'hidden' && ($form['ownerId'] === \OC::$server->getUserSession()->getUser())) { - $grantAccessAs = 'hidden'; - } elseif ($this->checkUserAccess($shares)) { - $grantAccessAs = 'userInvitation'; - } elseif ($this->checkGroupAccess($shares)) { - $grantAccessAs = 'groupInvitation'; - } elseif ($this->groupManager->isAdmin($currentUser)) { - $grantAccessAs = 'admin'; - } - - return $grantAccessAs; - } - /** * Read an entire form based on form id * @NoAdminRequired @@ -215,31 +113,6 @@ class ApiController extends Controller { } - /** - * Read all shares (users and groups with access) of a form based on the form id - * @NoAdminRequired - * @param Integer $formId - * @return Array - */ - public function getShares($formId) { - - $accessList = array(); - - try { - $form = $this->formMapper->find($formId); - if (!strpos('|public|hidden|registered', $form->getAccess())) { - $accessList = explode(';', $form->getAccess()); - $accessList = array_filter($accessList); - $accessList = array_map(array($this, 'convertAccessList'), $accessList); - } - } catch (DoesNotExistException $e) { - // return silently - } finally { - return $accessList; - } - - } - public function getQuestions($formId) : array { $questionList = []; try{ @@ -310,10 +183,8 @@ class ApiController extends Controller { $data = [ 'id' => $form['id'], 'result' => $result, - 'grantedAs' => $this->grantAccessAs($form, $shares), 'mode' => $mode, 'form' => $form, - 'shares' => $shares, 'questions' => $this->getQuestions($form['id']), ]; } catch (DoesNotExistException $e) { @@ -335,7 +206,6 @@ class ApiController extends Controller { 'id' => $form->getId(), 'form' => $form->read(), 'mode' => 'edit', - 'shares' => $this->getShares($form->getId()), 'questions' => $this->getQuestions($form->getId()) ]; } @@ -394,19 +264,12 @@ class ApiController extends Controller { $newForm->setIsAnonymous($form['isAnonymous']); $newForm->setSubmitOnce($form['submitOnce']); - if ($form['access'] === 'select') { - $shareAccess = ''; - foreach ($shares as $shareElement) { - if ($shareElement['type'] === 'user') { - $shareAccess = $shareAccess . 'user_' . $shareElement['id'] . ';'; - } elseif ($shareElement['type'] === 'group') { - $shareAccess = $shareAccess . 'group_' . $shareElement['id'] . ';'; - } - } - $newForm->setAccess(rtrim($shareAccess, ';')); - } else { - $newForm->setAccess($form['access']); + // Only write Users/Groups-Arrays if necessary. + if($form['access']['type'] !== 'selected') { + unset($form['access']['users']); + unset($form['access']['groups']); } + $newForm->setAccess($form['access']); if ($form['expires']) { $newForm->setExpirationDate(date('Y-m-d H:i:s', strtotime($form['expirationDate']))); @@ -466,7 +329,9 @@ class ApiController extends Controller { )); $form->setTitle('New form'); $form->setDescription(''); - $form->setAccess('public'); + $form->setAccess([ + 'type' => 'public' + ]); $this->formMapper->insert($form); diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 77a6b49..da1c625 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -47,6 +47,7 @@ use OCP\AppFramework\Http\TemplateResponse; use OCP\IGroup; use OCP\IGroupManager; use OCP\IRequest; +use OCP\ILogger; use OCP\IURLGenerator; use OCP\IUserManager; use OCP\User; //To do: replace according to API @@ -66,6 +67,9 @@ class PageController extends Controller { private $userMgr; private $groupManager; + /** @var ILogger */ + private $logger; + public function __construct( IRequest $request, IUserManager $userMgr, @@ -77,7 +81,8 @@ class PageController extends Controller { QuestionMapper $questionMapper, OptionMapper $optionMapper, SubmissionMapper $SubmissionMapper, - AnswerMapper $AnswerMapper + AnswerMapper $AnswerMapper, + ILogger $logger ) { parent::__construct(Application::APP_ID, $request); $this->userMgr = $userMgr; @@ -90,6 +95,7 @@ class PageController extends Controller { $this->optionMapper = $optionMapper; $this->submissionMapper = $SubmissionMapper; $this->answerMapper = $AnswerMapper; + $this->logger = $logger; } /** @@ -304,131 +310,55 @@ class PageController extends Controller { /** * @NoAdminRequired - * @param string $searchTerm - * @param string $groups - * @param string $users - * @return array - */ - public function search($searchTerm, $groups, $users) { - return array_merge($this->searchForGroups($searchTerm, $groups), $this->searchForUsers($searchTerm, $users)); - } - - /** - * @NoAdminRequired - * @param string $searchTerm - * @param string $groups - * @return array - */ - public function searchForGroups($searchTerm, $groups) { - $selectedGroups = json_decode($groups); - $groups = $this->groupManager->search($searchTerm); - $gids = []; - $sgids = []; - foreach ($selectedGroups as $sg) { - $sgids[] = str_replace('group_', '', $sg); - } - foreach ($groups as $g) { - $gids[] = $g->getGID(); - } - $diffGids = array_diff($gids, $sgids); - $gids = []; - foreach ($diffGids as $g) { - $gids[] = ['gid' => $g, 'isGroup' => true]; - } - return $gids; - } - - /** - * @NoAdminRequired - * @param string $searchTerm - * @param string $users - * @return array - */ - public function searchForUsers($searchTerm, $users) { - $selectedUsers = json_decode($users); - Util::writeLog('forms', print_r($selectedUsers, true), Util::ERROR); - $userNames = $this->userMgr->searchDisplayName($searchTerm); - $users = []; - $sUsers = []; - foreach ($selectedUsers as $su) { - $sUsers[] = str_replace('user_', '', $su); - } - foreach ($userNames as $u) { - $allreadyAdded = false; - foreach ($sUsers as &$su) { - if ($su === $u->getUID()) { - unset($su); - $allreadyAdded = true; - break; - } - } - if (!$allreadyAdded) { - $users[] = ['uid' => $u->getUID(), 'displayName' => $u->getDisplayName(), 'isGroup' => false]; - } else { - continue; - } - } - return $users; - } - - /** - * @return \OCP\IGroup[] - */ - private function getGroups() { - $groups = $this->groupManager->getUserGroups(\OC::$server->getUserSession()->getUser()); - return array_map(function(IGroup $group) { - return $group->getGID(); - }, $groups); - } - - /** * Check if user has access to this form - * - * @param Form $form - * @return bool */ - private function hasUserAccess($form) { + private function hasUserAccess(Form $form): bool { $access = $form->getAccess(); $ownerId = $form->getOwnerId(); - if ($access === 'public' || $access === 'hidden') { + + if ($access['type'] === 'public') { return true; } + + // Refuse access, if not public and no user logged in. if ($this->userId === null) { return false; } - if ($access === 'registered') { - if ($form->getSubmitOnce()) { - $participants = $this->submissionMapper->findParticipantsByForm($form->getId()); - foreach($participants as $participant) { - // Don't allow access if user has already taken part - if ($participant->getUserId() === $this->userId) return false; - } - } - return true; - } + + // Always grant access to owner. if ($ownerId === $this->userId) { return true; } - Util::writeLog('forms', $this->userId, Util::ERROR); - $userGroups = $this->getGroups(); - $arr = explode(';', $access); - foreach ($arr as $item) { - if (strpos($item, 'group_') === 0) { - $grp = substr($item, 6); - foreach ($userGroups as $userGroup) { - if ($userGroup === $grp) { - return true; - } - } - } else { - if (strpos($item, 'user_') === 0) { - $usr = substr($item, 5); - if ($usr === $this->userId) { - return true; - } + + // Refuse access, if SubmitOnce is set and user already has taken part. + if ($form->getSubmitOnce()) { + $participants = $this->submissionMapper->findParticipantsByForm($form->getId()); + foreach($participants as $participant) { + if ($participant === $this->userId) { + return false; } } } + + // Now all remaining users are allowed, if access-type 'registered'. + if ($access['type'] === 'registered') { + return true; + } + + // Selected Access remains. + // Grant Access, if user is in users-Array. + if (in_array($this->userId, $access['users'])) { + return true; + } + + // Check if access granted by group. + foreach ($access['groups'] as $group) { + if( $this->groupManager->isInGroup($this->userId, $group) ) { + return true; + } + } + + // None of the possible access-options matched. return false; } } diff --git a/lib/Db/Form.php b/lib/Db/Form.php index ae5163f..b1760c4 100644 --- a/lib/Db/Form.php +++ b/lib/Db/Form.php @@ -37,8 +37,8 @@ use OCP\AppFramework\Db\Entity; * @method void setDescription(string $value) * @method string getOwnerId() * @method void setOwnerId(string $value) - * @method string getAccess() - * @method void setAccess(string $value) + * @method array getAccess() + * @method void setAccess(array $value) * @method string getCreated() * @method void setCreated(string $value) * @method string getExpirationDate() @@ -54,7 +54,7 @@ class Form extends Entity { protected $title; protected $description; protected $ownerId; - protected $access; + protected $accessJson; protected $created; protected $expirationDate; protected $isAnonymous; @@ -68,11 +68,22 @@ class Form extends Entity { $this->addType('submitOnce', 'bool'); } + /** + * JSON-Decoding of access-column. + */ + public function getAccess(): array { + return json_decode($this->getAccessJson(), true); // assoc=true, => Convert to associative Array + } + + /** + * JSON-Encoding of access-column. + */ + public function setAccess(array $access) { + $this->setAccessJson(json_encode($access)); + } + public function read() { - $accessType = $this->getAccess(); - if (!strpos('|public|hidden|registered', $accessType)) { - $accessType = 'select'; - } + if ($this->getExpirationDate() === null) { $expired = false; $expires = false; @@ -89,7 +100,7 @@ class Form extends Entity { 'ownerId' => $this->getOwnerId(), 'ownerDisplayName' => \OC_User::getDisplayName($this->getOwnerId()), 'created' => $this->getCreated(), - 'access' => $accessType, + 'access' => $this->getAccess(), 'expires' => $expires, 'expired' => $expired, 'expirationDate' => $this->getExpirationDate(), diff --git a/lib/Db/SubmissionMapper.php b/lib/Db/SubmissionMapper.php index 046adac..0e65522 100644 --- a/lib/Db/SubmissionMapper.php +++ b/lib/Db/SubmissionMapper.php @@ -66,7 +66,7 @@ class SubmissionMapper extends QBMapper { * @throws \OCP\AppFramework\Db\DoesNotExistException if not found * @return array */ - public function findParticipantsByForm(int $formId, $limit = null, $offset = null): array { + public function findParticipantsByForm(int $formId): array { $qb = $this->db->getQueryBuilder(); $qb->select('user_id') @@ -75,7 +75,14 @@ class SubmissionMapper extends QBMapper { $qb->expr()->eq('form_id', $qb->createNamedParameter($formId, IQueryBuilder::PARAM_INT)) ); - return $this->findEntities($qb); + $submissionEntities = $this->findEntities($qb); + + // From array of submissionEntities produce array of userIds. + $userIds = array_map(function($submissionEntity) { + return $submissionEntity->getUserId(); + }, $submissionEntities); + + return $userIds; } /** diff --git a/lib/Migration/Version010200Date2020323141300.php b/lib/Migration/Version010200Date2020323141300.php index e656590..ba0370f 100644 --- a/lib/Migration/Version010200Date2020323141300.php +++ b/lib/Migration/Version010200Date2020323141300.php @@ -87,9 +87,8 @@ class Version010200Date2020323141300 extends SimpleMigrationStep { 'notnull' => true, 'length' => 64, ]); - $table->addColumn('access', Type::STRING, [ + $table->addColumn('access_json', Type::JSON, [ 'notnull' => false, - 'length' => 1024, ]); $table->addColumn('created', Type::DATETIME, [ 'notnull' => false, @@ -212,13 +211,15 @@ class Version010200Date2020323141300 extends SimpleMigrationStep { ->from('forms_events'); $cursor = $qb_fetch->execute(); while( $event = $cursor->fetch() ){ + $newAccessJSON = $this->convertAccessList($event['access']); + $qb_restore->insert('forms_v2_forms') ->values([ 'hash' => $qb_restore->createNamedParameter($event['hash'], IQueryBuilder::PARAM_STR), 'title' => $qb_restore->createNamedParameter($event['title'], IQueryBuilder::PARAM_STR), 'description' => $qb_restore->createNamedParameter($event['description'], IQueryBuilder::PARAM_STR), 'owner_id' => $qb_restore->createNamedParameter($event['owner'], IQueryBuilder::PARAM_STR), - 'access' => $qb_restore->createNamedParameter($event['access'], IQueryBuilder::PARAM_STR), + 'access_json' => $qb_restore->createNamedParameter($newAccessJSON, IQueryBuilder::PARAM_STR), 'created' => $qb_restore->createNamedParameter($event['created'], IQueryBuilder::PARAM_STR), 'expiration_date' => $qb_restore->createNamedParameter($event['expire'], IQueryBuilder::PARAM_STR), 'is_anonymous' => $qb_restore->createNamedParameter($event['is_anonymous'], IQueryBuilder::PARAM_BOOL), @@ -358,4 +359,34 @@ class Version010200Date2020323141300 extends SimpleMigrationStep { } } } + + /** + * Convert old Access-String into JSON of new Access-Structure. + * @param $accessString Old access-String + */ + private function convertAccessList($accessString) : string { + $accessArray = []; + + if ($accessString === 'public' || $accessString === 'registered') { + // Store type and return with empty users/groups. + $accessArray['type'] = $accessString; + return json_encode($accessArray); + } + + // Access 'selected' + $accessArray['type'] = 'selected'; + $accessArray['users'] = []; + $accessArray['groups'] = []; + + $stringExplode = explode(';', $accessString); + foreach($stringExplode as $string) { + if (strpos($string, 'user_') === 0) { + $accessArray['users'][] = substr($string, 5); + } elseif (strpos($string, 'group_') === 0) { + $accessArray['groups'][] = substr($string, 6); + } + } + + return json_encode($accessArray); + } } diff --git a/src/views/Sidebar.vue b/src/views/Sidebar.vue index 62440a5..8cf9156 100644 --- a/src/views/Sidebar.vue +++ b/src/views/Sidebar.vue @@ -38,7 +38,7 @@