From 5c22c1a73805c1087942eb0bc1b655ea68de8912 Mon Sep 17 00:00:00 2001 From: knotteye Date: Sat, 9 Jan 2021 15:22:23 -0600 Subject: [PATCH 1/6] Add migration script for channel bans table in the database. --- src/db/3.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/db/3.ts diff --git a/src/db/3.ts b/src/db/3.ts new file mode 100644 index 0000000..7037fa7 --- /dev/null +++ b/src/db/3.ts @@ -0,0 +1,9 @@ +import * as db from "../database"; + +async function run () { + await db.query('CREATE TABLE IF NOT EXISTS ch_bans(channel VARCHAR(25), target VARCHAR(45), time BIGINT, length INT DEFAULT 30)'); + await db.query('INSERT INTO ch_bans(channel) SELECT username FROM users'); + await db.query('INSERT INTO db_meta (version) VALUES (3)'); +} + +export { run } \ No newline at end of file From 57410dc969b81b352ea5e35fe79c003cffededdd Mon Sep 17 00:00:00 2001 From: knotteye Date: Sat, 9 Jan 2021 15:25:06 -0600 Subject: [PATCH 2/6] Update database functions to create and destroy rows in new table. --- src/database.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/database.ts b/src/database.ts index 0d733e7..05a572a 100644 --- a/src/database.ts +++ b/src/database.ts @@ -30,6 +30,7 @@ async function addUser(name: string, password: string){ await query('INSERT INTO user_meta (username, title, about, live) VALUES ('+raw.escape(name)+',\'\',\'\',false)'); await query('INSERT INTO chat_integration (username, irc, xmpp, twitch, discord) VALUES ('+raw.escape(name)+',\'\',\'\',\'\',\'\')'); await query('INSERT INTO twitch_mirror (username) VALUES ('+raw.escape(name)+')'); + await query('INSERT INTO ch_bans(channel) VALUES ('+raw.escape(name)+')'); return true; } @@ -40,6 +41,7 @@ async function rmUser(name: string){ await query('delete from user_meta where username='+raw.escape(name)+' limit 1'); await query('delete from chat_integration where username='+raw.escape(name)+' limit 1'); await query('delete from twitch_mirror where username='+raw.escape(name)+' limit 1'); + await query('delete from ch_bans where username='+raw.escape(name)+' limit 1'); return true; } From a882285bacd2ee53edd09bbeb0f3563d00a1004e Mon Sep 17 00:00:00 2001 From: knotteye Date: Sun, 10 Jan 2021 10:13:29 -0600 Subject: [PATCH 3/6] Fix database functions regarding ch_bans since it's a special case --- src/database.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/database.ts b/src/database.ts index 05a572a..8b1bfda 100644 --- a/src/database.ts +++ b/src/database.ts @@ -30,7 +30,6 @@ async function addUser(name: string, password: string){ await query('INSERT INTO user_meta (username, title, about, live) VALUES ('+raw.escape(name)+',\'\',\'\',false)'); await query('INSERT INTO chat_integration (username, irc, xmpp, twitch, discord) VALUES ('+raw.escape(name)+',\'\',\'\',\'\',\'\')'); await query('INSERT INTO twitch_mirror (username) VALUES ('+raw.escape(name)+')'); - await query('INSERT INTO ch_bans(channel) VALUES ('+raw.escape(name)+')'); return true; } @@ -41,7 +40,7 @@ async function rmUser(name: string){ await query('delete from user_meta where username='+raw.escape(name)+' limit 1'); await query('delete from chat_integration where username='+raw.escape(name)+' limit 1'); await query('delete from twitch_mirror where username='+raw.escape(name)+' limit 1'); - await query('delete from ch_bans where username='+raw.escape(name)+' limit 1'); + await query('delete from ch_bans where channel='+raw.escape(name)); return true; } From 814d826ec9e2f0f54926a5eabf93b993be048d3f Mon Sep 17 00:00:00 2001 From: knotteye Date: Sun, 10 Jan 2021 11:01:28 -0600 Subject: [PATCH 4/6] Modify the migration script to import existing data. --- package-lock.json | 8 ++++---- package.json | 1 + src/db/3.ts | 16 ++++++++++++++-- src/v3manual.ts | 6 ++++++ 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 src/v3manual.ts diff --git a/package-lock.json b/package-lock.json index 813819b..d816fbc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "satyr", - "version": "0.10.1", + "version": "0.10.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1110,9 +1110,9 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "ipaddr.js": { "version": "1.9.0", diff --git a/package.json b/package.json index d33fe2c..a97c46d 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "setup": "sh install/setup.sh", "migrate": "ts-node src/migrate.ts", "invite": "ts-node src/cli.ts --invite", + "v3-manual": "ts-node src/v3manual.ts", "make-templates": "nunjucks-precompile -i [\"\\.html$\",\"\\.njk$\"] templates > site/templates.js" }, "repository": { diff --git a/src/db/3.ts b/src/db/3.ts index 7037fa7..1606c57 100644 --- a/src/db/3.ts +++ b/src/db/3.ts @@ -1,9 +1,21 @@ import * as db from "../database"; +import * as dirty from "dirty"; async function run () { await db.query('CREATE TABLE IF NOT EXISTS ch_bans(channel VARCHAR(25), target VARCHAR(45), time BIGINT, length INT DEFAULT 30)'); - await db.query('INSERT INTO ch_bans(channel) SELECT username FROM users'); - await db.query('INSERT INTO db_meta (version) VALUES (3)'); + console.log('!!! This migration has a race condition when run from the `npm run migrate` command. If thats how this was called, please re-run this migration manually.\n!!! Run `npm run v3-manual` to do so'); + var bansdb = new dirty('./config/bans.db') + bansdb.on('load', async () => { + bansdb.forEach(async (key, val) => { + let ips = Object.keys(val); + for(var i=0;i Date: Sun, 10 Jan 2021 11:26:52 -0600 Subject: [PATCH 5/6] Fix a bug where we weren't setting X-Auth-As on /api/register Also fix new users appearing to not exist until they update their bio/profile --- src/database.ts | 2 +- src/http.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/database.ts b/src/database.ts index 8b1bfda..7a95310 100644 --- a/src/database.ts +++ b/src/database.ts @@ -27,7 +27,7 @@ async function addUser(name: string, password: string){ let dupe = await query('select * from users where username='+raw.escape(name)); if(dupe[0]) return false; await query('INSERT INTO users (username, password_hash, stream_key, record_flag) VALUES ('+raw.escape(name)+', '+raw.escape(hash)+', '+raw.escape(key)+', 0)'); - await query('INSERT INTO user_meta (username, title, about, live) VALUES ('+raw.escape(name)+',\'\',\'\',false)'); + await query('INSERT INTO user_meta (username, title, about, live) VALUES ('+raw.escape(name)+',\' \',\' \',false)'); await query('INSERT INTO chat_integration (username, irc, xmpp, twitch, discord) VALUES ('+raw.escape(name)+',\'\',\'\',\'\',\'\')'); await query('INSERT INTO twitch_mirror (username) VALUES ('+raw.escape(name)+')'); return true; diff --git a/src/http.ts b/src/http.ts index b06cef1..a331a9a 100644 --- a/src/http.ts +++ b/src/http.ts @@ -254,6 +254,7 @@ async function initAPI() { api.register(req.body.username, req.body.password, req.body.confirm, true).then((result) => { if(result[0]) return genToken(req.body.username).then((t) => { res.cookie('Authorization', t, {maxAge: 604800000, httpOnly: true, sameSite: 'Lax'}); + res.cookie('X-Auth-As', req.body.username, {maxAge: 604800000, httpOnly: false, sameSite: 'Lax'}) res.json(result); api.useInvite(req.body.invite); return; @@ -268,6 +269,7 @@ async function initAPI() { api.register(req.body.username, req.body.password, req.body.confirm).then( (result) => { if(result[0]) return genToken(req.body.username).then((t) => { res.cookie('Authorization', t, {maxAge: 604800000, httpOnly: true, sameSite: 'Lax'}); + res.cookie('X-Auth-As', req.body.username, {maxAge: 604800000, httpOnly: false, sameSite: 'Lax'}) res.json(result); return; }); From 69d81ec836bbfc2693bf5bae797f0f9f344234fd Mon Sep 17 00:00:00 2001 From: knotteye Date: Sun, 10 Jan 2021 12:31:11 -0600 Subject: [PATCH 6/6] Switch to using MySQL instead of bans.db --- src/http.ts | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/http.ts b/src/http.ts index a331a9a..3bc1753 100644 --- a/src/http.ts +++ b/src/http.ts @@ -17,7 +17,6 @@ const app = express(); const server = http.createServer(app); const io = socketio(server); const store = dirty(); -var banlist; var jwkey; try{ jwkey = JWK.asKey(readFileSync('./config/jwt.pem')); @@ -77,7 +76,7 @@ async function init(){ else res.status(404).render('404.njk', njkconf); //res.status(404).render('404.njk', njkconf); }); - banlist = new dirty('./config/bans.db').on('load', () => {initChat()}); + await initChat(); server.listen(config['http']['port']); } @@ -591,9 +590,10 @@ async function initChat() { socket.on('JOINROOM', async (data) => { let t: any = await db.query('select username from users where username='+db.raw.escape(data)); if(t[0]){ - if(banlist.get(data) && banlist.get(data)[socket['handshake']['address']]){ - if(Math.floor(banlist.get(data)[socket['handshake']['address']]['time'] + (banlist.get(data)[socket['handshake']['address']]['length'] * 60)) < Math.floor(Date.now() / 1000)){ - banlist.set(data, Object.assign({}, banlist.get(data), {[socket['handshake']['address']]: null})); + let b = await db.query('select * from ch_bans where target='+db.raw.escape(socket['handshake']['address'])+' and channel='+db.raw.escape(data)); + if(b[0]){ + if(Math.floor(b[0].time + (b[0].length * 60)) < Math.floor(Date.now() / 1000)){ + await db.query('delete from ch_bans where target='+db.raw.escape(b[0].target)+'and channel='+db.raw.escape(b[0].channel)+' and time='+db.raw.escape(b[0].time)+' and length='+db.raw.escape(b[0].length)); } else { socket.emit('ALERT', 'You are banned from that room'); @@ -682,23 +682,27 @@ async function initChat() { } else socket.emit('ALERT', 'Not authorized to do that.'); }); - socket.on('BAN', (data: Object) => { + socket.on('BAN', async (data: Object) => { if(socket.nick === data['room']){ let id: string = store.get(data['nick']); if(id){ if(Array.isArray(id)) { for(let i=0;i { + socket.on('UNBAN', async (data: Object) => { if(socket.nick === data['room']){ - if(banlist.get(data['room']) && banlist.get(data['room'])[data['ip']]){ - banlist.set(data['room'], Object.assign({}, banlist.get(data['room']), {[data['ip']]: null})); + let b = await db.query('select * from ch_bans where channel='+db.raw.escape(data['room'])+' and target='+db.raw.escape(data['ip'])); + if(b[0]){ + await db.query('delete from ch_bans where channel='+db.raw.escape(data['room'])+' and target='+db.raw.escape(data['ip'])); socket.emit('ALERT', data['ip']+' was unbanned.'); } else @@ -717,13 +722,13 @@ async function initChat() { } else socket.emit('ALERT', 'Not authorized to do that.'); }); - socket.on('LISTBAN', (data: Object) => { + socket.on('LISTBAN', async (data: Object) => { if(socket.nick === data['room']){ - if(banlist.get(data['room'])) { - let bans = Object.keys(banlist.get(data['room'])); + let b = await db.query('select target from ch_bans where channel='+db.raw.escape(data['room'])); + if(b[0]) { let str = ''; - for(let i=0;i