diff --git a/lib/Db/CircleInvitationRequest.php b/lib/Db/CircleInvitationRequest.php deleted file mode 100644 index 492214e67..000000000 --- a/lib/Db/CircleInvitationRequest.php +++ /dev/null @@ -1,54 +0,0 @@ -confirmValidId($circleInvitation->getCircleId()); - - $qb = $this->getQueryBuilder(); - $qb->insert(self::TABLE_INVITATIONS) - ->setValue('created', $qb->createNamedParameter($this->timezoneService->getUTCDate())); - $qb->setValue('circle_id', $qb->createNamedParameter($circleInvitation->getCircleId())) - ->setValue('invitation_code', $qb->createNamedParameter($circleInvitation->getInvitationCode())) - ->setValue('created_by', $qb->createNamedParameter($circleInvitation->getCreatedBy())); - $qb->executeStatement(); - } - - /** - * @throws InvalidIdException - */ - public function replace(CircleInvitation $circleInvitation): void { - $qb = $this->getQueryBuilder(); - $qb->delete(self::TABLE_INVITATIONS); - $qb->limitToCircleId($circleInvitation->getCircleId()); - $qb->executeStatement(); - - $this->save($circleInvitation); - } - - public function delete(string $circleId): void { - $qb = $this->getQueryBuilder(); - $qb->delete(self::TABLE_INVITATIONS); - $qb->limitToCircleId($circleId); - $qb->executeStatement(); - } -} diff --git a/lib/Entity/CircleInvitation.php b/lib/Entity/CircleInvitation.php new file mode 100644 index 000000000..143e0ad81 --- /dev/null +++ b/lib/Entity/CircleInvitation.php @@ -0,0 +1,53 @@ +created = new DateTime('now', new DateTimeZone('UTC')); + } + + public function jsonSerialize(): array { + return [ + 'circleId' => $this->circleId, + 'invitationCode' => $this->invitationCode, + 'createdBy' => $this->createdBy, + 'created' => $this->created->getTimestamp(), + ]; + } +} diff --git a/lib/Exceptions/CircleInvitationNotFoundException.php b/lib/Exceptions/CircleInvitationNotFoundException.php deleted file mode 100644 index 6b89202a3..000000000 --- a/lib/Exceptions/CircleInvitationNotFoundException.php +++ /dev/null @@ -1,13 +0,0 @@ -getBytesFromString(ISecureRandom::CHAR_HUMAN_READABLE, 16); $circleInvitation = new CircleInvitation(); - $circleInvitation->setCircleId($circle->getSingleId()); - $circleInvitation->setInvitationCode($invitationCode); - $circleInvitation->setCreatedBy($circle->getInitiator()->getUserId()); + $circleInvitation->circleId = $circle->getSingleId(); + $circleInvitation->invitationCode = $invitationCode; + $circleInvitation->createdBy = $circle->getInitiator()->getUserId(); $new->setCircleInvitation($circleInvitation); $event->getData()->sObj('circle_invitation', $circleInvitation); @@ -52,7 +52,7 @@ public function verify(FederatedEvent $event): void { public function manage(FederatedEvent $event): void { /** @var CircleInvitation $circleInvitation */ $circleInvitation = $event->getData()->gObj('circle_invitation'); - $this->circleInvitationRequest->replace($circleInvitation); + $this->circleInvitationRepository->replace($circleInvitation); // todo: do we need separate event here? $this->eventService->circleEditing($event); diff --git a/lib/FederatedItems/CircleJoin.php b/lib/FederatedItems/CircleJoin.php index f6626ccd3..b12238d8d 100644 --- a/lib/FederatedItems/CircleJoin.php +++ b/lib/FederatedItems/CircleJoin.php @@ -234,7 +234,7 @@ private function manageMemberStatus(Circle $circle, Member $member, ?string $inv throw new MemberAlreadyExistsException(StatusCode::$CIRCLE_JOIN[122], 122); } catch (MemberNotFoundException) { - $allowedToJoin = $invitationCode && $circle->getCircleInvitation()?->getInvitationCode() === $invitationCode; + $allowedToJoin = $invitationCode && $circle->getCircleInvitation()?->invitationCode === $invitationCode; if (!$circle->isConfig(Circle::CFG_OPEN) && !$allowedToJoin) { throw new FederatedItemBadRequestException(StatusCode::$CIRCLE_JOIN[124], 124); } diff --git a/lib/FederatedItems/CircleRevokeInvitation.php b/lib/FederatedItems/CircleRevokeInvitation.php index 9285ff19a..a49f0d87e 100644 --- a/lib/FederatedItems/CircleRevokeInvitation.php +++ b/lib/FederatedItems/CircleRevokeInvitation.php @@ -9,10 +9,10 @@ namespace OCA\Circles\FederatedItems; -use OCA\Circles\Db\CircleInvitationRequest; use OCA\Circles\IFederatedItem; use OCA\Circles\Model\Federated\FederatedEvent; use OCA\Circles\Model\Helpers\MemberHelper; +use OCA\Circles\Repository\CircleInvitationRepository; use OCA\Circles\Service\EventService; use OCA\Circles\Tools\Traits\TDeserialize; @@ -20,7 +20,7 @@ class CircleRevokeInvitation implements IFederatedItem { use TDeserialize; public function __construct( - private CircleInvitationRequest $circleInvitationRequest, + private CircleInvitationRepository $circleInvitationRepository, private EventService $eventService, ) { } @@ -40,7 +40,7 @@ public function verify(FederatedEvent $event): void { public function manage(FederatedEvent $event): void { $circle = clone $event->getCircle(); - $this->circleInvitationRequest->delete($circle->getSingleId()); + $this->circleInvitationRepository->deleteBy(['circleId' => $circle->getSingleId()]); // todo: do we need separate event here? $this->eventService->circleEditing($event); } diff --git a/lib/Model/Circle.php b/lib/Model/Circle.php index 1c80bfb00..b67fa39ac 100644 --- a/lib/Model/Circle.php +++ b/lib/Model/Circle.php @@ -12,6 +12,7 @@ use DateTime; use JsonSerializable; use OCA\Circles\Db\CircleRequest; +use OCA\Circles\Entity\CircleInvitation; use OCA\Circles\Exceptions\CircleNotFoundException; use OCA\Circles\Exceptions\FederatedItemException; use OCA\Circles\Exceptions\MemberHelperException; @@ -803,11 +804,14 @@ public function import(array $data): IDeserializable { } catch (InvalidItemException) { } - try { - /** @var CircleInvitation $circleInvitation */ - $circleInvitation = $this->deserialize($this->getArray('invitation', $data), CircleInvitation::class); + $invitationData = $this->getArray('invitation', $data); + if ($this->get('circleId', $invitationData) !== '') { + $circleInvitation = new CircleInvitation(); + $circleInvitation->circleId = $this->get('circleId', $invitationData); + $circleInvitation->invitationCode = $this->get('invitationCode', $invitationData); + $circleInvitation->createdBy = $this->get('createdBy', $invitationData); + $circleInvitation->created->setTimestamp($this->getInt('created', $invitationData)); $this->setCircleInvitation($circleInvitation); - } catch (InvalidItemException $e) { } return $this; @@ -860,7 +864,7 @@ public function jsonSerialize(): array { try { $initiatorHelper->mustBeAdmin(); $arr['settings'] = $this->getSettings(); - $arr['invitationCode'] = $this->getCircleInvitation()?->getInvitationCode(); + $arr['invitationCode'] = $this->getCircleInvitation()?->invitationCode; } catch (MemberHelperException|MemberLevelException) { } } diff --git a/lib/Model/CircleInvitation.php b/lib/Model/CircleInvitation.php deleted file mode 100644 index bc278d89c..000000000 --- a/lib/Model/CircleInvitation.php +++ /dev/null @@ -1,108 +0,0 @@ -circleId = $circleId; - - return $this; - } - - public function getCircleId(): string { - return $this->circleId; - } - - public function setInvitationCode(string $invitationCode): self { - $this->invitationCode = $invitationCode; - - return $this; - } - - public function getInvitationCode(): string { - return $this->invitationCode; - } - - public function setCreatedBy(string $createdBy): self { - $this->createdBy = $createdBy; - - return $this; - } - - public function getCreatedBy(): string { - return $this->createdBy; - } - - public function setCreated(int $created): self { - $this->created = $created; - - return $this; - } - - public function getCreated(): int { - return $this->created; - } - - public function import(array $data): IDeserializable { - if (!$this->get('circleId', $data)) { - throw new InvalidItemException(); - } - - $this->setCircleId($this->get('circleId', $data)) - ->setInvitationCode($this->get('invitationCode', $data)) - ->setCreatedBy($this->get('createdBy', $data)) - ->setCreated($this->getInt('created', $data)); - - return $this; - } - - public function jsonSerialize(): array { - $arr = [ - 'circleId' => $this->getCircleId(), - 'invitationCode' => $this->getInvitationCode(), - 'createdBy' => $this->getCreatedBy(), - 'created' => $this->getCreated(), - ]; - - return $arr; - } - - public function importFromDatabase(array $data, string $prefix = ''): IQueryRow { - if (!$this->get($prefix . 'circle_id', $data)) { - throw new CircleInvitationNotFoundException(); - } - - $this->setCircleId($this->get($prefix . 'circle_id', $data)) - ->setInvitationCode($this->get($prefix . 'invitation_code', $data)) - ->setCreatedBy($this->get($prefix . 'created_by', $data)); - - $created = $this->get($prefix . 'created', $data); - $dateTime = \DateTime::createFromFormat('Y-m-d H:i:s', $created); - $timestamp = $dateTime ? $dateTime->getTimestamp() : (int)strtotime($created); - $this->setCreated($timestamp); - - return $this; - } -} diff --git a/lib/Model/ModelManager.php b/lib/Model/ModelManager.php index fa7212bd1..e6aeb2419 100644 --- a/lib/Model/ModelManager.php +++ b/lib/Model/ModelManager.php @@ -14,8 +14,8 @@ use OCA\Circles\Db\CoreQueryBuilder; use OCA\Circles\Db\MemberRequest; use OCA\Circles\Db\MembershipRequest; +use OCA\Circles\Entity\CircleInvitation; use OCA\Circles\Entity\ShareToken; -use OCA\Circles\Exceptions\CircleInvitationNotFoundException; use OCA\Circles\Exceptions\CircleNotFoundException; use OCA\Circles\Exceptions\FederatedItemException; use OCA\Circles\Exceptions\FederatedUserNotFoundException; @@ -172,12 +172,6 @@ public function manageImportFromDatabase(ManagedModel $model, array $data, strin } } - if ($model instanceof CircleInvitation) { - if ($base === '') { - $base = CoreQueryBuilder::INVITATION; - } - } - if ($model instanceof Member) { if ($base === '') { $base = CoreQueryBuilder::MEMBER; @@ -258,12 +252,18 @@ private function importIntoCircle(Circle $circle, array $data, string $path, str } break; case CoreQueryBuilder::INVITATION: - try { - $circleInvitation = new CircleInvitation(); - $circleInvitation->importFromDatabase($data, $prefix); - $circle->setCircleInvitation($circleInvitation); - } catch (CircleInvitationNotFoundException $e) { + if (($data[$prefix . 'circle_id'] ?? '') === '') { + break; } + + $circleInvitation = new CircleInvitation(); + $circleInvitation->circleId = $data[$prefix . 'circle_id'] ?? ''; + $circleInvitation->invitationCode = $data[$prefix . 'invitation_code'] ?? ''; + $circleInvitation->createdBy = $data[$prefix . 'created_by'] ?? ''; + $circleInvitation->created = \DateTime::createFromFormat('Y-m-d H:i:s', $data[$prefix . 'created'] ?? '') + ?: new \DateTime((string)($data[$prefix . 'created'] ?? '')); + + $circle->setCircleInvitation($circleInvitation); break; } } diff --git a/lib/Repository/CircleInvitationRepository.php b/lib/Repository/CircleInvitationRepository.php new file mode 100644 index 000000000..5838bafe2 --- /dev/null +++ b/lib/Repository/CircleInvitationRepository.php @@ -0,0 +1,37 @@ + + */ +class CircleInvitationRepository extends Repository { + public const string entityClass = CircleInvitation::class; + + /** + * Replaces the circle's current invitation (if any) with a new one, since a circle can only + * have one active invitation at a time. + * + * @throws InvalidIdException + */ + public function replace(CircleInvitation $circleInvitation): CircleInvitation { + if (strlen($circleInvitation->circleId) < 14) { + throw new InvalidIdException(); + } + + $this->deleteBy(['circleId' => $circleInvitation->circleId]); + + return $this->insert($circleInvitation); + } +}