From 6dfbe0f25e342e3d43b767aa03300d1957427639 Mon Sep 17 00:00:00 2001 From: HF Date: Sat, 17 Sep 2022 02:33:15 +0200 Subject: [PATCH] quick fix #2 --- src/core/ChatProvider.js | 29 +++++++++++++++++++++++------ src/core/passport.js | 16 ++++++++++------ src/data/redis/chat.js | 5 ++++- src/data/redis/client.js | 2 +- src/data/redis/lua/allowedChat.lua | 8 ++++++++ src/routes/api/auth/register.js | 3 +++ 6 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/core/ChatProvider.js b/src/core/ChatProvider.js index 230440f..cf18069 100644 --- a/src/core/ChatProvider.js +++ b/src/core/ChatProvider.js @@ -363,11 +363,19 @@ export class ChatProvider { } case 'autoban': { - this.autobanPhrase = args.join(' '); - if (this.autobanPhrase === 'unset') { - this.autobanPhrase = null; + if (args[0]) { + this.autobanPhrase = args.join(' '); + if (this.autobanPhrase === 'unset' || this.autobanPhrase.length < 5) { + this.autobanPhrase = null; + } + return `Set autoban phrase on shard to ${this.autobanPhrase}`; } - return `Set autoban phrase to ${this.autobanPhrase}`; + // eslint-disable-next-line + if (this.autobanPhrase) { + // eslint-disable-next-line + return `Current autoban phrase on shard is ${this.autobanPhrase}, use "/autoban unset" to remove it`; + } + return 'Autoban phrase is currently not set on this shard'; } default: @@ -399,8 +407,15 @@ export class ChatProvider { if (this.autobanPhrase && message.includes(this.autobanPhrase)) { const { ipSub } = user; - banIP(ipSub, 'CHATBAN', 0, 1); - logger.info(`CHAT AUTOBANNED: ${ipSub}`); + if (!user.banned) { + banIP(ipSub, 'CHATBAN', 0, 1); + mute(id); + logger.info(`CHAT AUTOBANNED: ${ipSub}`); + user.banned = true; + } + return 'nope'; + } + if (user.banned) { return 'nope'; } @@ -422,6 +437,8 @@ export class ChatProvider { } if (allowed === 101) { // eslint-disable-next-line max-len return t`You are permanently muted, join our guilded to apppeal the mute`; + } if (allowed === 102) { + return t`You must solve a captcha. Place a pixel to get one.`; } if (allowed === 2) { return t`You are banned`; } if (allowed === 3) { diff --git a/src/core/passport.js b/src/core/passport.js index 243fad6..1015987 100644 --- a/src/core/passport.js +++ b/src/core/passport.js @@ -12,7 +12,7 @@ import RedditStrategy from 'passport-reddit/lib/passport-reddit/strategy'; import VkontakteStrategy from 'passport-vkontakte/lib/strategy'; import { sanitizeName } from '../utils/validation'; - +import logger from './logger'; import { RegUser } from '../data/sql'; import User, { regUserQueryInclude as include } from '../data/User'; import { auth } from './config'; @@ -70,7 +70,7 @@ passport.use(new JsonStrategy({ * OAuth SignIns, mail based * */ -async function oauthLogin(email, name, discordid = null) { +async function oauthLogin(provider, email, name, discordid = null) { if (!email) { throw new Error('You don\'t have a mail set in your account.'); } @@ -94,6 +94,8 @@ async function oauthLogin(email, name, discordid = null) { where: { name }, }); } + // eslint-disable-next-line max-len + logger.info(`Create new user from ${provider} oauth login ${email} / ${name}`); reguser = await RegUser.create({ email, name, @@ -121,7 +123,7 @@ passport.use(new FacebookStrategy({ try { const { displayName: name, emails } = profile; const email = emails[0].value; - const user = await oauthLogin(email, name); + const user = await oauthLogin('facebook', email, name); done(null, user); } catch (err) { done(err); @@ -144,7 +146,7 @@ passport.use(new DiscordStrategy({ 'Sorry, you can not use discord login with an discord account that does not have email set.', ); } - const user = await oauthLogin(email, name, id); + const user = await oauthLogin('discord', email, name, id); done(null, user); } catch (err) { done(err); @@ -162,7 +164,7 @@ passport.use(new GoogleStrategy({ try { const { displayName: name, emails } = profile; const email = emails[0].value; - const user = await oauthLogin(email, name); + const user = await oauthLogin('google', email, name); done(null, user); } catch (err) { done(err); @@ -201,6 +203,8 @@ passport.use(new RedditStrategy({ where: { name }, }); } + // eslint-disable-next-line max-len + logger.info(`Create new user from reddit oauth login ${name} / ${redditid}`); reguser = await RegUser.create({ name, verified: 1, @@ -234,7 +238,7 @@ passport.use(new VkontakteStrategy({ 'Sorry, you can not use vk login with an account that does not have a verified email set.', ); } - const user = await oauthLogin(email, name); + const user = await oauthLogin('vkontakte', email, name); done(null, user); } catch (err) { done(err); diff --git a/src/data/redis/chat.js b/src/data/redis/chat.js index 92d088c..f143fad 100644 --- a/src/data/redis/chat.js +++ b/src/data/redis/chat.js @@ -3,6 +3,8 @@ */ import client from './client'; import { PREFIX as ALLOWED_PREFIX } from './isAllowedCache'; +import { PREFIX as CAPTCHA_PREFIX } from './captcha'; +import { CAPTCHA_TIME } from '../../core/config'; const MUTE_PREFIX = 'MUTE_PREFIX'; const MUTEC_PREFIX = 'MUTE_PREFIXc'; @@ -22,8 +24,9 @@ export async function allowedChat( const mutecKey = `${MUTEC_PREFIX}:${channelId}`; const muteKey = `${MUTE_PREFIX}:${userId}`; const isalKey = `${ALLOWED_PREFIX}:${ip}`; + const captKey = (CAPTCHA_TIME >= 0) ? `${CAPTCHA_PREFIX}:${ip}` : 'nope'; return client.allowedChat( - mutecKey, muteKey, isalKey, + mutecKey, muteKey, isalKey, captKey, cc, ); } diff --git a/src/data/redis/client.js b/src/data/redis/client.js index ae65d30..fdf3068 100644 --- a/src/data/redis/client.js +++ b/src/data/redis/client.js @@ -18,7 +18,7 @@ const scripts = { transformReply(arr) { return arr.map((r) => Number(r)); }, }), allowedChat: defineScript({ - NUMBER_OF_KEYS: 3, + NUMBER_OF_KEYS: 4, SCRIPT: fs.readFileSync('./workers/lua/allowedChat.lua'), transformArguments(...args) { return args.map((a) => ((typeof a === 'string') ? a : a.toString())); diff --git a/src/data/redis/lua/allowedChat.lua b/src/data/redis/lua/allowedChat.lua index d437084..f0e1067 100644 --- a/src/data/redis/lua/allowedChat.lua +++ b/src/data/redis/lua/allowedChat.lua @@ -3,6 +3,7 @@ -- mutecKey: 'mutec:cid' hash of channel for country mutes -- muteKey: 'mute:uid' key for user mute -- isalKey: 'isal:ip' (proxycheck, blacklist, whitelist) +-- ishuman: 'human:ip' if captcha needed -- Args: -- cc: two letter country code of user -- Returns: @@ -10,6 +11,7 @@ -- 1: return status code -- 100: country muted -- 101: user permanently muted +-- 102: got captcha -- >0: isAllowed status code (see core/isAllowed) -- 0: success -- <0: time left for mute in seconds * -1 @@ -27,6 +29,12 @@ if ttl == -1 then ret[1] = 101 return ret end +-- check if captcha is needed +if KEYS[4] ~= "nope" and not redis.call('get', KEYS[4]) then + -- captcha + ret[1] = 102 + return ret +end if ttl > 0 then ret[1] = -ttl return ret diff --git a/src/routes/api/auth/register.js b/src/routes/api/auth/register.js index da88ea8..926e662 100644 --- a/src/routes/api/auth/register.js +++ b/src/routes/api/auth/register.js @@ -18,6 +18,9 @@ async function validate(email, name, password, captcha, captchaid, t, gettext) { const errors = []; const emailerror = gettext(validateEMail(email)); if (emailerror) errors.push(emailerror); + if (email.includes('emergentvillage.org') || email.includes('vintomaper')) { + errors.push(t`This email provider is not allowed`); + } const nameerror = validateName(name); if (nameerror) errors.push(nameerror); const passworderror = gettext(validatePassword(password));