mirror of
https://github.com/netzbegruenung/circles.git
synced 2024-05-14 00:56:05 +02:00
enforce password on new share
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
This commit is contained in:
parent
8172baabe5
commit
2cf48068f2
|
@ -40,8 +40,10 @@ use OCA\Circles\Events\AddingCircleMemberEvent;
|
|||
use OCA\Circles\Events\CircleMemberAddedEvent;
|
||||
use OCA\Circles\Events\Files\CreatingFileShareEvent;
|
||||
use OCA\Circles\Events\Files\FileShareCreatedEvent;
|
||||
use OCA\Circles\Events\Files\PreparingFileShareEvent;
|
||||
use OCA\Circles\Events\MembershipsCreatedEvent;
|
||||
use OCA\Circles\Events\MembershipsRemovedEvent;
|
||||
use OCA\Circles\Events\PreparingCircleMemberEvent;
|
||||
use OCA\Circles\Events\RemovingCircleMemberEvent;
|
||||
use OCA\Circles\Events\RequestingCircleMemberEvent;
|
||||
use OCA\Circles\Handlers\WebfingerHandler;
|
||||
|
@ -52,7 +54,9 @@ use OCA\Circles\Listeners\Examples\ExampleMembershipsRemoved;
|
|||
use OCA\Circles\Listeners\Examples\ExampleRequestingCircleMember;
|
||||
use OCA\Circles\Listeners\Files\AddingMemberSendMail as ListenerFilesAddingMemberSendMail;
|
||||
use OCA\Circles\Listeners\Files\CreatingShareSendMail as ListenerFilesCreatingShareSendMail;
|
||||
use OCA\Circles\Listeners\Files\PreparingShareSendMail as ListenerFilesPreparingShareSendMail;
|
||||
use OCA\Circles\Listeners\Files\MemberAddedSendMail as ListenerFilesMemberAddedSendMail;
|
||||
use OCA\Circles\Listeners\Files\PreparingMemberSendMail as ListenerFilesPreparingMemberSendMail;
|
||||
use OCA\Circles\Listeners\Files\RemovingMember as ListenerFilesRemovingMember;
|
||||
use OCA\Circles\Listeners\Files\ShareCreatedSendMail as ListenerFilesShareCreatedSendMail;
|
||||
use OCA\Circles\Listeners\GroupCreated;
|
||||
|
@ -141,6 +145,10 @@ class Application extends App implements IBootstrap {
|
|||
$context->registerEventListener(UserRemovedEvent::class, GroupMemberRemoved::class);
|
||||
|
||||
// Local Events (for Files/Shares/Notifications management)
|
||||
$context->registerEventListener(
|
||||
PreparingCircleMemberEvent::class,
|
||||
ListenerFilesPreparingMemberSendMail::class
|
||||
);
|
||||
$context->registerEventListener(
|
||||
AddingCircleMemberEvent::class,
|
||||
ListenerFilesAddingMemberSendMail::class
|
||||
|
@ -149,6 +157,10 @@ class Application extends App implements IBootstrap {
|
|||
CircleMemberAddedEvent::class,
|
||||
ListenerFilesMemberAddedSendMail::class
|
||||
);
|
||||
$context->registerEventListener(
|
||||
PreparingFileShareEvent::class,
|
||||
ListenerFilesPreparingShareSendMail::class
|
||||
);
|
||||
$context->registerEventListener(
|
||||
CreatingFileShareEvent::class,
|
||||
ListenerFilesCreatingShareSendMail::class
|
||||
|
|
|
@ -1049,6 +1049,13 @@ class CoreQueryBuilder extends NC22ExtendedQueryBuilder {
|
|||
$this->leftJoinShareToken($alias);
|
||||
|
||||
$aliasShareToken = $this->generateAlias($alias, self::TOKEN, $options);
|
||||
$this->generateSelectAlias(
|
||||
CoreRequestBuilder::$tables[CoreRequestBuilder::TABLE_TOKEN],
|
||||
$aliasShareToken,
|
||||
$aliasShareToken,
|
||||
[]
|
||||
);
|
||||
|
||||
$this->limit('token', $token, $aliasShareToken);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ use OCA\Circles\IFederatedUser;
|
|||
use OCA\Circles\Model\Mount;
|
||||
|
||||
/**
|
||||
* Class GSSharesRequest
|
||||
* Class MountRequest
|
||||
*
|
||||
* @package OCA\Circles\Db
|
||||
*/
|
||||
|
@ -49,8 +49,6 @@ class MountRequest extends MountRequestBuilder {
|
|||
* @param Mount $mount
|
||||
*/
|
||||
public function save(Mount $mount): void {
|
||||
// TODO: fix hash
|
||||
$hash = $this->token();
|
||||
$qb = $this->getMountInsertSql();
|
||||
$qb->setValue('circle_id', $qb->createNamedParameter($mount->getCircleId()))
|
||||
->setValue('mount_id', $qb->createNamedParameter($mount->getMountId()))
|
||||
|
@ -58,7 +56,7 @@ class MountRequest extends MountRequestBuilder {
|
|||
->setValue('token', $qb->createNamedParameter($mount->getToken()))
|
||||
->setValue('parent', $qb->createNamedParameter($mount->getParent()))
|
||||
->setValue('mountpoint', $qb->createNamedParameter($mount->getMountPoint()))
|
||||
->setValue('mountpoint_hash', $qb->createNamedParameter($hash));
|
||||
->setValue('mountpoint_hash', $qb->createNamedParameter(md5($mount->getMountPoint())));
|
||||
|
||||
$qb->execute();
|
||||
}
|
||||
|
|
59
lib/Events/Files/PreparingFileShareEvent.php
Normal file
59
lib/Events/Files/PreparingFileShareEvent.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
/**
|
||||
* Circles - Bring cloud-users closer together.
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Maxence Lange <maxence@artificial-owl.com>
|
||||
* @copyright 2021
|
||||
* @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\Circles\Events\Files;
|
||||
|
||||
use OCA\Circles\Events\CircleGenericEvent;
|
||||
use OCA\Circles\Model\Federated\FederatedEvent;
|
||||
use OCA\Circles\Model\Mount;
|
||||
|
||||
/**
|
||||
* Class PreparingFileShareEvent
|
||||
*
|
||||
* @package OCA\Circles\Events\Files
|
||||
*/
|
||||
class PreparingFileShareEvent extends CircleGenericEvent {
|
||||
|
||||
|
||||
/** @var Mount */
|
||||
private $mount;
|
||||
|
||||
|
||||
/**
|
||||
* PreparingFileShareEvent constructor.
|
||||
*
|
||||
* @param FederatedEvent $federatedEvent
|
||||
*/
|
||||
public function __construct(FederatedEvent $federatedEvent) {
|
||||
parent::__construct($federatedEvent);
|
||||
}
|
||||
}
|
56
lib/Events/PreparingCircleMemberEvent.php
Normal file
56
lib/Events/PreparingCircleMemberEvent.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
/**
|
||||
* Circles - Bring cloud-users closer together.
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Maxence Lange <maxence@artificial-owl.com>
|
||||
* @copyright 2021
|
||||
* @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\Circles\Events;
|
||||
|
||||
use OCA\Circles\Model\Federated\FederatedEvent;
|
||||
|
||||
/**
|
||||
* Class PreparingCircleMemberEvent
|
||||
*
|
||||
* This event is called when one or multiple members are added to a Circle.
|
||||
*
|
||||
* This event is called on the master instance of the circle, before AddingCircleMemberEvent.
|
||||
*
|
||||
* @package OCA\Circles\Events
|
||||
*/
|
||||
class PreparingCircleMemberEvent extends CircleMemberGenericEvent {
|
||||
|
||||
|
||||
/**
|
||||
* PreparingCircleMemberEvent constructor.
|
||||
*
|
||||
* @param FederatedEvent $federatedEvent
|
||||
*/
|
||||
public function __construct(FederatedEvent $federatedEvent) {
|
||||
parent::__construct($federatedEvent);
|
||||
}
|
||||
}
|
|
@ -32,7 +32,6 @@ declare(strict_types=1);
|
|||
namespace OCA\Circles\FederatedItems\Files;
|
||||
|
||||
use ArtificialOwl\MySmallPhpTools\Exceptions\InvalidItemException;
|
||||
use ArtificialOwl\MySmallPhpTools\Exceptions\ItemNotFoundException;
|
||||
use ArtificialOwl\MySmallPhpTools\Exceptions\UnknownTypeException;
|
||||
use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Logger;
|
||||
use ArtificialOwl\MySmallPhpTools\Traits\TStringTools;
|
||||
|
@ -94,24 +93,26 @@ class FileShare implements
|
|||
* @param FederatedEvent $event
|
||||
*/
|
||||
public function verify(FederatedEvent $event): void {
|
||||
// TODO: check and improve
|
||||
// TODO: Could we use a share lock ?
|
||||
// TODO: check (origin of file ?) and improve
|
||||
// TODO: Use a share lock
|
||||
|
||||
$this->eventService->fileSharePreparing($event);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param FederatedEvent $event
|
||||
*
|
||||
* @throws CircleNotFoundException
|
||||
* @throws InvalidItemException
|
||||
* @throws UnknownTypeException
|
||||
* @throws CircleNotFoundException
|
||||
* @throws ItemNotFoundException
|
||||
*/
|
||||
public function manage(FederatedEvent $event): void {
|
||||
$mount = null;
|
||||
if (!$this->configService->isLocalInstance($event->getOrigin())) {
|
||||
/** @var ShareWrapper $wrappedShare */
|
||||
$wrappedShare = $event->getParams()->gObj('wrappedShare', ShareWrapper::class);
|
||||
|
||||
$mount = new Mount();
|
||||
$mount->fromShare($wrappedShare);
|
||||
$mount->setMountId($this->token(15));
|
||||
|
|
|
@ -81,6 +81,11 @@ class MassiveMemberAdd extends SingleMemberAdd implements
|
|||
|
||||
$event->setMembers($filtered);
|
||||
$event->setOutcome($this->serializeArray($filtered));
|
||||
|
||||
foreach ($event->getMembers() as $member) {
|
||||
$event->setMember($member);
|
||||
$this->eventService->memberPreparing($event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -76,9 +76,9 @@ use OCA\Circles\StatusCode;
|
|||
use OCP\IUserManager;
|
||||
|
||||
/**
|
||||
* Class MemberAdd
|
||||
* Class SingleMemberAdd
|
||||
*
|
||||
* @package OCA\Circles\GlobalScale
|
||||
* @package OCA\Circles\FederatedItems
|
||||
*/
|
||||
class SingleMemberAdd implements
|
||||
IFederatedItem,
|
||||
|
@ -182,35 +182,7 @@ class SingleMemberAdd implements
|
|||
$event->setMembers([$member]);
|
||||
$event->setOutcome($this->serialize($member));
|
||||
|
||||
return;
|
||||
|
||||
|
||||
// $member = $this->membersRequest->getFreshNewMember(
|
||||
// $circle->getUniqueId(), $ident, $eventMember->getType(), $eventMember->getInstance()
|
||||
// );
|
||||
// $member->hasToBeInviteAble()
|
||||
//
|
||||
// $this->membersService->addMemberBasedOnItsType($circle, $member);
|
||||
//
|
||||
// $password = '';
|
||||
// $sendPasswordByMail = false;
|
||||
// if ($this->configService->enforcePasswordProtection($circle)) {
|
||||
// if ($circle->getSetting('password_single_enabled') === 'true') {
|
||||
// $password = $circle->getPasswordSingle();
|
||||
// } else {
|
||||
// $sendPasswordByMail = true;
|
||||
// $password = $this->miscService->token(15);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// $event->setData(
|
||||
// new SimpleDataStore(
|
||||
// [
|
||||
// 'password' => $password,
|
||||
// 'passwordByMail' => $sendPasswordByMail
|
||||
// ]
|
||||
// )
|
||||
// );
|
||||
$this->eventService->memberPreparing($event);
|
||||
}
|
||||
|
||||
|
||||
|
@ -234,7 +206,7 @@ class SingleMemberAdd implements
|
|||
$this->eventService->memberAdding($event);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// //
|
||||
// // TODO: verifiez comment se passe le cached name sur un member_add
|
||||
// //
|
||||
|
|
|
@ -46,7 +46,7 @@ use OCP\EventDispatcher\Event;
|
|||
use OCP\EventDispatcher\IEventListener;
|
||||
|
||||
/**
|
||||
* Class AddingMember
|
||||
* Class AddingMemberSendMail
|
||||
*
|
||||
* @package OCA\Circles\Listeners\Files
|
||||
*/
|
||||
|
@ -101,9 +101,7 @@ class AddingMemberSendMail implements IEventListener {
|
|||
return;
|
||||
}
|
||||
|
||||
$result = [];
|
||||
$member = $event->getMember();
|
||||
|
||||
if ($member->getUserType() === Member::TYPE_CIRCLE) {
|
||||
$members = $member->getBasedOn()->getInheritedMembers();
|
||||
} else {
|
||||
|
@ -111,9 +109,11 @@ class AddingMemberSendMail implements IEventListener {
|
|||
}
|
||||
|
||||
$circle = $event->getCircle();
|
||||
$federatedEvent = $event->getFederatedEvent();
|
||||
$shares = $this->shareWrapperService->getSharesToCircle($circle->getSingleId());
|
||||
$hashedPasswords = $federatedEvent->getParams()->gArray('hashedPasswords');
|
||||
|
||||
/** @var Member[] $members */
|
||||
$result = [];
|
||||
foreach ($members as $member) {
|
||||
if ($member->getUserType() !== Member::TYPE_MAIL
|
||||
&& $member->getUserType() !== Member::TYPE_CONTACT
|
||||
|
@ -124,13 +124,17 @@ class AddingMemberSendMail implements IEventListener {
|
|||
$files = [];
|
||||
foreach ($shares as $share) {
|
||||
try {
|
||||
$shareToken = $this->shareTokenService->generateShareToken($share, $member);
|
||||
$shareToken = $this->shareTokenService->generateShareToken(
|
||||
$share,
|
||||
$member,
|
||||
$this->get($member->getSingleId(), $hashedPasswords)
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$share->setShareToken($shareToken);
|
||||
$files[] = $share;
|
||||
$files[] = clone $share;
|
||||
}
|
||||
|
||||
$result[$member->getId()] = [
|
||||
|
@ -139,6 +143,6 @@ class AddingMemberSendMail implements IEventListener {
|
|||
];
|
||||
}
|
||||
|
||||
$event->getFederatedEvent()->setResultEntry('files', $result);
|
||||
$federatedEvent->addResultEntry('files', $result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,8 +114,8 @@ class CreatingShareSendMail implements IEventListener {
|
|||
}
|
||||
|
||||
$circle = $event->getCircle();
|
||||
|
||||
$federatedEvent = $event->getFederatedEvent();
|
||||
$hashedPasswords = $federatedEvent->getParams()->gArray('hashedPasswords');
|
||||
|
||||
$result = [];
|
||||
foreach ($circle->getInheritedMembers(false, true) as $member) {
|
||||
|
@ -136,7 +136,12 @@ class CreatingShareSendMail implements IEventListener {
|
|||
throw new ShareWrapperNotFoundException();
|
||||
}
|
||||
|
||||
$shareToken = $this->shareTokenService->generateShareToken($share, $member);
|
||||
$shareToken = $this->shareTokenService->generateShareToken(
|
||||
$share,
|
||||
$member,
|
||||
$this->get($member->getSingleId(), $hashedPasswords)
|
||||
);
|
||||
|
||||
$share->setShareToken($shareToken);
|
||||
} catch (Exception $e) {
|
||||
$share = null;
|
||||
|
@ -149,6 +154,6 @@ class CreatingShareSendMail implements IEventListener {
|
|||
];
|
||||
}
|
||||
|
||||
$event->getFederatedEvent()->setResultEntry('info', $result);
|
||||
$federatedEvent->setResultEntry('info', $result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCA\Circles\Listeners\Files;
|
||||
|
||||
use ArtificialOwl\MySmallPhpTools\Model\SimpleDataStore;
|
||||
use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Logger;
|
||||
use ArtificialOwl\MySmallPhpTools\Traits\TStringTools;
|
||||
use OCA\Circles\AppInfo\Application;
|
||||
|
@ -93,6 +94,8 @@ class MemberAddedSendMail implements IEventListener {
|
|||
$members = [$member];
|
||||
}
|
||||
|
||||
$clearPasswords = $event->getFederatedEvent()->getInternal()->gArray('clearPasswords');
|
||||
|
||||
/** @var Member[] $members */
|
||||
foreach ($members as $member) {
|
||||
if ($member->getUserType() !== Member::TYPE_MAIL
|
||||
|
@ -101,23 +104,24 @@ class MemberAddedSendMail implements IEventListener {
|
|||
continue;
|
||||
}
|
||||
|
||||
$mails = [];
|
||||
$shares = [];
|
||||
$mails = $shares = [];
|
||||
foreach ($event->getResults() as $origin => $item) {
|
||||
$files = $item->gData('files');
|
||||
if (!$files->hasKey($member->getId())) {
|
||||
continue;
|
||||
}
|
||||
foreach ($item->gArray('files') as $filesArray) {
|
||||
$files = new SimpleDataStore($filesArray);
|
||||
if (!$files->hasKey($member->getId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = $files->gData($member->getId());
|
||||
$shares = array_merge($shares, $data->gObjs('shares', ShareWrapper::class));
|
||||
$data = $files->gData($member->getId());
|
||||
$shares = array_merge($shares, $data->gObjs('shares', ShareWrapper::class));
|
||||
|
||||
// TODO: is it safe to use $origin to compare getInstance() ?
|
||||
// TODO: do we need to check the $origin ?
|
||||
// TODO: Solution would be to check the origin based on aliases using RemoteInstanceService
|
||||
// TODO: is it safe to use $origin to compare getInstance() ?
|
||||
// TODO: do we need to check the $origin ?
|
||||
// TODO: Solution would be to check the origin based on aliases using RemoteInstanceService
|
||||
// if ($member->getUserType() === Member::TYPE_CONTACT && $member->getInstance() === $origin) {
|
||||
$mails = $data->gArray('mails');
|
||||
$mails = array_merge($mails, $data->gArray('mails'));
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
if ($member->hasInvitedBy()) {
|
||||
|
@ -126,7 +130,14 @@ class MemberAddedSendMail implements IEventListener {
|
|||
$author = 'someone';
|
||||
}
|
||||
|
||||
$this->sendMailService->generateMail($author, $circle, $member, $shares, $mails);
|
||||
$this->sendMailService->generateMail(
|
||||
$author,
|
||||
$circle,
|
||||
$member,
|
||||
$shares,
|
||||
$mails,
|
||||
$this->get($member->getSingleId(), $clearPasswords)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
148
lib/Listeners/Files/PreparingMemberSendMail.php
Normal file
148
lib/Listeners/Files/PreparingMemberSendMail.php
Normal file
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
/**
|
||||
* Circles - Bring cloud-users closer together.
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Maxence Lange <maxence@artificial-owl.com>
|
||||
* @copyright 2021
|
||||
* @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\Circles\Listeners\Files;
|
||||
|
||||
use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Logger;
|
||||
use ArtificialOwl\MySmallPhpTools\Traits\TStringTools;
|
||||
use OCA\Circles\AppInfo\Application;
|
||||
use OCA\Circles\Events\PreparingCircleMemberEvent;
|
||||
use OCA\Circles\Exceptions\FederatedItemException;
|
||||
use OCA\Circles\Exceptions\RemoteInstanceException;
|
||||
use OCA\Circles\Exceptions\RemoteNotFoundException;
|
||||
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
|
||||
use OCA\Circles\Exceptions\RequestBuilderException;
|
||||
use OCA\Circles\Exceptions\UnknownRemoteException;
|
||||
use OCA\Circles\Model\Member;
|
||||
use OCA\Circles\Service\ConfigService;
|
||||
use OCA\Circles\Service\ContactService;
|
||||
use OCA\Circles\Service\ShareTokenService;
|
||||
use OCA\Circles\Service\ShareWrapperService;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Security\IHasher;
|
||||
|
||||
/**
|
||||
* Class PreparingMemberSendMail
|
||||
*
|
||||
* @package OCA\Circles\Listeners\Files
|
||||
*/
|
||||
class PreparingMemberSendMail implements IEventListener {
|
||||
use TStringTools;
|
||||
use TNC22Logger;
|
||||
|
||||
|
||||
/** @var IHasher */
|
||||
private $hasher;
|
||||
|
||||
/** @var ShareWrapperService */
|
||||
private $shareWrapperService;
|
||||
|
||||
/** @var ShareTokenService */
|
||||
private $shareTokenService;
|
||||
|
||||
/** @var ConfigService */
|
||||
private $configService;
|
||||
|
||||
/** @var ContactService */
|
||||
private $contactService;
|
||||
|
||||
|
||||
/**
|
||||
* AddingMember constructor.
|
||||
*
|
||||
* @param IHasher $hasher
|
||||
* @param ShareWrapperService $shareWrapperService
|
||||
* @param ShareTokenService $shareTokenService
|
||||
* @param ContactService $contactService
|
||||
* @param ConfigService $configService
|
||||
*/
|
||||
public function __construct(
|
||||
IHasher $hasher,
|
||||
ShareWrapperService $shareWrapperService,
|
||||
ShareTokenService $shareTokenService,
|
||||
ContactService $contactService,
|
||||
ConfigService $configService
|
||||
) {
|
||||
$this->hasher = $hasher;
|
||||
$this->shareWrapperService = $shareWrapperService;
|
||||
$this->shareTokenService = $shareTokenService;
|
||||
$this->contactService = $contactService;
|
||||
$this->configService = $configService;
|
||||
|
||||
$this->setup('app', Application::APP_ID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Event $event
|
||||
*
|
||||
* @throws RequestBuilderException
|
||||
* @throws FederatedItemException
|
||||
* @throws RemoteInstanceException
|
||||
* @throws RemoteNotFoundException
|
||||
* @throws RemoteResourceNotFoundException
|
||||
* @throws UnknownRemoteException
|
||||
*/
|
||||
public function handle(Event $event): void {
|
||||
if (!$event instanceof PreparingCircleMemberEvent
|
||||
|| !$this->configService->enforcePasswordOnSharedFile()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$member = $event->getMember();
|
||||
if ($member->getUserType() === Member::TYPE_CIRCLE) {
|
||||
$members = $member->getBasedOn()->getInheritedMembers();
|
||||
} else {
|
||||
$members = [$member];
|
||||
}
|
||||
|
||||
$federatedEvent = $event->getFederatedEvent();
|
||||
$clearPasswords = $federatedEvent->getInternal()->gArray('clearPasswords');
|
||||
$hashedPasswords = $federatedEvent->getParams()->gArray('hashedPasswords');
|
||||
|
||||
foreach ($members as $member) {
|
||||
if (($member->getUserType() !== Member::TYPE_MAIL
|
||||
&& $member->getUserType() !== Member::TYPE_CONTACT)
|
||||
|| array_key_exists($member->getSingleId(), $clearPasswords)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$clearPassword = $this->token(14);
|
||||
$clearPasswords[$member->getSingleId()] = $clearPassword;
|
||||
$hashedPasswords[$member->getSingleId()] = $this->hasher->hash($clearPassword);
|
||||
}
|
||||
|
||||
$federatedEvent->getInternal()->aArray('clearPasswords', $clearPasswords);
|
||||
$federatedEvent->getParams()->aArray('hashedPasswords', $hashedPasswords);
|
||||
}
|
||||
}
|
142
lib/Listeners/Files/PreparingShareSendMail.php
Normal file
142
lib/Listeners/Files/PreparingShareSendMail.php
Normal file
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
/**
|
||||
* Circles - Bring cloud-users closer together.
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Maxence Lange <maxence@artificial-owl.com>
|
||||
* @copyright 2021
|
||||
* @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\Circles\Listeners\Files;
|
||||
|
||||
use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Logger;
|
||||
use ArtificialOwl\MySmallPhpTools\Traits\TStringTools;
|
||||
use OCA\Circles\AppInfo\Application;
|
||||
use OCA\Circles\Events\Files\PreparingFileShareEvent;
|
||||
use OCA\Circles\Exceptions\FederatedItemException;
|
||||
use OCA\Circles\Exceptions\RemoteInstanceException;
|
||||
use OCA\Circles\Exceptions\RemoteNotFoundException;
|
||||
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
|
||||
use OCA\Circles\Exceptions\RequestBuilderException;
|
||||
use OCA\Circles\Exceptions\UnknownRemoteException;
|
||||
use OCA\Circles\Model\Member;
|
||||
use OCA\Circles\Service\ConfigService;
|
||||
use OCA\Circles\Service\ContactService;
|
||||
use OCA\Circles\Service\ShareTokenService;
|
||||
use OCA\Circles\Service\ShareWrapperService;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Security\IHasher;
|
||||
|
||||
/**
|
||||
* Class PreparingShareSendMail
|
||||
*
|
||||
* @package OCA\Circles\Listeners\Files
|
||||
*/
|
||||
class PreparingShareSendMail implements IEventListener {
|
||||
use TStringTools;
|
||||
use TNC22Logger;
|
||||
|
||||
|
||||
/** @var IHasher */
|
||||
private $hasher;
|
||||
|
||||
/** @var ShareWrapperService */
|
||||
private $shareWrapperService;
|
||||
|
||||
/** @var ShareTokenService */
|
||||
private $shareTokenService;
|
||||
|
||||
/** @var ConfigService */
|
||||
private $configService;
|
||||
|
||||
/** @var ContactService */
|
||||
private $contactService;
|
||||
|
||||
|
||||
/**
|
||||
* PreparingShareSendMail constructor.
|
||||
*
|
||||
* @param IHasher $hasher
|
||||
* @param ShareWrapperService $shareWrapperService
|
||||
* @param ShareTokenService $shareTokenService
|
||||
* @param ContactService $contactService
|
||||
* @param ConfigService $configService
|
||||
*/
|
||||
public function __construct(
|
||||
IHasher $hasher,
|
||||
ShareWrapperService $shareWrapperService,
|
||||
ShareTokenService $shareTokenService,
|
||||
ContactService $contactService,
|
||||
ConfigService $configService
|
||||
) {
|
||||
$this->hasher = $hasher;
|
||||
$this->shareWrapperService = $shareWrapperService;
|
||||
$this->shareTokenService = $shareTokenService;
|
||||
$this->contactService = $contactService;
|
||||
$this->configService = $configService;
|
||||
|
||||
$this->setup('app', Application::APP_ID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Event $event
|
||||
*
|
||||
* @throws FederatedItemException
|
||||
* @throws RemoteInstanceException
|
||||
* @throws RemoteNotFoundException
|
||||
* @throws RemoteResourceNotFoundException
|
||||
* @throws RequestBuilderException
|
||||
* @throws UnknownRemoteException
|
||||
*/
|
||||
public function handle(Event $event): void {
|
||||
if (!$event instanceof PreparingFileShareEvent
|
||||
|| !$this->configService->enforcePasswordOnSharedFile()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$circle = $event->getCircle();
|
||||
$federatedEvent = $event->getFederatedEvent();
|
||||
$clearPasswords = $federatedEvent->getInternal()->gArray('clearPasswords');
|
||||
$hashedPasswords = $federatedEvent->getParams()->gArray('hashedPasswords');
|
||||
|
||||
foreach ($circle->getInheritedMembers(false, true) as $member) {
|
||||
if (($member->getUserType() !== Member::TYPE_MAIL
|
||||
&& $member->getUserType() !== Member::TYPE_CONTACT)
|
||||
|| array_key_exists($member->getSingleId(), $clearPasswords)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$clearPassword = $this->token(14);
|
||||
$clearPasswords[$member->getSingleId()] = $clearPassword;
|
||||
$hashedPasswords[$member->getSingleId()] = $this->hasher->hash($clearPassword);
|
||||
}
|
||||
|
||||
$federatedEvent->getInternal()->aArray('clearPasswords', $clearPasswords);
|
||||
$federatedEvent->getParams()->aArray('hashedPasswords', $hashedPasswords);
|
||||
}
|
||||
}
|
|
@ -126,6 +126,7 @@ class ShareCreatedSendMail implements IEventListener {
|
|||
}
|
||||
|
||||
$circle = $event->getCircle();
|
||||
$clearPasswords = $event->getFederatedEvent()->getInternal()->gArray('clearPasswords');
|
||||
|
||||
foreach ($circle->getInheritedMembers(false, true) as $member) {
|
||||
if ($member->getUserType() !== Member::TYPE_MAIL
|
||||
|
@ -153,6 +154,7 @@ class ShareCreatedSendMail implements IEventListener {
|
|||
}
|
||||
|
||||
try {
|
||||
// are we sure the 'share' entry is valid and not spoofed !?
|
||||
/** @var ShareWrapper $share */
|
||||
$share = $data->gObj('share', ShareWrapper::class);
|
||||
} catch (Exception $e) {
|
||||
|
@ -166,7 +168,14 @@ class ShareCreatedSendMail implements IEventListener {
|
|||
$author = 'someone';
|
||||
}
|
||||
|
||||
$this->sendMailService->generateMail($author, $circle, $member, [$share], $mails);
|
||||
$this->sendMailService->generateMail(
|
||||
$author,
|
||||
$circle,
|
||||
$member,
|
||||
[$share],
|
||||
$mails,
|
||||
$this->get($member->getSingleId(), $clearPasswords)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
84
lib/Migration/Version0023Date20211216113101.php
Normal file
84
lib/Migration/Version0023Date20211216113101.php
Normal file
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
/**
|
||||
* Circles - Bring cloud-users closer together.
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Maxence Lange <maxence@artificial-owl.com>
|
||||
* @copyright 2021
|
||||
* @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\Circles\Migration;
|
||||
|
||||
use Closure;
|
||||
use Doctrine\DBAL\Schema\SchemaException;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
|
||||
/**
|
||||
* Class Version0023Date20211216113101
|
||||
*
|
||||
* @package OCA\Circles\Migration
|
||||
*/
|
||||
class Version0023Date20211216113101 extends SimpleMigrationStep {
|
||||
|
||||
|
||||
/**
|
||||
* @param IDBConnection $connection
|
||||
*/
|
||||
public function __construct(IDBConnection $connection) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
*
|
||||
* @return null|ISchemaWrapper
|
||||
* @throws SchemaException
|
||||
*/
|
||||
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
if ($schema->hasTable('circles_token')) {
|
||||
$table = $schema->getTable('circles_token');
|
||||
$table->changeColumn(
|
||||
'password', [
|
||||
'length' => 127
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
if ($schema->hasTable('circles_event')) {
|
||||
$table = $schema->getTable('circles_event');
|
||||
$table->setPrimaryKey(['token']);
|
||||
}
|
||||
|
||||
return $schema;
|
||||
}
|
||||
}
|
|
@ -80,6 +80,9 @@ class FederatedEvent implements JsonSerializable {
|
|||
/** @var SimpleDataStore */
|
||||
private $params;
|
||||
|
||||
/** @var SimpleDataStore */
|
||||
private $internal;
|
||||
|
||||
/** @var SimpleDataStore */
|
||||
private $data;
|
||||
|
||||
|
@ -120,6 +123,7 @@ class FederatedEvent implements JsonSerializable {
|
|||
public function __construct(string $class = '') {
|
||||
$this->class = $class;
|
||||
$this->params = new SimpleDataStore();
|
||||
$this->internal = new SimpleDataStore();
|
||||
$this->data = new SimpleDataStore();
|
||||
$this->result = new SimpleDataStore();
|
||||
}
|
||||
|
@ -391,6 +395,34 @@ class FederatedEvent implements JsonSerializable {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param SimpleDataStore $internal
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setInternal(SimpleDataStore $internal): self {
|
||||
$this->internal = $internal;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleDataStore
|
||||
*/
|
||||
public function getInternal(): SimpleDataStore {
|
||||
return $this->internal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function resetInternal(): self {
|
||||
$this->internal = new SimpleDataStore();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param SimpleDataStore $data
|
||||
*
|
||||
|
@ -413,6 +445,7 @@ class FederatedEvent implements JsonSerializable {
|
|||
* @return $this
|
||||
*/
|
||||
public function resetData(): self {
|
||||
$this->resetInternal();
|
||||
$this->data = new SimpleDataStore();
|
||||
|
||||
return $this;
|
||||
|
@ -550,6 +583,7 @@ class FederatedEvent implements JsonSerializable {
|
|||
$this->setClass($this->get('class', $data));
|
||||
$this->setSeverity($this->getInt('severity', $data));
|
||||
$this->setParams(new SimpleDataStore($this->getArray('params', $data)));
|
||||
$this->setInternal(new SimpleDataStore($this->getArray('internal', $data)));
|
||||
$this->setData(new SimpleDataStore($this->getArray('data', $data)));
|
||||
$this->setResult(new SimpleDataStore($this->getArray('result', $data)));
|
||||
$this->setOrigin($this->get('origin', $data));
|
||||
|
@ -587,6 +621,7 @@ class FederatedEvent implements JsonSerializable {
|
|||
'class' => $this->getClass(),
|
||||
'severity' => $this->getSeverity(),
|
||||
'params' => $this->getParams(),
|
||||
'internal' => $this->getInternal(),
|
||||
'data' => $this->getData(),
|
||||
'result' => $this->getResult(),
|
||||
'origin' => $this->getOrigin(),
|
||||
|
|
|
@ -48,6 +48,7 @@ use OCA\Circles\Exceptions\RemoteInstanceException;
|
|||
use OCA\Circles\Exceptions\RemoteNotFoundException;
|
||||
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
|
||||
use OCA\Circles\Exceptions\RequestBuilderException;
|
||||
use OCA\Circles\Exceptions\ShareTokenNotFoundException;
|
||||
use OCA\Circles\Exceptions\UnknownInterfaceException;
|
||||
use OCA\Circles\Exceptions\UnknownRemoteException;
|
||||
use OCA\Circles\IEntity;
|
||||
|
@ -463,6 +464,15 @@ class ModelManager {
|
|||
} catch (FileCacheNotFoundException $e) {
|
||||
}
|
||||
break;
|
||||
|
||||
case CoreQueryBuilder::TOKEN:
|
||||
try {
|
||||
$token = new ShareToken();
|
||||
$token->importFromDatabase($data, $prefix);
|
||||
$shareWrapper->setShareToken($token);
|
||||
} catch (ShareTokenNotFoundException $e) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ use ArtificialOwl\MySmallPhpTools\Exceptions\InvalidItemException;
|
|||
use ArtificialOwl\MySmallPhpTools\IDeserializable;
|
||||
use ArtificialOwl\MySmallPhpTools\Traits\TArrayTools;
|
||||
use JsonSerializable;
|
||||
use OCA\Circles\Exceptions\ShareTokenNotFoundException;
|
||||
use OCP\Share\IShare;
|
||||
|
||||
class ShareToken implements IDeserializable, INC22QueryRow, JsonSerializable {
|
||||
|
@ -277,8 +278,13 @@ class ShareToken implements IDeserializable, INC22QueryRow, JsonSerializable {
|
|||
* @param string $prefix
|
||||
*
|
||||
* @return INC22QueryRow
|
||||
* @throws ShareTokenNotFoundException
|
||||
*/
|
||||
public function importFromDatabase(array $data, string $prefix = ''): INC22QueryRow {
|
||||
if ($this->get($prefix . 'token', $data) === '') {
|
||||
throw new ShareTokenNotFoundException();
|
||||
}
|
||||
|
||||
$this->setShareId($this->getInt($prefix . 'share_id', $data));
|
||||
$this->setCircleId($this->get($prefix . 'circle_id', $data));
|
||||
$this->setSingleId($this->get($prefix . 'single_id', $data));
|
||||
|
|
|
@ -623,6 +623,9 @@ class ShareWrapper extends ManagedModel implements IDeserializable, INC22QueryRo
|
|||
$share->setTarget($this->getFileTarget());
|
||||
$share->setProviderId($this->getProviderId());
|
||||
$share->setStatus($this->getStatus());
|
||||
if ($this->hasShareToken() && $this->getShareToken()->getPassword() !== '') {
|
||||
$share->setPassword($this->getShareToken()->getPassword());
|
||||
}
|
||||
|
||||
$share->setShareTime($this->getShareTime())
|
||||
->setSharedWith($this->getSharedWith())
|
||||
|
|
|
@ -99,6 +99,7 @@ class ConfigService {
|
|||
public const KEYHOLE_CFG_REQUEST = 'keyhole_cfg_request';
|
||||
public const ROUTE_TO_CIRCLE = 'route_to_circle';
|
||||
public const EVENT_EXAMPLES = 'event_examples';
|
||||
public const ENFORCE_PASSWORD = 'enforce_password';
|
||||
|
||||
public const SELF_SIGNED_CERT = 'self_signed_cert';
|
||||
public const MEMBERS_LIMIT = 'members_limit';
|
||||
|
@ -129,7 +130,7 @@ class ConfigService {
|
|||
public const TEST_NC_BASE = 'test_nc_base';
|
||||
|
||||
|
||||
private $defaults = [
|
||||
private static $defaults = [
|
||||
self::FRONTAL_CLOUD_BASE => '',
|
||||
self::FRONTAL_CLOUD_ID => '',
|
||||
self::FRONTAL_CLOUD_SCHEME => 'https',
|
||||
|
@ -173,6 +174,7 @@ class ConfigService {
|
|||
self::KEYHOLE_CFG_REQUEST => '0',
|
||||
self::ROUTE_TO_CIRCLE => 'contacts.contacts.directcircle',
|
||||
self::EVENT_EXAMPLES => '0',
|
||||
self::ENFORCE_PASSWORD => '2',
|
||||
|
||||
self::SELF_SIGNED_CERT => '0',
|
||||
self::MEMBERS_LIMIT => '-1',
|
||||
|
@ -237,7 +239,7 @@ class ConfigService {
|
|||
return $value;
|
||||
}
|
||||
|
||||
return $this->get($key, $this->defaults);
|
||||
return $this->get($key, self::$defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -329,16 +331,43 @@ class ConfigService {
|
|||
* @return bool
|
||||
* @deprecated
|
||||
* should the password for a mail share be send to the recipient
|
||||
*
|
||||
*/
|
||||
public function sendPasswordByMail() {
|
||||
if ($this->isContactsBackend()) {
|
||||
return false;
|
||||
public function sendPasswordByMail(): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function enforcePasswordOnSharedFile(): bool {
|
||||
$localPolicy = $this->getAppValueInt(ConfigService::ENFORCE_PASSWORD);
|
||||
if ($localPolicy !== $this->getInt(ConfigService::ENFORCE_PASSWORD, self::$defaults)) {
|
||||
return ($localPolicy === 1);
|
||||
}
|
||||
|
||||
return ($this->config->getAppValue('sharebymail', 'sendpasswordmail', 'yes') === 'yes');
|
||||
// TODO: reimplement a way to set password protection on a single Circle
|
||||
// if ($circle->getSetting('password_enforcement') === 'true') {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
$sendPasswordMail = $this->config->getAppValue(
|
||||
'sharebymail',
|
||||
'sendpasswordmail',
|
||||
'yes'
|
||||
);
|
||||
|
||||
$enforcePasswordProtection = $this->config->getAppValue(
|
||||
'core',
|
||||
'shareapi_enforce_links_password',
|
||||
'no'
|
||||
);
|
||||
|
||||
return ($sendPasswordMail === 'yes'
|
||||
&& $enforcePasswordProtection === 'yes');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param DeprecatedCircle $circle
|
||||
*
|
||||
|
@ -348,15 +377,7 @@ class ConfigService {
|
|||
*
|
||||
*/
|
||||
public function enforcePasswordProtection(DeprecatedCircle $circle) {
|
||||
if ($this->isContactsBackend()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($circle->getSetting('password_enforcement') === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ($this->config->getAppValue('sharebymail', 'enforcePasswordProtection', 'no') === 'yes');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,8 +52,10 @@ use OCA\Circles\Events\EditingCircleEvent;
|
|||
use OCA\Circles\Events\EditingCircleMemberEvent;
|
||||
use OCA\Circles\Events\Files\CreatingFileShareEvent;
|
||||
use OCA\Circles\Events\Files\FileShareCreatedEvent;
|
||||
use OCA\Circles\Events\Files\PreparingFileShareEvent;
|
||||
use OCA\Circles\Events\MembershipsCreatedEvent;
|
||||
use OCA\Circles\Events\MembershipsRemovedEvent;
|
||||
use OCA\Circles\Events\PreparingCircleMemberEvent;
|
||||
use OCA\Circles\Events\RemovingCircleMemberEvent;
|
||||
use OCA\Circles\Events\RequestingCircleMemberEvent;
|
||||
use OCA\Circles\Model\Federated\FederatedEvent;
|
||||
|
@ -141,6 +143,14 @@ class EventService {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param FederatedEvent $federatedEvent
|
||||
*/
|
||||
public function memberPreparing(FederatedEvent $federatedEvent): void {
|
||||
$event = new PreparingCircleMemberEvent($federatedEvent);
|
||||
$this->eventDispatcher->dispatchTyped($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FederatedEvent $federatedEvent
|
||||
*/
|
||||
|
@ -305,6 +315,14 @@ class EventService {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param FederatedEvent $federatedEvent
|
||||
*/
|
||||
public function fileSharePreparing(FederatedEvent $federatedEvent): void {
|
||||
$event = new PreparingFileShareEvent($federatedEvent);
|
||||
$this->eventDispatcher->dispatchTyped($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FederatedEvent $federatedEvent
|
||||
* @param Mount|null $mount
|
||||
|
|
|
@ -155,7 +155,8 @@ class FederatedEventService extends NC22Signature {
|
|||
* @throws RequestBuilderException
|
||||
*/
|
||||
public function newEvent(FederatedEvent $event): array {
|
||||
$event->setOrigin($this->interfaceService->getLocalInstance());
|
||||
$event->setOrigin($this->interfaceService->getLocalInstance())
|
||||
->resetData();
|
||||
|
||||
$federatedItem = $this->getFederatedItem($event, false);
|
||||
$this->confirmInitiator($event, true);
|
||||
|
|
|
@ -108,12 +108,15 @@ class RemoteUpstreamService {
|
|||
* @throws UnknownRemoteException
|
||||
*/
|
||||
public function broadcastEvent(EventWrapper $wrapper): void {
|
||||
$event = clone $wrapper->getEvent();
|
||||
$event->resetInternal();
|
||||
|
||||
$this->interfaceService->setCurrentInterface($wrapper->getInterface());
|
||||
$data = $this->remoteStreamService->resultRequestRemoteInstance(
|
||||
$wrapper->getInstance(),
|
||||
RemoteInstance::INCOMING,
|
||||
Request::TYPE_POST,
|
||||
$wrapper->getEvent()
|
||||
$event
|
||||
);
|
||||
|
||||
$wrapper->getEvent()->setResult(new SimpleDataStore($data));
|
||||
|
|
|
@ -58,6 +58,9 @@ class SendMailService {
|
|||
/** @var Defaults */
|
||||
private $defaults;
|
||||
|
||||
/** @var ConfigService */
|
||||
private $configService;
|
||||
|
||||
|
||||
/**
|
||||
* SendMailService constructor.
|
||||
|
@ -65,15 +68,18 @@ class SendMailService {
|
|||
* @param IL10N $l10n
|
||||
* @param IMailer $mailer
|
||||
* @param Defaults $defaults
|
||||
* @param ConfigService $configService
|
||||
*/
|
||||
public function __construct(
|
||||
IL10N $l10n,
|
||||
IMailer $mailer,
|
||||
Defaults $defaults
|
||||
Defaults $defaults,
|
||||
ConfigService $configService
|
||||
) {
|
||||
$this->l10n = $l10n;
|
||||
$this->mailer = $mailer;
|
||||
$this->defaults = $defaults;
|
||||
$this->configService = $configService;
|
||||
}
|
||||
|
||||
|
||||
|
@ -83,8 +89,16 @@ class SendMailService {
|
|||
* @param Member $member
|
||||
* @param ShareWrapper[] $shares
|
||||
* @param array $mails
|
||||
* @param string $password
|
||||
*/
|
||||
public function generateMail(string $author, Circle $circle, Member $member, array $shares, array $mails): void {
|
||||
public function generateMail(
|
||||
string $author,
|
||||
Circle $circle,
|
||||
Member $member,
|
||||
array $shares,
|
||||
array $mails,
|
||||
string $password = ''
|
||||
): void {
|
||||
if (empty($shares)) {
|
||||
return;
|
||||
}
|
||||
|
@ -117,6 +131,8 @@ class SendMailService {
|
|||
$this->sendMailExistingShares($template, $author, $mail, sizeof($links) > 1);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
$this->sendMailPassword($author, $circle->getDisplayName(), $mail, $password);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,4 +210,74 @@ class SendMailService {
|
|||
|
||||
$this->mailer->send($message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $author
|
||||
* @param string $circleName
|
||||
* @param string $email
|
||||
* @param string $password
|
||||
*/
|
||||
private function sendMailPassword(
|
||||
string $author,
|
||||
string $circleName,
|
||||
string $email,
|
||||
string $password
|
||||
): void {
|
||||
if (!$this->configService->enforcePasswordOnSharedFile() || $password === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = $this->mailer->createMessage();
|
||||
$plainBodyPart = $this->l10n->t(
|
||||
"%1\$s shared some content with you.\nYou should have already received a separate email with a link to access it.\n",
|
||||
[$author]
|
||||
);
|
||||
$htmlBodyPart = $this->l10n->t(
|
||||
'%1$s shared some content with you. You should have already received a separate email with a link to access it.',
|
||||
[$author]
|
||||
);
|
||||
|
||||
$emailTemplate = $this->mailer->createEMailTemplate(
|
||||
'sharebymail.RecipientPasswordNotification',
|
||||
[
|
||||
'filename' => '',
|
||||
'password' => $password,
|
||||
'initiator' => $author,
|
||||
// 'initiatorEmail' => Util::getDefaultEmailAddress(''),
|
||||
'initiatorEmail' => '',
|
||||
'shareWith' => $circleName
|
||||
]
|
||||
);
|
||||
|
||||
$emailTemplate->setSubject(
|
||||
$this->l10n->t('Password to access content shared to you by %1$s', [$author])
|
||||
);
|
||||
$emailTemplate->addHeader();
|
||||
$emailTemplate->addHeading($this->l10n->t('Password to access content'), 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',
|
||||
[
|
||||
$author,
|
||||
$instanceName
|
||||
]
|
||||
);
|
||||
$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
|
||||
// if ($initiatorEmailAddress !== null) {
|
||||
// $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
|
||||
// $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
|
||||
// } else {
|
||||
$emailTemplate->addFooter();
|
||||
// }
|
||||
|
||||
$message->setTo([$email]);
|
||||
$message->useTemplate($emailTemplate);
|
||||
$this->mailer->send($message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ class ShareTokenService {
|
|||
/**
|
||||
* @param ShareWrapper $share
|
||||
* @param Member $member
|
||||
* @param string $password
|
||||
* @param string $hashedPassword
|
||||
*
|
||||
* @return ShareToken
|
||||
* @throws ShareTokenAlreadyExistException
|
||||
|
@ -96,7 +96,7 @@ class ShareTokenService {
|
|||
public function generateShareToken(
|
||||
ShareWrapper $share,
|
||||
Member $member,
|
||||
string $password = ''
|
||||
string $hashedPassword = ''
|
||||
): ShareToken {
|
||||
if ($member->getUserType() !== Member::TYPE_MAIL
|
||||
&& $member->getUserType() !== Member::TYPE_CONTACT) {
|
||||
|
@ -104,14 +104,13 @@ class ShareTokenService {
|
|||
}
|
||||
|
||||
$token = $this->token(19);
|
||||
|
||||
$shareToken = new ShareToken();
|
||||
$shareToken->setShareId((int)$share->getId())
|
||||
->setCircleId($share->getSharedWith())
|
||||
->setSingleId($member->getSingleId())
|
||||
->setMemberId($member->getId())
|
||||
->setToken($token)
|
||||
->setPassword($password)
|
||||
->setPassword($hashedPassword)
|
||||
->setAccepted(IShare::STATUS_ACCEPTED);
|
||||
|
||||
try {
|
||||
|
|
|
@ -143,8 +143,13 @@ class ShareByCircleProvider implements IShareProvider {
|
|||
* @param IURLGenerator $urlGenerator
|
||||
*/
|
||||
public function __construct(
|
||||
IDBConnection $connection, ISecureRandom $secureRandom, IUserManager $userManager,
|
||||
IRootFolder $rootFolder, IL10N $l10n, ILogger $logger, IURLGenerator $urlGenerator
|
||||
IDBConnection $connection,
|
||||
ISecureRandom $secureRandom,
|
||||
IUserManager $userManager,
|
||||
IRootFolder $rootFolder,
|
||||
IL10N $l10n,
|
||||
ILogger $logger,
|
||||
IURLGenerator $urlGenerator
|
||||
) {
|
||||
$this->userManager = $userManager;
|
||||
$this->rootFolder = $rootFolder;
|
||||
|
@ -232,8 +237,8 @@ class ShareByCircleProvider implements IShareProvider {
|
|||
}
|
||||
|
||||
$event = new FederatedEvent(FileShare::class);
|
||||
$event->setCircle($circle)
|
||||
->getParams()->sObj('wrappedShare', $wrappedShare);
|
||||
$event->setCircle($circle);
|
||||
$event->getParams()->sObj('wrappedShare', $wrappedShare);
|
||||
|
||||
$this->federatedEventService->newEvent($event);
|
||||
$this->eventService->localShareCreated($wrappedShare);
|
||||
|
|
Loading…
Reference in a new issue