session-desktop/ts/util/blockedNumberController.ts

149 lines
4.9 KiB
TypeScript
Raw Normal View History

2020-07-07 01:13:55 +02:00
import { createOrUpdateItem, getItemById } from '../../js/modules/data';
import { PubKey } from '../session/types';
import { MultiDeviceProtocol } from '../session/protocols';
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.
* 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.
*
2020-07-07 05:46:56 +02:00
* Make sure `load()` has been called before this function so that the correct blocked state is returned.
2020-07-07 01:13:55 +02:00
*
* @param number The device.
*/
public static isBlocked(device: string | PubKey): boolean {
2020-07-07 05:46:56 +02:00
// 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.
2020-07-07 01:13:55 +02:00
const stringValue =
device instanceof PubKey ? device.key : device.toLowerCase();
return this.blockedNumbers.has(stringValue);
}
/**
* Check if a group id is blocked.
2020-07-07 05:46:56 +02:00
* Make sure `load()` has been called before this function so that the correct blocked state is returned.
*
2020-07-07 01:13:55 +02:00
* @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.
2020-07-07 01:13:55 +02:00
*
* @param user The user to block.
*/
public static async block(user: string | PubKey): Promise<void> {
// The reason we add all linked device to block number set instead of checking if any device of a user is in the `isBlocked` function because
// `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 primary = await MultiDeviceProtocol.getPrimaryDevice(user);
if (!this.blockedNumbers.has(primary.key)) {
this.blockedNumbers.add(primary.key);
await this.saveToDB(BLOCKED_NUMBERS_ID, this.blockedNumbers);
}
2020-07-07 01:13:55 +02:00
}
/**
* Unblock a user.
* This will only unblock the primary device of the user.
*
2020-07-07 01:13:55 +02:00
* @param user The user to unblock.
*/
public static async unblock(user: string | PubKey): Promise<void> {
await this.load();
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);
}
2020-07-07 01:13:55 +02:00
}
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);
}
2020-07-07 03:42:56 +02:00
public static getBlockedNumbers(): Array<string> {
return [...this.blockedNumbers];
2020-07-07 01:13:55 +02:00
}
2020-07-07 03:42:56 +02:00
public static getBlockedGroups(): Array<string> {
return [...this.blockedGroups];
2020-07-07 01:13:55 +02:00
}
// ---- 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;
}
}
2020-07-07 03:42:56 +02:00
public static reset() {
2020-07-07 01:13:55 +02:00
this.loaded = false;
this.blockedNumbers = new Set();
this.blockedGroups = new Set();
}
private static async getNumbersFromDB(id: string): Promise<Set<string>> {
const data = await getItemById(id);
if (!data || !data.value) {
return new Set();
}
return new Set(data.value);
}
private static async saveToDB(
id: string,
numbers: Set<string>
): Promise<void> {
await createOrUpdateItem({
id,
value: [...numbers],
});
}
}