Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,4 @@
* `announcement-preset` (local) - Whether the `channel` and `announcement` presets are supported (channels disallow calls for everyone and only show the participants list to moderators, announcements additionally are not listable, can not be left by non-moderators and notify about all messages by default)
* `config => call => external-call-service` (local) - The target URL for an external call service if one is configured
* `bot-features-api` (local) - Whether bots can fetch their own enabled features using their shared secret
* `promote-demote-owner` - Whether owners can promote other participants to owner and demote other owners again, by sending the `participantType` parameter when promoting or demoting a participant
2 changes: 2 additions & 0 deletions docs/chat.md
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,8 @@ See [OCP\RichObjectStrings\Definitions](https://github.com/nextcloud/server/blob
* `group_removed` - {actor} removed group {group} from the conversation
* `circle_added` - {actor} added circle {circle} to the conversation
* `circle_removed` - {actor} removed circle {circle} from the conversation
* `owner_promoted` - {actor} promoted {user} to owner
* `owner_demoted` - {actor} demoted {user} from owner
* `moderator_promoted` - {actor} promoted {user} to moderator
* `moderator_demoted` - {actor} demoted {user} from moderator
* `guest_moderator_promoted` - {actor} promoted {user} to moderator
Expand Down
12 changes: 10 additions & 2 deletions docs/occ.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,26 +332,34 @@ Demotes participants of a room to regular users

### Usage

* `talk:room:demote <token> <participant>...`
* `talk:room:demote [--to-moderator] [--] <token> <participant>...`

| Arguments | Description | Is required | Is array | Default |
|---|---|---|---|---|
| `token` | Token of the room in which users should be demoted | yes | no | *Required* |
| `participant` | Demotes the given participants of the room to regular users | yes | yes | *Required* |

| Options | Description | Accept value | Is value required | Is multiple | Default |
|---|---|---|---|---|---|
| `--to-moderator` | Demotes the given owners to moderators instead of regular users | no | no | no | `false` |

## talk:room:promote

Promotes participants of a room to moderators

### Usage

* `talk:room:promote <token> <participant>...`
* `talk:room:promote [--owner] [--] <token> <participant>...`

| Arguments | Description | Is required | Is array | Default |
|---|---|---|---|---|
| `token` | Token of the room in which users should be promoted | yes | no | *Required* |
| `participant` | Promotes the given participants of the room to moderators | yes | yes | *Required* |

| Options | Description | Accept value | Is value required | Is multiple | Default |
|---|---|---|---|---|---|
| `--owner` | Promotes the given participants to owners instead of moderators | no | no | no | `false` |

## talk:room:remove

Remove users from a room
Expand Down
1 change: 1 addition & 0 deletions lib/Capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ class Capabilities implements IPublicCapability {
'bot-features-api',
'classified-conversations',
'announcement-preset',
'promote-demote-owner',
];

public const CONDITIONAL_FEATURES = [
Expand Down
26 changes: 26 additions & 0 deletions lib/Chat/Parser/SystemMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,32 @@ protected function parseMessage(Message $chatMessage, $allowInaccurate): void {
} elseif ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator removed {phone}');
}
} elseif ($message === 'owner_promoted') {
$parsedParameters['user'] = $this->getUser($parameters['user']);
$parsedMessage = $this->l->t('{actor} promoted {user} to owner');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You promoted {user} to owner');
} elseif ($this->isCurrentParticipantChangedUser($currentActorType, $currentActorId, $parsedParameters['user'])) {
$parsedMessage = $this->l->t('{actor} promoted you to owner');
if ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator promoted you to owner');
}
} elseif ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator promoted {user} to owner');
}
} elseif ($message === 'owner_demoted') {
$parsedParameters['user'] = $this->getUser($parameters['user']);
$parsedMessage = $this->l->t('{actor} demoted {user} from owner');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You demoted {user} from owner');
} elseif ($this->isCurrentParticipantChangedUser($currentActorType, $currentActorId, $parsedParameters['user'])) {
$parsedMessage = $this->l->t('{actor} demoted you from owner');
if ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator demoted you from owner');
}
} elseif ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator demoted {user} from owner');
}
} elseif ($message === 'moderator_promoted') {
$parsedParameters['user'] = $this->getUser($parameters['user']);
$parsedMessage = $this->l->t('{actor} promoted {user} to moderator');
Expand Down
6 changes: 5 additions & 1 deletion lib/Chat/SystemMessage/Listener.php
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,11 @@ public function sendSystemMessageAboutPromoteOrDemoteModerator(ParticipantModifi
return;
}

if ($event->getNewValue() === Participant::MODERATOR) {
if ($event->getNewValue() === Participant::OWNER) {
$this->sendSystemMessage($room, 'owner_promoted', ['user' => $attendee->getActorId()]);
} elseif ($event->getOldValue() === Participant::OWNER) {
$this->sendSystemMessage($room, 'owner_demoted', ['user' => $attendee->getActorId()]);
} elseif ($event->getNewValue() === Participant::MODERATOR) {
$this->sendSystemMessage($room, 'moderator_promoted', ['user' => $attendee->getActorId()]);
} elseif ($event->getNewValue() === Participant::USER) {
if ($event->getOldValue() === Participant::USER_SELF_JOINED) {
Expand Down
15 changes: 13 additions & 2 deletions lib/Command/Room/Demote.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class Demote extends Base {
Expand All @@ -33,12 +34,18 @@ protected function configure(): void {
'participant',
InputArgument::REQUIRED | InputArgument::IS_ARRAY,
'Demotes the given participants of the room to regular users'
)->addOption(
'to-moderator',
null,
InputOption::VALUE_NONE,
'Demotes the given owners to moderators instead of regular users'
);
}

protected function execute(InputInterface $input, OutputInterface $output): int {
$token = $input->getArgument('token');
$users = $input->getArgument('participant');
$toModerator = $input->getOption('to-moderator');

try {
$room = $this->manager->getRoomByToken($token);
Expand All @@ -58,13 +65,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}

try {
$this->removeRoomModerators($room, $users);
$this->removeRoomModerators($room, $users, $toModerator);
} catch (InvalidArgumentException $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return 1;
}

$output->writeln('<info>Participants successfully demoted to regular users.</info>');
if ($toModerator) {
$output->writeln('<info>Participants successfully demoted to moderators.</info>');
} else {
$output->writeln('<info>Participants successfully demoted to regular users.</info>');
}
return 0;
}

Expand Down
15 changes: 13 additions & 2 deletions lib/Command/Room/Promote.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class Promote extends Base {
Expand All @@ -33,12 +34,18 @@ protected function configure(): void {
'participant',
InputArgument::REQUIRED | InputArgument::IS_ARRAY,
'Promotes the given participants of the room to moderators'
)->addOption(
'owner',
null,
InputOption::VALUE_NONE,
'Promotes the given participants to owners instead of moderators'
);
}

protected function execute(InputInterface $input, OutputInterface $output): int {
$token = $input->getArgument('token');
$users = $input->getArgument('participant');
$toOwner = $input->getOption('owner');

try {
$room = $this->manager->getRoomByToken($token);
Expand All @@ -58,13 +65,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}

try {
$this->addRoomModerators($room, $users);
$this->addRoomModerators($room, $users, $toOwner);
} catch (InvalidArgumentException $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return 1;
}

$output->writeln('<info>Participants successfully promoted to moderators.</info>');
if ($toOwner) {
$output->writeln('<info>Participants successfully promoted to owners.</info>');
} else {
$output->writeln('<info>Participants successfully promoted to moderators.</info>');
}
return 0;
}

Expand Down
23 changes: 16 additions & 7 deletions lib/Command/Room/TRoomCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ protected function setRoomOwner(Room $room, string $userId): void {
protected function unsetRoomOwner(Room $room): void {
$participants = $this->participantService->getParticipantsForRoom($room);
foreach ($participants as $participant) {
if ($participant->getAttendee()->getParticipantType() === Participant::OWNER) {
if ($participant->isOwner()) {
$this->participantService->updateParticipantType($room, $participant, Participant::USER);
}
}
Expand Down Expand Up @@ -308,10 +308,11 @@ protected function removeRoomParticipants(Room $room, array $userIds): void {
/**
* @param Room $room
* @param string[] $userIds
* @param bool $toOwner Promote to owner instead of moderator
*
* @throws InvalidArgumentException
*/
protected function addRoomModerators(Room $room, array $userIds): void {
protected function addRoomModerators(Room $room, array $userIds, bool $toOwner = false): void {
$participants = [];
foreach ($userIds as $userId) {
if ($userId === MatterbridgeManager::BRIDGE_BOT_USERID) {
Expand All @@ -324,23 +325,30 @@ protected function addRoomModerators(Room $room, array $userIds): void {
throw new InvalidArgumentException(sprintf("User '%s' is no participant.", $userId));
}

if ($participant->getAttendee()->getParticipantType() !== Participant::OWNER) {
// Owners are not demoted to moderators by a promotion
if ($toOwner || !$participant->isOwner()) {
$participants[] = $participant;
}
}

$participantType = $toOwner ? Participant::OWNER : Participant::MODERATOR;
foreach ($participants as $participant) {
$this->participantService->updateParticipantType($room, $participant, Participant::MODERATOR);
$this->participantService->updateParticipantType($room, $participant, $participantType);
}
}

/**
* @param Room $room
* @param string[] $userIds
* @param bool $toModerator Demote owners to moderator instead of regular user
*
* @throws InvalidArgumentException
*/
protected function removeRoomModerators(Room $room, array $userIds): void {
protected function removeRoomModerators(Room $room, array $userIds, bool $toModerator = false): void {
$demotableTypes = $toModerator
? [Participant::OWNER]
: [Participant::OWNER, Participant::MODERATOR];

$participants = [];
foreach ($userIds as $userId) {
try {
Expand All @@ -349,13 +357,14 @@ protected function removeRoomModerators(Room $room, array $userIds): void {
throw new InvalidArgumentException(sprintf("User '%s' is no participant.", $userId));
}

if ($participant->getAttendee()->getParticipantType() === Participant::MODERATOR) {
if (in_array($participant->getAttendee()->getParticipantType(), $demotableTypes, true)) {
$participants[] = $participant;
}
}

$participantType = $toModerator ? Participant::MODERATOR : Participant::USER;
foreach ($participants as $participant) {
$this->participantService->updateParticipantType($room, $participant, Participant::USER);
$this->participantService->updateParticipantType($room, $participant, $participantType);
}
}

Expand Down
Loading
Loading