Remove old API version handlings

Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Joas Schilling 2021-03-04 20:41:00 +01:00
Родитель a3cf504fda
Коммит 84fa5678e2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 7076EA9751AACDDA
9 изменённых файлов: 135 добавлений и 564 удалений

Просмотреть файл

@ -317,15 +317,6 @@ return [
'token' => '^[a-z0-9]{4,30}$',
],
],
[
'name' => 'Room#removeParticipantFromRoom',
'url' => '/api/{apiVersion}/room/{token}/participants',
'verb' => 'DELETE',
'requirements' => [
'apiVersion' => 'v(4)',
'token' => '^[a-z0-9]{4,30}$',
],
],
[
'name' => 'Room#removeSelfFromRoom',
'url' => '/api/{apiVersion}/room/{token}/participants/self',
@ -335,15 +326,6 @@ return [
'token' => '^[a-z0-9]{4,30}$',
],
],
[
'name' => 'Room#removeGuestFromRoom',
'url' => '/api/{apiVersion}/room/{token}/participants/guests',
'verb' => 'DELETE',
'requirements' => [
'apiVersion' => 'v(4)',
'token' => '^[a-z0-9]{4,30}$',
],
],
[
'name' => 'Room#removeAttendeeFromRoom',
'url' => '/api/{apiVersion}/room/{token}/attendees',

Просмотреть файл

@ -1,8 +1,9 @@
# Call API
* Base endpoint for API v1 is: `/ocs/v2.php/apps/spreed/api/v1`
* Base endpoint for API v2 is: `/ocs/v2.php/apps/spreed/api/v2`
* Base endpoint for API v3 is: `/ocs/v2.php/apps/spreed/api/v3`
* API v1: 🏁 Removed with API v4
* API v2: 🏁 Removed with API v4
* API v3: 🏁 Removed with API v4
* API v4: Base endpoint `/ocs/v2.php/apps/spreed/api/v4`
## Get list of connected participants
@ -21,12 +22,11 @@
field | type | API | Description
------|------|-----|------------
`userId` | string | v1 and v2 only | Is empty for guests
`actorType` | string | v3 | Actor type of the attendee (see [Constants - Attendee types](constants.md#attendee-types))
`actorId` | string | v3 | The user id, guest random id or email address of the attendee
`displayName` | string | v3 | The display name of the attendee
`lastPing` | int | * | Timestamp of the last ping of the user (should be used for sorting)
`sessionId` | string | * | 512 character long string
`actorType` | string | v4 | Actor type of the attendee (see [Constants - Attendee types](constants.md#attendee-types))
`actorId` | string | v4 | The user id, guest random id or email address of the attendee
`displayName` | string | v4 | The display name of the attendee
`lastPing` | int | v4 | Timestamp of the last ping of the user (should be used for sorting)
`sessionId` | string | v4 | 512 character long string
## Join a call

Просмотреть файл

@ -19,7 +19,7 @@ title: Constants
* `1` regular users only, excluding guest app users
* `2` everyone
### Webinary lobby states
### Webinar lobby states
* `0` no lobby
* `1` lobby for non moderators

Просмотреть файл

@ -1,8 +1,9 @@
# Conversation API
* Base endpoint for API v1 is: `/ocs/v2.php/apps/spreed/api/v1`
* Base endpoint for API v2 is: `/ocs/v2.php/apps/spreed/api/v2`
* Base endpoint for API v3 is: `/ocs/v2.php/apps/spreed/api/v3`
* API v1: 🏁 Removed with API v4
* API v2: 🏁 Removed with API v4
* API v3: 🏁 Removed with API v4
* API v4: Base endpoint `/ocs/v2.php/apps/spreed/api/v4`
## Get user´s conversations
@ -29,37 +30,37 @@
`type` | int | * | See list of conversation types in the [constants list](constants.md#conversation-types)
`name` | string | * | Name of the conversation (can also be empty)
`displayName` | string | * | `name` if non empty, otherwise it falls back to a list of participants
`description` | string | v3 | Description of the conversation (can also be empty) (only available with `room-description` capability)
`description` | string | * | Description of the conversation (can also be empty) (only available with `room-description` capability)
`participantType` | int | * | Permissions level of the current user
`attendeeId` | int | v3 | Unique attendee id
`attendeePin` | string | v3 | Unique dial-in authentication code for this user, when the conversation has SIP enabled (see `sipEnabled` attribute)
`actorType` | string | v3 | Currently known `users|guests|emails|groups`
`actorId` | string | v3 | The unique identifier for the given actor type
`participantInCall` | bool | 🏴 v1 | **Deprecated:** ~~Flag if a **random** active session of the current user (might be from a different device) is in the call (deprecated, use `participantFlags` instead)~~
`participantFlags` | int | * | **Deprecated:** ~~Flags of a **random** active session of the current user (might be from a different device) (only available with `in-call-flags` capability)~~
`attendeeId` | int | * | Unique attendee id
`attendeePin` | string | * | Unique dial-in authentication code for this user, when the conversation has SIP enabled (see `sipEnabled` attribute)
`actorType` | string | * | Currently known `users|guests|emails|groups`
`actorId` | string | * | The unique identifier for the given actor type
`participantInCall` | 🏁 | 🏁 | **Removed:** use `participantFlags` instead
`participantFlags` | int | * | "In call" flags of the user's session making the request (only available with `in-call-flags` capability)
`readOnly` | int | * | Read-only state for the current user (only available with `read-only-rooms` capability)
`listable` | int | * | Listable scope for the room (only available with `listable-rooms` capability)
`count` | int | 🏴 v1 | **Deprecated:** ~~Number of active users~~ - always returns `0`
`numGuests` | int | 🏴 v1 | Number of active guests
`lastPing` | int | * | **Deprecated:** ~~Timestamp of the last ping of a **random** active session of the current user (might be from a different device)~~
`sessionId` | string | * | `'0'` if not connected, otherwise an up to 512 character long string that is the identifier of a **random** active session of the current user (might be from a different device), should only be used to pre-check if the user joined in another device, but this might be outdated by the time of usage, so better check via [Get list of participants in a conversation](participant.md#get-list-of-participants-in-a-conversation)
`count` | 🏁 | 🏁 | **Removed:** Count the users on the [Get list of participants in a conversation](participant.md#get-list-of-participants-in-a-conversation) endpoint
`numGuests` | 🏁 | 🏁 | **Removed:** Count the guests on the [Get list of participants in a conversation](participant.md#get-list-of-participants-in-a-conversation) endpoin
`lastPing` | int | * | Timestamp of the user's session making the request
`sessionId` | string | * | `'0'` if not connected, otherwise an up to 512 character long string that is the identifier of the user's session making the request. Should only be used to pre-check if the user joined already with this session, but this might be outdated by the time of usage, so better check via [Get list of participants in a conversation](participant.md#get-list-of-participants-in-a-conversation)
`hasPassword` | bool | * | Flag if the conversation has a password
`hasCall` | bool | * | Flag if the conversation has an active call
`callFlag` | int | v3 | Combined flag of all participants in the current call (see [constants list](constants.md#participant-in-call-flag), only available with `conversation-call-flags` capability)
`callFlag` | int | * | Combined flag of all participants in the current call (see [constants list](constants.md#participant-in-call-flag), only available with `conversation-call-flags` capability)
`canStartCall` | bool | * | Flag if the user can start a new call in this conversation (joining is always possible) (only available with `start-call-flag` capability)
`canDeleteConversation` | bool | v2 | Flag if the user can delete the conversation for everyone (not possible without moderator permissions or in one-to-one conversations)
`canLeaveConversation` | bool | v2 | Flag if the user can leave the conversation (not possible for the last user with moderator permissions)
`canDeleteConversation` | bool | * | Flag if the user can delete the conversation for everyone (not possible without moderator permissions or in one-to-one conversations)
`canLeaveConversation` | bool | * | Flag if the user can leave the conversation (not possible for the last user with moderator permissions)
`lastActivity` | int | * | Timestamp of the last activity in the conversation, in seconds and UTC time zone
`isFavorite` | bool | * | Flag if the conversation is favorited by the user
`notificationLevel` | int | * | The notification level for the user (one of `Participant::NOTIFY_*` (1-3))
`lobbyState` | int | * | Webinary lobby restriction (0-1), if the participant is a moderator they can always join the conversation (only available with `webinary-lobby` capability)
`notificationLevel` | int | * | The notification level for the user (See [Participant notification levels](constants.md#Participant-notification-levels))
`lobbyState` | int | * | Webinar lobby restriction (0-1), if the participant is a moderator they can always join the conversation (only available with `webinary-lobby` capability) (See [Webinar lobby states](constants.md#webinar-lobby-states))
`lobbyTimer` | int | * | Timestamp when the lobby will be automatically disabled (only available with `webinary-lobby` capability)
`sipEnabled` | int | v3 | SIP enable status (0-1)
`canEnableSIP` | int | v3 | Whether the given user can enable SIP for this conversation. Note that when the token is not-numeric only, SIP can not be enabled even if the user is permitted and a moderator of the conversation
`sipEnabled` | int | * | SIP enable status (0-1)
`canEnableSIP` | int | * | Whether the given user can enable SIP for this conversation. Note that when the token is not-numeric only, SIP can not be enabled even if the user is permitted and a moderator of the conversation
`unreadMessages` | int | * | Number of unread chat messages in the conversation (only available with `chat-v2` capability)
`unreadMention` | bool | * | Flag if the user was mentioned since their last visit
`lastReadMessage` | int | * | ID of the last read message in a room (only available with `chat-read-marker` capability)
`lastCommonReadMessage` | int | v3 | ID of the last message read by every user that has read privacy set to public in a room. When the user themself has it set to private the value is `0` (only available with `chat-read-status` capability)
`lastCommonReadMessage` | int | * | ID of the last message read by every user that has read privacy set to public in a room. When the user themself has it set to private the value is `0` (only available with `chat-read-status` capability)
`lastMessage` | message | * | Last message in a conversation if available, otherwise empty
`objectType` | string | * | The type of object that the conversation is associated with; "share:password" if the conversation is used to request a password for a share, otherwise empty
`objectId` | string | * | Share token if "objectType" is "share:password", otherwise empty
@ -207,7 +208,7 @@
field | type | Description
------|------|------------
`state` | int | New state for the conversation
`state` | int | New state for the conversation, see [constants list](constants.md#read-only-states)
* Response:
- Status code:
@ -233,25 +234,9 @@
+ `403 Forbidden` When the conversation is not a public conversation
+ `404 Not Found` When the conversation could not be found for the participant
## Set conversation password
* Method: `PUT`
* Endpoint: `/room/{token}/password`
* Data:
field | type | Description
------|------|------------
`password` | string | Set a new password for the conversation
* Response:
- Status code:
+ `200 OK`
+ `403 Forbidden` When the current user is not a moderator/owner
+ `403 Forbidden` When the conversation is not a public conversation
+ `404 Not Found` When the conversation could not be found for the participant
## Add conversation to favorites
* Required capability: `favorites`
* Method: `POST`
* Endpoint: `/room/{token}/favorite`
@ -263,6 +248,7 @@
## Remove conversation from favorites
* Required capability: `favorites`
* Method: `DELETE`
* Endpoint: `/room/{token}/favorite`
@ -274,6 +260,7 @@
## Set notification level
* Required capability: `notification-levels`
* Method: `POST`
* Endpoint: `/room/{token}/notify`
* Data:

Просмотреть файл

@ -1,8 +1,9 @@
# Participant API
* Base endpoint for API v1 is: `/ocs/v2.php/apps/spreed/api/v1`
* Base endpoint for API v2 is: `/ocs/v2.php/apps/spreed/api/v2`
* Base endpoint for API v3 is: `/ocs/v2.php/apps/spreed/api/v3`
* API v1: 🏁 Removed with API v4
* API v2: 🏁 Removed with API v4
* API v3: 🏁 Removed with API v4
* API v4: Base endpoint `/ocs/v2.php/apps/spreed/api/v4`
## Get list of participants in a conversation
@ -26,10 +27,9 @@
field | type | API | Description
------|------|-----|------------
`userId` | string | v1 + v2 only | Is empty for guests
`attendeeId` | int | v3 | Unique attendee id
`actorType` | string | v3 | Currently known `users|guests|emails|groups`
`actorId` | string | v3 | The unique identifier for the given actor type
`attendeeId` | int | * | Unique attendee id
`actorType` | string | * | Currently known `users|guests|emails|groups`
`actorId` | string | * | The unique identifier for the given actor type
`displayName` | string | * | Can be empty for guests
`participantType` | int | * | Permissions level of the participant (see [constants list](constants.md#participant-types))
`lastPing` | int | * | Timestamp of the last ping of the user (should be used for sorting)
@ -67,7 +67,6 @@
## Delete an attendee by id from a conversation
* API: Only `v3` or later
* Method: `DELETE`
* Endpoint: `/room/{token}/attendees`
* Data:
@ -86,27 +85,6 @@
+ `404 Not Found` When the conversation could not be found for the participant
+ `404 Not Found` When the participant to remove could not be found
## Delete a participant from a conversation
* API: Only `v1` and `v2` (Use [Delete an attendee by id from a conversation](#delete-an-attendee-by-id-from-a-conversation) in later version)
* Method: `DELETE`
* Endpoint: `/room/{token}/participants`
* Data:
field | type | Description
------|------|------------
`participant` | string | User to remove
* Response:
- Status code:
+ `200 OK`
+ `400 Bad Request` When the participant is a moderator or owner
+ `400 Bad Request` When there are no other moderators or owners left
+ `403 Forbidden` When the current user is not a moderator or owner
+ `403 Forbidden` When the participant to remove is an owner
+ `404 Not Found` When the conversation could not be found for the participant
+ `404 Not Found` When the participant to remove could not be found
## Remove yourself from a conversation
* Method: `DELETE`
@ -118,25 +96,6 @@
+ `400 Bad Request` When the participant is a moderator or owner and there are no other moderators or owners left.
+ `404 Not Found` When the conversation could not be found for the participant
## Remove a guest from a conversation
* API: Only `v1` and `v2` (Use [Delete an attendee by id from a conversation](#delete-an-attendee-by-id-from-a-conversation) in later versions)
* Method: `DELETE`
* Endpoint: `/room/{token}/participants/guests`
* Data:
field | type | Description
------|------|------------
`participant` | string | Session ID of the guest to remove
* Response:
- Status code:
+ `200 OK`
+ `400 Bad Request` When the target participant is not a guest
+ `403 Forbidden` When the current user is not a moderator or owner
+ `404 Not Found` When the conversation could not be found for the participant
+ `404 Not Found` When the target participant could not be found
## Join a conversation (available for call and chat)
* Method: `POST`
@ -145,7 +104,7 @@
field | type | Description
------|------|------------
`password` | string | Optional: Password is only required for users which are of type `4` or `5` and only when the conversation has `hasPassword` set to true.
`password` | string | Optional: Password is only required for users which are self joined or guests and only when the conversation has `hasPassword` set to true.
`force` | bool | If set to `false` and the user has an active session already a `409 Conflict` will be returned (Default: true - to keep the old behaviour)
* Response:
@ -153,7 +112,7 @@
+ `200 OK`
+ `403 Forbidden` When the password is required and didn't match
+ `404 Not Found` When the conversation could not be found for the participant
+ `409 Conflict` When the user already has an active session in the conversation. The suggested behaviour is to ask the user whether they want to kill the old session and force join unless the last ping is older than 60 seconds or older than 40 seconds when the conflicting session is not marked as in a call.
+ `409 Conflict` When the user already has an active Talk session in the conversation with this Nextcloud session. The suggested behaviour is to ask the user whether they want to kill the old session and force join unless the last ping is older than 60 seconds or older than 40 seconds when the conflicting session is not marked as in a call.
- Data in case of `200 OK`: See array definition in [Get user´s conversations](conversation.md#get-user-s-conversations)
@ -174,7 +133,7 @@
field | type | Description
------|------|------------
`attendeeId` | int or null | Attendee id can be used for guests and users
`attendeeId` | int or null | Attendee id can be used for guests and users, not setting it will resend all invitations
* Response:
- Status code:
@ -198,11 +157,9 @@
* Endpoint: `/room/{token}/moderators`
* Data:
field | type | API | Description
------|------|-----|------------
`participant` | string or null | v1 + v2 | User to demote
`sessionId` | string or null | v1 + v2 | Guest session to demote
`attendeeId` | int or null | v3 | Attendee id can be used for guests and users
field | type | Description
------|------|------------
`attendeeId` | int | Attendee id can be used for guests and users
* Response:
- Status code:
@ -219,11 +176,9 @@
* Endpoint: `/room/{token}/moderators`
* Data:
field | type | API | Description
------|------|-----|------------
`participant` | string or null | v1 + v2 | User to demote
`sessionId` | string or null | v1 + v2 | Guest session to demote
`attendeeId` | int or null | v3 | Attendee id can be used for guests and users
field | type | Description
------|------|------------
`attendeeId` | int | Attendee id can be used for guests and users
* Response:
- Status code:
@ -238,7 +193,6 @@
Note: This is only allowed with validate SIP bridge requests
* API: Only `v3` or later
* Required capability: `sip-support`
* Method: `GET`
* Endpoint: `/room/{token}/pin/{pin}`

Просмотреть файл

@ -8,9 +8,10 @@ Group and public conversations can be used to host webinars. Those online meetin
## Base endpoint
* Base endpoint for API v1 is: `/ocs/v2.php/apps/spreed/api/v1`
* Base endpoint for API v2 is: `/ocs/v2.php/apps/spreed/api/v2`
* Base endpoint for API v3 is: `/ocs/v2.php/apps/spreed/api/v3`
* API v1: 🏁 Removed with API v4
* API v2: 🏁 Removed with API v4
* API v3: 🏁 Removed with API v4
* API v4: Base endpoint `/ocs/v2.php/apps/spreed/api/v4`
## Set lobby for a conversation

Просмотреть файл

@ -72,42 +72,28 @@ class CallController extends AEnvironmentAwareController {
$participants = $this->participantService->getParticipantsInCall($this->room, $timeout);
foreach ($participants as $participant) {
if ($this->getAPIVersion() >= 3) {
$displayName = $participant->getAttendee()->getActorId();
if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) {
if ($participant->getAttendee()->getDisplayName()) {
$displayName = $participant->getAttendee()->getDisplayName();
} else {
$user = $this->userManager->get($participant->getAttendee()->getActorId());
if ($user instanceof IUser) {
$displayName = $user->getDisplayName();
}
}
} else {
$displayName = $participant->getAttendee()->getActorId();
if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) {
if ($participant->getAttendee()->getDisplayName()) {
$displayName = $participant->getAttendee()->getDisplayName();
} else {
$user = $this->userManager->get($participant->getAttendee()->getActorId());
if ($user instanceof IUser) {
$displayName = $user->getDisplayName();
}
}
$result[] = [
'actorType' => $participant->getAttendee()->getActorType(),
'actorId' => $participant->getAttendee()->getActorId(),
'displayName' => $displayName,
'token' => $this->room->getToken(),
'lastPing' => $participant->getSession()->getLastPing(),
'sessionId' => $participant->getSession()->getSessionId(),
];
} else {
$userId = '';
if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) {
$userId = $participant->getAttendee()->getActorId();
}
$result[] = [
'userId' => $userId,
'token' => $this->room->getToken(),
'lastPing' => $participant->getSession()->getLastPing(),
'sessionId' => $participant->getSession()->getSessionId(),
];
$displayName = $participant->getAttendee()->getDisplayName();
}
$result[] = [
'actorType' => $participant->getAttendee()->getActorType(),
'actorId' => $participant->getAttendee()->getActorId(),
'displayName' => $displayName,
'token' => $this->room->getToken(),
'lastPing' => $participant->getSession()->getLastPing(),
'sessionId' => $participant->getSession()->getSessionId(),
];
}
return new DataResponse($result);

Просмотреть файл

@ -257,10 +257,6 @@ class RoomController extends AEnvironmentAwareController {
return new DataResponse([], Http::STATUS_UNAUTHORIZED);
}
if ($isSIPBridgeRequest && $this->getAPIVersion() < 3) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
// The SIP bridge only needs room details (public, sip enabled, lobby state, etc)
$includeLastMessage = !$isSIPBridgeRequest;
@ -334,209 +330,7 @@ class RoomController extends AEnvironmentAwareController {
* @throws RoomNotFoundException
*/
protected function formatRoom(Room $room, ?Participant $currentParticipant, bool $isSIPBridgeRequest = false): array {
if ($this->getAPIVersion() >= 2) {
return $this->formatRoomV2andV3($room, $currentParticipant, $isSIPBridgeRequest);
}
return $this->formatRoomV1($room, $currentParticipant);
}
/**
* @param Room $room
* @param Participant|null $currentParticipant
* @return array
* @throws RoomNotFoundException
*/
protected function formatRoomV1(Room $room, ?Participant $currentParticipant): array {
$roomData = [
'id' => $room->getId(),
'token' => $room->getToken(),
'type' => $room->getType(),
'name' => '',
'displayName' => '',
'objectType' => '',
'objectId' => '',
'participantType' => Participant::GUEST,
// Deprecated, use participantFlags instead.
'participantInCall' => false,
'participantFlags' => Participant::FLAG_DISCONNECTED,
'readOnly' => Room::READ_WRITE,
'count' => 0,
'hasPassword' => $room->hasPassword(),
'hasCall' => false,
'canStartCall' => false,
'lastActivity' => 0,
'lastReadMessage' => 0,
'unreadMessages' => 0,
'unreadMention' => false,
'isFavorite' => false,
'notificationLevel' => Participant::NOTIFY_NEVER,
'lobbyState' => Webinary::LOBBY_NONE,
'lobbyTimer' => 0,
'lastPing' => 0,
'sessionId' => '0',
'participants' => [],
'numGuests' => 0,
'guestList' => '',
'lastMessage' => [],
];
if (!$currentParticipant instanceof Participant) {
return $roomData;
}
$attendee = $currentParticipant->getAttendee();
$userId = $attendee->getActorType() === Attendee::ACTOR_USERS ? $attendee->getActorId() : '';
$lastActivity = $room->getLastActivity();
if ($lastActivity instanceof \DateTimeInterface) {
$lastActivity = $lastActivity->getTimestamp();
} else {
$lastActivity = 0;
}
$lobbyTimer = $room->getLobbyTimer();
if ($lobbyTimer instanceof \DateTimeInterface) {
$lobbyTimer = $lobbyTimer->getTimestamp();
} else {
$lobbyTimer = 0;
}
$roomData = array_merge($roomData, [
'name' => $room->getName(),
'displayName' => $room->getDisplayName($userId),
'objectType' => $room->getObjectType(),
'objectId' => $room->getObjectId(),
'participantType' => $attendee->getParticipantType(),
'readOnly' => $room->getReadOnly(),
'count' => 0, // Deprecated, remove in future API version
'hasCall' => $room->getActiveSince() instanceof \DateTimeInterface,
'lastActivity' => $lastActivity,
'isFavorite' => $attendee->isFavorite(),
'notificationLevel' => $attendee->getNotificationLevel(),
'lobbyState' => $room->getLobbyState(),
'lobbyTimer' => $lobbyTimer,
]);
$session = $currentParticipant->getSession();
if ($session instanceof Session) {
$roomData = array_merge($roomData, [
// Deprecated, use participantFlags instead.
'participantInCall' => ($session->getInCall() & Participant::FLAG_IN_CALL) !== 0,
'participantFlags' => $session->getInCall(),
'lastPing' => $session->getLastPing(),
'sessionId' => $session->getSessionId(),
]);
}
if ($roomData['notificationLevel'] === Participant::NOTIFY_DEFAULT) {
if ($currentParticipant->isGuest()) {
$roomData['notificationLevel'] = Participant::NOTIFY_NEVER;
} elseif ($room->getType() === Room::ONE_TO_ONE_CALL) {
$roomData['notificationLevel'] = Participant::NOTIFY_ALWAYS;
} else {
$adminSetting = (int) $this->config->getAppValue('spreed', 'default_group_notification', Participant::NOTIFY_DEFAULT);
if ($adminSetting === Participant::NOTIFY_DEFAULT) {
$roomData['notificationLevel'] = Participant::NOTIFY_MENTION;
} else {
$roomData['notificationLevel'] = $adminSetting;
}
}
}
if ($room->getLobbyState() === Webinary::LOBBY_NON_MODERATORS &&
!$currentParticipant->hasModeratorPermissions()) {
// No participants and chat messages for users in the lobby.
$roomData['hasCall'] = false;
return $roomData;
}
$roomData['canStartCall'] = $currentParticipant->canStartCall($this->config);
if ($userId !== '') {
$currentUser = $this->userManager->get($userId);
if ($currentUser instanceof IUser) {
$lastReadMessage = $attendee->getLastReadMessage();
if ($lastReadMessage === -1) {
/*
* Because the migration from the old comment_read_markers was
* not possible in a programmatic way with a reasonable O(1) or O(n)
* but only with O(user×chat), we do the conversion here.
*/
$lastReadMessage = $this->chatManager->getLastReadMessageFromLegacy($room, $currentUser);
$this->participantService->updateLastReadMessage($currentParticipant, $lastReadMessage);
}
$roomData['unreadMessages'] = $this->chatManager->getUnreadCount($room, $lastReadMessage);
$lastMention = $attendee->getLastMentionMessage();
$roomData['unreadMention'] = $lastMention !== 0 && $lastReadMessage < $lastMention;
$roomData['lastReadMessage'] = $lastReadMessage;
}
}
$numActiveGuests = 0;
$cleanGuests = false;
$participantList = [];
$participants = $this->participantService->getSessionsAndParticipantsForRoom($room); // FIXME NEEDS the session but can potentially kill APIv1?
uasort($participants, function (Participant $participant1, Participant $participant2) {
$s1 = $participant1->getSession() ? $participant1->getSession()->getLastPing() : 0;
$s2 = $participant2->getSession() ? $participant2->getSession()->getLastPing() : 0;
return $s2 - $s1;
});
foreach ($participants as $participant) {
/** @var Participant $participant */
if ($participant->isGuest()) {
if ($participant->getSession()) {
if ($participant->getSession()->getLastPing() <= $this->timeFactory->getTime() - 100) {
$cleanGuests = true;
} else {
$numActiveGuests++;
}
}
} elseif ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) {
$attendee = $participant->getAttendee();
$session = $participant->getSession();
$user = $this->userManager->get($attendee->getActorId());
if ($user instanceof IUser) {
$participantList[(string)$user->getUID()] = [
'name' => $user->getDisplayName(),
'type' => $attendee->getParticipantType(),
'call' => $session ? $session->getInCall() : Participant::FLAG_DISCONNECTED,
'sessionId' => $session ? $session->getSessionId() : '0',
];
if ($room->getType() === Room::ONE_TO_ONE_CALL &&
$user->getUID() !== $currentParticipant->getAttendee()->getActorId()) {
// FIXME This should not be done, but currently all the clients use it to get the avatar of the user …
$roomData['name'] = $user->getUID();
}
}
if ($session && $session->getLastPing() <= $this->timeFactory->getTime() - 100) {
$this->participantService->leaveRoomAsSession($room, $participant);
}
}
}
if ($cleanGuests) {
$this->participantService->cleanGuestParticipants($room);
}
$lastMessage = $room->getLastMessage();
if ($lastMessage instanceof IComment) {
$lastMessage = $this->formatLastMessage($room, $currentParticipant, $lastMessage);
} else {
$lastMessage = [];
}
$roomData = array_merge($roomData, [
'participants' => $participantList,
'numGuests' => $numActiveGuests,
'lastMessage' => $lastMessage,
]);
return $roomData;
return $this->formatRoomV4($room, $currentParticipant, $isSIPBridgeRequest);
}
/**
@ -546,7 +340,7 @@ class RoomController extends AEnvironmentAwareController {
* @return array
* @throws RoomNotFoundException
*/
protected function formatRoomV2andV3(Room $room, ?Participant $currentParticipant, bool $isSIPBridgeRequest = false): array {
protected function formatRoomV4(Room $room, ?Participant $currentParticipant, bool $isSIPBridgeRequest = false): array {
$roomData = [
'id' => $room->getId(),
'token' => $room->getToken(),
@ -575,21 +369,17 @@ class RoomController extends AEnvironmentAwareController {
'sessionId' => '0',
'guestList' => '',
'lastMessage' => [],
'sipEnabled' => Webinary::SIP_DISABLED,
'actorType' => '',
'actorId' => '',
'attendeeId' => 0,
'canEnableSIP' => false,
'attendeePin' => '',
'description' => '',
'lastCommonReadMessage' => 0,
'listable' => Room::LISTABLE_NONE,
'callFlag' => Participant::FLAG_DISCONNECTED,
];
if ($this->getAPIVersion() >= 3) {
$roomData = array_merge($roomData, [
'sipEnabled' => Webinary::SIP_DISABLED,
'actorType' => '',
'actorId' => '',
'attendeeId' => 0,
'canEnableSIP' => false,
'attendeePin' => '',
'description' => '',
'lastCommonReadMessage' => 0,
'listable' => Room::LISTABLE_NONE,
'callFlag' => Participant::FLAG_DISCONNECTED,
]);
}
$lastActivity = $room->getLastActivity();
if ($lastActivity instanceof \DateTimeInterface) {
@ -645,32 +435,28 @@ class RoomController extends AEnvironmentAwareController {
'notificationLevel' => $attendee->getNotificationLevel(),
'lobbyState' => $room->getLobbyState(),
'lobbyTimer' => $lobbyTimer,
'actorType' => $attendee->getActorType(),
'actorId' => $attendee->getActorId(),
'attendeeId' => $attendee->getId(),
'description' => $room->getDescription(),
'listable' => $room->getListable(),
]);
if ($this->getAPIVersion() >= 3) {
if ($this->talkConfig->isSIPConfigured()) {
$roomData['sipEnabled'] = $room->getSIPEnabled();
if ($room->getSIPEnabled() === Webinary::SIP_ENABLED) {
// Generate a PIN if the attendee is a user and doesn't have one.
$this->participantService->generatePinForParticipant($room, $currentParticipant);
$roomData['attendeePin'] = $attendee->getPin();
}
if ($currentParticipant->getAttendee()->getReadPrivacy() === Participant::PRIVACY_PUBLIC) {
if (isset($this->commonReadMessages[$room->getId()])) {
$roomData['lastCommonReadMessage'] = $this->commonReadMessages[$room->getId()];
} else {
$roomData['lastCommonReadMessage'] = $this->chatManager->getLastCommonReadMessage($room);
}
}
$roomData = array_merge($roomData, [
'actorType' => $attendee->getActorType(),
'actorId' => $attendee->getActorId(),
'attendeeId' => $attendee->getId(),
'description' => $room->getDescription(),
'listable' => $room->getListable(),
]);
if ($this->talkConfig->isSIPConfigured()) {
$roomData['sipEnabled'] = $room->getSIPEnabled();
if ($room->getSIPEnabled() === Webinary::SIP_ENABLED) {
// Generate a PIN if the attendee is a user and doesn't have one.
$this->participantService->generatePinForParticipant($room, $currentParticipant);
if ($currentParticipant->getAttendee()->getReadPrivacy() === Participant::PRIVACY_PUBLIC) {
if (isset($this->commonReadMessages[$room->getId()])) {
$roomData['lastCommonReadMessage'] = $this->commonReadMessages[$room->getId()];
} else {
$roomData['lastCommonReadMessage'] = $this->chatManager->getLastCommonReadMessage($room);
}
$roomData['attendeePin'] = $attendee->getPin();
}
}
@ -735,14 +521,12 @@ class RoomController extends AEnvironmentAwareController {
$roomData['canDeleteConversation'] = $room->getType() !== Room::ONE_TO_ONE_CALL
&& $currentParticipant->hasModeratorPermissions(false);
$roomData['canLeaveConversation'] = true;
if ($this->getAPIVersion() >= 3) {
$roomData['canEnableSIP'] =
$this->talkConfig->isSIPConfigured()
&& !preg_match(Room::SIP_INCOMPATIBLE_REGEX, $room->getToken())
&& ($room->getType() === Room::GROUP_CALL || $room->getType() === Room::PUBLIC_CALL)
&& $currentParticipant->hasModeratorPermissions(false)
&& $this->talkConfig->canUserEnableSIP($currentUser);
}
$roomData['canEnableSIP'] =
$this->talkConfig->isSIPConfigured()
&& !preg_match(Room::SIP_INCOMPATIBLE_REGEX, $room->getToken())
&& ($room->getType() === Room::GROUP_CALL || $room->getType() === Room::PUBLIC_CALL)
&& $currentParticipant->hasModeratorPermissions(false)
&& $this->talkConfig->canUserEnableSIP($currentUser);
}
}
@ -1162,22 +946,22 @@ class RoomController extends AEnvironmentAwareController {
'lastPing' => 0,
'sessionId' => '0', // FIXME empty string or null?
'participantType' => $participant->getAttendee()->getParticipantType(),
'attendeeId' => $attendeeId,
'actorId' => $participant->getAttendee()->getActorId(),
'actorType' => $participant->getAttendee()->getActorType(),
'displayName' => $participant->getAttendee()->getActorId(),
'attendeePin' => '',
];
if ($this->getAPIVersion() >= 3) {
$result['attendeeId'] = $attendeeId;
$result['actorId'] = $participant->getAttendee()->getActorId();
$result['actorType'] = $participant->getAttendee()->getActorType();
$result['attendeePin'] = '';
if ($this->talkConfig->isSIPConfigured()
&& $this->room->getSIPEnabled() === Webinary::SIP_ENABLED
&& ($this->participant->hasModeratorPermissions(false)
|| $this->participant->getAttendee()->getId() === $participant->getAttendee()->getId())) {
// Generate a PIN if the attendee is a user and doesn't have one.
$this->participantService->generatePinForParticipant($this->room, $participant);
if ($this->talkConfig->isSIPConfigured()
&& $this->room->getSIPEnabled() === Webinary::SIP_ENABLED
&& ($this->participant->hasModeratorPermissions(false)
|| $this->participant->getAttendee()->getId() === $participant->getAttendee()->getId())) {
// Generate a PIN if the attendee is a user and doesn't have one.
$this->participantService->generatePinForParticipant($this->room, $participant);
$result['attendeePin'] = (string) $participant->getAttendee()->getPin();
}
$result['attendeePin'] = (string) $participant->getAttendee()->getPin();
}
if ($participant->getSession() instanceof Session) {
$result['inCall'] = $participant->getSession()->getInCall();
$result['lastPing'] = $participant->getSession()->getLastPing();
@ -1190,9 +974,6 @@ class RoomController extends AEnvironmentAwareController {
$this->participantService->leaveRoomAsSession($this->room, $participant);
}
if ($this->getAPIVersion() < 3) {
$result['userId'] = $participant->getAttendee()->getActorId();
}
$result['displayName'] = $participant->getAttendee()->getDisplayName();
if (!$result['displayName']) {
$user = $this->userManager->get($userId);
@ -1214,16 +995,7 @@ class RoomController extends AEnvironmentAwareController {
continue;
}
if ($this->getAPIVersion() < 3) {
$result['userId'] = '';
}
$result['displayName'] = $participant->getAttendee()->getDisplayName();
} elseif ($this->getAPIVersion() >= 3) {
// Other types are only reported on v3 or later
$result['displayName'] = $participant->getAttendee()->getActorId();
} else {
// Skip unknown actor types
continue;
}
$results[$attendeeId] = $result;
@ -1357,47 +1129,6 @@ class RoomController extends AEnvironmentAwareController {
return new DataResponse([]);
}
/**
* @PublicPage
* @RequireParticipant
*
* @param string $participant
* @return DataResponse
*/
public function removeParticipantFromRoom(string $participant): DataResponse {
$attendee = $this->participant->getAttendee();
if ($attendee->getActorType() === Attendee::ACTOR_USERS && $attendee->getActorId() === $participant) {
// Removing self, abusing moderator power
return $this->removeSelfFromRoomLogic($this->room, $this->participant);
}
if (!$this->participant->hasModeratorPermissions()) {
return new DataResponse([], Http::STATUS_FORBIDDEN);
}
if ($this->room->getType() === Room::ONE_TO_ONE_CALL) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
try {
$targetParticipant = $this->room->getParticipant($participant);
} catch (ParticipantNotFoundException $e) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
}
if ($targetParticipant->getAttendee()->getParticipantType() === Participant::OWNER) {
return new DataResponse([], Http::STATUS_FORBIDDEN);
}
$targetUser = $this->userManager->get($participant);
if (!$targetUser instanceof IUser) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
}
$this->participantService->removeUser($this->room, $targetUser, Room::PARTICIPANT_REMOVED);
return new DataResponse([]);
}
/**
* @NoAdminRequired
* @RequireLoggedInParticipant
@ -1439,36 +1170,6 @@ class RoomController extends AEnvironmentAwareController {
return new DataResponse();
}
/**
* @PublicPage
* @RequireModeratorParticipant
*
* @param string $participant
* @return DataResponse
*/
public function removeGuestFromRoom(string $participant): DataResponse {
try {
$targetParticipant = $this->room->getParticipantBySession($participant);
} catch (ParticipantNotFoundException $e) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
}
if (!$targetParticipant->isGuest()) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
$targetSession = $targetParticipant->getSession();
$currentSession = $this->participant->getSession();
if ($targetSession instanceof Session
&& $currentSession instanceof Session
&& $targetSession->getSessionId() === $currentSession->getSessionId()) {
return new DataResponse([], Http::STATUS_FORBIDDEN);
}
$this->participantService->removeAttendee($this->room, $targetParticipant, Room::PARTICIPANT_REMOVED);
return new DataResponse([]);
}
/**
* @PublicPage
* @RequireModeratorParticipant
@ -1711,47 +1412,35 @@ class RoomController extends AEnvironmentAwareController {
* @PublicPage
* @RequireModeratorParticipant
*
* @param int|null $attendeeId
* @param string|null $participant
* @param string|null $sessionId
* @param int $attendeeId
* @return DataResponse
*/
public function promoteModerator(?int $attendeeId, ?string $participant, ?string $sessionId): DataResponse {
return $this->changeParticipantType($attendeeId, $participant, $sessionId, true);
public function promoteModerator(int $attendeeId): DataResponse {
return $this->changeParticipantType($attendeeId, true);
}
/**
* @PublicPage
* @RequireModeratorParticipant
*
* @param int|null $attendeeId
* @param string|null $participant
* @param string|null $sessionId
* @param int $attendeeId
* @return DataResponse
*/
public function demoteModerator(?int $attendeeId, ?string $participant, ?string $sessionId): DataResponse {
return $this->changeParticipantType($attendeeId, $participant, $sessionId, false);
public function demoteModerator(int $attendeeId): DataResponse {
return $this->changeParticipantType($attendeeId, false);
}
/**
* Toggle a user/guest to moderator/guest-moderator or vice-versa based on
* attendeeId (v3) or userId/sessionId (v1+v2)
* attendeeId
*
* @param int|null $attendeeId
* @param string|null $userId
* @param string|null $sessionId
* @param int $attendeeId
* @param bool $promote Shall the attendee be promoted or demoted
* @return DataResponse
*/
protected function changeParticipantType(?int $attendeeId, ?string $userId, ?string $sessionId, bool $promote): DataResponse {
protected function changeParticipantType(int $attendeeId, bool $promote): DataResponse {
try {
if ($attendeeId !== null) {
$targetParticipant = $this->room->getParticipantByAttendeeId($attendeeId);
} elseif ($userId !== null) {
$targetParticipant = $this->room->getParticipant($userId);
} else {
$targetParticipant = $this->room->getParticipantBySession($sessionId);
}
$targetParticipant = $this->room->getParticipantByAttendeeId($attendeeId);
} catch (ParticipantNotFoundException $e) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
}
@ -1828,7 +1517,7 @@ class RoomController extends AEnvironmentAwareController {
}
}
return new DataResponse($this->formatRoomV2andV3($this->room, $this->participant));
return new DataResponse($this->formatRoom($this->room, $this->participant));
}
/**
@ -1856,7 +1545,7 @@ class RoomController extends AEnvironmentAwareController {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
return new DataResponse($this->formatRoomV2andV3($this->room, $this->participant));
return new DataResponse($this->formatRoom($this->room, $this->participant));
}
/**

Просмотреть файл

@ -185,32 +185,6 @@ const removeCurrentUserFromConversation = async function(token) {
return response
}
const removeUserFromConversation = async function(token, userId) {
try {
const response = await axios.delete(generateOcsUrl('apps/spreed/api/v4', 2) + `room/${token}/participants`, {
params: {
participant: userId,
},
})
return response
} catch (error) {
console.debug(error)
}
}
const removeGuestFromConversation = async function(token, sessionId) {
try {
const response = await axios.delete(generateOcsUrl('apps/spreed/api/v4', 2) + `room/${token}/participants/guests`, {
params: {
participant: sessionId,
},
})
return response
} catch (error) {
console.debug(error)
}
}
const removeAttendeeFromConversation = async function(token, attendeeId) {
const response = await axios.delete(generateOcsUrl('apps/spreed/api/v4', 2) + `room/${token}/attendees`, {
params: {
@ -267,8 +241,6 @@ export {
leaveConversationSync,
addParticipant,
removeCurrentUserFromConversation,
removeUserFromConversation,
removeGuestFromConversation,
removeAttendeeFromConversation,
promoteToModerator,
demoteFromModerator,