Continue working on banned channels

This commit is contained in:
Calvin Montgomery 2022-09-03 15:58:42 -07:00
parent ae5dbf5f48
commit 913348d46e
8 changed files with 191 additions and 28 deletions

107
bin/admin.js Normal file → Executable file
View file

@ -49,24 +49,107 @@ let commands = [
let [name, externalReason, internalReason] = args;
let answer = await rl.question(`Ban ${name} with external reason "${externalReason}" and internal reason "${internalReason}"? `);
if (!/^[yY]$/.test(answer)) {
console.log('Aborted.');
process.exit(1);
}
if (/^[yY]$/.test(answer)) {
let res = await doCommand({
command: 'ban-channel',
name,
externalReason,
internalReason
});
let res = await doCommand({
command: 'ban-channel',
name,
externalReason,
internalReason
});
console.log(`Status: ${res.status}`);
if (res.status === 'error') {
switch (res.status) {
case 'error':
console.log('Error:', res.error);
process.exit(1);
} else {
break;
case 'success':
console.log('Ban succeeded.');
process.exit(0);
}
} else {
break;
default:
console.log(`Unknown result: ${res.status}`);
process.exit(1);
break;
}
}
},
{
command: 'unban-channel',
handler: async args => {
if (args.length !== 1) {
console.log('Usage: unban-channel <name>');
process.exit(1);
}
let [name] = args;
let answer = await rl.question(`Unban ${name}? `);
if (!/^[yY]$/.test(answer)) {
console.log('Aborted.');
process.exit(1);
}
let res = await doCommand({
command: 'unban-channel',
name
});
switch (res.status) {
case 'error':
console.log('Error:', res.error);
process.exit(1);
break;
case 'success':
console.log('Unban succeeded.');
process.exit(0);
break;
default:
console.log(`Unknown result: ${res.status}`);
process.exit(1);
break;
}
}
},
{
command: 'show-banned-channel',
handler: async args => {
if (args.length !== 1) {
console.log('Usage: show-banned-channel <name>');
process.exit(1);
}
let [name] = args;
let res = await doCommand({
command: 'show-banned-channel',
name
});
switch (res.status) {
case 'error':
console.log('Error:', res.error);
process.exit(1);
break;
case 'success':
if (res.ban != null) {
console.log(`Channel: ${name}`);
console.log(`Ban issued: ${res.ban.createdAt}`);
console.log(`Banned by: ${res.ban.bannedBy}`);
console.log(`External reason:\n${res.ban.externalReason}`);
console.log(`Internal reason:\n${res.ban.internalReason}`);
} else {
console.log(`Channel ${name} is not banned.`);
}
process.exit(0);
break;
default:
console.log(`Unknown result: ${res.status}`);
process.exit(1);
break;
}
}
}

View file

@ -10,3 +10,15 @@ export async function handleBanChannel({ name, externalReason, internalReason })
return { status: 'success' };
}
export async function handleUnbanChannel({ name }) {
await Server.getServer().bannedChannelsController.unbanChannel(name, '[console]');
return { status: 'success' };
}
export async function handleShowBannedChannel({ name }) {
let banInfo = await Server.getServer().bannedChannelsController.getBannedChannel(name);
return { status: 'success', ban: banInfo };
}

View file

@ -66,7 +66,6 @@ var defaults = {
}
},
"youtube-v3-key": "",
"channel-blacklist": [],
"channel-path": "r",
"channel-save-interval": 5,
"max-channels-per-user": 5,
@ -372,13 +371,6 @@ function preprocessConfig(cfg) {
}
}
/* Convert channel blacklist to a hashtable */
var tbl = {};
cfg["channel-blacklist"].forEach(function (c) {
tbl[c.toLowerCase()] = true;
});
cfg["channel-blacklist"] = tbl;
/* Check channel path */
if(!/^[-\w]+$/.test(cfg["channel-path"])){
LOGGER.error("Channel paths may only use the same characters as usernames and channel names.");

View file

@ -1,3 +1,4 @@
import { eventlog } from '../logger';
const LOGGER = require('@calzoneman/jsli')('BannedChannelsController');
export class BannedChannelsController {
@ -6,8 +7,13 @@ export class BannedChannelsController {
this.globalMessageBus = globalMessageBus;
}
/*
* TODO: add an audit log to the database
*/
async banChannel({ name, externalReason, internalReason, bannedBy }) {
LOGGER.info(`Banning channel ${name} (banned by ${bannedBy})`);
eventlog.log(`[acp] ${bannedBy} banned channel ${name}`);
let banInfo = await this.dbChannels.getBannedChannel(name);
if (banInfo !== null) {
@ -26,4 +32,61 @@ export class BannedChannelsController {
{ channel: name, externalReason }
);
}
async unbanChannel(name, unbannedBy) {
LOGGER.info(`Unbanning channel ${name}`);
eventlog.log(`[acp] ${unbannedBy} unbanned channel ${name}`);
this.globalMessageBus.emit(
'ChannelUnbanned',
{ channel: name }
);
await this.dbChannels.removeBannedChannel(name);
}
async getBannedChannel(name) {
// TODO: cache
return this.dbChannels.getBannedChannel(name);
}
}
class Cache {
constructor({ maxElem, maxAge }) {
this.maxElem = maxElem;
this.maxAge = maxAge;
this.cache = new Map();
}
put(key, value) {
this.cache.set(key, { value: value, at: Date.now() });
if (this.cache.size > this.maxElem) {
this.cache.delete(this.cache.keys().next());
}
}
get(key) {
let val = this.cache.get(key);
if (val != null) {
return val.value;
} else {
return null;
}
}
delete(key) {
this.cache.delete(key);
}
cleanup() {
let now = Date.now();
for (let [key, value] of this.cache) {
if (value.at < now - this.maxAge) {
this.cache.delete(key);
}
}
}
}

View file

@ -763,10 +763,22 @@ module.exports = {
banned_by: bannedBy
});
let update = tx.raw(createMySQLDuplicateKeyUpdate(
['external_reason', 'internal_reason']
['external_reason', 'internal_reason', 'banned_by']
));
return tx.raw(insert.toString() + update.toString());
});
},
removeBannedChannel: async function removeBannedChannel(name) {
if (!valid(name)) {
throw new Error("Invalid channel name");
}
return await db.getDB().runTransaction(async tx => {
await tx.table('banned_channels')
.where({ channel_name: name })
.delete();
});
}
};

View file

@ -33,7 +33,11 @@ async function handleCliCmd(cmd) {
try {
switch (cmd.command) {
case 'ban-channel':
return await bannedChannels.handleBanChannel(cmd);
return bannedChannels.handleBanChannel(cmd);
case 'unban-channel':
return bannedChannels.handleUnbanChannel(cmd);
case 'show-banned-channel':
return bannedChannels.handleShowBannedChannel(cmd);
default:
throw new Error(`Unrecognized command "${cmd.command}"`);
}
@ -52,6 +56,7 @@ function handleLine(line, client) {
client.write(JSON.stringify(res) + '\n');
}).catch(error => {
LOGGER.error(`Unexpected error in handleCliCmd: ${error.stack}`);
client.write('{"status":"error","error":"internal error"}\n');
});
} catch (_error) {
}

View file

@ -76,10 +76,6 @@ User.prototype.handleJoinChannel = function handleJoinChannel(data) {
}
data.name = data.name.toLowerCase();
if (data.name in Config.get("channel-blacklist")) {
this.kick("This channel is blacklisted.");
return;
}
this.waitFlag(Flags.U_READY, () => {
var chan;

View file

@ -198,8 +198,8 @@ module.exports = {
app,
ioConfig,
chanPath,
async name => null
/*require('../database/channels').getBannedChannel*/
// TODO: banController
require('../database/channels').getBannedChannel
);
require('./routes/index')(app, channelIndex, webConfig.getMaxIndexEntries());
require('./routes/socketconfig')(app, clusterClient);