2021-05-25 22:40:04 +00:00
|
|
|
// Copyright 2021 Signal Messenger, LLC
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
|
|
|
import { assert } from 'chai';
|
2022-11-22 18:43:43 +00:00
|
|
|
import { LibSignalErrorBase } from '@signalapp/libsignal-client';
|
2021-05-25 22:40:04 +00:00
|
|
|
|
2022-01-31 21:51:24 +00:00
|
|
|
import {
|
|
|
|
_analyzeSenderKeyDevices,
|
|
|
|
_shouldFailSend,
|
|
|
|
} from '../../util/sendToGroup';
|
2023-08-10 16:43:33 +00:00
|
|
|
import { generateAci } from '../../types/ServiceId';
|
2021-05-25 22:40:04 +00:00
|
|
|
|
2021-10-26 19:15:33 +00:00
|
|
|
import type { DeviceType } from '../../textsecure/Types.d';
|
2022-01-31 21:51:24 +00:00
|
|
|
import {
|
|
|
|
ConnectTimeoutError,
|
|
|
|
HTTPError,
|
2023-01-21 00:50:34 +00:00
|
|
|
IncorrectSenderKeyAuthError,
|
2022-01-31 21:51:24 +00:00
|
|
|
MessageError,
|
|
|
|
OutgoingIdentityKeyError,
|
|
|
|
OutgoingMessageError,
|
|
|
|
SendMessageChallengeError,
|
|
|
|
SendMessageNetworkError,
|
|
|
|
SendMessageProtoError,
|
2023-01-21 00:50:34 +00:00
|
|
|
UnknownRecipientError,
|
2022-01-31 21:51:24 +00:00
|
|
|
UnregisteredUserError,
|
|
|
|
} from '../../textsecure/Errors';
|
2021-05-25 22:40:04 +00:00
|
|
|
|
|
|
|
describe('sendToGroup', () => {
|
2023-08-10 16:43:33 +00:00
|
|
|
const serviceIdOne = generateAci();
|
|
|
|
const serviceIdTwo = generateAci();
|
2022-07-08 20:46:25 +00:00
|
|
|
|
2021-05-25 22:40:04 +00:00
|
|
|
describe('#_analyzeSenderKeyDevices', () => {
|
|
|
|
function getDefaultDeviceList(): Array<DeviceType> {
|
|
|
|
return [
|
|
|
|
{
|
2023-08-10 16:43:33 +00:00
|
|
|
serviceId: serviceIdOne,
|
2021-05-25 22:40:04 +00:00
|
|
|
id: 1,
|
2021-07-30 18:35:25 +00:00
|
|
|
registrationId: 11,
|
2021-05-25 22:40:04 +00:00
|
|
|
},
|
|
|
|
{
|
2023-08-10 16:43:33 +00:00
|
|
|
serviceId: serviceIdOne,
|
2021-05-25 22:40:04 +00:00
|
|
|
id: 2,
|
2021-07-30 18:35:25 +00:00
|
|
|
registrationId: 22,
|
2021-05-25 22:40:04 +00:00
|
|
|
},
|
|
|
|
{
|
2023-08-10 16:43:33 +00:00
|
|
|
serviceId: serviceIdTwo,
|
2021-05-25 22:40:04 +00:00
|
|
|
id: 2,
|
2021-07-30 18:35:25 +00:00
|
|
|
registrationId: 33,
|
2021-05-25 22:40:04 +00:00
|
|
|
},
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
it('returns nothing if new and previous lists are the same', () => {
|
|
|
|
const memberDevices = getDefaultDeviceList();
|
|
|
|
const devicesForSend = getDefaultDeviceList();
|
|
|
|
|
|
|
|
const {
|
|
|
|
newToMemberDevices,
|
2023-08-10 16:43:33 +00:00
|
|
|
newToMemberServiceIds,
|
2021-05-25 22:40:04 +00:00
|
|
|
removedFromMemberDevices,
|
2023-08-10 16:43:33 +00:00
|
|
|
removedFromMemberServiceIds,
|
2021-05-25 22:40:04 +00:00
|
|
|
} = _analyzeSenderKeyDevices(memberDevices, devicesForSend);
|
|
|
|
|
|
|
|
assert.isEmpty(newToMemberDevices);
|
2023-08-10 16:43:33 +00:00
|
|
|
assert.isEmpty(newToMemberServiceIds);
|
2021-05-25 22:40:04 +00:00
|
|
|
assert.isEmpty(removedFromMemberDevices);
|
2023-08-10 16:43:33 +00:00
|
|
|
assert.isEmpty(removedFromMemberServiceIds);
|
2021-05-25 22:40:04 +00:00
|
|
|
});
|
|
|
|
it('returns set of new devices', () => {
|
|
|
|
const memberDevices = getDefaultDeviceList();
|
|
|
|
const devicesForSend = getDefaultDeviceList();
|
|
|
|
|
|
|
|
memberDevices.pop();
|
|
|
|
memberDevices.pop();
|
|
|
|
|
|
|
|
const {
|
|
|
|
newToMemberDevices,
|
2023-08-10 16:43:33 +00:00
|
|
|
newToMemberServiceIds,
|
2021-05-25 22:40:04 +00:00
|
|
|
removedFromMemberDevices,
|
2023-08-10 16:43:33 +00:00
|
|
|
removedFromMemberServiceIds,
|
2021-05-25 22:40:04 +00:00
|
|
|
} = _analyzeSenderKeyDevices(memberDevices, devicesForSend);
|
|
|
|
|
|
|
|
assert.deepEqual(newToMemberDevices, [
|
|
|
|
{
|
2023-08-10 16:43:33 +00:00
|
|
|
serviceId: serviceIdOne,
|
2021-05-25 22:40:04 +00:00
|
|
|
id: 2,
|
2021-07-30 18:35:25 +00:00
|
|
|
registrationId: 22,
|
2021-05-25 22:40:04 +00:00
|
|
|
},
|
|
|
|
{
|
2023-08-10 16:43:33 +00:00
|
|
|
serviceId: serviceIdTwo,
|
2021-05-25 22:40:04 +00:00
|
|
|
id: 2,
|
2021-07-30 18:35:25 +00:00
|
|
|
registrationId: 33,
|
2021-05-25 22:40:04 +00:00
|
|
|
},
|
|
|
|
]);
|
2023-08-10 16:43:33 +00:00
|
|
|
assert.deepEqual(newToMemberServiceIds, [serviceIdOne, serviceIdTwo]);
|
2021-05-25 22:40:04 +00:00
|
|
|
assert.isEmpty(removedFromMemberDevices);
|
2023-08-10 16:43:33 +00:00
|
|
|
assert.isEmpty(removedFromMemberServiceIds);
|
2021-05-25 22:40:04 +00:00
|
|
|
});
|
|
|
|
it('returns set of removed devices', () => {
|
|
|
|
const memberDevices = getDefaultDeviceList();
|
|
|
|
const devicesForSend = getDefaultDeviceList();
|
|
|
|
|
|
|
|
devicesForSend.pop();
|
|
|
|
devicesForSend.pop();
|
|
|
|
|
|
|
|
const {
|
|
|
|
newToMemberDevices,
|
2023-08-10 16:43:33 +00:00
|
|
|
newToMemberServiceIds,
|
2021-05-25 22:40:04 +00:00
|
|
|
removedFromMemberDevices,
|
2023-08-10 16:43:33 +00:00
|
|
|
removedFromMemberServiceIds,
|
2021-05-25 22:40:04 +00:00
|
|
|
} = _analyzeSenderKeyDevices(memberDevices, devicesForSend);
|
|
|
|
|
|
|
|
assert.isEmpty(newToMemberDevices);
|
2023-08-10 16:43:33 +00:00
|
|
|
assert.isEmpty(newToMemberServiceIds);
|
2021-05-25 22:40:04 +00:00
|
|
|
assert.deepEqual(removedFromMemberDevices, [
|
|
|
|
{
|
2023-08-10 16:43:33 +00:00
|
|
|
serviceId: serviceIdOne,
|
2021-05-25 22:40:04 +00:00
|
|
|
id: 2,
|
2021-07-30 18:35:25 +00:00
|
|
|
registrationId: 22,
|
2021-05-25 22:40:04 +00:00
|
|
|
},
|
|
|
|
{
|
2023-08-10 16:43:33 +00:00
|
|
|
serviceId: serviceIdTwo,
|
2021-05-25 22:40:04 +00:00
|
|
|
id: 2,
|
2021-07-30 18:35:25 +00:00
|
|
|
registrationId: 33,
|
2021-05-25 22:40:04 +00:00
|
|
|
},
|
|
|
|
]);
|
2023-08-10 16:43:33 +00:00
|
|
|
assert.deepEqual(removedFromMemberServiceIds, [
|
|
|
|
serviceIdOne,
|
|
|
|
serviceIdTwo,
|
|
|
|
]);
|
2021-05-25 22:40:04 +00:00
|
|
|
});
|
|
|
|
it('returns empty removals if partial send', () => {
|
|
|
|
const memberDevices = getDefaultDeviceList();
|
|
|
|
const devicesForSend = getDefaultDeviceList();
|
|
|
|
|
|
|
|
devicesForSend.pop();
|
|
|
|
devicesForSend.pop();
|
|
|
|
|
|
|
|
const isPartialSend = true;
|
|
|
|
const {
|
|
|
|
newToMemberDevices,
|
2023-08-10 16:43:33 +00:00
|
|
|
newToMemberServiceIds,
|
2021-05-25 22:40:04 +00:00
|
|
|
removedFromMemberDevices,
|
2023-08-10 16:43:33 +00:00
|
|
|
removedFromMemberServiceIds,
|
2021-05-25 22:40:04 +00:00
|
|
|
} = _analyzeSenderKeyDevices(
|
|
|
|
memberDevices,
|
|
|
|
devicesForSend,
|
|
|
|
isPartialSend
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.isEmpty(newToMemberDevices);
|
2023-08-10 16:43:33 +00:00
|
|
|
assert.isEmpty(newToMemberServiceIds);
|
2021-05-25 22:40:04 +00:00
|
|
|
assert.isEmpty(removedFromMemberDevices);
|
2023-08-10 16:43:33 +00:00
|
|
|
assert.isEmpty(removedFromMemberServiceIds);
|
2021-05-25 22:40:04 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-01-31 21:51:24 +00:00
|
|
|
describe('#_shouldFailSend', () => {
|
|
|
|
it('returns false for a generic error', async () => {
|
|
|
|
const error = new Error('generic');
|
|
|
|
assert.isFalse(_shouldFailSend(error, 'testing generic'));
|
|
|
|
});
|
|
|
|
|
|
|
|
it("returns true for any error with 'untrusted' identity", async () => {
|
2022-11-22 18:43:43 +00:00
|
|
|
const error = new LibSignalErrorBase(
|
|
|
|
'untrusted identity',
|
|
|
|
'UntrustedIdentity',
|
|
|
|
'ignored'
|
|
|
|
);
|
2022-01-31 21:51:24 +00:00
|
|
|
assert.isTrue(_shouldFailSend(error, 'logId'));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('returns true for certain types of error subclasses', async () => {
|
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
2022-02-25 23:39:24 +00:00
|
|
|
new OutgoingIdentityKeyError('something'),
|
2022-01-31 21:51:24 +00:00
|
|
|
'testing OutgoingIdentityKeyError'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
|
|
|
new UnregisteredUserError(
|
2023-08-10 16:43:33 +00:00
|
|
|
generateAci(),
|
2022-01-31 21:51:24 +00:00
|
|
|
new HTTPError('something', {
|
|
|
|
code: 400,
|
|
|
|
headers: {},
|
|
|
|
})
|
|
|
|
),
|
|
|
|
'testing UnregisteredUserError'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
|
|
|
new ConnectTimeoutError('something'),
|
|
|
|
'testing ConnectTimeoutError'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('returns false for unspecified error codes', () => {
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
const error: any = new Error('generic');
|
|
|
|
|
|
|
|
error.code = 422;
|
|
|
|
assert.isFalse(_shouldFailSend(error, 'testing generic 422'));
|
|
|
|
|
|
|
|
error.code = 204;
|
|
|
|
assert.isFalse(_shouldFailSend(error, 'testing generic 204'));
|
|
|
|
});
|
|
|
|
|
2023-01-21 00:50:34 +00:00
|
|
|
it('returns false for specific errors', () => {
|
|
|
|
const unknownRecipient = new UnknownRecipientError();
|
|
|
|
assert.isFalse(
|
|
|
|
_shouldFailSend(unknownRecipient, 'testing unknown recipient')
|
|
|
|
);
|
|
|
|
|
|
|
|
const incorrectAuth = new IncorrectSenderKeyAuthError();
|
|
|
|
assert.isFalse(_shouldFailSend(incorrectAuth, 'testing incorrect auth'));
|
|
|
|
});
|
|
|
|
|
2022-01-31 21:51:24 +00:00
|
|
|
it('returns true for a specified error codes', () => {
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
const error: any = new Error('generic');
|
2022-10-12 21:50:38 +00:00
|
|
|
error.code = 428;
|
2022-01-31 21:51:24 +00:00
|
|
|
|
|
|
|
assert.isTrue(_shouldFailSend(error, 'testing generic'));
|
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
|
|
|
new HTTPError('something', {
|
|
|
|
code: 404,
|
|
|
|
headers: {},
|
|
|
|
}),
|
|
|
|
'testing HTTPError'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
|
|
|
new OutgoingMessageError(
|
|
|
|
'something',
|
|
|
|
null,
|
|
|
|
null,
|
|
|
|
new HTTPError('something', {
|
|
|
|
code: 413,
|
|
|
|
headers: {},
|
|
|
|
})
|
|
|
|
),
|
|
|
|
'testing OutgoingMessageError'
|
|
|
|
)
|
|
|
|
);
|
2022-02-25 00:26:58 +00:00
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
|
|
|
new OutgoingMessageError(
|
|
|
|
'something',
|
|
|
|
null,
|
|
|
|
null,
|
|
|
|
new HTTPError('something', {
|
|
|
|
code: 429,
|
|
|
|
headers: {},
|
|
|
|
})
|
|
|
|
),
|
|
|
|
'testing OutgoingMessageError'
|
|
|
|
)
|
|
|
|
);
|
2022-01-31 21:51:24 +00:00
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
|
|
|
new SendMessageNetworkError(
|
|
|
|
'something',
|
|
|
|
null,
|
|
|
|
new HTTPError('something', {
|
|
|
|
code: 428,
|
|
|
|
headers: {},
|
|
|
|
})
|
|
|
|
),
|
|
|
|
'testing SendMessageNetworkError'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
|
|
|
new SendMessageChallengeError(
|
|
|
|
'something',
|
|
|
|
new HTTPError('something', {
|
|
|
|
code: 500,
|
|
|
|
headers: {},
|
|
|
|
})
|
|
|
|
),
|
|
|
|
'testing SendMessageChallengeError'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
|
|
|
new MessageError(
|
|
|
|
'something',
|
|
|
|
new HTTPError('something', {
|
|
|
|
code: 508,
|
|
|
|
headers: {},
|
|
|
|
})
|
|
|
|
),
|
|
|
|
'testing MessageError'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
it('returns true for errors inside of SendMessageProtoError', () => {
|
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
2023-05-10 01:25:37 +00:00
|
|
|
new SendMessageProtoError({
|
|
|
|
dataMessage: undefined,
|
|
|
|
editMessage: undefined,
|
|
|
|
}),
|
2022-01-31 21:51:24 +00:00
|
|
|
'testing missing errors list'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
const error: any = new Error('generic');
|
2022-10-12 21:50:38 +00:00
|
|
|
error.code = 428;
|
2022-01-31 21:51:24 +00:00
|
|
|
|
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
2023-05-10 01:25:37 +00:00
|
|
|
new SendMessageProtoError({
|
|
|
|
dataMessage: undefined,
|
|
|
|
editMessage: undefined,
|
|
|
|
errors: [error],
|
|
|
|
}),
|
2022-01-31 21:51:24 +00:00
|
|
|
'testing one error with code'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.isTrue(
|
|
|
|
_shouldFailSend(
|
|
|
|
new SendMessageProtoError({
|
2023-05-10 01:25:37 +00:00
|
|
|
dataMessage: undefined,
|
|
|
|
editMessage: undefined,
|
2022-01-31 21:51:24 +00:00
|
|
|
errors: [
|
|
|
|
new Error('something'),
|
|
|
|
new ConnectTimeoutError('something'),
|
|
|
|
],
|
|
|
|
}),
|
|
|
|
'testing ConnectTimeoutError'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
2021-05-25 22:40:04 +00:00
|
|
|
});
|