Call link admin key fix and in-call approve, deny, remove

This commit is contained in:
ayumi-signal 2024-04-30 09:36:34 -07:00 committed by GitHub
parent 5df8924197
commit 8ec585d54c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 599 additions and 43 deletions

View file

@ -10,12 +10,15 @@ import { reducer as rootReducer } from '../../../state/reducer';
import { noopAction } from '../../../state/ducks/noop';
import type {
ActiveCallStateType,
CallingActionType,
CallingStateType,
DirectCallStateType,
GroupCallReactionsReceivedActionType,
GroupCallStateChangeActionType,
GroupCallStateType,
HandleCallLinkUpdateType,
SendGroupCallReactionActionType,
StartCallLinkLobbyType,
} from '../../../state/ducks/calling';
import {
actions,
@ -36,8 +39,11 @@ import {
import { generateAci } from '../../../types/ServiceId';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
import type { UnwrapPromise } from '../../../types/Util';
import { CallLinkRestrictions } from '../../../types/CallLink';
import { FAKE_CALL_LINK } from '../../../test-both/helpers/fakeCallLink';
import {
FAKE_CALL_LINK,
FAKE_CALL_LINK_WITH_ADMIN_KEY,
getCallLinkState,
} from '../../../test-both/helpers/fakeCallLink';
const ACI_1 = generateAci();
const NOW = new Date('2020-01-23T04:56:00.000');
@ -109,6 +115,7 @@ describe('calling duck', () => {
localDemuxId: 1,
peekInfo: {
acis: [creatorAci],
pendingAcis: [],
creatorAci,
eraId: 'xyz',
maxDevices: 16,
@ -902,6 +909,7 @@ describe('calling duck', () => {
hasLocalVideo: false,
peekInfo: {
acis: [creatorAci],
pendingAcis: [],
creatorAci,
eraId: 'xyz',
maxDevices: 16,
@ -932,6 +940,7 @@ describe('calling duck', () => {
localDemuxId: 1,
peekInfo: {
acis: [creatorAci],
pendingAcis: [],
creatorAci,
eraId: 'xyz',
maxDevices: 16,
@ -967,6 +976,7 @@ describe('calling duck', () => {
hasLocalVideo: false,
peekInfo: {
acis: [ACI_1],
pendingAcis: [],
maxDevices: 16,
deviceCount: 1,
},
@ -995,6 +1005,7 @@ describe('calling duck', () => {
localDemuxId: 1,
peekInfo: {
acis: [ACI_1],
pendingAcis: [],
maxDevices: 16,
deviceCount: 1,
},
@ -1041,6 +1052,7 @@ describe('calling duck', () => {
hasLocalVideo: false,
peekInfo: {
acis: [ACI_1],
pendingAcis: [],
maxDevices: 16,
deviceCount: 1,
},
@ -1095,6 +1107,7 @@ describe('calling duck', () => {
hasLocalVideo: false,
peekInfo: {
acis: [ACI_1],
pendingAcis: [],
maxDevices: 16,
deviceCount: 1,
},
@ -1136,6 +1149,7 @@ describe('calling duck', () => {
hasLocalVideo: false,
peekInfo: {
acis: [ACI_1],
pendingAcis: [],
maxDevices: 16,
deviceCount: 1,
},
@ -1170,6 +1184,7 @@ describe('calling duck', () => {
hasLocalVideo: true,
peekInfo: {
acis: [ACI_1],
pendingAcis: [],
maxDevices: 16,
deviceCount: 1,
},
@ -1216,6 +1231,7 @@ describe('calling duck', () => {
hasLocalVideo: true,
peekInfo: {
acis: [ACI_1],
pendingAcis: [],
maxDevices: 16,
deviceCount: 1,
},
@ -1262,6 +1278,7 @@ describe('calling duck', () => {
hasLocalVideo: true,
peekInfo: {
acis: [],
pendingAcis: [],
maxDevices: 16,
deviceCount: 0,
},
@ -1292,6 +1309,7 @@ describe('calling duck', () => {
hasLocalVideo: true,
peekInfo: {
acis: [ACI_1],
pendingAcis: [],
maxDevices: 16,
deviceCount: 1,
},
@ -1304,42 +1322,42 @@ describe('calling duck', () => {
});
describe('handleCallLinkUpdate', () => {
const { roomId, rootKey, expiration } = FAKE_CALL_LINK;
const {
roomId,
name,
restrictions,
expiration,
revoked,
rootKey,
adminKey,
} = FAKE_CALL_LINK;
beforeEach(function (this: Mocha.Context) {
this.callingServiceReadCallLink = this.sandbox
.stub(callingService, 'readCallLink')
.resolves({
callLinkState: {
name: 'Signal Call',
restrictions: CallLinkRestrictions.None,
expiration,
revoked: false,
},
callLinkState: getCallLinkState(FAKE_CALL_LINK),
errorStatusCode: undefined,
});
});
it('reads the call link from calling service', async function (this: Mocha.Context) {
const doAction = async (
payload: HandleCallLinkUpdateType
): Promise<{ dispatch: sinon.SinonSpy }> => {
const { handleCallLinkUpdate } = actions;
const dispatch = sinon.spy();
await handleCallLinkUpdate({ rootKey, adminKey: null })(
dispatch,
getEmptyRootState,
null
);
await handleCallLinkUpdate(payload)(dispatch, getEmptyRootState, null);
return { dispatch };
};
it('reads the call link from calling service', async function (this: Mocha.Context) {
await doAction({ rootKey, adminKey: null });
sinon.assert.calledOnce(this.callingServiceReadCallLink);
});
it('dispatches HANDLE_CALL_LINK_UPDATE', async () => {
const { handleCallLinkUpdate } = actions;
const dispatch = sinon.spy();
await handleCallLinkUpdate({ rootKey, adminKey: null })(
dispatch,
getEmptyRootState,
null
);
const { dispatch } = await doAction({ rootKey, adminKey: null });
sinon.assert.calledOnce(dispatch);
sinon.assert.calledWith(dispatch, {
@ -1347,16 +1365,115 @@ describe('calling duck', () => {
payload: {
roomId,
callLinkDetails: {
name: 'Signal Call',
restrictions: CallLinkRestrictions.None,
name,
restrictions,
expiration,
revoked: false,
revoked,
rootKey,
adminKey: null,
adminKey,
},
},
});
});
it('can save adminKey', async () => {
const { dispatch } = await doAction({ rootKey, adminKey: 'banana' });
sinon.assert.calledOnce(dispatch);
sinon.assert.calledWith(dispatch, {
type: 'calling/HANDLE_CALL_LINK_UPDATE',
payload: {
roomId,
callLinkDetails: {
name,
restrictions,
expiration,
revoked,
rootKey,
adminKey: 'banana',
},
},
});
});
});
describe('startCallLinkLobby', () => {
const callLobbyData = {
callMode: CallMode.Adhoc,
connectionState: GroupCallConnectionState.NotConnected,
hasLocalAudio: true,
hasLocalVideo: true,
joinState: GroupCallJoinState.NotJoined,
peekInfo: [],
remoteParticipants: [],
};
const callLinkState = getCallLinkState(FAKE_CALL_LINK);
const getStateWithAdminKey = (): RootStateType => ({
...getEmptyRootState(),
calling: {
...getEmptyState(),
callLinks: {
[FAKE_CALL_LINK_WITH_ADMIN_KEY.roomId]:
FAKE_CALL_LINK_WITH_ADMIN_KEY,
},
},
});
beforeEach(function (this: Mocha.Context) {
this.callingServiceReadCallLink = this.sandbox
.stub(callingService, 'readCallLink')
.resolves({
callLinkState,
errorStatusCode: undefined,
});
this.callingServiceStartCallLinkLobby = this.sandbox
.stub(callingService, 'startCallLinkLobby')
.resolves(callLobbyData);
});
const doAction = async (
payload: StartCallLinkLobbyType
): Promise<{ dispatch: sinon.SinonSpy }> => {
const { startCallLinkLobby } = actions;
const dispatch = sinon.spy();
await startCallLinkLobby(payload)(dispatch, getEmptyRootState, null);
return { dispatch };
};
it('reads the link and dispatches START_CALL_LINK_LOBBY', async function (this: Mocha.Context) {
const { roomId, rootKey } = FAKE_CALL_LINK;
const { dispatch } = await doAction({ rootKey });
sinon.assert.calledOnce(dispatch);
sinon.assert.calledWith(dispatch, {
type: 'calling/START_CALL_LINK_LOBBY',
payload: {
...callLobbyData,
callLinkState,
callLinkRootKey: rootKey,
conversationId: roomId,
isConversationTooBigToRing: false,
},
});
});
it('preserves adminKey', () => {
const { startCallLinkLobby } = actions;
const { roomId, rootKey, adminKey } = FAKE_CALL_LINK_WITH_ADMIN_KEY;
const dispatch = sinon.spy();
const result = reducer(
getStateWithAdminKey().calling,
startCallLinkLobby({
rootKey,
})(
dispatch,
getStateWithAdminKey,
null
) as unknown as Readonly<CallingActionType>
);
assert.equal(result.callLinks[roomId]?.adminKey, adminKey);
});
});
describe('peekNotConnectedGroupCall', () => {
@ -1503,6 +1620,7 @@ describe('calling duck', () => {
localDemuxId: undefined,
peekInfo: {
acis: [],
pendingAcis: [],
maxDevices: Infinity,
deviceCount: 0,
},
@ -1956,6 +2074,7 @@ describe('calling duck', () => {
joinState: GroupCallJoinState.NotJoined,
peekInfo: {
acis: [creatorAci],
pendingAcis: [],
creatorAci,
eraId: 'xyz',
maxDevices: 16,
@ -1983,6 +2102,7 @@ describe('calling duck', () => {
localDemuxId: undefined,
peekInfo: {
acis: [creatorAci],
pendingAcis: [],
creatorAci,
eraId: 'xyz',
maxDevices: 16,
@ -2022,6 +2142,7 @@ describe('calling duck', () => {
const call = result.callsByConversation['fake-conversation-id'];
assert.deepEqual(call?.callMode === CallMode.Group && call.peekInfo, {
acis: [],
pendingAcis: [],
maxDevices: Infinity,
deviceCount: 0,
});
@ -2053,6 +2174,7 @@ describe('calling duck', () => {
result.callsByConversation['fake-group-call-conversation-id'];
assert.deepEqual(call?.callMode === CallMode.Group && call.peekInfo, {
acis: [creatorAci],
pendingAcis: [],
creatorAci,
eraId: 'xyz',
maxDevices: 16,
@ -2081,6 +2203,7 @@ describe('calling duck', () => {
joinState: GroupCallJoinState.NotJoined,
peekInfo: {
acis: [differentCreatorAci],
pendingAcis: [],
creatorAci: differentCreatorAci,
eraId: 'abc',
maxDevices: 5,
@ -2103,6 +2226,7 @@ describe('calling duck', () => {
const call = result.callsByConversation['fake-conversation-id'];
assert.deepEqual(call?.callMode === CallMode.Group && call.peekInfo, {
acis: [differentCreatorAci],
pendingAcis: [],
creatorAci: differentCreatorAci,
eraId: 'abc',
maxDevices: 5,

View file

@ -100,6 +100,7 @@ describe('state/selectors/calling', () => {
localDemuxId: undefined,
peekInfo: {
acis: [ACI_1],
pendingAcis: [],
creatorAci: ACI_1,
maxDevices: Infinity,
deviceCount: 1,
@ -180,6 +181,7 @@ describe('state/selectors/calling', () => {
...incomingGroupCall,
peekInfo: {
acis: [],
pendingAcis: [],
maxDevices: Infinity,
deviceCount: 1,
},