diff --git a/lib/Db/Share.php b/lib/Db/Share.php
index f8e54237a..ccf3f479e 100644
--- a/lib/Db/Share.php
+++ b/lib/Db/Share.php
@@ -69,12 +69,16 @@ class Share extends EntityWithUser implements JsonSerializable {
public const TYPE_CONTACTGROUP = 'contactGroup';
+ public const CONVERATABLE_PUBLIC_SHARES = [
+ self::TYPE_EMAIL,
+ self::TYPE_CONTACT,
+ ];
+
// Share types, that are allowed for public access (without login)
public const SHARE_PUBLIC_ACCESS_ALLOWED = [
self::TYPE_PUBLIC,
- self::TYPE_CONTACT,
- self::TYPE_EMAIL,
self::TYPE_EXTERNAL,
+ ...self::CONVERATABLE_PUBLIC_SHARES,
];
// Share types, that are allowed for authenticated access (with login)
diff --git a/lib/Service/ShareService.php b/lib/Service/ShareService.php
index 24c374ef4..16c4b4784 100644
--- a/lib/Service/ShareService.php
+++ b/lib/Service/ShareService.php
@@ -36,9 +36,15 @@
use OCP\DB\Exception;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Security\ISecureRandom;
+use phpDocumentor\Reflection\Types\This;
use Psr\Log\LoggerInterface;
class ShareService {
+ private const SHARES_TO_CONVERT_ON_ACCESS = [
+ Share::TYPE_EMAIL,
+ Share::TYPE_CONTACT,
+ ];
+
/** @var Share[] * */
private array $shares;
@@ -107,7 +113,7 @@ public function listNotInvited(int $pollId): array {
* If user is not authorized for this poll, create a personal share
* for this user and return the created share instead of the public share
*/
- private function convertPublicToPersonalShare(): void {
+ private function convertPublicShareToPersonalShare(): void {
try {
$this->share = $this->createNewShare(
$this->share->getPollId(),
@@ -128,6 +134,7 @@ private function convertPublicToPersonalShare(): void {
* @param string $token Token of share to get
*/
public function request(string $token): Share {
+
$this->share = $this->shareMapper->findByToken($token);
$this->validateShareType();
@@ -139,8 +146,14 @@ public function request(string $token): Share {
// Exception: logged in user, accesses the poll via public share link
if ($this->share->getType() === Share::TYPE_PUBLIC && $this->userSession->getIsLoggedIn()) {
- $this->convertPublicToPersonalShare();
+ $this->convertPublicShareToPersonalShare();
+ }
+
+ // Exception for convertable (email and contact) shares
+ if (in_array($this->share->getType(), Share::CONVERATABLE_PUBLIC_SHARES, true)) {
+ $this->convertPersonalPublicShareToExternalShare();
}
+
return $this->share;
}
@@ -270,9 +283,55 @@ public function deleteEmailAddress(Share $share): Share {
}
}
+ /**
+ * Convert convertable public shares to external share and generates a unique user id
+ * @param string|null $userId
+ * @param string|null $displayName
+ * @param string|null $emailAddress
+ * @param string|null $timeZone
+ * @param string|null $language
+ */
+ private function convertPersonalPublicShareToExternalShare(
+ string|null $userId = null,
+ string|null $displayName = null,
+ string|null $emailAddress = null,
+ string|null $timeZone = null,
+ string|null $language = null,
+ ): void {
+
+ // paranoia double check
+ if (!in_array($this->share->getType(), Share::CONVERATABLE_PUBLIC_SHARES, true)) {
+ return;
+ }
+
+ $this->share->setUserId($userId ?? $this->generatePublicUserId());
+ $this->share->setDisplayName($displayName ?? $this->share->getDisplayName());
+ $this->share->setTimeZoneName($timeZone ?? $this->share->getTimeZoneName());
+ $this->share->setLanguage($language ?? $this->share->getLanguage());
+
+ if ($emailAddress && $emailAddress !== $this->share->getEmailAddress()) {
+ // reset invitation sent, if email address is changed
+ $this->share->setInvitationSent(0);
+ }
+
+ $this->share->setEmailAddress($emailAddress ?? $this->share->getEmailAddress());
+
+ // convert to type external
+ $this->share->setType(Share::TYPE_EXTERNAL);
+
+ // remove personal information from user id
+ $this->share->setUserId($this->generatePublicUserId());
+ $this->share = $this->shareMapper->update($this->share);
+ }
+
/**
* Create a personal share from a public share
* or update an email share with the displayName
+ * @param string $publicShareToken
+ * @param string $displayName
+ * @param string $emailAddress
+ * @param string $timeZone
+ * @return Share
*/
public function register(
string $publicShareToken,
@@ -300,23 +359,12 @@ public function register(
$timeZone
);
$this->eventDispatcher->dispatchTyped(new ShareRegistrationEvent($this->share));
- } elseif (
- $this->share->getType() === Share::TYPE_EMAIL
- || $this->share->getType() === Share::TYPE_CONTACT
- ) {
+
+ } elseif (in_array($this->share->getType(), Share::CONVERATABLE_PUBLIC_SHARES, true)) {
// Convert email and contact shares to external share, if user registers
- $this->share->setType(Share::TYPE_EXTERNAL);
- $this->share->setUserId($userId);
- $this->share->setDisplayName($displayName);
- $this->share->setTimeZoneName($timeZone);
- $this->share->setLanguage($language);
+ // this should be avoided by the actual use cases, but keep code in case of later changes
+ $this->convertPersonalPublicShareToExternalShare($userId, $displayName, $emailAddress, $timeZone, $language);
- // prepare for resending invitation to new email address
- if ($emailAddress !== $this->share->getEmailAddress()) {
- $this->share->setInvitationSent(0);
- }
- $this->share->setEmailAddress($emailAddress);
- $this->shareMapper->update($this->share);
} else {
throw new ForbiddenException('Share does not allow registering for poll');
}
diff --git a/src/js/components/User/UserMenu.vue b/src/js/components/User/UserMenu.vue
index 048d54db4..16cbc86ef 100644
--- a/src/js/components/User/UserMenu.vue
+++ b/src/js/components/User/UserMenu.vue
@@ -17,7 +17,7 @@
-
{{ t('polls', 'Edit Email Address') }}
-
{{ t('polls', 'Subscribe to notifications') }}
-