Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(webinar): spark-623318 return correct info when not reach JBH #4126

Open
wants to merge 8 commits into
base: next
Choose a base branch
from
2 changes: 2 additions & 0 deletions packages/@webex/plugin-meetings/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ export const ICE_AND_DTLS_CONNECTION_TIMEOUT = 20000;
export const ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT = 35000;
export const WEBINAR_ERROR_WEBCAST = [403026];
export const WEBINAR_ERROR_REGISTRATIONID = [403037, 403137];
export const JOIN_ERROR_REASON_FOR_END_USER = [403003];

// ******************** REGEX **********************
// Please alphabetize
Expand Down Expand Up @@ -1333,6 +1334,7 @@ export const MEETING_INFO_FAILURE_REASON = {
WEBINAR_REGISTRATION: 'WEBINAR_REGISTRATION', // webinar need registration
NEED_JOIN_WITH_WEBCAST: 'NEED_JOIN_WITH_WEBCAST', // webinar need using webcast join
WEBINAR_NEED_REGISTRATIONID: 'WEBINAR_NEED_REGISTRATIONID', // webinar need registrationID
NOT_REACH_JBH: 'NOT_REACH_JBH', // Meeting is not allow to access since not reach JBH time
OTHER: 'OTHER', // any other error (network, etc)
};

Expand Down
14 changes: 14 additions & 0 deletions packages/@webex/plugin-meetings/src/meeting/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ import {
NAMED_MEDIA_GROUP_TYPE_AUDIO,
WEBINAR_ERROR_WEBCAST,
WEBINAR_ERROR_REGISTRATIONID,
JOIN_ERROR_REASON_FOR_END_USER,
} from '../constants';
import BEHAVIORAL_METRICS from '../metrics/constants';
import ParameterError from '../common/errors/parameter';
Expand Down Expand Up @@ -162,6 +163,7 @@ import {ConnectionStateHandler, ConnectionStateEvent} from './connectionStateHan
import JoinWebinarError from '../common/errors/join-webinar-error';
import Member from '../member';
import MultistreamNotSupportedError from '../common/errors/multistream-not-supported-error';
import JoinMeetingError from '../common/errors/join-meeting';

// default callback so we don't call an undefined function, but in practice it should never be used
const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
Expand Down Expand Up @@ -1790,6 +1792,18 @@ export default class Meeting extends StatelessWebexPlugin {
`Meeting:index#fetchMeetingInfo --> Info Unable to fetch meeting info for ${this.destination} - password required (code=${err?.body?.code}).`
);

// Handle the case where user hasn't reached Join Before Host (JBH) time (error code 403003)
if (JOIN_ERROR_REASON_FOR_END_USER.includes(err.wbxAppApiCode)) {
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.NOT_REACH_JBH;
this.meetingInfoFailureCode = err.wbxAppApiCode;

if (err.meetingInfo) {
this.meetingInfo = err.meetingInfo;
}

throw new JoinMeetingError();
}

// when wbxappapi requires password it still populates partial meeting info in the response
if (err.meetingInfo) {
this.meetingInfo = err.meetingInfo;
Expand Down
33 changes: 33 additions & 0 deletions packages/@webex/plugin-meetings/test/unit/spec/meeting/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ import {ERROR_DESCRIPTIONS} from '@webex/internal-plugin-metrics/src/call-diagno
import MeetingCollection from '@webex/plugin-meetings/src/meetings/collection';

import {EVENT_TRIGGERS as VOICEAEVENTS} from '@webex/internal-plugin-voicea';
import JoinMeetingError from '../../../../src/common/errors/join-meeting';

describe('plugin-meetings', () => {
const logger = {
Expand Down Expand Up @@ -6339,6 +6340,38 @@ describe('plugin-meetings', () => {
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.REQUIRED);
});

it('handles meetingInfoProvider not reach JBH', async () => {
meeting.destination = FAKE_DESTINATION;
meeting.destinationType = FAKE_TYPE;
meeting.attrs.meetingInfoProvider = {
fetchMeetingInfo: sinon
.stub()
.throws(new MeetingInfoV2PasswordError(403003, FAKE_MEETING_INFO)),
};

await assert.isRejected(meeting.fetchMeetingInfo({sendCAevents: true}), JoinMeetingError);

assert.calledWith(
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
FAKE_DESTINATION,
FAKE_TYPE,
null,
null,
undefined,
'locus-id',
{},
{meetingId: meeting.id, sendCAevents: true}
);

assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
assert.equal(meeting.meetingInfoFailureCode, 403003);
assert.equal(
meeting.meetingInfoFailureReason,
MEETING_INFO_FAILURE_REASON.NOT_REACH_JBH
);
assert.equal(meeting.requiredCaptcha, null);
});

it('handles meetingInfoProvider policy error', async () => {
meeting.destination = FAKE_DESTINATION;
meeting.destinationType = FAKE_TYPE;
Expand Down