/* * Copyright (C) Sapphirecode - All Rights Reserved * This file is part of Auth-Server-Helper which is released under MIT. * See file 'LICENSE' for full license details. * Created by Timo Hocker , December 2020 */ import { debug } from './debug'; import { redis_blacklist_store } from './RedisData/RedisBlacklistStore'; const logger = debug ('blacklist'); interface Signature { hash: string; iat: number; } class Blacklist { private _signatures: Signature[]; public constructor () { this._signatures = []; } public async clear ( before: number = Number.POSITIVE_INFINITY ): Promise { logger.extend ('clear') ('clearing blacklist'); for (let i = this._signatures.length - 1; i >= 0; i--) { if (this._signatures[i].iat < before) { // eslint-disable-next-line no-await-in-loop await this.remove_signature (i); } } } public async add_signature (hash: string): Promise { logger.extend ('add_signature') ('blacklisting signature %s', hash); this._signatures.push ({ iat: Date.now (), hash }); await redis_blacklist_store.add (hash); } public async remove_signature (signature: number | string): Promise { const log = logger.extend ('remove_signature'); log ('removing signature from blacklist %s', signature); let key = ''; if (typeof signature === 'string') { log ('received string, searching through signatures'); key = signature; for (let i = this._signatures.length - 1; i >= 0; i--) { if (this._signatures[i].hash === signature) this._signatures.splice (i, 1); } } else { log ('received index, removing at index'); key = this._signatures[signature].hash; this._signatures.splice (signature, 1); } await redis_blacklist_store.remove (key); } public async is_valid (hash: string): Promise { const log = logger.extend ('is_valid'); log ('checking signature for blacklist entry %s', hash); for (const sig of this._signatures) { if (sig.hash === hash) { log ('found matching blacklist entry'); return false; } } log ('signature is not blacklisted locally, checking redis'); if (await redis_blacklist_store.get (hash)) { log ('signature is blacklisted in redis'); return false; } log ('signature is not blacklisted'); return true; } public export_blacklist (): Signature[] { logger.extend ('export_blacklist') ('exporting blacklist'); return this._signatures; } public import_blacklist (data: Signature[]): void { logger.extend ('import_blacklist') ( 'importing %d blacklist entries', data.length ); this._signatures.push (...data); } public sync_redis (url: string): void { redis_blacklist_store.connect (url); } } const bl = (new Blacklist); export { Blacklist }; export default bl;