feat: remove blocked group tracking separately from the pubkeys

pull/2620/head
Audric Ackermann 2 years ago
parent b2237efe51
commit f88acdb567

@ -91,10 +91,7 @@ export async function blockConvoById(conversationId: string) {
return;
}
const promise = conversation.isPrivate()
? BlockedNumberController.block(conversation.id)
: BlockedNumberController.blockGroup(conversation.id);
await promise;
await BlockedNumberController.block(conversation.id);
await conversation.commit();
ToastUtils.pushToastSuccess('blocked', window.i18n('blocked'));
}
@ -112,10 +109,7 @@ export async function unblockConvoById(conversationId: string) {
if (!conversation.id || conversation.isPublic()) {
return;
}
const promise = conversation.isPrivate()
? BlockedNumberController.unblock(conversationId)
: BlockedNumberController.unblockGroup(conversationId);
await promise;
await BlockedNumberController.unblock(conversationId);
ToastUtils.pushToastSuccess('unblocked', window.i18n('unblocked'));
await conversation.commit();
}

@ -89,7 +89,7 @@ export async function handleClosedGroupControlMessage(
return;
}
if (BlockedNumberController.isGroupBlocked(PubKey.cast(envelope.source))) {
if (BlockedNumberController.isBlocked(PubKey.cast(envelope.source))) {
window?.log?.warn('Message ignored; destined for blocked group');
await removeFromCache(envelope);
return;

@ -72,6 +72,7 @@ async function handleUserProfileUpdate(result: IncomingConfResult): Promise<Inco
return result;
}
// tslint:disable-next-line: cyclomatic-complexity
async function handleContactsUpdate(result: IncomingConfResult): Promise<IncomingConfResult> {
if (!result.needsDump) {
return result;
@ -116,11 +117,7 @@ async function handleContactsUpdate(result: IncomingConfResult): Promise<Incomin
const convoBlocked = wrapperConvo.blocked || false;
if (convoBlocked !== existingConvo.isBlocked()) {
if (existingConvo.isPrivate()) {
await BlockedNumberController.setBlocked(wrapperConvo.id, convoBlocked);
} else {
await BlockedNumberController.setGroupBlocked(wrapperConvo.id, convoBlocked);
}
await BlockedNumberController.setBlocked(wrapperConvo.id, convoBlocked);
}
if (wrapperConvo.nickname !== existingConvo.getNickname()) {

@ -268,7 +268,7 @@ export async function updateOrCreateClosedGroup(details: GroupInfo | GroupInfoV3
const isBlocked = details.blocked || false;
if (conversation.isClosedGroup() || conversation.isMediumGroup()) {
await BlockedNumberController.setGroupBlocked(conversation.id as string, isBlocked);
await BlockedNumberController.setBlocked(conversation.id as string, isBlocked);
}
if (details.admins?.length) {

@ -25,7 +25,7 @@ export function persistedJobFromData<T extends TypeOfPersistedData>(
case 'FakeSleepForJobMultiType':
return (new FakeSleepForMultiJob(data) as unknown) as PersistedJob<T>;
default:
console.warn('unknown persisted job type:', (data as any).jobType);
console.error('unknown persisted job type:', (data as any).jobType);
return null;
}
}

@ -405,9 +405,7 @@ export const _getSortedConversations = (
};
}
const isBlocked =
BlockedNumberController.isBlocked(conversation.id) ||
BlockedNumberController.isGroupBlocked(conversation.id);
const isBlocked = BlockedNumberController.isBlocked(conversation.id);
if (isBlocked) {
conversation = {

@ -28,6 +28,7 @@ describe('ConfigurationMessage_receiving', () => {
let config: ConfigurationMessage;
beforeEach(() => {
TestUtils.stubWindowFeatureFlags();
Sinon.stub(cache, 'removeFromCache').resolves();
sender = TestUtils.generateFakePubKey().key;
config = new ConfigurationMessage({

@ -1,23 +1,24 @@
import { expect } from 'chai';
import * as crypto from 'crypto';
import _ from 'lodash';
import Sinon, * as sinon from 'sinon';
import { MessageSender } from '../../../../session/sending';
import { TestUtils } from '../../../test-utils';
import { MessageEncrypter } from '../../../../session/crypto';
import { SignalService } from '../../../../protobuf';
import { PubKey, RawMessage } from '../../../../session/types';
import { MessageUtils, UserUtils } from '../../../../session/utils';
import _ from 'lodash';
import { OpenGroupMessageV2 } from '../../../../session/apis/open_group_api/opengroupV2/OpenGroupMessageV2';
import { OpenGroupPollingUtils } from '../../../../session/apis/open_group_api/opengroupV2/OpenGroupPollingUtils';
import { TEST_identityKeyPair } from '../crypto/MessageEncrypter_test';
import { stubCreateObjectUrl, stubData, stubUtilWorker } from '../../../test-utils/utils';
import { SogsBlinding } from '../../../../session/apis/open_group_api/sogsv3/sogsBlinding';
import { Onions } from '../../../../session/apis/snode_api/onions';
import { OnionV4 } from '../../../../session/onions/onionv4';
import { OnionSending } from '../../../../session/onions/onionSend';
import { OpenGroupMessageV2 } from '../../../../session/apis/open_group_api/opengroupV2/OpenGroupMessageV2';
import { GetNetworkTime } from '../../../../session/apis/snode_api/getNetworkTime';
import { SnodeNamespaces } from '../../../../session/apis/snode_api/namespaces';
import { Onions } from '../../../../session/apis/snode_api/onions';
import { getConversationController } from '../../../../session/conversations/ConversationController';
import { MessageEncrypter } from '../../../../session/crypto';
import { OnionSending } from '../../../../session/onions/onionSend';
import { OnionV4 } from '../../../../session/onions/onionv4';
import { MessageSender } from '../../../../session/sending';
import { PubKey, RawMessage } from '../../../../session/types';
import { MessageUtils, UserUtils } from '../../../../session/utils';
import { TestUtils } from '../../../test-utils';
import { stubCreateObjectUrl, stubData, stubUtilWorker } from '../../../test-utils/utils';
import { TEST_identityKeyPair } from '../crypto/MessageEncrypter_test';
describe('MessageSender', () => {
afterEach(() => {
@ -26,6 +27,7 @@ describe('MessageSender', () => {
beforeEach(() => {
TestUtils.stubWindowLog();
TestUtils.stubWindowFeatureFlags();
});
// tslint:disable-next-line: max-func-body-length
@ -35,7 +37,7 @@ describe('MessageSender', () => {
let encryptStub: sinon.SinonStub<[PubKey, Uint8Array, SignalService.Envelope.Type]>;
beforeEach(() => {
sessionMessageAPISendStub = Sinon.stub(MessageSender, 'sendMessagesToSnode').resolves();
sessionMessageAPISendStub = Sinon.stub(MessageSender, 'sendMessagesDataToSnode').resolves();
stubData('getMessageById').resolves();
@ -101,6 +103,7 @@ describe('MessageSender', () => {
it('should pass the correct values to lokiMessageAPI', async () => {
const device = TestUtils.generateFakePubKey();
const visibleMessage = TestUtils.generateVisibleMessage();
Sinon.stub(getConversationController(), 'get').returns(undefined as any);
const rawMessage = await MessageUtils.toRawMessage(
device,
@ -121,7 +124,7 @@ describe('MessageSender', () => {
// This test assumes the encryption stub returns the plainText passed into it.
const device = TestUtils.generateFakePubKey();
Sinon.stub(getConversationController(), 'get').returns(undefined as any);
const visibleMessage = TestUtils.generateVisibleMessage();
const rawMessage = await MessageUtils.toRawMessage(
device,
@ -171,6 +174,7 @@ describe('MessageSender', () => {
describe('SESSION_MESSAGE', () => {
it('should set the envelope source to be empty', async () => {
messageEncyrptReturnEnvelopeType = SignalService.Envelope.Type.SESSION_MESSAGE;
Sinon.stub(getConversationController(), 'get').returns(undefined as any);
// This test assumes the encryption stub returns the plainText passed into it.
const device = TestUtils.generateFakePubKey();

@ -40,7 +40,7 @@ describe('SwarmPolling', () => {
let clock: Sinon.SinonFakeTimers;
beforeEach(async () => {
getConversationController().reset();
TestUtils.stubWindowFeatureFlags();
// Utils Stubs
Sinon.stub(UserUtils, 'getOurPubKeyStrFromCache').returns(ourNumber);

@ -46,11 +46,12 @@ describe('Message Utils', () => {
SnodeNamespaces.UserContacts
);
expect(Object.keys(rawMessage)).to.have.length(5);
expect(Object.keys(rawMessage)).to.have.length(6);
// do not believe tslint. those calls to.exist are actually correct here
// tslint:disable: no-unused-expression
expect(rawMessage.identifier).to.exist;
expect(rawMessage.namespace).to.exist;
expect(rawMessage.device).to.exist;
expect(rawMessage.encryption).to.exist;
expect(rawMessage.plainTextBuffer).to.exist;

@ -86,6 +86,10 @@ export const stubWindowLog = () => {
});
};
export const stubWindowFeatureFlags = () => {
stubWindow('sessionFeatureFlags', { debug: {} } as any);
};
export async function expectAsyncToThrow(toAwait: () => Promise<any>, errorMessageToCatch: string) {
try {
await toAwait();

@ -38,27 +38,19 @@ describe('BlockedNumberController', () => {
describe('load', () => {
it('should load data from the database', async () => {
const normal = TestUtils.generateFakePubKey();
const group = TestUtils.generateFakePubKey();
memoryDB.blocked = [normal.key];
memoryDB['blocked-groups'] = [group.key];
await BlockedNumberController.load();
const blockedNumbers = BlockedNumberController.getBlockedNumbers();
const blockedGroups = BlockedNumberController.getBlockedGroups();
expect(blockedNumbers).to.have.lengthOf(1);
expect(blockedNumbers).to.include(normal.key);
expect(blockedGroups).to.have.lengthOf(1);
expect(blockedGroups).to.include(group.key);
});
it('should return empty if nothing in the db exists', async () => {
await BlockedNumberController.load();
const blockedNumbers = BlockedNumberController.getBlockedNumbers();
const blockedGroups = BlockedNumberController.getBlockedGroups();
expect(blockedNumbers).to.be.empty;
expect(blockedGroups).to.be.empty;
});
});
@ -72,7 +64,6 @@ describe('BlockedNumberController', () => {
expect(blockedNumbers).to.have.lengthOf(1);
expect(blockedNumbers).to.include(other.key);
expect(memoryDB.blocked).to.include(other.key);
expect(BlockedNumberController.getBlockedGroups()).to.be.empty;
});
});
@ -103,52 +94,15 @@ describe('BlockedNumberController', () => {
});
});
describe('blockGroup', () => {
it('should block a group', async () => {
const group = TestUtils.generateFakePubKey();
await BlockedNumberController.blockGroup(group);
const blockedGroups = BlockedNumberController.getBlockedGroups();
expect(blockedGroups).to.have.lengthOf(1);
expect(blockedGroups).to.include(group.key);
expect(memoryDB['blocked-groups']).to.have.lengthOf(1);
expect(memoryDB['blocked-groups']).to.include(group.key);
expect(BlockedNumberController.getBlockedNumbers()).to.be.empty;
});
});
describe('unblockGroup', () => {
it('should unblock a group', async () => {
const group = TestUtils.generateFakePubKey();
const another = TestUtils.generateFakePubKey();
memoryDB['blocked-groups'] = [group.key, another.key];
await BlockedNumberController.unblockGroup(group);
const blockedGroups = BlockedNumberController.getBlockedGroups();
expect(blockedGroups).to.have.lengthOf(1);
expect(blockedGroups).to.include(another.key);
expect(memoryDB['blocked-groups']).to.have.lengthOf(1);
expect(memoryDB['blocked-groups']).to.include(another.key);
});
});
describe('isBlocked', () => {
it('should return true if number is blocked', async () => {
const pubKey = TestUtils.generateFakePubKey();
const groupPubKey = TestUtils.generateFakePubKey();
memoryDB.blocked = [pubKey.key];
memoryDB['blocked-groups'] = [groupPubKey.key];
await BlockedNumberController.load();
expect(BlockedNumberController.isBlocked(pubKey.key)).to.equal(
true,
'Expected isBlocked to return true for user pubkey'
);
expect(BlockedNumberController.isBlocked(groupPubKey.key)).to.equal(
false,
'Expected isBlocked to return false for a group pubkey'
);
});
it('should return false if number is not blocked', async () => {
@ -189,32 +143,4 @@ describe('BlockedNumberController', () => {
expect(isBlocked).to.equal(false, 'Expected isBlockedAsync to return false.');
});
});
describe('isGroupBlocked', () => {
it('should return true if group is blocked', async () => {
const pubKey = TestUtils.generateFakePubKey();
const groupPubKey = TestUtils.generateFakePubKey();
memoryDB.blocked = [pubKey.key];
memoryDB['blocked-groups'] = [groupPubKey.key];
await BlockedNumberController.load();
expect(BlockedNumberController.isGroupBlocked(pubKey.key)).to.equal(
false,
'Expected isGroupBlocked to return false for user pubkey'
);
expect(BlockedNumberController.isGroupBlocked(groupPubKey.key)).to.equal(
true,
'Expected isGroupBlocked to return true for a group pubkey'
);
});
it('should return false if group is not blocked', async () => {
const groupPubKey = TestUtils.generateFakePubKey();
memoryDB['blocked-groups'] = [];
await BlockedNumberController.load();
expect(BlockedNumberController.isGroupBlocked(groupPubKey.key)).to.equal(
false,
'Expected isGroupBlocked to return false'
);
});
});
});

@ -4,13 +4,11 @@ import { PubKey } from '../session/types';
import { UserUtils } from '../session/utils';
const BLOCKED_NUMBERS_ID = 'blocked';
const BLOCKED_GROUPS_ID = 'blocked-groups';
// tslint:disable-next-line: no-unnecessary-class
export class BlockedNumberController {
private static loaded: boolean = false;
private static blockedNumbers: Set<string> = new Set();
private static blockedGroups: Set<string> = new Set();
/**
* Check if a device is blocked.
@ -44,19 +42,7 @@ export class BlockedNumberController {
}
/**
* Check if a group id is blocked.
* Make sure `load()` has been called before this function so that the correct blocked state is returned.
*
* @param groupId The group id.
*/
public static isGroupBlocked(groupId: string | PubKey): boolean {
const stringValue = groupId instanceof PubKey ? groupId.key : groupId.toLowerCase();
return this.blockedGroups.has(stringValue);
}
/**
* Block a user.
* This will only block the primary device of the user.
* Block a user or group, by pubkey
*
* @param user The user to block.
*/
@ -125,41 +111,15 @@ export class BlockedNumberController {
return BlockedNumberController.unblock(user);
}
public static async setGroupBlocked(groupId: string | PubKey, blocked: boolean): Promise<void> {
if (blocked) {
return BlockedNumberController.blockGroup(groupId);
}
return BlockedNumberController.unblockGroup(groupId);
}
public static async blockGroup(groupId: string | PubKey): Promise<void> {
await this.load();
const id = PubKey.cast(groupId);
this.blockedGroups.add(id.key);
await this.saveToDB(BLOCKED_GROUPS_ID, this.blockedGroups);
}
public static async unblockGroup(groupId: string | PubKey): Promise<void> {
await this.load();
const id = PubKey.cast(groupId);
this.blockedGroups.delete(id.key);
await this.saveToDB(BLOCKED_GROUPS_ID, this.blockedGroups);
}
public static getBlockedNumbers(): Array<string> {
return [...this.blockedNumbers];
}
public static getBlockedGroups(): Array<string> {
return [...this.blockedGroups];
}
// ---- DB
public static async load() {
if (!this.loaded) {
this.blockedNumbers = await this.getNumbersFromDB(BLOCKED_NUMBERS_ID);
this.blockedGroups = await this.getNumbersFromDB(BLOCKED_GROUPS_ID);
this.loaded = true;
}
}
@ -167,7 +127,6 @@ export class BlockedNumberController {
public static reset() {
this.loaded = false;
this.blockedNumbers = new Set();
this.blockedGroups = new Set();
}
private static async getNumbersFromDB(id: string): Promise<Set<string>> {

Loading…
Cancel
Save