Skip to content

Commit d7f4a6e

Browse files
authored
Merge pull request #3923 from nextcloud/enh/restrict-poll-owner
Add restricted owners
2 parents 55ea796 + 27bd55c commit d7f4a6e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+823
-376
lines changed

lib/AppInfo/Application.php

+2
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,15 @@ private function registerServices(IRegistrationContext $context): void {
161161
$context->registerService(CommentMapper::class, function (ContainerInterface $c): CommentMapper {
162162
return new CommentMapper(
163163
$c->get(IDBConnection::class),
164+
$c->get(UserSession::class),
164165
);
165166
});
166167

167168
$context->registerService(VoteMapper::class, function (ContainerInterface $c): VoteMapper {
168169
return new VoteMapper(
169170
$c->get(IDBConnection::class),
170171
$c->get(LoggerInterface::class),
172+
$c->get(UserSession::class),
171173
);
172174
});
173175

lib/Controller/PollController.php

+12
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,18 @@ public function update(int $pollId, array $poll): JSONResponse {
111111
]);
112112
}
113113

114+
/**
115+
* Lock Anonymous
116+
* @param int $pollId Poll id
117+
*/
118+
#[NoAdminRequired]
119+
#[FrontpageRoute(verb: 'PUT', url: '/poll/{pollId}/lockAnonymous')]
120+
public function lockAnonymous(int $pollId): JSONResponse {
121+
return $this->response(fn () => [
122+
'poll' => $this->pollService->lockAnonymous($pollId),
123+
]);
124+
}
125+
114126
/**
115127
* Send confirmation mails
116128
* @param int $pollId Poll id

lib/Controller/PublicController.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public function getPoll(): JSONResponse {
105105
public function getSession(): JSONResponse {
106106
return $this->response(fn () => [
107107
'token' => $this->request->getParam('token'),
108-
'currentUser' => $this->userSession->getUser(),
108+
'currentUser' => $this->userSession->getCurrentUser(),
109109
'appPermissions' => $this->appSettings->getPermissionsArray(),
110110
'appSettings' => $this->appSettings->getAppSettings(),
111111
'share' => $this->userSession->getShare(),

lib/Controller/UserApiController.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public function writePreferences(array $preferences): DataResponse {
5252
public function getSession(): DataResponse {
5353
return $this->response(fn () => [
5454
'token' => $this->request->getParam('token'),
55-
'currentUser' => $this->userSession->getUser(),
55+
'currentUser' => $this->userSession->getCurrentUser(),
5656
'appPermissions' => $this->appSettings->getPermissionsArray(),
5757
'appSettings' => $this->appSettings->getAppSettings(),
5858
]);

lib/Controller/UserController.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public function writePreferences(array $preferences): JSONResponse {
6363
public function getSession(): JSONResponse {
6464
return $this->response(fn () => [
6565
'token' => $this->request->getParam('token'),
66-
'currentUser' => $this->userSession->getUser(),
66+
'currentUser' => $this->userSession->getCurrentUser(),
6767
'appPermissions' => $this->appSettings->getPermissionsArray(),
6868
'appSettings' => $this->appSettings->getAppSettings(),
6969
'preferences' => $this->preferencesService->get(),

lib/Db/CommentMapper.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace OCA\Polls\Db;
1010

11+
use OCA\Polls\UserSession;
1112
use OCP\DB\QueryBuilder\IQueryBuilder;
1213
use OCP\IDBConnection;
1314

@@ -18,7 +19,10 @@ class CommentMapper extends QBMapperWithUser {
1819
public const TABLE = Comment::TABLE;
1920

2021
/** @psalm-suppress PossiblyUnusedMethod */
21-
public function __construct(IDBConnection $db) {
22+
public function __construct(
23+
IDBConnection $db,
24+
private UserSession $userSession,
25+
) {
2226
parent::__construct($db, self::TABLE, Comment::class);
2327
}
2428

@@ -82,13 +86,15 @@ public function purgeDeletedComments(int $offset): void {
8286
* Build the enhanced query with joined tables
8387
*/
8488
protected function buildQuery(): IQueryBuilder {
89+
$currentUserId = $this->userSession->getCurrentUserId();
8590
$qb = $this->db->getQueryBuilder();
8691

8792
$qb->select(self::TABLE . '.*')
8893
->from($this->getTableName(), self::TABLE)
8994
->groupBy(self::TABLE . '.id');
9095

9196
$this->joinAnon($qb, self::TABLE);
97+
$this->joinShareRole($qb, self::TABLE, $currentUserId);
9298
return $qb;
9399
}
94100
}

lib/Db/EntityWithUser.php

+51-27
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88

99
namespace OCA\Polls\Db;
1010

11-
use OCA\Polls\Helper\Container;
11+
use OCA\Polls\Model\User\Anon;
1212
use OCA\Polls\Model\UserBase;
1313
use OCA\Polls\UserSession;
1414
use OCP\AppFramework\Db\Entity;
15+
use OCP\Server;
1516

1617
/**
1718
* @psalm-suppress UnusedProperty
@@ -23,17 +24,15 @@
2324
* @method string getPollOwnerId()
2425
* @method string getPollShowResults()
2526
* @method int getPollExpire()
27+
* @method string getShareType()
2628
*/
2729

2830
abstract class EntityWithUser extends Entity {
2931
protected int $anonymized = 0;
3032
protected string $pollOwnerId = '';
3133
protected string $pollShowResults = '';
3234
protected int $pollExpire = 0;
33-
34-
public const ANON_FULL = 'anonymous';
35-
public const ANON_PRIVACY = 'privacy';
36-
public const ANON_NONE = 'ful_view';
35+
protected ?string $shareType = '';
3736

3837
public function __construct() {
3938
// joined Attributes
@@ -42,41 +41,66 @@ public function __construct() {
4241
}
4342

4443
/**
45-
* Anonymized the user completely (ANON_FULL) or just strips out personal information
44+
* Is the current user the owner of the entity
45+
* @return bool
4646
*/
47-
public function getAnonymizeLevel(): string {
48-
$currentUserId = Container::queryClass(UserSession::class)->getCurrentUserId();
49-
// Don't censor for poll owner or it is the current user's entity
50-
if ($this->getPollOwnerId() === $currentUserId || $this->getIsOwner()) {
51-
return self::ANON_NONE;
47+
public function getCurrentUserIsEntityUser(): bool {
48+
$userSession = Server::get(UserSession::class);
49+
return $userSession->getCurrentUserId() === $this->getUserId();
50+
}
51+
52+
private function getEntityAnonymization(): bool {
53+
if ($this->getCurrentUserIsEntityUser()) {
54+
// if the current user is the owner of the entity, don't anonymize the entity
55+
return false;
5256
}
5357

54-
// Anonymize if poll's anonymize setting is true
55-
if ((bool)$this->anonymized) {
56-
return self::ANON_FULL;
58+
if ($this->getAnonymized() < 0) {
59+
// the poll is anonymized and locked, anonymize the entity
60+
return true;
5761
}
5862

59-
// Anonymize if votes are hidden
63+
if ($this->getAnonymized() > 0) {
64+
// the poll is anonymized and unlocked
65+
$userSession = Server::get(UserSession::class);
66+
if ($this->getPollOwnerId() === $userSession->getCurrentUserId()) {
67+
// if the current user is the poll owner, don't anonymize the entity
68+
return false;
69+
}
70+
if ($this->getShareType() === Share::TYPE_ADMIN) {
71+
// if the current user is a delegated admin, don't anonymize the entity
72+
return false;
73+
}
74+
// if the current user is not the poll owner, anonymize the entity
75+
return true;
76+
}
77+
78+
// the poll is not anonymized
6079
if ($this->getPollShowResults() === Poll::SHOW_RESULTS_NEVER
61-
|| ($this->getPollShowResults() === Poll::SHOW_RESULTS_CLOSED && (
62-
!$this->getPollExpire() || $this->getPollExpire() > time()
63-
))
64-
) {
65-
return self::ANON_FULL;
80+
|| ($this->getPollShowResults() === Poll::SHOW_RESULTS_CLOSED
81+
&& !$this->getPollExpire() > time())) {
82+
83+
// Do not anonymize the poll owner
84+
return !($this instanceof Poll);
6685
}
6786

68-
return self::ANON_PRIVACY;
87+
// in all other cases, don't anonymize the entity
88+
return false;
6989
}
7090

71-
public function getIsOwner(): bool {
72-
return Container::queryClass(UserSession::class)->getCurrentUserId() === $this->getUserId();
73-
}
7491

92+
/**
93+
* @return UserBase Gets owner of the entity
94+
*/
7595
public function getUser(): UserBase {
76-
/** @var UserMapper */
77-
$userMapper = (Container::queryClass(UserMapper::class));
96+
if ($this->getEntityAnonymization()) {
97+
$user = new Anon($this->getUserId());
98+
return $user;
99+
}
100+
101+
$userMapper = (Server::get(UserMapper::class));
102+
78103
$user = $userMapper->getParticipant($this->getUserId(), $this->getPollId());
79-
$user->setAnonymizeLevel($this->getAnonymizeLevel());
80104
return $user;
81105
}
82106
}

lib/Db/Option.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public function jsonSerialize(): array {
117117
'duration' => $this->getDuration(),
118118
'locked' => $this->getIsLocked(),
119119
'hash' => $this->getPollOptionHash(),
120-
'isOwner' => $this->getIsOwner(),
120+
'isOwner' => $this->getCurrentUserIsEntityUser(),
121121
'votes' => $this->getVotes(),
122122
'owner' => $this->getOwnerUser(),
123123
];

lib/Db/OptionMapper.php

+1
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ protected function buildQuery(bool $hideResults = false): IQueryBuilder {
173173
$this->joinCurrentUserVote($qb, self::TABLE, $currentUserId);
174174
$this->joinCurrentUserVoteCount($qb, self::TABLE, $currentUserId);
175175
$this->joinAnon($qb, self::TABLE);
176+
$this->joinShareRole($qb, self::TABLE, $currentUserId);
176177

177178

178179
return $qb;

0 commit comments

Comments
 (0)