Skip to content

Commit 6dd5c8e

Browse files
committed
share with group members only
Signed-off-by: Maxence Lange <maxence@artificial-owl.com> fix Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
1 parent 5351f7d commit 6dd5c8e

7 files changed

Lines changed: 117 additions & 5 deletions

File tree

‎lib/FederatedItems/CircleJoin.php‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ private function manageMemberStatus(Circle $circle, Member $member) {
305305
throw new FederatedItemBadRequestException(StatusCode::$CIRCLE_JOIN[124], 124);
306306
}
307307

308+
if ($this->membershipService->limitToGroupMembersOnly($member, $circle)) {
309+
throw new FederatedItemBadRequestException(StatusCode::$CIRCLE_JOIN[125], 125);
310+
}
311+
308312
$member->setId($this->token(ManagedModel::ID_LENGTH));
309313

310314
if ($circle->isConfig(Circle::CFG_REQUEST)) {

‎lib/FederatedItems/SingleMemberAdd.php‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,11 @@ protected function generateMember(FederatedEvent $event, Circle $circle, Member
345345
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[128], 128);
346346
}
347347

348+
if (!$event->getParams()->gBool('force_group_member')
349+
&& $this->membershipService->limitToGroupMembersOnly($federatedUser, $circle)) {
350+
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[133], 133);
351+
}
352+
348353
if (!$this->configService->isLocalInstance($member->getInstance())) {
349354
if ($circle->isConfig(Circle::CFG_LOCAL)) {
350355
throw new FederatedItemBadRequestException(StatusCode::$MEMBER_ADD[126], 126);

‎lib/Model/Federated/FederatedEvent.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,8 @@ public function setParams(SimpleDataStore $params): self {
388388
}
389389

390390
/**
391+
* params are kept between master and slave in GS setup
392+
*
391393
* @return SimpleDataStore
392394
*/
393395
public function getParams(): SimpleDataStore {
@@ -396,6 +398,8 @@ public function getParams(): SimpleDataStore {
396398

397399

398400
/**
401+
* internal are only available to master in GS setup
402+
*
399403
* @param SimpleDataStore $internal
400404
*
401405
* @return self
@@ -424,6 +428,8 @@ public function resetInternal(): self {
424428

425429

426430
/**
431+
* data are generated within the FederatedEvent
432+
*
427433
* @param SimpleDataStore $data
428434
*
429435
* @return self

‎lib/Service/MemberService.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public function __construct(
136136
/**
137137
* @param string $memberId
138138
* @param string $circleId
139-
* @param bool $canBeVisitor
139+
* @param MemberProbe|null $probe
140140
*
141141
* @return Member
142142
* @throws InitiatorNotFoundException

‎lib/Service/MembershipService.php‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,17 @@
3636
use OCA\Circles\Db\CircleRequest;
3737
use OCA\Circles\Db\MemberRequest;
3838
use OCA\Circles\Db\MembershipRequest;
39+
use OCA\Circles\Exceptions\CircleNotFoundException;
3940
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
4041
use OCA\Circles\Exceptions\MembershipNotFoundException;
4142
use OCA\Circles\Exceptions\OwnerNotFoundException;
4243
use OCA\Circles\Exceptions\RequestBuilderException;
44+
use OCA\Circles\IFederatedUser;
4345
use OCA\Circles\Model\Circle;
4446
use OCA\Circles\Model\FederatedUser;
4547
use OCA\Circles\Model\Member;
4648
use OCA\Circles\Model\Membership;
49+
use OCP\Share\IManager;
4750

4851
/**
4952
* Class MembershipService
@@ -54,6 +57,9 @@ class MembershipService {
5457
use TNC22Logger;
5558

5659

60+
/** @var IManager */
61+
private $shareManager;
62+
5763
/** @var MembershipRequest */
5864
private $membershipRequest;
5965

@@ -73,19 +79,22 @@ class MembershipService {
7379
/**
7480
* MembershipService constructor.
7581
*
82+
* @param IManager $shareManager
7683
* @param MembershipRequest $membershipRequest
7784
* @param CircleRequest $circleRequest
7885
* @param MemberRequest $memberRequest
7986
* @param EventService $eventService
8087
* @param OutputService $outputService
8188
*/
8289
public function __construct(
90+
IManager $shareManager,
8391
MembershipRequest $membershipRequest,
8492
CircleRequest $circleRequest,
8593
MemberRequest $memberRequest,
8694
EventService $eventService,
8795
OutputService $outputService
8896
) {
97+
$this->shareManager = $shareManager;
8998
$this->membershipRequest = $membershipRequest;
9099
$this->circleRequest = $circleRequest;
91100
$this->memberRequest = $memberRequest;
@@ -385,4 +394,43 @@ private function getMembershipsFromList(array $list, string $circleId): Membersh
385394

386395
throw new ItemNotFoundException();
387396
}
397+
398+
399+
/**
400+
* based on Core Configuration, limit new members to shareGroupMembersOnly
401+
* returns false if the new member is good to go.
402+
*
403+
* @param FederatedUser $federatedUser
404+
* @param Circle $circle
405+
*
406+
* @return bool
407+
* @throws RequestBuilderException
408+
*/
409+
public function limitToGroupMembersOnly(IFederatedUser $federatedUser, Circle $circle): bool {
410+
if (!$this->shareManager->shareWithGroupMembersOnly()) {
411+
return false;
412+
}
413+
414+
$memberMemberships = array_map(function (Membership $membership): string {
415+
return $membership->getCircleId();
416+
}, $federatedUser->getMemberships());
417+
$ownerMemberships = array_map(function (Membership $membership): string {
418+
return $membership->getCircleId();
419+
}, $circle->getOwner()->getMemberships());
420+
421+
// we compare list of circles both (future member & owner) belongs to and check that at least one
422+
// of those Circles is based on a Nextcloud Group.
423+
foreach (array_intersect($memberMemberships, $ownerMemberships) as $circleId) {
424+
try {
425+
$groupCircle = $this->circleRequest->getCircle($circleId);
426+
if ($groupCircle->getSource() === Member::TYPE_GROUP) {
427+
return false;
428+
}
429+
} catch (CircleNotFoundException $e) {
430+
continue;
431+
}
432+
}
433+
434+
return true;
435+
}
388436
}

‎lib/Service/SyncService.php‎

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
use OCA\Circles\Exceptions\RequestBuilderException;
5656
use OCA\Circles\Exceptions\SingleCircleNotFoundException;
5757
use OCA\Circles\Exceptions\UnknownRemoteException;
58+
use OCA\Circles\FederatedItems\MemberRemove;
5859
use OCA\Circles\FederatedItems\SingleMemberAdd;
5960
use OCA\Circles\Model\Circle;
6061
use OCA\Circles\Model\Federated\FederatedEvent;
@@ -63,6 +64,7 @@
6364
use OCA\Circles\Model\Member;
6465
use OCP\IGroupManager;
6566
use OCP\IUserManager;
67+
use OCP\Share\IManager;
6668

6769
/**
6870
* Class SyncService
@@ -89,6 +91,8 @@ class SyncService {
8991
/** @var IGroupManager */
9092
private $groupManager;
9193

94+
/** @var IManager */
95+
private $shareManager;
9296

9397
/** @var CircleRequest */
9498
private $circleRequest;
@@ -99,6 +103,9 @@ class SyncService {
99103
/** @var FederatedUserService */
100104
private $federatedUserService;
101105

106+
/** @var MemberService */
107+
private $memberService;
108+
102109
/** @var federatedEventService */
103110
private $federatedEventService;
104111

@@ -120,6 +127,7 @@ class SyncService {
120127
*
121128
* @param IUserManager $userManager
122129
* @param IGroupManager $groupManager
130+
* @param IManager $shareManager
123131
* @param CircleRequest $circleRequest
124132
* @param MemberRequest $memberRequest
125133
* @param FederatedUserService $federatedUserService
@@ -132,8 +140,10 @@ class SyncService {
132140
public function __construct(
133141
IUserManager $userManager,
134142
IGroupManager $groupManager,
143+
IManager $shareManager,
135144
CircleRequest $circleRequest,
136145
MemberRequest $memberRequest,
146+
MemberService $memberService,
137147
FederatedUserService $federatedUserService,
138148
federatedEventService $federatedEventService,
139149
CircleService $circleService,
@@ -143,8 +153,10 @@ public function __construct(
143153
) {
144154
$this->userManager = $userManager;
145155
$this->groupManager = $groupManager;
156+
$this->shareManager = $shareManager;
146157
$this->circleRequest = $circleRequest;
147158
$this->memberRequest = $memberRequest;
159+
$this->memberService = $memberService;
148160
$this->federatedUserService = $federatedUserService;
149161
$this->federatedEventService = $federatedEventService;
150162
$this->circleService = $circleService;
@@ -299,6 +311,7 @@ public function syncNextcloudGroup(string $groupId): Circle {
299311
$event = new FederatedEvent(SingleMemberAdd::class);
300312
$event->setCircle($circle);
301313
$event->setMember($member);
314+
$event->getParams()->sBool('force_group_member', true);
302315

303316
try {
304317
$this->federatedEventService->newEvent($event);
@@ -451,6 +464,7 @@ public function groupMemberAdded(string $groupId, string $userId): void {
451464
$event = new FederatedEvent(SingleMemberAdd::class);
452465
$event->setCircle($circle);
453466
$event->setMember($member);
467+
$event->getParams()->sBool('force_group_member', true);
454468
$this->federatedEventService->newEvent($event);
455469

456470
// $this->memberRequest->insertOrUpdate($member);
@@ -482,8 +496,41 @@ public function groupMemberRemoved(string $groupId, string $userId): void {
482496
$circle = $this->federatedUserService->getGroupCircle($groupId);
483497
$federatedUser = $this->federatedUserService->getLocalFederatedUser($userId);
484498

485-
$this->memberRequest->deleteFederatedUserFromCircle($federatedUser, $circle);
486-
$this->membershipService->onUpdate($federatedUser->getSingleId());
499+
$member = $this->memberRequest->getMember($circle->getSingleId(), $federatedUser->getSingleId());
500+
$event = new FederatedEvent(MemberRemove::class);
501+
$event->setCircle($member->getCircle());
502+
$event->setMember($member);
503+
504+
$this->maintainGroupMemberOnly($federatedUser);
505+
}
506+
507+
508+
/**
509+
* in case of limitation shareGroupMembersOnly, clean membership on existing Circles related to
510+
* the removed group member.
511+
*
512+
* @param FederatedUser $federatedUser
513+
*
514+
* @throws RequestBuilderException
515+
*/
516+
private function maintainGroupMemberOnly(FederatedUser $federatedUser): void {
517+
if (!$this->shareManager->shareWithGroupMembersOnly()) {
518+
return;
519+
}
520+
521+
foreach ($federatedUser->getMemberships() as $membership) {
522+
try {
523+
$circle = $this->circleRequest->getCircle($membership->getCircleId());
524+
} catch (CircleNotFoundException $e) {
525+
continue;
526+
}
527+
528+
if (!$this->membershipService->limitToGroupMembersOnly($federatedUser, $circle)) {
529+
continue;
530+
}
531+
532+
echo 'NO NON ' . json_encode($circle) . "\n";
533+
}
487534
}
488535

489536

‎lib/StatusCode.php‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ class StatusCode {
4949
121 => 'Circle is full',
5050
122 => 'You are already a member',
5151
123 => 'Already requesting to join the circle',
52-
124 => 'Circle is closed'
52+
124 => 'Circle is closed',
53+
125 => 'You must belongs to one of the Nextcloud Groups from Circle\'s owner'
5354
];
5455

5556
public static $CIRCLE_LEAVE = [
@@ -69,7 +70,8 @@ class StatusCode {
6970
129 => 'Member does not contains a patron',
7071
130 => 'Member is invited by an entity that does not belongs to the instance at the origin of the request',
7172
131 => 'Member is a non-local Circle',
72-
132 => 'Member type not allowed'
73+
132 => 'Member type not allowed',
74+
133 => 'Member must belongs to one of the Nextcloud Groups from Circle\'s owner'
7375
];
7476

7577
public static $MEMBER_LEVEL = [

0 commit comments

Comments
 (0)