Skip to content

Commit

Permalink
send existing shares to mail address on new member
Browse files Browse the repository at this point in the history
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
  • Loading branch information
ArtificialOwl committed Jul 10, 2020
1 parent f8d8246 commit bf82e57
Show file tree
Hide file tree
Showing 3 changed files with 261 additions and 7 deletions.
2 changes: 1 addition & 1 deletion lib/Circles/FileSharingBroadcaster.php
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ public function sendMailExitingShares(
}

try {
$template = $this->generateMailExitingShares($author, $circleName);
$template = $this->generateMailExitingShares($author, $circle->getName());
$this->fillMailExistingShares($template, $data);
$this->sendMailExistingShares($template, $author, $recipient);
$this->sendPasswordExistingShares($author, $recipient, $password);
Expand Down
7 changes: 7 additions & 0 deletions lib/GlobalScale/AGlobalScaleEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
use OCA\Circles\Service\MiscService;
use OCP\Defaults;
use OCP\Files\IRootFolder;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Mail\IMailer;
Expand All @@ -68,6 +69,9 @@ abstract class AGlobalScaleEvent {
/** @var IURLGenerator */
protected $urlGenerator;

/** @var IL10N */
protected $l10n;

/** @var IMailer */
protected $mailer;

Expand Down Expand Up @@ -113,6 +117,7 @@ abstract class AGlobalScaleEvent {
*
* @param IRootFolder $rootFolder
* @param IURLGenerator $urlGenerator
* @param IL10N $l10n
* @param IMailer $mailer
* @param Defaults $defaults
* @param IUserManager $userManager
Expand All @@ -130,6 +135,7 @@ abstract class AGlobalScaleEvent {
public function __construct(
IRootFolder $rootFolder,
IURLGenerator $urlGenerator,
IL10N $l10n,
IMailer $mailer,
Defaults $defaults,
IUserManager $userManager,
Expand All @@ -146,6 +152,7 @@ public function __construct(
) {
$this->rootFolder = $rootFolder;
$this->urlGenerator = $urlGenerator;
$this->l10n = $l10n;
$this->mailer = $mailer;
$this->defaults = $defaults;
$this->userManager = $userManager;
Expand Down
259 changes: 253 additions & 6 deletions lib/GlobalScale/MemberAdd.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@


use daita\MySmallPhpTools\Model\SimpleDataStore;
use Exception;
use OC\User\NoUserException;
use OCA\Circles\Exceptions\CircleDoesNotExistException;
use OCA\Circles\Exceptions\CircleTypeNotValidException;
Expand All @@ -42,7 +43,14 @@
use OCA\Circles\Exceptions\MemberCantJoinCircleException;
use OCA\Circles\Exceptions\MemberIsNotModeratorException;
use OCA\Circles\Exceptions\MembersLimitException;
use OCA\Circles\Exceptions\TokenDoesNotExistException;
use OCA\Circles\Model\Circle;
use OCA\Circles\Model\GlobalScale\GSEvent;
use OCA\Circles\Model\Member;
use OCA\Circles\Model\SharesToken;
use OCP\IUser;
use OCP\Mail\IEMailTemplate;
use OCP\Util;


/**
Expand Down Expand Up @@ -86,6 +94,8 @@ public function verify(GSEvent $event, bool $localCheck = false, bool $mustBeChe
);

$circle = $event->getCircle();
// $this->storeAuthorFromEvent($circle);

if (!$event->isForced()) {
$circle->getHigherViewer()
->hasToBeModerator();
Expand All @@ -99,6 +109,12 @@ public function verify(GSEvent $event, bool $localCheck = false, bool $mustBeChe
$this->circlesService->checkThatCircleIsNotFull($circle);
$this->membersService->addMemberBasedOnItsType($circle, $member);

$password = '';
if ($this->configService->enforcePasswordProtection($circle)) {
$password = $this->miscService->token(15);
}

$event->setData(new SimpleDataStore(['password' => $password]));
$event->setMember($member);
}

Expand All @@ -117,6 +133,11 @@ public function manage(GSEvent $event): void {
$this->membersRequest->updateMember($member);
}

$password = $event->getData()
->g('password');
$shares = $this->generateUnknownSharesLinks($circle, $member, $password);

$event->setResult(new SimpleDataStore(['unknownShares' => $shares]));
$this->eventsService->onMemberNew($circle, $member);
}

Expand All @@ -125,12 +146,238 @@ public function manage(GSEvent $event): void {
* @param GSEvent[] $events
*/
public function result(array $events): void {
// $instances = array_keys($events);
// foreach ($instances as $instance) {
// $event = $events[$instance];
// $this->miscService->log('---- ' . $instance . ' -- ' . json_encode($event->getResult()));
// }
$password = '';
$circle = $member = null;
$links = [];
foreach ($events as $event) {
$password = $event->getData()
->g('password');

$circle = $event->getCircle();
$member = $event->getMember();

$links = array_merge(
$links, $event->getResult()
->gArray('unknownShares')
);
}

if ($circle->getViewer() === null) {
$author = $circle->getOwner()
->getUserId();
} else {
$author = $circle->getViewer()
->getUserId();
}
$recipient = $member->getUserId();

try {
$template = $this->generateMailExitingShares($author, $circle->getName());
$this->fillMailExistingShares($template, $links);
$this->sendMailExistingShares($template, $author, $recipient);
$this->sendPasswordExistingShares($author, $recipient, $password);
} catch (Exception $e) {
$this->miscService->log('Failed to send mail about existing share ' . $e->getMessage());
}
}

}

/**
* @param Circle $circle
* @param Member $member
* @param string $password
*
* @return array
*/
private function generateUnknownSharesLinks(Circle $circle, Member $member, string $password): array {
$unknownShares = $this->getUnknownShares($member);

$data = [];
foreach ($unknownShares as $share) {
try {
$data[] = $this->getMailLinkFromShare($share, $member, $password);
} catch (TokenDoesNotExistException $e) {
}
}

return $data;
}


/**
* @param Member $member
*
* @return array
*/
private function getUnknownShares(Member $member): array {
$allShares = $this->sharesRequest->getSharesForCircle($member->getCircleId());
$knownShares = array_map(
function(SharesToken $shareToken) {
return $shareToken->getShareId();
},
$this->tokensRequest->getTokensFromMember($member)
);

$unknownShares = [];
foreach ($allShares as $share) {
if (!in_array($share['id'], $knownShares)) {
$unknownShares[] = $share;
}
}

return $unknownShares;
}


/**
* @param array $share
* @param Member $member
* @param string $password
*
* @return array
* @throws TokenDoesNotExistException
*/
private function getMailLinkFromShare(array $share, Member $member, string $password = '') {
$sharesToken = $this->tokensRequest->generateTokenForMember($member, (int)$share['id'], $password);
$link = $this->urlGenerator->linkToRouteAbsolute(
'files_sharing.sharecontroller.showShare',
['token' => $sharesToken->getToken()]
);
$author = $share['uid_initiator'];
$filename = basename($share['file_target']);

return [
'author' => $author,
'link' => $link,
'filename' => $filename
];
}


/**
* @param string $author
* @param string $circleName
*
* @return IEMailTemplate
*/
private function generateMailExitingShares(string $author, string $circleName): IEMailTemplate {
$emailTemplate = $this->mailer->createEMailTemplate('circles.ExistingShareNotification', []);
$emailTemplate->addHeader();

$text = $this->l10n->t('%s shared multiple files with \'%s\'.', [$author, $circleName]);
$emailTemplate->addBodyText(htmlspecialchars($text), $text);

return $emailTemplate;
}

/**
* @param IEMailTemplate $emailTemplate
* @param array $links
*/
private function fillMailExistingShares(IEMailTemplate $emailTemplate, array $links) {
foreach ($links as $item) {
$emailTemplate->addBodyButton(
$this->l10n->t('Open »%s«', [htmlspecialchars($item['filename'])]), $item['link']
);
}
}


/**
* @param IEMailTemplate $emailTemplate
* @param string $author
* @param string $recipient
*
* @throws Exception
*/
private function sendMailExistingShares(IEMailTemplate $emailTemplate, string $author, string $recipient
) {
$subject = $this->l10n->t('%s shared multiple files with you.', [$author]);

$instanceName = $this->defaults->getName();
$senderName = $this->l10n->t('%s on %s', [$author, $instanceName]);

$message = $this->mailer->createMessage();

$message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
$message->setSubject($subject);
$message->setPlainBody($emailTemplate->renderText());
$message->setHtmlBody($emailTemplate->renderHtml());
$message->setTo([$recipient]);

$this->mailer->send($message);
}


/**
* @param string $author
* @param string $email
* @param string $password
*
* @throws Exception
*/
protected function sendPasswordExistingShares(string $author, string $email, string $password) {
if ($password === '') {
return;
}

$message = $this->mailer->createMessage();

$authorUser = $this->userManager->get($author);
$authorName = ($authorUser instanceof IUser) ? $authorUser->getDisplayName() : $author;
$authorEmail = ($authorUser instanceof IUser) ? $authorUser->getEMailAddress() : null;

$this->miscService->log("Sending password mail about existing files to '" . $email . "'", 0);

$plainBodyPart = $this->l10n->t(
"%1\$s shared multiple files with you.\nYou should have already received a separate mail with a link to access them.\n",
[$authorName]
);
$htmlBodyPart = $this->l10n->t(
'%1$s shared multiple files with you. You should have already received a separate mail with a link to access them.',
[$authorName]
);

$emailTemplate = $this->mailer->createEMailTemplate(
'sharebymail.RecipientPasswordNotification', [
'password' => $password,
'author' => $author
]
);

$emailTemplate->setSubject(
$this->l10n->t(
'Password to access files shared to you by %1$s', [$authorName]
)
);
$emailTemplate->addHeader();
$emailTemplate->addHeading($this->l10n->t('Password to access files'), false);
$emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
$emailTemplate->addBodyText($this->l10n->t('It is protected with the following password:'));
$emailTemplate->addBodyText($password);

// The "From" contains the sharers name
$instanceName = $this->defaults->getName();
$senderName = $this->l10n->t(
'%1$s via %2$s',
[
$authorName,
$instanceName
]
);

$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
if ($authorEmail !== null) {
$message->setReplyTo([$authorEmail => $authorName]);
$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
} else {
$emailTemplate->addFooter();
}

$message->setTo([$email]);
$message->useTemplate($emailTemplate);
$this->mailer->send($message);
}


}

0 comments on commit bf82e57

Please sign in to comment.