| @@ 61-447 (lines=387) @@ | ||
| 58 | * |
|
| 59 | * @package OCA\Circles\GlobalScale |
|
| 60 | */ |
|
| 61 | class MemberAdd extends AGlobalScaleEvent { |
|
| 62 | ||
| 63 | ||
| 64 | /** |
|
| 65 | * @param GSEvent $event |
|
| 66 | * @param bool $localCheck |
|
| 67 | * @param bool $mustBeChecked |
|
| 68 | * |
|
| 69 | * @throws CircleDoesNotExistException |
|
| 70 | * @throws ConfigNoCircleAvailableException |
|
| 71 | * @throws EmailAccountInvalidFormatException |
|
| 72 | * @throws GlobalScaleDSyncException |
|
| 73 | * @throws GlobalScaleEventException |
|
| 74 | * @throws MemberAlreadyExistsException |
|
| 75 | * @throws MemberCantJoinCircleException |
|
| 76 | * @throws MembersLimitException |
|
| 77 | * @throws NoUserException |
|
| 78 | * @throws CircleTypeNotValidException |
|
| 79 | * @throws MemberIsNotModeratorException |
|
| 80 | */ |
|
| 81 | public function verify(GSEvent $event, bool $localCheck = false, bool $mustBeChecked = false): void { |
|
| 82 | parent::verify($event, $localCheck, true); |
|
| 83 | ||
| 84 | $eventMember = $event->getMember(); |
|
| 85 | $this->cleanMember($eventMember); |
|
| 86 | ||
| 87 | if ($eventMember->getInstance() === '') { |
|
| 88 | $eventMember->setInstance($event->getSource()); |
|
| 89 | } |
|
| 90 | ||
| 91 | $ident = $eventMember->getUserId(); |
|
| 92 | $this->membersService->verifyIdentBasedOnItsType( |
|
| 93 | $ident, $eventMember->getType(), $eventMember->getInstance() |
|
| 94 | ); |
|
| 95 | ||
| 96 | $circle = $event->getDeprecatedCircle(); |
|
| 97 | ||
| 98 | if (!$event->isForced()) { |
|
| 99 | $circle->getHigherViewer() |
|
| 100 | ->hasToBeModerator(); |
|
| 101 | } |
|
| 102 | ||
| 103 | $member = $this->membersRequest->getFreshNewMember( |
|
| 104 | $circle->getUniqueId(), $ident, $eventMember->getType(), $eventMember->getInstance() |
|
| 105 | ); |
|
| 106 | $member->hasToBeInviteAble(); |
|
| 107 | $member->setCachedName($eventMember->getCachedName()); |
|
| 108 | ||
| 109 | $this->circlesService->checkThatCircleIsNotFull($circle); |
|
| 110 | $this->membersService->addMemberBasedOnItsType($circle, $member); |
|
| 111 | ||
| 112 | $password = ''; |
|
| 113 | $sendPasswordByMail = false; |
|
| 114 | if ($this->configService->enforcePasswordProtection($circle)) { |
|
| 115 | if ($circle->getSetting('password_single_enabled') === 'true') { |
|
| 116 | $password = $circle->getPasswordSingle(); |
|
| 117 | } else { |
|
| 118 | $sendPasswordByMail = true; |
|
| 119 | $password = $this->miscService->token(15); |
|
| 120 | } |
|
| 121 | } |
|
| 122 | ||
| 123 | $event->setData( |
|
| 124 | new SimpleDataStore( |
|
| 125 | [ |
|
| 126 | 'password' => $password, |
|
| 127 | 'passwordByMail' => $sendPasswordByMail |
|
| 128 | ] |
|
| 129 | ) |
|
| 130 | ); |
|
| 131 | $event->setMember($member); |
|
| 132 | } |
|
| 133 | ||
| 134 | ||
| 135 | /** |
|
| 136 | * @param GSEvent $event |
|
| 137 | * |
|
| 138 | * @throws MemberAlreadyExistsException |
|
| 139 | */ |
|
| 140 | public function manage(GSEvent $event): void { |
|
| 141 | $circle = $event->getDeprecatedCircle(); |
|
| 142 | $member = $event->getMember(); |
|
| 143 | if ($member->getJoined() === '') { |
|
| 144 | $this->membersRequest->createMember($member); |
|
| 145 | } else { |
|
| 146 | $this->membersRequest->updateMemberLevel($member); |
|
| 147 | } |
|
| 148 | ||
| 149 | ||
| 150 | // |
|
| 151 | // TODO: verifiez comment se passe le cached name sur un member_add |
|
| 152 | // |
|
| 153 | $cachedName = $member->getCachedName(); |
|
| 154 | $password = $event->getData() |
|
| 155 | ->g('password'); |
|
| 156 | ||
| 157 | $shares = $this->generateUnknownSharesLinks($circle, $member, $password); |
|
| 158 | $result = [ |
|
| 159 | 'unknownShares' => $shares, |
|
| 160 | 'cachedName' => $cachedName |
|
| 161 | ]; |
|
| 162 | ||
| 163 | if ($member->getType() === DeprecatedMember::TYPE_CONTACT |
|
| 164 | && $this->configService->isLocalInstance($member->getInstance())) { |
|
| 165 | $result['contact'] = $this->miscService->getInfosFromContact($member); |
|
| 166 | } |
|
| 167 | ||
| 168 | $event->setResult(new SimpleDataStore($result)); |
|
| 169 | $this->eventsService->onMemberNew($circle, $member); |
|
| 170 | } |
|
| 171 | ||
| 172 | ||
| 173 | /** |
|
| 174 | * @param GSEvent[] $events |
|
| 175 | * |
|
| 176 | * @throws Exception |
|
| 177 | */ |
|
| 178 | public function result(array $events): void { |
|
| 179 | $password = $cachedName = ''; |
|
| 180 | $circle = $member = null; |
|
| 181 | $links = []; |
|
| 182 | $recipients = []; |
|
| 183 | foreach ($events as $event) { |
|
| 184 | $data = $event->getData(); |
|
| 185 | if ($data->gBool('passwordByMail') !== false) { |
|
| 186 | $password = $data->g('password'); |
|
| 187 | } |
|
| 188 | $circle = $event->getDeprecatedCircle(); |
|
| 189 | $member = $event->getMember(); |
|
| 190 | $result = $event->getResult(); |
|
| 191 | if ($result->g('cachedName') !== '') { |
|
| 192 | $cachedName = $result->g('cachedName'); |
|
| 193 | } |
|
| 194 | ||
| 195 | $links = array_merge($links, $result->gArray('unknownShares')); |
|
| 196 | $contact = $result->gArray('contact'); |
|
| 197 | if (!empty($contact)) { |
|
| 198 | $recipients = $contact['emails']; |
|
| 199 | } |
|
| 200 | } |
|
| 201 | ||
| 202 | if (empty($links) || $circle === null || $member === null) { |
|
| 203 | return; |
|
| 204 | } |
|
| 205 | ||
| 206 | if ($cachedName !== '') { |
|
| 207 | $member->setCachedName($cachedName); |
|
| 208 | $this->membersService->updateMember($member); |
|
| 209 | } |
|
| 210 | ||
| 211 | if ($member->getType() === DeprecatedMember::TYPE_MAIL |
|
| 212 | || $member->getType() === DeprecatedMember::TYPE_CONTACT) { |
|
| 213 | if ($member->getType() === DeprecatedMember::TYPE_MAIL) { |
|
| 214 | $recipients = [$member->getUserId()]; |
|
| 215 | } |
|
| 216 | ||
| 217 | foreach ($recipients as $recipient) { |
|
| 218 | $this->memberIsMailbox($circle, $recipient, $links, $password); |
|
| 219 | } |
|
| 220 | } |
|
| 221 | } |
|
| 222 | ||
| 223 | ||
| 224 | /** |
|
| 225 | * @param DeprecatedCircle $circle |
|
| 226 | * @param string $recipient |
|
| 227 | * @param array $links |
|
| 228 | * @param string $password |
|
| 229 | */ |
|
| 230 | private function memberIsMailbox(DeprecatedCircle $circle, string $recipient, array $links, string $password) { |
|
| 231 | if ($circle->getViewer() === null) { |
|
| 232 | $author = $circle->getOwner() |
|
| 233 | ->getUserId(); |
|
| 234 | } else { |
|
| 235 | $author = $circle->getViewer() |
|
| 236 | ->getUserId(); |
|
| 237 | } |
|
| 238 | ||
| 239 | try { |
|
| 240 | $template = $this->generateMailExitingShares($author, $circle->getName()); |
|
| 241 | $this->fillMailExistingShares($template, $links); |
|
| 242 | $this->sendMailExistingShares($template, $author, $recipient); |
|
| 243 | $this->sendPasswordExistingShares($author, $recipient, $password); |
|
| 244 | } catch (Exception $e) { |
|
| 245 | $this->miscService->log('Failed to send mail about existing share ' . $e->getMessage()); |
|
| 246 | } |
|
| 247 | } |
|
| 248 | ||
| 249 | ||
| 250 | /** |
|
| 251 | * @param DeprecatedCircle $circle |
|
| 252 | * @param DeprecatedMember $member |
|
| 253 | * @param string $password |
|
| 254 | * |
|
| 255 | * @return array |
|
| 256 | */ |
|
| 257 | private function generateUnknownSharesLinks(DeprecatedCircle $circle, DeprecatedMember $member, string $password): array { |
|
| 258 | $unknownShares = $this->getUnknownShares($member); |
|
| 259 | ||
| 260 | $data = []; |
|
| 261 | foreach ($unknownShares as $share) { |
|
| 262 | try { |
|
| 263 | $data[] = $this->getMailLinkFromShare($share, $member, $password); |
|
| 264 | } catch (TokenDoesNotExistException $e) { |
|
| 265 | } |
|
| 266 | } |
|
| 267 | ||
| 268 | return $data; |
|
| 269 | } |
|
| 270 | ||
| 271 | ||
| 272 | /** |
|
| 273 | * @param DeprecatedMember $member |
|
| 274 | * |
|
| 275 | * @return array |
|
| 276 | */ |
|
| 277 | private function getUnknownShares(DeprecatedMember $member): array { |
|
| 278 | $allShares = $this->sharesRequest->getSharesForCircle($member->getCircleId()); |
|
| 279 | $knownShares = array_map( |
|
| 280 | function(SharesToken $shareToken) { |
|
| 281 | return $shareToken->getShareId(); |
|
| 282 | }, |
|
| 283 | $this->tokensRequest->getTokensFromMember($member) |
|
| 284 | ); |
|
| 285 | ||
| 286 | $unknownShares = []; |
|
| 287 | foreach ($allShares as $share) { |
|
| 288 | if (!in_array($share['id'], $knownShares)) { |
|
| 289 | $unknownShares[] = $share; |
|
| 290 | } |
|
| 291 | } |
|
| 292 | ||
| 293 | return $unknownShares; |
|
| 294 | } |
|
| 295 | ||
| 296 | ||
| 297 | /** |
|
| 298 | * @param array $share |
|
| 299 | * @param DeprecatedMember $member |
|
| 300 | * @param string $password |
|
| 301 | * |
|
| 302 | * @return array |
|
| 303 | * @throws TokenDoesNotExistException |
|
| 304 | */ |
|
| 305 | private function getMailLinkFromShare(array $share, DeprecatedMember $member, string $password = '') { |
|
| 306 | $sharesToken = $this->tokensRequest->generateTokenForMember($member, (int)$share['id'], $password); |
|
| 307 | $link = $this->urlGenerator->linkToRouteAbsolute( |
|
| 308 | 'files_sharing.sharecontroller.showShare', |
|
| 309 | ['token' => $sharesToken->getToken()] |
|
| 310 | ); |
|
| 311 | $author = $share['uid_initiator']; |
|
| 312 | $filename = basename($share['file_target']); |
|
| 313 | ||
| 314 | return [ |
|
| 315 | 'author' => $author, |
|
| 316 | 'link' => $link, |
|
| 317 | 'filename' => $filename |
|
| 318 | ]; |
|
| 319 | } |
|
| 320 | ||
| 321 | ||
| 322 | /** |
|
| 323 | * @param string $author |
|
| 324 | * @param string $circleName |
|
| 325 | * |
|
| 326 | * @return IEMailTemplate |
|
| 327 | */ |
|
| 328 | private function generateMailExitingShares(string $author, string $circleName): IEMailTemplate { |
|
| 329 | $emailTemplate = $this->mailer->createEMailTemplate('circles.ExistingShareNotification', []); |
|
| 330 | $emailTemplate->addHeader(); |
|
| 331 | ||
| 332 | $text = $this->l10n->t('%s shared multiple files with \'%s\'.', [$author, $circleName]); |
|
| 333 | $emailTemplate->addBodyText(htmlspecialchars($text), $text); |
|
| 334 | ||
| 335 | return $emailTemplate; |
|
| 336 | } |
|
| 337 | ||
| 338 | /** |
|
| 339 | * @param IEMailTemplate $emailTemplate |
|
| 340 | * @param array $links |
|
| 341 | */ |
|
| 342 | private function fillMailExistingShares(IEMailTemplate $emailTemplate, array $links) { |
|
| 343 | foreach ($links as $item) { |
|
| 344 | $emailTemplate->addBodyButton( |
|
| 345 | $this->l10n->t('Open »%s«', [htmlspecialchars($item['filename'])]), $item['link'] |
|
| 346 | ); |
|
| 347 | } |
|
| 348 | } |
|
| 349 | ||
| 350 | ||
| 351 | /** |
|
| 352 | * @param IEMailTemplate $emailTemplate |
|
| 353 | * @param string $author |
|
| 354 | * @param string $recipient |
|
| 355 | * |
|
| 356 | * @throws Exception |
|
| 357 | */ |
|
| 358 | private function sendMailExistingShares(IEMailTemplate $emailTemplate, string $author, string $recipient |
|
| 359 | ) { |
|
| 360 | $subject = $this->l10n->t('%s shared multiple files with you.', [$author]); |
|
| 361 | ||
| 362 | $instanceName = $this->defaults->getName(); |
|
| 363 | $senderName = $this->l10n->t('%s on %s', [$author, $instanceName]); |
|
| 364 | ||
| 365 | $message = $this->mailer->createMessage(); |
|
| 366 | ||
| 367 | $message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]); |
|
| 368 | $message->setSubject($subject); |
|
| 369 | $message->setPlainBody($emailTemplate->renderText()); |
|
| 370 | $message->setHtmlBody($emailTemplate->renderHtml()); |
|
| 371 | $message->setTo([$recipient]); |
|
| 372 | ||
| 373 | $this->mailer->send($message); |
|
| 374 | } |
|
| 375 | ||
| 376 | ||
| 377 | /** |
|
| 378 | * @param string $author |
|
| 379 | * @param string $email |
|
| 380 | * @param string $password |
|
| 381 | * |
|
| 382 | * @throws Exception |
|
| 383 | */ |
|
| 384 | protected function sendPasswordExistingShares(string $author, string $email, string $password) { |
|
| 385 | if ($password === '') { |
|
| 386 | return; |
|
| 387 | } |
|
| 388 | ||
| 389 | $message = $this->mailer->createMessage(); |
|
| 390 | ||
| 391 | $authorUser = $this->userManager->get($author); |
|
| 392 | $authorName = ($authorUser instanceof IUser) ? $authorUser->getDisplayName() : $author; |
|
| 393 | $authorEmail = ($authorUser instanceof IUser) ? $authorUser->getEMailAddress() : null; |
|
| 394 | ||
| 395 | $this->miscService->log("Sending password mail about existing files to '" . $email . "'", 0); |
|
| 396 | ||
| 397 | $plainBodyPart = $this->l10n->t( |
|
| 398 | "%1\$s shared multiple files with you.\nYou should have already received a separate mail with a link to access them.\n", |
|
| 399 | [$authorName] |
|
| 400 | ); |
|
| 401 | $htmlBodyPart = $this->l10n->t( |
|
| 402 | '%1$s shared multiple files with you. You should have already received a separate mail with a link to access them.', |
|
| 403 | [$authorName] |
|
| 404 | ); |
|
| 405 | ||
| 406 | $emailTemplate = $this->mailer->createEMailTemplate( |
|
| 407 | 'sharebymail.RecipientPasswordNotification', [ |
|
| 408 | 'password' => $password, |
|
| 409 | 'author' => $author |
|
| 410 | ] |
|
| 411 | ); |
|
| 412 | ||
| 413 | $emailTemplate->setSubject( |
|
| 414 | $this->l10n->t( |
|
| 415 | 'Password to access files shared to you by %1$s', [$authorName] |
|
| 416 | ) |
|
| 417 | ); |
|
| 418 | $emailTemplate->addHeader(); |
|
| 419 | $emailTemplate->addHeading($this->l10n->t('Password to access files'), false); |
|
| 420 | $emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart); |
|
| 421 | $emailTemplate->addBodyText($this->l10n->t('It is protected with the following password:')); |
|
| 422 | $emailTemplate->addBodyText($password); |
|
| 423 | ||
| 424 | // The "From" contains the sharers name |
|
| 425 | $instanceName = $this->defaults->getName(); |
|
| 426 | $senderName = $this->l10n->t( |
|
| 427 | '%1$s via %2$s', |
|
| 428 | [ |
|
| 429 | $authorName, |
|
| 430 | $instanceName |
|
| 431 | ] |
|
| 432 | ); |
|
| 433 | ||
| 434 | $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]); |
|
| 435 | if ($authorEmail !== null) { |
|
| 436 | $message->setReplyTo([$authorEmail => $authorName]); |
|
| 437 | $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan()); |
|
| 438 | } else { |
|
| 439 | $emailTemplate->addFooter(); |
|
| 440 | } |
|
| 441 | ||
| 442 | $message->setTo([$email]); |
|
| 443 | $message->useTemplate($emailTemplate); |
|
| 444 | $this->mailer->send($message); |
|
| 445 | } |
|
| 446 | ||
| 447 | } |
|
| 448 | ||
| @@ 63-449 (lines=387) @@ | ||
| 60 | * |
|
| 61 | * @package OCA\Circles\GlobalScale |
|
| 62 | */ |
|
| 63 | class MemberAdd extends AGlobalScaleEvent { |
|
| 64 | ||
| 65 | ||
| 66 | /** |
|
| 67 | * @param GSEvent $event |
|
| 68 | * @param bool $localCheck |
|
| 69 | * @param bool $mustBeChecked |
|
| 70 | * |
|
| 71 | * @throws CircleDoesNotExistException |
|
| 72 | * @throws ConfigNoCircleAvailableException |
|
| 73 | * @throws EmailAccountInvalidFormatException |
|
| 74 | * @throws GlobalScaleDSyncException |
|
| 75 | * @throws GlobalScaleEventException |
|
| 76 | * @throws MemberAlreadyExistsException |
|
| 77 | * @throws MemberCantJoinCircleException |
|
| 78 | * @throws MembersLimitException |
|
| 79 | * @throws NoUserException |
|
| 80 | * @throws CircleTypeNotValidException |
|
| 81 | * @throws MemberIsNotModeratorException |
|
| 82 | */ |
|
| 83 | public function verify(GSEvent $event, bool $localCheck = false, bool $mustBeChecked = false): void { |
|
| 84 | parent::verify($event, $localCheck, true); |
|
| 85 | ||
| 86 | $eventMember = $event->getMember(); |
|
| 87 | $this->cleanMember($eventMember); |
|
| 88 | ||
| 89 | if ($eventMember->getInstance() === '') { |
|
| 90 | $eventMember->setInstance($event->getSource()); |
|
| 91 | } |
|
| 92 | ||
| 93 | $ident = $eventMember->getUserId(); |
|
| 94 | $this->membersService->verifyIdentBasedOnItsType( |
|
| 95 | $ident, $eventMember->getType(), $eventMember->getInstance() |
|
| 96 | ); |
|
| 97 | ||
| 98 | $circle = $event->getDeprecatedCircle(); |
|
| 99 | ||
| 100 | if (!$event->isForced()) { |
|
| 101 | $circle->getHigherViewer() |
|
| 102 | ->hasToBeModerator(); |
|
| 103 | } |
|
| 104 | ||
| 105 | $member = $this->membersRequest->getFreshNewMember( |
|
| 106 | $circle->getUniqueId(), $ident, $eventMember->getType(), $eventMember->getInstance() |
|
| 107 | ); |
|
| 108 | $member->hasToBeInviteAble(); |
|
| 109 | $member->setCachedName($eventMember->getCachedName()); |
|
| 110 | ||
| 111 | $this->circlesService->checkThatCircleIsNotFull($circle); |
|
| 112 | $this->membersService->addMemberBasedOnItsType($circle, $member); |
|
| 113 | ||
| 114 | $password = ''; |
|
| 115 | $sendPasswordByMail = false; |
|
| 116 | if ($this->configService->enforcePasswordProtection($circle)) { |
|
| 117 | if ($circle->getSetting('password_single_enabled') === 'true') { |
|
| 118 | $password = $circle->getPasswordSingle(); |
|
| 119 | } else { |
|
| 120 | $sendPasswordByMail = true; |
|
| 121 | $password = $this->miscService->token(15); |
|
| 122 | } |
|
| 123 | } |
|
| 124 | ||
| 125 | $event->setData( |
|
| 126 | new SimpleDataStore( |
|
| 127 | [ |
|
| 128 | 'password' => $password, |
|
| 129 | 'passwordByMail' => $sendPasswordByMail |
|
| 130 | ] |
|
| 131 | ) |
|
| 132 | ); |
|
| 133 | $event->setMember($member); |
|
| 134 | } |
|
| 135 | ||
| 136 | ||
| 137 | /** |
|
| 138 | * @param GSEvent $event |
|
| 139 | * |
|
| 140 | * @throws MemberAlreadyExistsException |
|
| 141 | */ |
|
| 142 | public function manage(GSEvent $event): void { |
|
| 143 | $circle = $event->getDeprecatedCircle(); |
|
| 144 | $member = $event->getMember(); |
|
| 145 | if ($member->getJoined() === '') { |
|
| 146 | $this->membersRequest->createMember($member); |
|
| 147 | } else { |
|
| 148 | $this->membersRequest->updateMemberLevel($member); |
|
| 149 | } |
|
| 150 | ||
| 151 | ||
| 152 | // |
|
| 153 | // TODO: verifiez comment se passe le cached name sur un member_add |
|
| 154 | // |
|
| 155 | $cachedName = $member->getCachedName(); |
|
| 156 | $password = $event->getData() |
|
| 157 | ->g('password'); |
|
| 158 | ||
| 159 | $shares = $this->generateUnknownSharesLinks($circle, $member, $password); |
|
| 160 | $result = [ |
|
| 161 | 'unknownShares' => $shares, |
|
| 162 | 'cachedName' => $cachedName |
|
| 163 | ]; |
|
| 164 | ||
| 165 | if ($member->getType() === DeprecatedMember::TYPE_CONTACT |
|
| 166 | && $this->configService->isLocalInstance($member->getInstance())) { |
|
| 167 | $result['contact'] = $this->miscService->getInfosFromContact($member); |
|
| 168 | } |
|
| 169 | ||
| 170 | $event->setResult(new SimpleDataStore($result)); |
|
| 171 | $this->eventsService->onMemberNew($circle, $member); |
|
| 172 | } |
|
| 173 | ||
| 174 | ||
| 175 | /** |
|
| 176 | * @param GSEvent[] $events |
|
| 177 | * |
|
| 178 | * @throws Exception |
|
| 179 | */ |
|
| 180 | public function result(array $events): void { |
|
| 181 | $password = $cachedName = ''; |
|
| 182 | $circle = $member = null; |
|
| 183 | $links = []; |
|
| 184 | $recipients = []; |
|
| 185 | foreach ($events as $event) { |
|
| 186 | $data = $event->getData(); |
|
| 187 | if ($data->gBool('passwordByMail') !== false) { |
|
| 188 | $password = $data->g('password'); |
|
| 189 | } |
|
| 190 | $circle = $event->getDeprecatedCircle(); |
|
| 191 | $member = $event->getMember(); |
|
| 192 | $result = $event->getResult(); |
|
| 193 | if ($result->g('cachedName') !== '') { |
|
| 194 | $cachedName = $result->g('cachedName'); |
|
| 195 | } |
|
| 196 | ||
| 197 | $links = array_merge($links, $result->gArray('unknownShares')); |
|
| 198 | $contact = $result->gArray('contact'); |
|
| 199 | if (!empty($contact)) { |
|
| 200 | $recipients = $contact['emails']; |
|
| 201 | } |
|
| 202 | } |
|
| 203 | ||
| 204 | if (empty($links) || $circle === null || $member === null) { |
|
| 205 | return; |
|
| 206 | } |
|
| 207 | ||
| 208 | if ($cachedName !== '') { |
|
| 209 | $member->setCachedName($cachedName); |
|
| 210 | $this->membersService->updateMember($member); |
|
| 211 | } |
|
| 212 | ||
| 213 | if ($member->getType() === DeprecatedMember::TYPE_MAIL |
|
| 214 | || $member->getType() === DeprecatedMember::TYPE_CONTACT) { |
|
| 215 | if ($member->getType() === DeprecatedMember::TYPE_MAIL) { |
|
| 216 | $recipients = [$member->getUserId()]; |
|
| 217 | } |
|
| 218 | ||
| 219 | foreach ($recipients as $recipient) { |
|
| 220 | $this->memberIsMailbox($circle, $recipient, $links, $password); |
|
| 221 | } |
|
| 222 | } |
|
| 223 | } |
|
| 224 | ||
| 225 | ||
| 226 | /** |
|
| 227 | * @param DeprecatedCircle $circle |
|
| 228 | * @param string $recipient |
|
| 229 | * @param array $links |
|
| 230 | * @param string $password |
|
| 231 | */ |
|
| 232 | private function memberIsMailbox(DeprecatedCircle $circle, string $recipient, array $links, string $password) { |
|
| 233 | if ($circle->getViewer() === null) { |
|
| 234 | $author = $circle->getOwner() |
|
| 235 | ->getUserId(); |
|
| 236 | } else { |
|
| 237 | $author = $circle->getViewer() |
|
| 238 | ->getUserId(); |
|
| 239 | } |
|
| 240 | ||
| 241 | try { |
|
| 242 | $template = $this->generateMailExitingShares($author, $circle->getName()); |
|
| 243 | $this->fillMailExistingShares($template, $links); |
|
| 244 | $this->sendMailExistingShares($template, $author, $recipient); |
|
| 245 | $this->sendPasswordExistingShares($author, $recipient, $password); |
|
| 246 | } catch (Exception $e) { |
|
| 247 | $this->miscService->log('Failed to send mail about existing share ' . $e->getMessage()); |
|
| 248 | } |
|
| 249 | } |
|
| 250 | ||
| 251 | ||
| 252 | /** |
|
| 253 | * @param DeprecatedCircle $circle |
|
| 254 | * @param DeprecatedMember $member |
|
| 255 | * @param string $password |
|
| 256 | * |
|
| 257 | * @return array |
|
| 258 | */ |
|
| 259 | private function generateUnknownSharesLinks(DeprecatedCircle $circle, DeprecatedMember $member, string $password): array { |
|
| 260 | $unknownShares = $this->getUnknownShares($member); |
|
| 261 | ||
| 262 | $data = []; |
|
| 263 | foreach ($unknownShares as $share) { |
|
| 264 | try { |
|
| 265 | $data[] = $this->getMailLinkFromShare($share, $member, $password); |
|
| 266 | } catch (TokenDoesNotExistException $e) { |
|
| 267 | } |
|
| 268 | } |
|
| 269 | ||
| 270 | return $data; |
|
| 271 | } |
|
| 272 | ||
| 273 | ||
| 274 | /** |
|
| 275 | * @param DeprecatedMember $member |
|
| 276 | * |
|
| 277 | * @return array |
|
| 278 | */ |
|
| 279 | private function getUnknownShares(DeprecatedMember $member): array { |
|
| 280 | $allShares = $this->sharesRequest->getSharesForCircle($member->getCircleId()); |
|
| 281 | $knownShares = array_map( |
|
| 282 | function(SharesToken $shareToken) { |
|
| 283 | return $shareToken->getShareId(); |
|
| 284 | }, |
|
| 285 | $this->tokensRequest->getTokensFromMember($member) |
|
| 286 | ); |
|
| 287 | ||
| 288 | $unknownShares = []; |
|
| 289 | foreach ($allShares as $share) { |
|
| 290 | if (!in_array($share['id'], $knownShares)) { |
|
| 291 | $unknownShares[] = $share; |
|
| 292 | } |
|
| 293 | } |
|
| 294 | ||
| 295 | return $unknownShares; |
|
| 296 | } |
|
| 297 | ||
| 298 | ||
| 299 | /** |
|
| 300 | * @param array $share |
|
| 301 | * @param DeprecatedMember $member |
|
| 302 | * @param string $password |
|
| 303 | * |
|
| 304 | * @return array |
|
| 305 | * @throws TokenDoesNotExistException |
|
| 306 | */ |
|
| 307 | private function getMailLinkFromShare(array $share, DeprecatedMember $member, string $password = '') { |
|
| 308 | $sharesToken = $this->tokensRequest->generateTokenForMember($member, (int)$share['id'], $password); |
|
| 309 | $link = $this->urlGenerator->linkToRouteAbsolute( |
|
| 310 | 'files_sharing.sharecontroller.showShare', |
|
| 311 | ['token' => $sharesToken->getToken()] |
|
| 312 | ); |
|
| 313 | $author = $share['uid_initiator']; |
|
| 314 | $filename = basename($share['file_target']); |
|
| 315 | ||
| 316 | return [ |
|
| 317 | 'author' => $author, |
|
| 318 | 'link' => $link, |
|
| 319 | 'filename' => $filename |
|
| 320 | ]; |
|
| 321 | } |
|
| 322 | ||
| 323 | ||
| 324 | /** |
|
| 325 | * @param string $author |
|
| 326 | * @param string $circleName |
|
| 327 | * |
|
| 328 | * @return IEMailTemplate |
|
| 329 | */ |
|
| 330 | private function generateMailExitingShares(string $author, string $circleName): IEMailTemplate { |
|
| 331 | $emailTemplate = $this->mailer->createEMailTemplate('circles.ExistingShareNotification', []); |
|
| 332 | $emailTemplate->addHeader(); |
|
| 333 | ||
| 334 | $text = $this->l10n->t('%s shared multiple files with \'%s\'.', [$author, $circleName]); |
|
| 335 | $emailTemplate->addBodyText(htmlspecialchars($text), $text); |
|
| 336 | ||
| 337 | return $emailTemplate; |
|
| 338 | } |
|
| 339 | ||
| 340 | /** |
|
| 341 | * @param IEMailTemplate $emailTemplate |
|
| 342 | * @param array $links |
|
| 343 | */ |
|
| 344 | private function fillMailExistingShares(IEMailTemplate $emailTemplate, array $links) { |
|
| 345 | foreach ($links as $item) { |
|
| 346 | $emailTemplate->addBodyButton( |
|
| 347 | $this->l10n->t('Open »%s«', [htmlspecialchars($item['filename'])]), $item['link'] |
|
| 348 | ); |
|
| 349 | } |
|
| 350 | } |
|
| 351 | ||
| 352 | ||
| 353 | /** |
|
| 354 | * @param IEMailTemplate $emailTemplate |
|
| 355 | * @param string $author |
|
| 356 | * @param string $recipient |
|
| 357 | * |
|
| 358 | * @throws Exception |
|
| 359 | */ |
|
| 360 | private function sendMailExistingShares(IEMailTemplate $emailTemplate, string $author, string $recipient |
|
| 361 | ) { |
|
| 362 | $subject = $this->l10n->t('%s shared multiple files with you.', [$author]); |
|
| 363 | ||
| 364 | $instanceName = $this->defaults->getName(); |
|
| 365 | $senderName = $this->l10n->t('%s on %s', [$author, $instanceName]); |
|
| 366 | ||
| 367 | $message = $this->mailer->createMessage(); |
|
| 368 | ||
| 369 | $message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]); |
|
| 370 | $message->setSubject($subject); |
|
| 371 | $message->setPlainBody($emailTemplate->renderText()); |
|
| 372 | $message->setHtmlBody($emailTemplate->renderHtml()); |
|
| 373 | $message->setTo([$recipient]); |
|
| 374 | ||
| 375 | $this->mailer->send($message); |
|
| 376 | } |
|
| 377 | ||
| 378 | ||
| 379 | /** |
|
| 380 | * @param string $author |
|
| 381 | * @param string $email |
|
| 382 | * @param string $password |
|
| 383 | * |
|
| 384 | * @throws Exception |
|
| 385 | */ |
|
| 386 | protected function sendPasswordExistingShares(string $author, string $email, string $password) { |
|
| 387 | if ($password === '') { |
|
| 388 | return; |
|
| 389 | } |
|
| 390 | ||
| 391 | $message = $this->mailer->createMessage(); |
|
| 392 | ||
| 393 | $authorUser = $this->userManager->get($author); |
|
| 394 | $authorName = ($authorUser instanceof IUser) ? $authorUser->getDisplayName() : $author; |
|
| 395 | $authorEmail = ($authorUser instanceof IUser) ? $authorUser->getEMailAddress() : null; |
|
| 396 | ||
| 397 | $this->miscService->log("Sending password mail about existing files to '" . $email . "'", 0); |
|
| 398 | ||
| 399 | $plainBodyPart = $this->l10n->t( |
|
| 400 | "%1\$s shared multiple files with you.\nYou should have already received a separate mail with a link to access them.\n", |
|
| 401 | [$authorName] |
|
| 402 | ); |
|
| 403 | $htmlBodyPart = $this->l10n->t( |
|
| 404 | '%1$s shared multiple files with you. You should have already received a separate mail with a link to access them.', |
|
| 405 | [$authorName] |
|
| 406 | ); |
|
| 407 | ||
| 408 | $emailTemplate = $this->mailer->createEMailTemplate( |
|
| 409 | 'sharebymail.RecipientPasswordNotification', [ |
|
| 410 | 'password' => $password, |
|
| 411 | 'author' => $author |
|
| 412 | ] |
|
| 413 | ); |
|
| 414 | ||
| 415 | $emailTemplate->setSubject( |
|
| 416 | $this->l10n->t( |
|
| 417 | 'Password to access files shared to you by %1$s', [$authorName] |
|
| 418 | ) |
|
| 419 | ); |
|
| 420 | $emailTemplate->addHeader(); |
|
| 421 | $emailTemplate->addHeading($this->l10n->t('Password to access files'), false); |
|
| 422 | $emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart); |
|
| 423 | $emailTemplate->addBodyText($this->l10n->t('It is protected with the following password:')); |
|
| 424 | $emailTemplate->addBodyText($password); |
|
| 425 | ||
| 426 | // The "From" contains the sharers name |
|
| 427 | $instanceName = $this->defaults->getName(); |
|
| 428 | $senderName = $this->l10n->t( |
|
| 429 | '%1$s via %2$s', |
|
| 430 | [ |
|
| 431 | $authorName, |
|
| 432 | $instanceName |
|
| 433 | ] |
|
| 434 | ); |
|
| 435 | ||
| 436 | $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]); |
|
| 437 | if ($authorEmail !== null) { |
|
| 438 | $message->setReplyTo([$authorEmail => $authorName]); |
|
| 439 | $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan()); |
|
| 440 | } else { |
|
| 441 | $emailTemplate->addFooter(); |
|
| 442 | } |
|
| 443 | ||
| 444 | $message->setTo([$email]); |
|
| 445 | $message->useTemplate($emailTemplate); |
|
| 446 | $this->mailer->send($message); |
|
| 447 | } |
|
| 448 | ||
| 449 | } |
|
| 450 | ||