@wazo/sdk 0.38.7 → 0.38.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/wazo-sdk.js +2 -2
- package/esm/__tests__/api-client.test.js +163 -2
- package/esm/__tests__/web-rtc-client.test.js +248 -27
- package/esm/api/auth.js +12 -0
- package/esm/api/calld.js +8 -0
- package/esm/api/confd.js +134 -2
- package/esm/api/ctid-ng.js +1 -0
- package/esm/api-client.js +163 -2
- package/esm/checker/Checker.js +204 -24
- package/esm/checker/checks/aor.js +163 -2
- package/esm/checker/checks/api.js +163 -2
- package/esm/checker/checks/index.js +204 -24
- package/esm/checker/checks/wazo-websocket.js +2 -0
- package/esm/checker/checks/webrtc-transport.js +202 -24
- package/esm/checker/checks/webrtc.js +202 -24
- package/esm/domain/AdHocAPIConference.js +170 -4
- package/esm/domain/Features.js +170 -4
- package/esm/domain/Meeting.js +18 -0
- package/esm/domain/MeetingAuthorization.js +70 -0
- package/esm/domain/Phone/CTIPhone.js +170 -4
- package/esm/domain/Phone/WebRTCPhone.js +2 -3
- package/esm/domain/__tests__/Meeting.test.js +87 -1
- package/esm/domain/__tests__/MeetingAuthorization.test.js +109 -0
- package/esm/index.js +300 -36
- package/esm/service/CallApi.js +170 -4
- package/esm/service/getApiClient.js +176 -5
- package/esm/simple/Auth.js +301 -37
- package/esm/simple/Configuration.js +300 -36
- package/esm/simple/Directory.js +170 -4
- package/esm/simple/Phone.js +300 -36
- package/esm/simple/Softphone.js +5 -0
- package/esm/simple/Websocket.js +3 -0
- package/esm/simple/index.js +300 -36
- package/esm/simple/room/LocalParticipant.js +300 -36
- package/esm/simple/room/Participant.js +300 -36
- package/esm/simple/room/RemoteParticipant.js +300 -36
- package/esm/simple/room/Room.js +300 -36
- package/esm/simple/room/SipRoom.js +300 -36
- package/esm/simple/room/Stream.js +300 -36
- package/esm/simple/room/__tests__/Participant.test.js +14812 -0
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +300 -36
- package/esm/simple/utils.js +300 -36
- package/esm/utils/__tests__/object.test.js +57 -0
- package/esm/utils/__tests__/string.test.js +30 -0
- package/esm/utils/object.js +24 -0
- package/esm/utils/string.js +10 -0
- package/esm/web-rtc-client.js +202 -24
- package/esm/websocket-client.js +3 -1
- package/lib/__tests__/api-client.test.js +163 -2
- package/lib/__tests__/web-rtc-client.test.js +248 -27
- package/lib/api/auth.js +12 -0
- package/lib/api/calld.js +8 -0
- package/lib/api/confd.js +134 -2
- package/lib/api/ctid-ng.js +1 -0
- package/lib/api-client.js +163 -2
- package/lib/checker/Checker.js +204 -24
- package/lib/checker/checks/aor.js +163 -2
- package/lib/checker/checks/api.js +163 -2
- package/lib/checker/checks/index.js +204 -24
- package/lib/checker/checks/wazo-websocket.js +2 -0
- package/lib/checker/checks/webrtc-transport.js +202 -24
- package/lib/checker/checks/webrtc.js +202 -24
- package/lib/domain/AdHocAPIConference.js +170 -4
- package/lib/domain/Features.js +170 -4
- package/lib/domain/Meeting.js +18 -0
- package/lib/domain/MeetingAuthorization.js +79 -0
- package/lib/domain/Phone/CTIPhone.js +170 -4
- package/lib/domain/Phone/WebRTCPhone.js +2 -3
- package/lib/domain/__tests__/Meeting.test.js +87 -1
- package/lib/domain/__tests__/MeetingAuthorization.test.js +111 -0
- package/lib/index.js +300 -36
- package/lib/service/CallApi.js +170 -4
- package/lib/service/getApiClient.js +176 -4
- package/lib/simple/Auth.js +301 -36
- package/lib/simple/Configuration.js +300 -36
- package/lib/simple/Directory.js +170 -4
- package/lib/simple/Phone.js +300 -36
- package/lib/simple/Softphone.js +5 -0
- package/lib/simple/Websocket.js +3 -0
- package/lib/simple/index.js +300 -36
- package/lib/simple/room/LocalParticipant.js +300 -36
- package/lib/simple/room/Participant.js +300 -36
- package/lib/simple/room/RemoteParticipant.js +300 -36
- package/lib/simple/room/Room.js +300 -36
- package/lib/simple/room/SipRoom.js +300 -36
- package/lib/simple/room/Stream.js +300 -36
- package/lib/simple/room/__tests__/Participant.test.js +14822 -0
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +300 -36
- package/lib/simple/utils.js +300 -36
- package/lib/utils/__tests__/object.test.js +59 -0
- package/lib/utils/__tests__/string.test.js +32 -0
- package/lib/utils/object.js +28 -0
- package/lib/utils/string.js +14 -0
- package/lib/web-rtc-client.js +202 -24
- package/lib/websocket-client.js +3 -0
- package/package.json +1 -1
- package/src/__tests__/web-rtc-client.test.js +46 -3
- package/src/api/auth.js +12 -0
- package/src/api/calld.js +8 -0
- package/src/api/confd.js +43 -2
- package/src/api-client.js +8 -0
- package/src/domain/Meeting.js +20 -0
- package/src/domain/MeetingAuthorization.js +67 -0
- package/src/domain/Phone/WebRTCPhone.js +1 -3
- package/src/domain/__tests__/Meeting.test.js +70 -1
- package/src/domain/__tests__/MeetingAuthorization.test.js +58 -0
- package/src/service/getApiClient.js +13 -2
- package/src/simple/Auth.js +35 -4
- package/src/simple/Softphone.js +5 -0
- package/src/simple/index.js +2 -1
- package/src/simple/room/Participant.js +40 -0
- package/src/simple/room/Room.js +2 -2
- package/src/simple/room/SipRoom.js +1 -1
- package/src/simple/room/__tests__/Participant.test.js +81 -0
- package/src/types/WebSocketMessage.js +7 -1
- package/src/utils/__tests__/object.test.js +35 -0
- package/src/utils/__tests__/string.test.js +23 -0
- package/src/utils/object.js +15 -0
- package/src/utils/string.js +8 -0
- package/src/web-rtc-client.js +39 -22
- package/src/websocket-client.js +2 -0
package/src/api/calld.js
CHANGED
|
@@ -137,6 +137,14 @@ export default (client: ApiRequester, baseUrl: string) => ({
|
|
|
137
137
|
getMeetingParticipantsAsUser: async (meetingUuid: string): Promise<Object> =>
|
|
138
138
|
client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
|
|
139
139
|
|
|
140
|
+
banMeetingParticipant: (meetingUuid: string, participantUuid: string) =>
|
|
141
|
+
client.delete(
|
|
142
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/participants/${participantUuid}`,
|
|
143
|
+
null,
|
|
144
|
+
null,
|
|
145
|
+
ApiRequester.successResponseParser,
|
|
146
|
+
),
|
|
147
|
+
|
|
140
148
|
listTrunks: () => client.get(`${baseUrl}/trunks`),
|
|
141
149
|
|
|
142
150
|
mute: (callId: string) =>
|
package/src/api/confd.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/* @flow */
|
|
2
2
|
import ApiRequester from '../utils/api-requester';
|
|
3
3
|
import type { UUID, ListConfdUsersResponse, ListApplicationsResponse } from '../domain/types';
|
|
4
|
+
import type { MeetingCreateArguments, MeetingUpdateArguments } from '../domain/Meeting';
|
|
4
5
|
import Profile from '../domain/Profile';
|
|
5
6
|
import SipLine from '../domain/SipLine';
|
|
6
7
|
import ExternalApp from '../domain/ExternalApp';
|
|
7
8
|
import Meeting from '../domain/Meeting';
|
|
9
|
+
import MeetingAuthorization from '../domain/MeetingAuthorization';
|
|
10
|
+
import { convertKeysFromCamelToUnderscore } from '../utils/object';
|
|
8
11
|
|
|
9
12
|
export default (client: ApiRequester, baseUrl: string) => ({
|
|
10
13
|
listUsers: (): Promise<ListConfdUsersResponse> => client.get(`${baseUrl}/users`, null),
|
|
@@ -72,8 +75,18 @@ export default (client: ApiRequester, baseUrl: string) => ({
|
|
|
72
75
|
getMyMeetings: (): Promise<Meeting> =>
|
|
73
76
|
client.get(`${baseUrl}/users/me/meetings`).then(response => Meeting.parseMany(response.items)),
|
|
74
77
|
|
|
75
|
-
createMyMeeting: (
|
|
76
|
-
client
|
|
78
|
+
createMyMeeting: (args: MeetingCreateArguments): Promise<Meeting> =>
|
|
79
|
+
client
|
|
80
|
+
.post(`${baseUrl}/users/me/meetings`, convertKeysFromCamelToUnderscore(args))
|
|
81
|
+
.then(Meeting.parse),
|
|
82
|
+
|
|
83
|
+
updateMyMeeting: (meetingUuid: string, data: MeetingUpdateArguments): Promise<Boolean> =>
|
|
84
|
+
client.put(
|
|
85
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}`,
|
|
86
|
+
convertKeysFromCamelToUnderscore(data),
|
|
87
|
+
null,
|
|
88
|
+
ApiRequester.successResponseParser,
|
|
89
|
+
),
|
|
77
90
|
|
|
78
91
|
deleteMyMeeting: (meetingUuid: string): Promise<Meeting> =>
|
|
79
92
|
client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
|
|
@@ -81,6 +94,34 @@ export default (client: ApiRequester, baseUrl: string) => ({
|
|
|
81
94
|
getMeeting: (meetingUuid: string): Promise<Meeting> =>
|
|
82
95
|
client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
83
96
|
|
|
97
|
+
meetingAuthorizations: (meetingUuid: string): Promise<Array<MeetingAuthorization>> =>
|
|
98
|
+
client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations`, null).then(MeetingAuthorization.parseMany),
|
|
99
|
+
|
|
100
|
+
meetingAuthorizationReject: (meetingUuid: string, authorizationUuid: string): Promise<Boolean> =>
|
|
101
|
+
client.put(
|
|
102
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/reject`,
|
|
103
|
+
{},
|
|
104
|
+
null,
|
|
105
|
+
ApiRequester.successResponseParser,
|
|
106
|
+
),
|
|
107
|
+
|
|
108
|
+
meetingAuthorizationAccept: (meetingUuid: string, authorizationUuid: string): Promise<Boolean> =>
|
|
109
|
+
client.put(
|
|
110
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/accept`,
|
|
111
|
+
{},
|
|
112
|
+
null,
|
|
113
|
+
ApiRequester.successResponseParser,
|
|
114
|
+
),
|
|
115
|
+
|
|
84
116
|
guestGetMeeting: (meetingUuid: string): Promise<Meeting> =>
|
|
85
117
|
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
118
|
+
|
|
119
|
+
guestAuthorizationRequest: (userUuid: string, meetingUuid: string, username: string): Promise<> =>
|
|
120
|
+
client
|
|
121
|
+
.post(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations`, { guest_name: username })
|
|
122
|
+
.then(MeetingAuthorization.parse),
|
|
123
|
+
|
|
124
|
+
guestAuthorizationCheck: (userUuid: string, meetingUuid: string, authorizationUuid: string): Promise<> =>
|
|
125
|
+
client.get(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations/${authorizationUuid}`, null),
|
|
126
|
+
|
|
86
127
|
});
|
package/src/api-client.js
CHANGED
|
@@ -57,6 +57,7 @@ export default class ApiClient {
|
|
|
57
57
|
refreshExpiration: ?number;
|
|
58
58
|
refreshBackend: ?string;
|
|
59
59
|
refreshTenantId: ?string;
|
|
60
|
+
refreshDomainName: ?string;
|
|
60
61
|
isMobile: boolean;
|
|
61
62
|
fetchOptions: Object;
|
|
62
63
|
|
|
@@ -98,6 +99,7 @@ export default class ApiClient {
|
|
|
98
99
|
refreshToken: this.refreshToken,
|
|
99
100
|
refreshBackend: this.refreshBackend,
|
|
100
101
|
refreshTenantId: this.refreshTenantId,
|
|
102
|
+
refreshDomainName: this.refreshDomainName,
|
|
101
103
|
refreshExpiration: this.refreshExpiration,
|
|
102
104
|
isMobile: this.isMobile,
|
|
103
105
|
});
|
|
@@ -113,6 +115,7 @@ export default class ApiClient {
|
|
|
113
115
|
this.refreshExpiration,
|
|
114
116
|
this.isMobile,
|
|
115
117
|
this.refreshTenantId,
|
|
118
|
+
this.refreshDomainName,
|
|
116
119
|
);
|
|
117
120
|
|
|
118
121
|
logger.info('token refreshed', { token: session.token });
|
|
@@ -166,9 +169,14 @@ export default class ApiClient {
|
|
|
166
169
|
}
|
|
167
170
|
|
|
168
171
|
setRefreshTenantId(tenantId: ?string) {
|
|
172
|
+
console.warn('Use of `setRefreshTenantId` is deprecated, use `setRefreshDomainName` instead');
|
|
169
173
|
this.refreshTenantId = tenantId;
|
|
170
174
|
}
|
|
171
175
|
|
|
176
|
+
setRefreshDomainName(domainName: ?string) {
|
|
177
|
+
this.refreshDomainName = domainName;
|
|
178
|
+
}
|
|
179
|
+
|
|
172
180
|
setIsMobile(isMobile: boolean) {
|
|
173
181
|
this.isMobile = isMobile;
|
|
174
182
|
}
|
package/src/domain/Meeting.js
CHANGED
|
@@ -3,6 +3,19 @@ import moment from 'moment';
|
|
|
3
3
|
|
|
4
4
|
import newFrom from '../utils/new-from';
|
|
5
5
|
|
|
6
|
+
import MeetingAuthorization from './MeetingAuthorization';
|
|
7
|
+
|
|
8
|
+
export type MeetingCreateArguments = {
|
|
9
|
+
name: string,
|
|
10
|
+
requireAuthorization: boolean,
|
|
11
|
+
persistent: boolean,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type MeetingUpdateArguments = {
|
|
15
|
+
name?: string,
|
|
16
|
+
requireAuthorization?: boolean,
|
|
17
|
+
}
|
|
18
|
+
|
|
6
19
|
export type MeetingCreationResponse = {
|
|
7
20
|
guest_sip_authorization: string,
|
|
8
21
|
ingress_http_uri: string,
|
|
@@ -13,6 +26,7 @@ export type MeetingCreationResponse = {
|
|
|
13
26
|
exten: string,
|
|
14
27
|
persistent: boolean,
|
|
15
28
|
creation_time: string,
|
|
29
|
+
require_authorization: boolean,
|
|
16
30
|
}
|
|
17
31
|
|
|
18
32
|
export default class Meeting {
|
|
@@ -27,6 +41,8 @@ export default class Meeting {
|
|
|
27
41
|
persistent: boolean;
|
|
28
42
|
ownerUuids: Array<string>;
|
|
29
43
|
creationTime: Date;
|
|
44
|
+
pendingAuthorizations: Array<MeetingAuthorization>
|
|
45
|
+
requireAuthorization: boolean;
|
|
30
46
|
|
|
31
47
|
static parse(plain: MeetingCreationResponse): Meeting {
|
|
32
48
|
return new Meeting({
|
|
@@ -39,6 +55,7 @@ export default class Meeting {
|
|
|
39
55
|
extension: plain.exten,
|
|
40
56
|
persistent: plain.persistent,
|
|
41
57
|
creationTime: moment(plain.creation_time).toDate(),
|
|
58
|
+
requireAuthorization: plain.require_authorization,
|
|
42
59
|
});
|
|
43
60
|
}
|
|
44
61
|
|
|
@@ -63,6 +80,7 @@ export default class Meeting {
|
|
|
63
80
|
extension,
|
|
64
81
|
persistent,
|
|
65
82
|
creationTime,
|
|
83
|
+
requireAuthorization,
|
|
66
84
|
}: Object = {}) {
|
|
67
85
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
68
86
|
this.uri = uri;
|
|
@@ -73,6 +91,7 @@ export default class Meeting {
|
|
|
73
91
|
this.extension = extension;
|
|
74
92
|
this.persistent = persistent;
|
|
75
93
|
this.creationTime = creationTime;
|
|
94
|
+
this.requireAuthorization = requireAuthorization;
|
|
76
95
|
|
|
77
96
|
// Useful to compare instead of instanceof with minified code
|
|
78
97
|
this.type = 'Meeting';
|
|
@@ -83,4 +102,5 @@ export default class Meeting {
|
|
|
83
102
|
const [username, secret] = atob(this.guestSipAuthorization).split(':');
|
|
84
103
|
return { username, secret };
|
|
85
104
|
}
|
|
105
|
+
|
|
86
106
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
export type RawMeetingAuthorization = {
|
|
4
|
+
created_at: string,
|
|
5
|
+
meeting_uuid: string,
|
|
6
|
+
uuid: string,
|
|
7
|
+
guest_uuid: string,
|
|
8
|
+
guest_name: string,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const PENDING = 'pending';
|
|
12
|
+
export const ACCEPTED = 'accepted';
|
|
13
|
+
export const REJECTED = 'rejected';
|
|
14
|
+
export const POST_PROCESSING = 'post_processing';
|
|
15
|
+
export const POST_PROCESSED_SUCCESS = 'post_processed_success';
|
|
16
|
+
export const POST_PROCESSED_ERROR = 'post_processed_error';
|
|
17
|
+
|
|
18
|
+
export default class MeetingAuthorization {
|
|
19
|
+
meetingUuid: string;
|
|
20
|
+
uuid: string;
|
|
21
|
+
userUuid: string;
|
|
22
|
+
userName: string;
|
|
23
|
+
status: string;
|
|
24
|
+
|
|
25
|
+
constructor({
|
|
26
|
+
meetingUuid,
|
|
27
|
+
uuid,
|
|
28
|
+
userUuid,
|
|
29
|
+
userName,
|
|
30
|
+
}: Object = {}) {
|
|
31
|
+
this.meetingUuid = meetingUuid;
|
|
32
|
+
this.uuid = uuid;
|
|
33
|
+
this.userUuid = userUuid;
|
|
34
|
+
this.userName = userName;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setStatus(status: string) {
|
|
38
|
+
this.status = status;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getStatus() {
|
|
42
|
+
return this.status;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static parse(plain: RawMeetingAuthorization) {
|
|
46
|
+
const {
|
|
47
|
+
meeting_uuid: meetingUuid,
|
|
48
|
+
uuid,
|
|
49
|
+
guest_uuid: userUuid,
|
|
50
|
+
guest_name: userName,
|
|
51
|
+
} = plain;
|
|
52
|
+
|
|
53
|
+
return new MeetingAuthorization({
|
|
54
|
+
meetingUuid,
|
|
55
|
+
uuid,
|
|
56
|
+
userUuid,
|
|
57
|
+
userName,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static parseMany(items: RawMeetingAuthorization[]): Array<MeetingAuthorization> {
|
|
62
|
+
if (!items) {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
return items.map(MeetingAuthorization.parse);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -531,9 +531,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
531
531
|
|
|
532
532
|
try {
|
|
533
533
|
if (this.currentScreenShare.stream) {
|
|
534
|
-
this.currentScreenShare.stream.getTracks()
|
|
535
|
-
.filter(track => track.kind === 'video')
|
|
536
|
-
.forEach(track => track.stop());
|
|
534
|
+
this.currentScreenShare.stream.getTracks().forEach(track => track.stop());
|
|
537
535
|
}
|
|
538
536
|
|
|
539
537
|
if (restoreLocalStream) {
|
|
@@ -1,9 +1,76 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
/* global btoa */
|
|
3
3
|
|
|
4
|
+
import moment from 'moment';
|
|
4
5
|
import Meeting from '../Meeting';
|
|
5
6
|
|
|
7
|
+
const rawCreationTime = '2021-12-21T15:56:42.880Z';
|
|
8
|
+
|
|
6
9
|
describe('Meeting domain', () => {
|
|
10
|
+
it('should retain its values when parsed', () => {
|
|
11
|
+
const args = {
|
|
12
|
+
guest_sip_authorization: 'some-guest-sip-authorization',
|
|
13
|
+
ingress_http_uri: 'some-uri',
|
|
14
|
+
name: 'some-name',
|
|
15
|
+
owner_uuids: ['some-owner-uuid'],
|
|
16
|
+
port: 'some-port',
|
|
17
|
+
uuid: 'some-uuid',
|
|
18
|
+
exten: 'some-exten',
|
|
19
|
+
persistent: true,
|
|
20
|
+
creation_time: rawCreationTime,
|
|
21
|
+
require_authorization: true,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const meeting = Meeting.parse(args);
|
|
25
|
+
const {
|
|
26
|
+
uri,
|
|
27
|
+
uuid,
|
|
28
|
+
name,
|
|
29
|
+
port,
|
|
30
|
+
extension,
|
|
31
|
+
persistent,
|
|
32
|
+
ownerUuids,
|
|
33
|
+
creationTime,
|
|
34
|
+
requireAuthorization,
|
|
35
|
+
} = meeting;
|
|
36
|
+
|
|
37
|
+
expect(uri).toEqual(args.ingress_http_uri);
|
|
38
|
+
expect(uuid).toEqual(args.uuid);
|
|
39
|
+
expect(name).toEqual(args.name);
|
|
40
|
+
expect(port).toEqual(args.port);
|
|
41
|
+
expect(extension).toEqual(args.exten);
|
|
42
|
+
expect(persistent).toEqual(args.persistent);
|
|
43
|
+
expect(ownerUuids).toEqual(args.owner_uuids);
|
|
44
|
+
expect(creationTime).toEqual(moment(rawCreationTime).toDate());
|
|
45
|
+
expect(requireAuthorization).toEqual(args.require_authorization);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should retain its values when instantiated', () => {
|
|
49
|
+
const keys = [
|
|
50
|
+
'uuid',
|
|
51
|
+
'name',
|
|
52
|
+
'guestSipAuthorization',
|
|
53
|
+
'ownerUuids',
|
|
54
|
+
'port',
|
|
55
|
+
'uri',
|
|
56
|
+
'extension',
|
|
57
|
+
'persistent',
|
|
58
|
+
'creationTime',
|
|
59
|
+
'requireAuthorization',
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const args = keys.reduce((acc, key) => {
|
|
63
|
+
acc[key] = `some-${key}`;
|
|
64
|
+
return acc;
|
|
65
|
+
}, {});
|
|
66
|
+
|
|
67
|
+
const meeting = new Meeting(args);
|
|
68
|
+
|
|
69
|
+
keys.forEach(key =>
|
|
70
|
+
// $FlowFixMe
|
|
71
|
+
expect(meeting[key]).toEqual(`some-${key}`));
|
|
72
|
+
});
|
|
73
|
+
|
|
7
74
|
it('can return username and secret from an base64 encrypted string', () => {
|
|
8
75
|
const USERNAME = 'username';
|
|
9
76
|
const SECRET = 'secret';
|
|
@@ -18,6 +85,7 @@ describe('Meeting domain', () => {
|
|
|
18
85
|
uuid: '',
|
|
19
86
|
exten: '',
|
|
20
87
|
persistent: false,
|
|
88
|
+
require_authorization: false,
|
|
21
89
|
};
|
|
22
90
|
|
|
23
91
|
const meeting = Meeting.parse(args);
|
|
@@ -30,7 +98,7 @@ describe('Meeting domain', () => {
|
|
|
30
98
|
|
|
31
99
|
it('should return a date from a string', () => {
|
|
32
100
|
const args = {
|
|
33
|
-
creation_time:
|
|
101
|
+
creation_time: rawCreationTime,
|
|
34
102
|
guest_sip_authorization: '',
|
|
35
103
|
ingress_http_uri: '',
|
|
36
104
|
name: '',
|
|
@@ -39,6 +107,7 @@ describe('Meeting domain', () => {
|
|
|
39
107
|
uuid: '',
|
|
40
108
|
exten: '',
|
|
41
109
|
persistent: false,
|
|
110
|
+
require_authorization: false,
|
|
42
111
|
};
|
|
43
112
|
|
|
44
113
|
const { creationTime } = Meeting.parse(args);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import MeetingAuthorization from '../MeetingAuthorization';
|
|
2
|
+
|
|
3
|
+
describe('MeetingAuthorization', () => {
|
|
4
|
+
describe('parse', () => {
|
|
5
|
+
it('should parse a raw input', () => {
|
|
6
|
+
const rawAuthorization = {
|
|
7
|
+
created_at: 'today',
|
|
8
|
+
meeting_uuid: 'meeting_uuid',
|
|
9
|
+
uuid: 'uuid',
|
|
10
|
+
guest_uuid: 'guest_uuid',
|
|
11
|
+
guest_name: 'guest_name',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const authorization = {
|
|
15
|
+
meetingUuid: rawAuthorization.meeting_uuid,
|
|
16
|
+
uuid: rawAuthorization.uuid,
|
|
17
|
+
userUuid: rawAuthorization.guest_uuid,
|
|
18
|
+
userName: rawAuthorization.guest_name,
|
|
19
|
+
status: undefined,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const response = MeetingAuthorization.parse(rawAuthorization);
|
|
23
|
+
expect(response).toEqual(authorization);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('parseMany', () => {
|
|
28
|
+
it('should parse multiple raw inputs', () => {
|
|
29
|
+
const rawAuthorizations = [
|
|
30
|
+
{
|
|
31
|
+
created_at: 'today1',
|
|
32
|
+
meeting_uuid: 'meeting_uuid1',
|
|
33
|
+
uuid: 'uuid1',
|
|
34
|
+
guest_uuid: 'guest_uuid1',
|
|
35
|
+
guest_name: 'guest_name1',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
created_at: 'today2',
|
|
39
|
+
meeting_uuid: 'meeting_uuid2',
|
|
40
|
+
uuid: 'uuid2',
|
|
41
|
+
guest_uuid: 'guest_uuid2',
|
|
42
|
+
guest_name: 'guest_name2',
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const authorizations = rawAuthorizations.map(rawAuthorization => ({
|
|
47
|
+
meetingUuid: rawAuthorization.meeting_uuid,
|
|
48
|
+
uuid: rawAuthorization.uuid,
|
|
49
|
+
userUuid: rawAuthorization.guest_uuid,
|
|
50
|
+
userName: rawAuthorization.guest_name,
|
|
51
|
+
status: undefined,
|
|
52
|
+
}));
|
|
53
|
+
|
|
54
|
+
const response = MeetingAuthorization.parseMany(rawAuthorizations);
|
|
55
|
+
expect(response).toEqual(authorizations);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -11,6 +11,7 @@ global.wazoClientId = global.wazoClientId || {};
|
|
|
11
11
|
global.wazoClientToken = global.wazoClientToken || {};
|
|
12
12
|
global.wazoRefreshToken = global.wazoRefreshToken || {};
|
|
13
13
|
global.wazoRefreshTenantId = global.wazoRefreshTenantId || {};
|
|
14
|
+
global.wazoRefreshDomainName = global.wazoRefreshDomainName || {};
|
|
14
15
|
global.wazoOnRefreshToken = global.wazoOnRefreshToken || {};
|
|
15
16
|
global.wazoOnRefreshTokenError = global.wazoOnRefreshTokenError || {};
|
|
16
17
|
global.wazoRefreshExpiration = global.wazoRefreshExpiration || {};
|
|
@@ -35,9 +36,14 @@ export const setRefreshToken = (newRefreshToken: ?string, forServer: ?string = n
|
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
export const setRefreshTenantId = (refreshTenantId: ?string, forServer: ?string = null) => {
|
|
39
|
+
console.warn('Use of `setRefreshTenantId` is deprecated, please use `setRefreshDomainName` instead');
|
|
38
40
|
global.wazoRefreshTenantId[forServer] = refreshTenantId;
|
|
39
41
|
};
|
|
40
42
|
|
|
43
|
+
export const setRefreshDomainName = (refreshDomainName: ?string, forServer: ?string = null) => {
|
|
44
|
+
global.wazoRefreshDomainName[forServer] = refreshDomainName;
|
|
45
|
+
};
|
|
46
|
+
|
|
41
47
|
export const setOnRefreshToken = (onRefreshToken: Function, forServer: ?string = null) => {
|
|
42
48
|
global.wazoOnRefreshToken[forServer] = onRefreshToken;
|
|
43
49
|
};
|
|
@@ -64,6 +70,7 @@ export const setFetchOptions = (fetchOptions: Object, forServer: ?string = null)
|
|
|
64
70
|
|
|
65
71
|
const fillClient = (apiClient: WazoApiClient) => {
|
|
66
72
|
const { server, token, clientId } = apiClient.client;
|
|
73
|
+
const tenantId = global.wazoRefreshTenantId[server] || global.wazoRefreshTenantId[null] || apiClient.refreshTenantId;
|
|
67
74
|
|
|
68
75
|
// try with null server when dealing with non-related server info
|
|
69
76
|
apiClient.setToken(global.wazoClientToken[server] || global.wazoClientToken[null] || token);
|
|
@@ -72,8 +79,12 @@ const fillClient = (apiClient: WazoApiClient) => {
|
|
|
72
79
|
|
|
73
80
|
apiClient.setRefreshToken(global.wazoRefreshToken[server] || global.wazoRefreshToken[null] || apiClient.refreshToken);
|
|
74
81
|
|
|
75
|
-
|
|
76
|
-
|
|
82
|
+
if (tenantId) {
|
|
83
|
+
apiClient.setRefreshTenantId(tenantId);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
apiClient.setRefreshDomainName(
|
|
87
|
+
global.wazoRefreshDomainName[server] || global.wazoRefreshDomainName[null] || apiClient.refreshDomainName,
|
|
77
88
|
);
|
|
78
89
|
|
|
79
90
|
apiClient.setFetchOptions(global.wazoFetchOptions[server] || global.wazoFetchOptions[null] || apiClient.fetchOptions);
|
package/src/simple/Auth.js
CHANGED
|
@@ -11,6 +11,7 @@ import getApiClient, {
|
|
|
11
11
|
setOnRefreshToken,
|
|
12
12
|
setFetchOptions,
|
|
13
13
|
setRefreshTenantId,
|
|
14
|
+
setRefreshDomainName,
|
|
14
15
|
setOnRefreshTokenError,
|
|
15
16
|
} from '../service/getApiClient';
|
|
16
17
|
import IssueReporter from '../service/IssueReporter';
|
|
@@ -20,6 +21,7 @@ import Wazo from './index';
|
|
|
20
21
|
export class InvalidSubscription extends Error {}
|
|
21
22
|
export class InvalidAuthorization extends Error {}
|
|
22
23
|
export class NoTenantIdError extends Error {}
|
|
24
|
+
export class NoDomainNameError extends Error {}
|
|
23
25
|
|
|
24
26
|
const logger = IssueReporter.loggerFor('simple-auth');
|
|
25
27
|
|
|
@@ -83,9 +85,24 @@ class Auth {
|
|
|
83
85
|
setFetchOptions(options);
|
|
84
86
|
}
|
|
85
87
|
|
|
86
|
-
async logIn(username: string, password: string, backend?: string,
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
async logIn(username: string, password: string, backend?: string, extra?: string | Object) {
|
|
89
|
+
let tenantId = null;
|
|
90
|
+
let domainName = null;
|
|
91
|
+
if (typeof extra === 'string') {
|
|
92
|
+
tenantId = extra;
|
|
93
|
+
}
|
|
94
|
+
if (extra && typeof extra === 'object') {
|
|
95
|
+
domainName = extra.domainName;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (backend && backend !== this.BACKEND_WAZO && !tenantId && !domainName) {
|
|
99
|
+
if (!tenantId) {
|
|
100
|
+
throw new NoTenantIdError('No tenant id');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (!domainName) {
|
|
104
|
+
throw new NoDomainNameError('No domain name');
|
|
105
|
+
}
|
|
89
106
|
}
|
|
90
107
|
|
|
91
108
|
this.authenticated = false;
|
|
@@ -95,6 +112,7 @@ class Auth {
|
|
|
95
112
|
password,
|
|
96
113
|
backend,
|
|
97
114
|
tenantId,
|
|
115
|
+
domainName,
|
|
98
116
|
expiration: this.expiration,
|
|
99
117
|
mobile: this.mobile,
|
|
100
118
|
});
|
|
@@ -103,7 +121,13 @@ class Auth {
|
|
|
103
121
|
getApiClient().setRefreshBackend(backend);
|
|
104
122
|
}
|
|
105
123
|
|
|
106
|
-
|
|
124
|
+
if (tenantId) {
|
|
125
|
+
getApiClient().setRefreshTenantId(tenantId);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (domainName) {
|
|
129
|
+
getApiClient().setRefreshDomainName(domainName);
|
|
130
|
+
}
|
|
107
131
|
|
|
108
132
|
return this._onAuthenticated(rawSession);
|
|
109
133
|
}
|
|
@@ -202,11 +226,18 @@ class Auth {
|
|
|
202
226
|
}
|
|
203
227
|
|
|
204
228
|
setRefreshTenantId(refreshTenantId: string) {
|
|
229
|
+
console.warn('Use of `setRefreshTenantId` is deprecated, use `setRefreshDomainName` instead.');
|
|
205
230
|
setRefreshTenantId(refreshTenantId);
|
|
206
231
|
|
|
207
232
|
getApiClient().setRefreshTenantId(refreshTenantId);
|
|
208
233
|
}
|
|
209
234
|
|
|
235
|
+
setRefreshDomainName(domainName: string) {
|
|
236
|
+
setRefreshDomainName(domainName);
|
|
237
|
+
|
|
238
|
+
getApiClient().setRefreshDomainName(domainName);
|
|
239
|
+
}
|
|
240
|
+
|
|
210
241
|
forceRefreshToken() {
|
|
211
242
|
getApiClient().forceRefreshToken();
|
|
212
243
|
}
|
package/src/simple/Softphone.js
CHANGED
|
@@ -107,6 +107,7 @@ class Softphone {
|
|
|
107
107
|
wrapUpDuration,
|
|
108
108
|
enableAgent = true,
|
|
109
109
|
tenantId,
|
|
110
|
+
domainName,
|
|
110
111
|
debug = false,
|
|
111
112
|
}: Object = {}) {
|
|
112
113
|
this.url = url || 'https://softphone.wazo.io';
|
|
@@ -131,8 +132,12 @@ class Softphone {
|
|
|
131
132
|
config.port = port;
|
|
132
133
|
}
|
|
133
134
|
if (tenantId) {
|
|
135
|
+
console.warn('Use of `tenantId` is deprecated when calling `Softphone.init()`, use `domainName` instead');
|
|
134
136
|
config.tenantId = tenantId;
|
|
135
137
|
}
|
|
138
|
+
if (domainName) {
|
|
139
|
+
config.domainName = domainName;
|
|
140
|
+
}
|
|
136
141
|
if (wrapUpDuration) {
|
|
137
142
|
config.wrapUpDuration = wrapUpDuration;
|
|
138
143
|
}
|
package/src/simple/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* global window */
|
|
2
|
-
import Auth, { InvalidSubscription, InvalidAuthorization, NoTenantIdError } from './Auth';
|
|
2
|
+
import Auth, { InvalidSubscription, InvalidAuthorization, NoTenantIdError, NoDomainNameError } from './Auth';
|
|
3
3
|
import Phone from './Phone';
|
|
4
4
|
import Websocket from './Websocket';
|
|
5
5
|
import Room from './room/Room';
|
|
@@ -106,6 +106,7 @@ const Wazo = {
|
|
|
106
106
|
CanceledCallError,
|
|
107
107
|
SFUNotAvailableError,
|
|
108
108
|
NoTenantIdError,
|
|
109
|
+
NoDomainNameError,
|
|
109
110
|
};
|
|
110
111
|
|
|
111
112
|
if (window) {
|
|
@@ -4,6 +4,7 @@ import IssueReporter from '../../service/IssueReporter';
|
|
|
4
4
|
|
|
5
5
|
import Room, { SIGNAL_TYPE_PARTICIPANT_UPDATE } from './Room';
|
|
6
6
|
import Contact from '../../domain/Contact';
|
|
7
|
+
import getApiClient from '../../service/getApiClient';
|
|
7
8
|
|
|
8
9
|
const logger = IssueReporter.loggerFor('room');
|
|
9
10
|
|
|
@@ -20,6 +21,7 @@ class Participant extends Emitter {
|
|
|
20
21
|
videoMuted: boolean;
|
|
21
22
|
screensharing: boolean;
|
|
22
23
|
isOnHold: boolean;
|
|
24
|
+
banned: boolean;
|
|
23
25
|
extra: Object;
|
|
24
26
|
|
|
25
27
|
ON_UPDATED: string;
|
|
@@ -37,6 +39,7 @@ class Participant extends Emitter {
|
|
|
37
39
|
ON_EXTRA_CHANGE: string;
|
|
38
40
|
ON_HOLD: string;
|
|
39
41
|
ON_RESUME: string;
|
|
42
|
+
ON_BAN: string;
|
|
40
43
|
|
|
41
44
|
/**
|
|
42
45
|
* @param room Room The room where the participant is
|
|
@@ -60,6 +63,7 @@ class Participant extends Emitter {
|
|
|
60
63
|
this.screensharing = false;
|
|
61
64
|
this.isOnHold = false;
|
|
62
65
|
this.extra = extra;
|
|
66
|
+
this.banned = false;
|
|
63
67
|
|
|
64
68
|
this.ON_UPDATED = 'participant/ON_UPDATED';
|
|
65
69
|
this.ON_START_TALKING = 'participant/ON_START_TALKING';
|
|
@@ -76,6 +80,7 @@ class Participant extends Emitter {
|
|
|
76
80
|
this.ON_EXTRA_CHANGE = 'participant/ON_EXTRA_CHANGE';
|
|
77
81
|
this.ON_HOLD = 'participant/ON_HOLD';
|
|
78
82
|
this.ON_RESUME = 'participant/ON_RESUME';
|
|
83
|
+
this.ON_BAN = 'participant/ON_BAN';
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
triggerEvent(name: string, ...args: any[]) {
|
|
@@ -116,6 +121,10 @@ class Participant extends Emitter {
|
|
|
116
121
|
status.extra = this.extra;
|
|
117
122
|
break;
|
|
118
123
|
}
|
|
124
|
+
case this.ON_BAN: {
|
|
125
|
+
status.banned = true;
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
119
128
|
default:
|
|
120
129
|
break;
|
|
121
130
|
}
|
|
@@ -220,6 +229,11 @@ class Participant extends Emitter {
|
|
|
220
229
|
this.triggerUpdate(this.ON_RESUME, broadcast);
|
|
221
230
|
}
|
|
222
231
|
|
|
232
|
+
onBan(broadcast: boolean = true) {
|
|
233
|
+
this.banned = true;
|
|
234
|
+
this.triggerUpdate(this.ON_BAN, broadcast);
|
|
235
|
+
}
|
|
236
|
+
|
|
223
237
|
getStatus() {
|
|
224
238
|
return {
|
|
225
239
|
callId: this.callId,
|
|
@@ -266,6 +280,10 @@ class Participant extends Emitter {
|
|
|
266
280
|
}
|
|
267
281
|
}
|
|
268
282
|
|
|
283
|
+
if (status.banned) {
|
|
284
|
+
this.onBan(false);
|
|
285
|
+
}
|
|
286
|
+
|
|
269
287
|
// Poor man's object comparison
|
|
270
288
|
if (typeof status.extra !== 'undefined' && JSON.stringify(this.extra) !== JSON.stringify(status.extra)) {
|
|
271
289
|
this.extra = { ...this.extra, ...status.extra };
|
|
@@ -293,6 +311,28 @@ class Participant extends Emitter {
|
|
|
293
311
|
this.streams = streams;
|
|
294
312
|
this.videoStreams = streams;
|
|
295
313
|
}
|
|
314
|
+
|
|
315
|
+
async ban(apiRequestDelay: ?number = null) {
|
|
316
|
+
const { meetingUuid } = this.room;
|
|
317
|
+
if (!meetingUuid) {
|
|
318
|
+
throw new Error('Attempting to ban a participant without a `meetingUuid`');
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// this notifies all that someone is being banned
|
|
322
|
+
this.onBan(true);
|
|
323
|
+
|
|
324
|
+
// this allows to delay the actual ban, in order for the banned participant as well as others to react to the situation
|
|
325
|
+
if (apiRequestDelay) {
|
|
326
|
+
await this.delay(apiRequestDelay);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// proceed with the actual kick
|
|
330
|
+
return getApiClient().calld.banMeetingParticipant(meetingUuid, this.callId);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
async delay(ms: number) {
|
|
334
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
335
|
+
}
|
|
296
336
|
}
|
|
297
337
|
|
|
298
338
|
export default Participant;
|