Always block the primary device instead of all devices.

Added isBlockedAsync function.
This commit is contained in:
Mikunj 2020-07-07 15:28:25 +10:00
parent 2a1afa9fe7
commit f008a8b3ef
5 changed files with 116 additions and 49 deletions

View File

@ -234,10 +234,7 @@
if (this.isPrivate()) {
const primary = this.getPrimaryDevicePubKey();
return (
BlockedNumberController.isBlocked(primary) ||
BlockedNumberController.isBlocked(this.id)
);
return BlockedNumberController.isBlocked(primary);
}
return false;

View File

@ -97,16 +97,7 @@ function unpad(paddedData: ArrayBuffer): ArrayBuffer {
}
export async function isBlocked(number: string) {
const ourDevice = await MultiDeviceProtocol.isOurDevice(number);
if (ourDevice) {
return false;
}
const primary = await MultiDeviceProtocol.getPrimaryDevice(number);
return (
BlockedNumberController.isBlocked(primary) ||
BlockedNumberController.isBlocked(number)
);
return BlockedNumberController.isBlockedAsync(number);
}
async function decryptPreKeyWhisperMessage(
@ -163,7 +154,6 @@ async function decryptUnidentifiedSender(
// tslint:disable-next-line: no-shadowed-variable
const blocked = await isBlocked(source.getName());
if (blocked) {
await BlockedNumberController.block(source.getName());
window.log.info(
'Dropping blocked message with error after sealed sender decryption'
);
@ -200,7 +190,6 @@ async function decryptUnidentifiedSender(
const blocked = await isBlocked(sender.getName());
if (blocked) {
await BlockedNumberController.block(sender.getName());
window.log.info('Dropping blocked message after sealed sender decryption');
return null;
}

View File

@ -156,7 +156,6 @@ async function handleRequestDetail(
// so this check is not appropriate here
const blocked = await isBlocked(envelope.source);
if (blocked) {
await BlockedNumberController.block(envelope.source);
return;
}

View File

@ -5,6 +5,7 @@ import { BlockedNumberController } from '../../util/blockedNumberController';
import { TestUtils } from '../test-utils';
import { PubKey } from '../../session/types';
import { MultiDeviceProtocol } from '../../session/protocols';
import { UserUtil } from '../../util';
describe('BlockedNumberController', () => {
const sandbox = sinon.createSandbox();
@ -63,34 +64,29 @@ describe('BlockedNumberController', () => {
});
describe('block', async () => {
it('should block all linked devices of a user', async () => {
const pubKey = TestUtils.generateFakePubKey();
const linkedDevice = TestUtils.generateFakePubKey();
sandbox
.stub(MultiDeviceProtocol, 'getAllDevices')
.resolves([pubKey, linkedDevice]);
it('should block the primary device of the user', async () => {
const primary = TestUtils.generateFakePubKey();
const secondary = TestUtils.generateFakePubKey();
sandbox.stub(MultiDeviceProtocol, 'getPrimaryDevice').resolves(primary);
await BlockedNumberController.block(linkedDevice);
await BlockedNumberController.block(secondary);
const expected = [pubKey.key, linkedDevice.key];
const blockedNumbers = BlockedNumberController.getBlockedNumbers();
expect(blockedNumbers).to.have.lengthOf(2);
expect(blockedNumbers).to.have.same.members(expected);
expect(memoryDB.blocked).to.have.same.members(expected);
expect(blockedNumbers).to.have.lengthOf(1);
expect(blockedNumbers).to.include(primary.key);
expect(memoryDB.blocked).to.include(primary.key);
expect(BlockedNumberController.getBlockedGroups()).to.be.empty;
});
});
describe('unblock', async () => {
it('should unblock all linked device of a user', async () => {
const pubKey = TestUtils.generateFakePubKey();
const linkedDevice = TestUtils.generateFakePubKey();
memoryDB.blocked = [pubKey.key, linkedDevice.key];
sandbox
.stub(MultiDeviceProtocol, 'getAllDevices')
.resolves([pubKey, linkedDevice]);
it('should unblock the primary device', async () => {
const primary = TestUtils.generateFakePubKey();
const secondary = TestUtils.generateFakePubKey();
memoryDB.blocked = [primary.key];
sandbox.stub(MultiDeviceProtocol, 'getPrimaryDevice').resolves(primary);
await BlockedNumberController.unblock(linkedDevice);
await BlockedNumberController.unblock(secondary);
const blockedNumbers = BlockedNumberController.getBlockedNumbers();
expect(blockedNumbers).to.be.empty;
@ -101,7 +97,7 @@ describe('BlockedNumberController', () => {
const pubKey = TestUtils.generateFakePubKey();
const another = TestUtils.generateFakePubKey();
memoryDB.blocked = [pubKey.key, another.key];
sandbox.stub(MultiDeviceProtocol, 'getAllDevices').resolves([pubKey]);
sandbox.stub(MultiDeviceProtocol, 'getPrimaryDevice').resolves(pubKey);
await BlockedNumberController.unblock(pubKey);
@ -145,7 +141,7 @@ describe('BlockedNumberController', () => {
});
describe('isBlocked', async () => {
it('should return the correct value', async () => {
it('should return true if number is blocked', async () => {
const pubKey = TestUtils.generateFakePubKey();
const groupPubKey = TestUtils.generateFakePubKey();
memoryDB.blocked = [pubKey.key];
@ -160,10 +156,62 @@ describe('BlockedNumberController', () => {
'Expected isBlocked to return false for a group pubkey'
);
});
it('should return false if number is not blocked', async () => {
const pubKey = TestUtils.generateFakePubKey();
memoryDB.blocked = [];
await BlockedNumberController.load();
expect(BlockedNumberController.isBlocked(pubKey.key)).to.equal(
false,
'Expected isBlocked to return false'
);
});
});
describe('isBlockedAsync', () => {
let ourDevices: Array<PubKey>;
beforeEach(() => {
ourDevices = TestUtils.generateFakePubKeys(2);
sandbox.stub(MultiDeviceProtocol, 'getOurDevices').resolves(ourDevices);
});
it('should return false for our device', async () => {
for (const device of ourDevices) {
const isBlocked = await BlockedNumberController.isBlockedAsync(device);
expect(isBlocked).to.equal(
false,
'Expected our devices to return false'
);
}
});
it('should return true if the primary device is blocked', async () => {
const primary = TestUtils.generateFakePubKey();
const secondary = TestUtils.generateFakePubKey();
sandbox.stub(MultiDeviceProtocol, 'getPrimaryDevice').resolves(primary);
memoryDB.blocked = [primary.key];
const isBlocked = await BlockedNumberController.isBlockedAsync(secondary);
expect(isBlocked).to.equal(
true,
'Expected isBlockedAsync to return true.'
);
});
it('should return false if device is not blocked', async () => {
const primary = TestUtils.generateFakePubKey();
sandbox.stub(MultiDeviceProtocol, 'getPrimaryDevice').resolves(primary);
memoryDB.blocked = [];
const isBlocked = await BlockedNumberController.isBlockedAsync(primary);
expect(isBlocked).to.equal(
false,
'Expected isBlockedAsync to return false.'
);
});
});
describe('isGroupBlocked', async () => {
it('should return the correct value', async () => {
it('should return true if group is blocked', async () => {
const pubKey = TestUtils.generateFakePubKey();
const groupPubKey = TestUtils.generateFakePubKey();
memoryDB.blocked = [pubKey.key];
@ -178,5 +226,15 @@ describe('BlockedNumberController', () => {
'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'
);
});
});
});

View File

@ -13,6 +13,25 @@ export class BlockedNumberController {
/**
* Check if a device is blocked.
* This will use `MultiDeviceProtocol` to determine wether a user is blocked or not.
*
* @param user The user.
*/
public static async isBlockedAsync(user: string | PubKey): Promise<boolean> {
await this.load();
const isOurDevice = await MultiDeviceProtocol.isOurDevice(user);
if (isOurDevice) {
return false;
}
const primary = await MultiDeviceProtocol.getPrimaryDevice(user);
return this.blockedNumbers.has(primary.key);
}
/**
* Check if a device is blocked synchronously.
* This will only check against the memory cache on if a device is blocked, it is reccomended to pass in the primary device pub key.
*
* Make sure `load()` has been called before this function so that the correct blocked state is returned.
*
* @param number The device.
@ -32,15 +51,14 @@ export class BlockedNumberController {
* @param groupId The group id.
*/
public static isGroupBlocked(groupId: string | PubKey): boolean {
// This function is not `async` because the old `isBlocked` function in js was also not async.
// To convert it means we'll have to re-wire all our UI components to work with async.
const stringValue =
groupId instanceof PubKey ? groupId.key : groupId.toLowerCase();
return this.blockedGroups.has(stringValue);
}
/**
* Block a user (including their linked devices).
* Block a user.
* This will only block the primary device of the user.
*
* @param user The user to block.
*/
@ -49,20 +67,26 @@ export class BlockedNumberController {
// `isBlocked` is used synchronously in the code. To check if any device is blocked needs it to be async, which would mean all calls to `isBlocked` will also need to be async and so on
// This is too much of a hassle at the moment as some UI code will have to be migrated to work with this async call.
await this.load();
const devices = await MultiDeviceProtocol.getAllDevices(user);
devices.forEach(pubKey => this.blockedNumbers.add(pubKey.key));
await this.saveToDB(BLOCKED_NUMBERS_ID, this.blockedNumbers);
const primary = await MultiDeviceProtocol.getPrimaryDevice(user);
if (!this.blockedNumbers.has(primary.key)) {
this.blockedNumbers.add(primary.key);
await this.saveToDB(BLOCKED_NUMBERS_ID, this.blockedNumbers);
}
}
/**
* Unblock a user (including their linked devices).
* Unblock a user.
* This will only unblock the primary device of the user.
*
* @param user The user to unblock.
*/
public static async unblock(user: string | PubKey): Promise<void> {
await this.load();
const devices = await MultiDeviceProtocol.getAllDevices(user);
devices.forEach(pubKey => this.blockedNumbers.delete(pubKey.key));
await this.saveToDB(BLOCKED_NUMBERS_ID, this.blockedNumbers);
const primary = await MultiDeviceProtocol.getPrimaryDevice(user);
if (this.blockedNumbers.has(primary.key)) {
this.blockedNumbers.delete(primary.key);
await this.saveToDB(BLOCKED_NUMBERS_ID, this.blockedNumbers);
}
}
public static async blockGroup(groupId: string | PubKey): Promise<void> {