Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change shares and acl #3246

Merged
merged 17 commits into from
Jan 15, 2024
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
# Changelog
All notable changes to this project will be documented in this file.
##
## [6.0.0] - tbd
## [6.1.0] - tbd
### Changes
- Only Nextcloud 28 and up
### New
- Removed deletion timer of shares, options and comments
### Fixes
- Fix locked users, when registering with nextcloud user to a public poll
- Fixed typo which caused unnecessary error logging
- Fixed export of html files

## [6.0.1] - 2023-12-10
### Fixes
- Some minor fixes regarding user apperances

## [6.0.0] - 2023-12-09
### Changes
- Only Nextcloud 28 and up
### Fixes
Expand Down
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<name>Polls</name>
<summary>A polls app, similar to Doodle/Dudle with the possibility to restrict access.</summary>
<description>A polls app, similar to Doodle/Dudle with the possibility to restrict access (members, certain groups/users, hidden and public).</description>
<version>6.0.1</version>
<version>6.1.0-beta1</version>
<licence>agpl</licence>
<author>Vinzenz Rosenkranz</author>
<author>René Gieling</author>
Expand Down
26 changes: 9 additions & 17 deletions lib/Controller/BaseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);
/**
* @copyright Copyright (c) 2017 Vinzenz Rosenkranz <[email protected]>
* @copyright Copyright (c) 2020 René Gieling <[email protected]>
*
* @author René Gieling <[email protected]>
*
Expand Down Expand Up @@ -50,10 +50,8 @@ public function __construct(
* response
*/
#[NoAdminRequired]
protected function response(Closure $callback, string $token = ''): JSONResponse {
if ($token) {
$this->session->set(AppConstants::SESSION_KEY_SHARE_TOKEN, $token);
}
protected function response(Closure $callback): JSONResponse {
$this->session->remove(AppConstants::SESSION_KEY_SHARE_TOKEN);

try {
return new JSONResponse($callback(), Http::STATUS_OK);
Expand All @@ -66,10 +64,8 @@ protected function response(Closure $callback, string $token = ''): JSONResponse
* response
*/
#[NoAdminRequired]
protected function responseLong(Closure $callback, string $token = ''): JSONResponse {
if ($token) {
$this->session->set(AppConstants::SESSION_KEY_SHARE_TOKEN, $token);
}
protected function responseLong(Closure $callback): JSONResponse {
$this->session->remove(AppConstants::SESSION_KEY_SHARE_TOKEN);

try {
return new JSONResponse($callback(), Http::STATUS_OK);
Expand All @@ -82,10 +78,8 @@ protected function responseLong(Closure $callback, string $token = ''): JSONResp
* responseCreate
*/
#[NoAdminRequired]
protected function responseCreate(Closure $callback, string $token = ''): JSONResponse {
if ($token) {
$this->session->set(AppConstants::SESSION_KEY_SHARE_TOKEN, $token);
}
protected function responseCreate(Closure $callback): JSONResponse {
$this->session->remove(AppConstants::SESSION_KEY_SHARE_TOKEN);

try {
return new JSONResponse($callback(), Http::STATUS_CREATED);
Expand All @@ -98,10 +92,8 @@ protected function responseCreate(Closure $callback, string $token = ''): JSONRe
* responseDeleteTolerant
*/
#[NoAdminRequired]
protected function responseDeleteTolerant(Closure $callback, string $token = ''): JSONResponse {
if ($token) {
$this->session->set(AppConstants::SESSION_KEY_SHARE_TOKEN, $token);
}
protected function responseDeleteTolerant(Closure $callback): JSONResponse {
$this->session->remove(AppConstants::SESSION_KEY_SHARE_TOKEN);

try {
return new JSONResponse($callback(), Http::STATUS_OK);
Expand Down
88 changes: 88 additions & 0 deletions lib/Controller/BasePublicController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);
/**
* @copyright Copyright (c) 2024 René Gieling <[email protected]>
*
* @author René Gieling <[email protected]>
*
* @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 <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\Polls\Controller;

use Closure;
use OCA\Polls\AppConstants;
use OCA\Polls\Exceptions\Exception;
use OCA\Polls\Exceptions\NoUpdatesException;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\JSONResponse;
use OCP\IRequest;
use OCP\ISession;

class BasePublicController extends Controller {
public function __construct(
string $appName,
IRequest $request,
protected ISession $session,
) {
parent::__construct($appName, $request);
}

/**
* response
*/
#[NoAdminRequired]
protected function response(Closure $callback, string $token): JSONResponse {
$this->session->set(AppConstants::SESSION_KEY_SHARE_TOKEN, $token);

try {
return new JSONResponse($callback(), Http::STATUS_OK);
} catch (Exception $e) {
return new JSONResponse(['message' => $e->getMessage()], $e->getStatus());
}
}

/**
* response
*/
#[NoAdminRequired]
protected function responseLong(Closure $callback, string $token): JSONResponse {
$this->session->set(AppConstants::SESSION_KEY_SHARE_TOKEN, $token);

try {
return new JSONResponse($callback(), Http::STATUS_OK);
} catch (NoUpdatesException $e) {
return new JSONResponse([], Http::STATUS_NOT_MODIFIED);
}
}
/**
* responseCreate
*/
#[NoAdminRequired]
protected function responseCreate(Closure $callback, string $token): JSONResponse {
$this->session->set(AppConstants::SESSION_KEY_SHARE_TOKEN, $token);

try {
return new JSONResponse($callback(), Http::STATUS_CREATED);
} catch (Exception $e) {
return new JSONResponse(['message' => $e->getMessage()], $e->getStatus());
}
}
}
14 changes: 7 additions & 7 deletions lib/Controller/PublicController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);
/**
* @copyright Copyright (c) 2017 Vinzenz Rosenkranz <[email protected]>
* @copyright Copyright (c) 2020 René Gieling <[email protected]>
*
* @author René Gieling <[email protected]>
*
Expand Down Expand Up @@ -47,7 +47,7 @@
use OCP\IUserSession;
use OCP\Util;

class PublicController extends BaseController {
class PublicController extends BasePublicController {
public function __construct(
string $appName,
IRequest $request,
Expand Down Expand Up @@ -115,7 +115,7 @@ public function getShare(string $token): JSONResponse {
$validateShareType = true;
$publicRequest = true;
return $this->response(fn () => [
'share' => $this->shareService->get($token, $validateShareType, $publicRequest)
'share' => $this->shareService->request($token, $validateShareType, $publicRequest)
], $token);
}

Expand Down Expand Up @@ -236,7 +236,7 @@ public function restoreComment(int $commentId, string $token): JSONResponse {

return $this->response(fn () => [
'comment' => $this->commentService->delete($comment, $this->acl->setToken($token, Acl::PERMISSION_COMMENT_ADD), true)
]);
], $token);
}

/**
Expand Down Expand Up @@ -285,10 +285,10 @@ public function validatePublicUsername(string $userName, string $token): JSONRes
* Validate email address (simple validation)
*/
#[PublicPage]
public function validateEmailAddress(string $emailAddress): JSONResponse {
public function validateEmailAddress(string $emailAddress, string $token = ''): JSONResponse {
return $this->response(fn () => [
'result' => $this->systemService->validateEmailAddress($emailAddress), 'emailAddress' => $emailAddress
]);
], $token);
}

/**
Expand All @@ -308,7 +308,7 @@ public function setDisplayName(string $token, string $displayName): JSONResponse
#[PublicPage]
public function setEmailAddress(string $token, string $emailAddress = ''): JSONResponse {
return $this->response(fn () => [
'share' => $this->shareService->setEmailAddress($this->shareService->get($token), $emailAddress, true)
'share' => $this->shareService->setEmailAddress($this->shareService->get($token), $emailAddress)
], $token);
}

Expand Down
7 changes: 5 additions & 2 deletions lib/Db/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,10 @@ public function getPollOptionTextStart(): string {
return htmlspecialchars_decode($this->pollOptionText);
}
public function getIsLocked(): bool {
return $this->getUserVoteAnswer() !== Vote::VOTE_YES && $this->getUserVoteAnswer() !== Vote::VOTE_EVENTUALLY && ($this->getIsLockedByOptionLimit() || $this->getIsLockedByVotesLimit());
return $this->getDeleted()
|| ($this->getUserVoteAnswer() !== Vote::VOTE_YES
&& $this->getUserVoteAnswer() !== Vote::VOTE_EVENTUALLY
&& ($this->getIsLockedByOptionLimit() || $this->getIsLockedByVotesLimit()));
}

/**
Expand All @@ -174,7 +177,7 @@ public function getIsLockedByVotesLimit(): bool {
// IF a vote limit is set
// AND the user did not vote yes for this option
// AND the count of yes votes of the current user is EQUAL OR GREATER THAN the vote limit
// return true (locked option)
// return true (locked option for current user)
return $this->getVoteLimit() && $this->getUserCountYesVotes() >= $this->getVoteLimit();
}

Expand Down
19 changes: 19 additions & 0 deletions lib/Db/OptionMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ public function getAll(): array {

/**
* @return Option[]
* @param int $pollId
* @param bool $hideResults Whether the results should be hidden
* @param bool $getDeleted also search for deleted options
* @psalm-return array<array-key, Option>
*/
public function findByPoll(int $pollId, bool $hideResults = false, bool $getDeleted = false): array {
Expand All @@ -96,8 +98,25 @@ public function findByPoll(int $pollId, bool $hideResults = false, bool $getDele

return $this->findEntities($qb);
}
/**
* @return Option
* @param int $pollId
* @param string $pollOptionText option text
* @param bool $getDeleted also search for deleted options
*/
public function findByPollAndText(int $pollId, string $pollOptionText, bool $getDeleted = false): Option {
$qb = $this->buildQuery();
$qb->where($qb->expr()->eq(self::TABLE . '.poll_id', $qb->createNamedParameter($pollId, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq(self::TABLE . '.poll_option_text', $qb->createNamedParameter($pollOptionText, IQueryBuilder::PARAM_STR)));
if (!$getDeleted) {
$qb->andWhere($qb->expr()->eq(self::TABLE . '.deleted', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
}

return $this->findEntity($qb);
}

/**
* @return Option
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found
*/
public function find(int $id): Option {
Expand Down
15 changes: 9 additions & 6 deletions lib/Db/Share.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,20 @@ public function jsonSerialize(): array {
'invitationSent' => $this->getInvitationSent(),
'reminderSent' => $this->getReminderSent(),
'locked' => $this->getDeleted() ? 0 : $this->getLocked(),
'displayName' => $this->getDisplayName(),
'isNoUser' => !(in_array($this->getType(), [self::TYPE_USER, self::TYPE_ADMIN], true)),
// 'displayName' => $this->getDisplayName(),
'label' => $this->getDisplayName(),
'URL' => $this->getURL(),
'showLogin' => $this->appSettings->getBooleanSetting(AppSettings::SETTING_SHOW_LOGIN),
'publicPollEmail' => $this->getPublicPollEmail(),
'voted' => $this->getVoted(),
'deleted' => $this->getDeleted(),
'user' => [
'displayName' => $this->getDisplayName(),
'emailAddress' => $this->getEmailAddress(),
'isNoUser' => !(in_array($this->getType(), [self::TYPE_USER, self::TYPE_ADMIN], true)),
'type' => $this->getType(),
'userId' => $this->getUserId(),
]
];
}

Expand Down Expand Up @@ -235,10 +242,6 @@ private function setMiscSettingsArray(array $value): void {
$this->setMiscSettings(json_encode($value));
}

private function getVoteCount(): int {
return 0;
}

private function getMiscSettingsArray(): array {
if ($this->getMiscSettings()) {
return json_decode($this->getMiscSettings(), true);
Expand Down
4 changes: 2 additions & 2 deletions lib/Db/ShareMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,15 @@ public function findByPollUnreminded(int $pollId, bool $getDeleted = false): arr
/**
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found
*/
public function findByPollAndUser(int $pollId, string $userId, bool $getDeleted = false): Share {
public function findByPollAndUser(int $pollId, string $userId, bool $findDeleted = false): Share {
$qb = $this->db->getQueryBuilder();

$qb->select('*')
->from($this->getTableName())
->where($qb->expr()->eq('poll_id', $qb->createNamedParameter($pollId, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));

if (!$getDeleted) {
if (!$findDeleted) {
$qb->andWhere($qb->expr()->eq('deleted', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
}

Expand Down
6 changes: 3 additions & 3 deletions lib/Db/UserMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ public function getCurrentUser(): UserBase {
$token = $this->session->get(AppConstants::SESSION_KEY_SHARE_TOKEN);


if ($token) {
$this->currentUser = $this->getUserFromShareToken($token);
} else {
if ($this->isLoggedIn()) {
$this->currentUser = $this->getUserFromUserBase($this->userSession->getUser()->getUID());
} else {
$this->currentUser = $this->getUserFromShareToken($token);
}

// store userId in session to avoid unecessary db access
Expand Down
1 change: 1 addition & 0 deletions lib/Db/Vote.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public function __construct() {
$this->addType('id', 'int');
$this->addType('pollId', 'int');
$this->addType('voteOptionId', 'int');
$this->addType('deleted', 'int');
}

/**
Expand Down
Loading