diff --git a/lib/Controller/BanController.php b/lib/Controller/BanController.php index ed39a9dd57..45f6ad45c4 100644 --- a/lib/Controller/BanController.php +++ b/lib/Controller/BanController.php @@ -12,6 +12,7 @@ namespace OCA\Talk\Controller; use OCA\Talk\Middleware\Attribute\RequireModeratorParticipant; use OCA\Talk\Model\Attendee; use OCA\Talk\ResponseDefinitions; +use OCA\Talk\Service\BanService; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\DataResponse; @@ -24,6 +25,7 @@ class BanController extends AEnvironmentAwareController { public function __construct( string $appName, IRequest $request, + protected BanService $banService ) { parent::__construct($appName, $request); } @@ -45,25 +47,28 @@ class BanController extends AEnvironmentAwareController { #[PublicPage] #[RequireModeratorParticipant] public function banActor(string $actorType, string $actorId, string $internalNote = ''): DataResponse { - if ($actorId === 'wrong') { + try { + $attendee = $this->participant->getAttendee(); + $roomId = $attendee->getRoomId(); + $bannedId = $attendee->getActorId(); + $bannedType = $attendee->getActorType(); + + $ban = $this->banService->createBan( + $actorId, + $actorType, + $roomId, + $bannedId, + $bannedType, + null, + $internalNote + ); + + return new DataResponse($ban->jsonSerialize(), Http::STATUS_OK); + } catch (\InvalidArgumentException $e) { return new DataResponse([ - 'error' => 'actor', + 'error' => $e->getMessage(), ], Http::STATUS_BAD_REQUEST); } - - - return new DataResponse( - [ - 'id' => random_int(1, 1337), - 'actorType' => $this->participant->getAttendee()->getActorType(), - 'actorId' => $this->participant->getAttendee()->getActorId(), - 'bannedType' => $actorType, - 'bannedId' => $actorId, - 'bannedTime' => time(), - 'internalNote' => $internalNote ?: 'Lorem ipsum', - ], - Http::STATUS_OK - ); } /** @@ -77,17 +82,14 @@ class BanController extends AEnvironmentAwareController { */ #[PublicPage] #[RequireModeratorParticipant] - public function listBans(): DataResponse { - return new DataResponse([ - $this->randomBan(Attendee::ACTOR_USERS, 'test'), - $this->randomBan(Attendee::ACTOR_USERS, '123456'), - $this->randomBan(Attendee::ACTOR_FEDERATED_USERS, 'admin@nextcloud.local'), - $this->randomBan('ip', '127.0.0.1'), - $this->randomBan('ip', '127.0.0.1/32'), - $this->randomBan('ip', '127.0.0.0/24'), - $this->randomBan('ip', '::1/24'), - $this->randomBan('ip', '2001:0db8:85a3::/48'), - ], Http::STATUS_OK); + public function listBans(int $roomId): DataResponse { + $bans = $this->banService->getBansForRoom($roomId); + $result = array_map(function ($ban) { + return $ban->jsonSerialize(); + }, $bans); + + /** @psalm-var list $result */ + return new DataResponse($result, Http::STATUS_OK); } /** @@ -103,6 +105,7 @@ class BanController extends AEnvironmentAwareController { #[PublicPage] #[RequireModeratorParticipant] public function unbanActor(int $banId): DataResponse { + $this->banService->findAndDeleteBanById($banId); return new DataResponse([], Http::STATUS_OK); } diff --git a/lib/Migration/Version20000Date20240621150333.php b/lib/Migration/Version20000Date20240621150333.php index f929eb9a2e..98091d3e67 100644 --- a/lib/Migration/Version20000Date20240621150333.php +++ b/lib/Migration/Version20000Date20240621150333.php @@ -55,7 +55,7 @@ class Version20000Date20240621150333 extends SimpleMigrationStep { $table->addColumn('banned_at', Types::DATETIME, [ 'notnull' => false, ]); - $table->addColumn('reason', Types::TEXT, [ + $table->addColumn('internalNote', Types::TEXT, [ 'notnull' => false, ]); diff --git a/lib/Model/Ban.php b/lib/Model/Ban.php index f16ac3162b..1d6ceed542 100644 --- a/lib/Model/Ban.php +++ b/lib/Model/Ban.php @@ -17,32 +17,32 @@ use OCP\AppFramework\Db\Entity; * @method string getActorType() * @method void setRoomId(int $roomId) * @method int getRoomId() - * @method void setBannedByActorId(string $bannedByActorId) - * @method string getBannedByActorId() - * @method void setBannedByActorType(string $bannedByActorType) - * @method string getBannedByActorType() - * @method void setBannedAt(\DateTime $bannedAt) - * @method \DateTime getBannedAt() - * @method void setReason(string $reason) - * @method string getReason() + * @method void setBannedId(string $bannedId) + * @method string getBannedId() + * @method void setBannedType(string $bannedType) + * @method string getBannedType() + * @method void setBannedTime(\DateTime $bannedTime) + * @method \DateTime getBannedTime() + * @method void setInternalNote(string $internalNote) + * @method string getInternalNote() */ class Ban extends Entity implements \JsonSerializable { protected string $actorId = ''; protected string $actorType = ''; protected int $roomId = 0; - protected string $bannedByActorId = ''; - protected string $bannedByActorType = ''; - protected ?\DateTime $bannedAt = null; - protected ?string $reason = null; + protected string $bannedId = ''; + protected string $bannedType = ''; + protected ?\DateTime $bannedTime = null; + protected ?string $internalNote = null; public function __construct() { $this->addType('actorId', 'string'); $this->addType('actorType', 'string'); $this->addType('roomId', 'int'); - $this->addType('bannedByActorId', 'string'); - $this->addType('bannedByActorType', 'string'); - $this->addType('bannedAt', 'datetime'); - $this->addType('reason', 'string'); + $this->addType('bannedId', 'string'); + $this->addType('bannedType', 'string'); + $this->addType('bannedTime', 'datetime'); + $this->addType('internalNote', 'string'); } public function jsonSerialize(): array { @@ -50,10 +50,10 @@ class Ban extends Entity implements \JsonSerializable { 'actorId' => $this->getActorId(), 'actorType' => $this->getActorType(), 'roomId' => $this->getRoomId(), - 'bannedByActorId' => $this->getBannedByActorId(), - 'bannedByActorType' => $this->getBannedByActorType(), - 'bannedAt' => $this->getBannedAt() ? $this->getBannedAt()->getTimestamp() : null, - 'reason' => $this->getReason(), + 'bannedId' => $this->getBannedId(), + 'bannedType' => $this->getBannedType(), + 'bannedTime' => $this->getBannedTime() ? $this->getBannedTime()->getTimestamp() : null, + 'internalNote' => $this->getInternalNote(), ]; } } diff --git a/lib/Model/BanMapper.php b/lib/Model/BanMapper.php index b23d430671..2de2d9b946 100644 --- a/lib/Model/BanMapper.php +++ b/lib/Model/BanMapper.php @@ -50,6 +50,15 @@ class BanMapper extends QBMapper { return $this->findEntities($query); } + public function findByBanId(int $banId): Ban { + $query = $this->db->getQueryBuilder(); + $query->select('*') + ->from($this->getTableName()) + ->where($query->expr()->eq('id', $query->createNamedParameter($banId, IQueryBuilder::PARAM_INT))); + + return $this->findEntity($query); + } + public function deleteBanForActorAndRoom(string $actorId, string $actorType, int $roomId): void { $query = $this->db->getQueryBuilder(); $query->delete($this->getTableName()) diff --git a/lib/Service/BanService.php b/lib/Service/BanService.php index 4a33b4f21f..79b7cc20f9 100644 --- a/lib/Service/BanService.php +++ b/lib/Service/BanService.php @@ -25,30 +25,30 @@ class BanService { /** * Validate the ban data. */ - private function validateBanData(string $actorId, string $actorType, int $roomId, string $bannedByActorId, string $bannedByActorType, ?DateTime $bannedAt, ?string $reason): void { - if (empty($actorId) || empty($actorType) || empty($roomId) || empty($bannedByActorId) || empty($bannedByActorType)) { + private function validateBanData(string $actorId, string $actorType, int $roomId, string $bannedId, string $bannedType, ?DateTime $bannedTime, ?string $internalNote): void { + if (empty($actorId) || empty($actorType) || empty($roomId) || empty($bannedId) || empty($bannedType)) { throw new \InvalidArgumentException("Invalid ban data provided."); } - if ($bannedAt !== null && !$bannedAt instanceof DateTime) { - throw new \InvalidArgumentException("Invalid date format for bannedAt."); + if ($bannedTime !== null && !$bannedTime instanceof DateTime) { + throw new \InvalidArgumentException("Invalid date format for bannedTime."); } } /** * Create a new ban */ - public function createBan(string $actorId, string $actorType, int $roomId, string $bannedByActorId, string $bannedByActorType, ?DateTime $bannedAt, ?string $reason): Ban { - $this->validateBanData($actorId, $actorType, $roomId, $bannedByActorId, $bannedByActorType, $bannedAt, $reason); + public function createBan(string $actorId, string $actorType, int $roomId, string $bannedId, string $bannedType, ?DateTime $bannedTime, ?string $internalNote): Ban { + $this->validateBanData($actorId, $actorType, $roomId, $bannedId, $bannedType, $bannedTime, $internalNote); $ban = new Ban(); $ban->setActorId($actorId); $ban->setActorType($actorType); $ban->setRoomId($roomId); - $ban->setBannedByActorId($bannedByActorId); - $ban->setBannedByActorType($bannedByActorType); - $ban->setBannedAt($bannedAt ?? $this->timeFactory->getTime()); - $ban->setReason($reason); + $ban->setBannedId($bannedId); + $ban->setBannedType($bannedType); + $ban->setBannedTime($bannedTime ?? $this->timeFactory->getTime()); + $ban->setInternalNote($internalNote); return $this->banMapper->insert($ban); } @@ -85,4 +85,16 @@ class BanService { public function getBansForRoom(int $roomId): array { return $this->banMapper->findByRoomId($roomId); } + + /** + * Retrieve a ban by its ID and delete it. + */ + public function findAndDeleteBanById(int $banId): void { + try { + $ban = $this->banMapper->findByBanId($banId); + $this->banMapper->delete($ban); + } catch (DoesNotExistException $e) { + // Ban does not exist + } + } } diff --git a/tests/integration/features/conversation-1/ban.feature b/tests/integration/features/conversation-1/ban.feature new file mode 100644 index 0000000000..e69de29bb2