diff --git a/locales/de/auth.json b/locales/de/auth.json index c60fc00d..e920c3b4 100644 --- a/locales/de/auth.json +++ b/locales/de/auth.json @@ -1,15 +1,15 @@ { - "login": { - "INVALID_LOGIN": "Ungültige E-Mail oder Telefonnummer", - "INVALID_PASSWORD": "Ungültiges Passwort" - }, - "register": { - "REGISTRATION_DISABLED": "Neue Nutzer können sich nicht mehr registrieren", - "INVITE_ONLY": "Du musst eingeladen werden, um dich zu registrieren", - "EMAIL_INVALID": "Ungültige E-Mail Adresse", - "EMAIL_ALREADY_REGISTERED": "Es existiert bereits ein Account mit dieser E-Mail Adresse", - "DATE_OF_BIRTH_UNDERAGE": "Du musst mindestens {{years}} Jahre alt sein", - "CONSENT_REQUIRED": "Du musst den AGB's und Datenschutzbestimmungen zustimmen", - "USERNAME_TOO_MANY_USERS": "Es haben bereits zu viele Nutzer den gleichen Nutzernamen" - } -} \ No newline at end of file + "login": { + "INVALID_LOGIN": "E-Mail oder Telefonnummer nicht gefunden", + "INVALID_PASSWORD": "Ungültiges Passwort" + }, + "register": { + "REGISTRATION_DISABLED": "Neue Nutzer können sich nicht mehr registrieren", + "INVITE_ONLY": "Du musst eingeladen werden, um dich zu registrieren", + "EMAIL_INVALID": "Ungültige E-Mail Adresse", + "EMAIL_ALREADY_REGISTERED": "Es existiert bereits ein Account mit dieser E-Mail Adresse", + "DATE_OF_BIRTH_UNDERAGE": "Du musst mindestens {{years}} Jahre alt sein", + "CONSENT_REQUIRED": "Du musst den AGB's und Datenschutzbestimmungen zustimmen", + "USERNAME_TOO_MANY_USERS": "Es haben bereits zu viele Nutzer den gleichen Nutzernamen" + } +} diff --git a/locales/en/auth.json b/locales/en/auth.json index 88c2c003..025a3876 100644 --- a/locales/en/auth.json +++ b/locales/en/auth.json @@ -1,15 +1,15 @@ { - "login": { - "INVALID_LOGIN": "Invalid E-Mail or Phone", - "INVALID_PASSWORD": "Invalid Password" - }, - "register": { - "REGISTRATION_DISABLED": "New user registration is disabled", - "INVITE_ONLY": "You must be invited to register", - "EMAIL_INVALID": "Invalid Email", - "EMAIL_ALREADY_REGISTERED": "Email is already registered", - "DATE_OF_BIRTH_UNDERAGE": "You need to be {{years}} years or older", - "CONSENT_REQUIRED": "You must agree to Terms of Service and Privacy Policy.", - "USERNAME_TOO_MANY_USERS": "Too many users have this username, please try another" - } -} \ No newline at end of file + "login": { + "INVALID_LOGIN": "E-Mail or Phone not found", + "INVALID_PASSWORD": "Invalid Password" + }, + "register": { + "REGISTRATION_DISABLED": "New user registration is disabled", + "INVITE_ONLY": "You must be invited to register", + "EMAIL_INVALID": "Invalid Email", + "EMAIL_ALREADY_REGISTERED": "Email is already registered", + "DATE_OF_BIRTH_UNDERAGE": "You need to be {{years}} years or older", + "CONSENT_REQUIRED": "You must agree to Terms of Service and Privacy Policy.", + "USERNAME_TOO_MANY_USERS": "Too many users have this username, please try another" + } +} diff --git a/src/Server.ts b/src/Server.ts index c7f36233..f17d4c9d 100644 --- a/src/Server.ts +++ b/src/Server.ts @@ -2,7 +2,7 @@ import "missing-native-js-functions"; import fs from "fs/promises"; import { Connection } from "mongoose"; import { Server, ServerOptions } from "lambert-server"; -import { Authentication, GlobalRateLimit } from "./middlewares/"; +import { Authentication, CORS, GlobalRateLimit } from "./middlewares/"; import Config from "./util/Config"; import { db } from "@fosscord/server-util"; import i18next from "i18next"; @@ -15,10 +15,9 @@ import fetch from "node-fetch"; import mongoose from "mongoose"; // this will return the new updated document for findOneAndUpdate -mongoose.set('returnOriginal', false); // https://mongoosejs.com/docs/api/model.html#model_Model.findOneAndUpdate +mongoose.set("returnOriginal", false); // https://mongoosejs.com/docs/api/model.html#model_Model.findOneAndUpdate - -export interface FosscordServerOptions extends ServerOptions { } +export interface FosscordServerOptions extends ServerOptions {} declare global { namespace Express { @@ -56,6 +55,7 @@ export class FosscordServer extends Server { this.app.use(GlobalRateLimit); this.app.use(Authentication); + this.app.use(CORS); this.app.use(BodyParser({ inflate: true })); const languages = await fs.readdir(__dirname + "/../locales/"); const namespaces = await fs.readdir(__dirname + "/../locales/en/"); diff --git a/src/index.ts b/src/index.ts index c6417126..554c296f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,6 @@ export * from "./schema/Channel"; export * from "./schema/Guild"; export * from "./schema/Invite"; export * from "./schema/Message"; -export * from "./util/Captcha"; export * from "./util/Config"; export * from "./util/Constants"; export * from "./util/Event"; diff --git a/src/middlewares/CORS.ts b/src/middlewares/CORS.ts index 336051bd..b47de251 100644 --- a/src/middlewares/CORS.ts +++ b/src/middlewares/CORS.ts @@ -4,4 +4,11 @@ import { NextFunction, Request, Response } from "express"; export function CORS(req: Request, res: Response, next: NextFunction) { res.set("Access-Control-Allow-Origin", "*"); + res.set( + "Content-security-policy", + "script-src 'https://hcaptcha.com, https://*.hcaptcha.com' frame-src 'https://hcaptcha.com, https://*.hcaptcha.com' style-src 'https://hcaptcha.com, https://*.hcaptcha.com' connect-src 'https://hcaptcha.com, https://*.hcaptcha.com'" + ); + res.set("Access-Control-Allow-Headers", req.header("Access-Control-Request-Headers")); + + next(); } diff --git a/src/routes/auth/login.ts b/src/routes/auth/login.ts index 5c43db1b..a0fc1190 100644 --- a/src/routes/auth/login.ts +++ b/src/routes/auth/login.ts @@ -20,11 +20,26 @@ router.post( $gift_code_sku_id: String, }), async (req: Request, res: Response) => { - const { login, password } = req.body; + const { login, password, captcha_key } = req.body; const email = adjustEmail(login); const query: any[] = [{ phone: login }]; if (email) query.push({ email }); + const config = Config.get(); + + if (config.login.requireCaptcha && config.security.captcha.enabled) { + if (!captcha_key) { + const { sitekey, service } = config.security.captcha; + return res.status(400).json({ + captcha_key: ["captcha-required"], + captcha_sitekey: sitekey, + captcha_service: service, + }); + } + + // TODO: check captcha + } + const user = await UserModel.findOne({ $or: query }, `user_data.hash id user_settings.locale user_settings.theme`).exec(); if (!user) { diff --git a/src/util/Captcha.ts b/src/util/Captcha.ts deleted file mode 100644 index cb0ff5c3..00000000 --- a/src/util/Captcha.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/src/util/Config.ts b/src/util/Config.ts index e500197f..f1f0f458 100644 --- a/src/util/Config.ts +++ b/src/util/Config.ts @@ -1,6 +1,5 @@ import { Config, Snowflake } from "@fosscord/server-util"; import crypto from "crypto"; -import fs from "fs"; export default { init() { @@ -75,10 +74,14 @@ export interface DefaultOptions { forwadedFor: string | null; captcha: { enabled: boolean; - service: "recaptcha" | null; // TODO: hcaptcha, custom + service: "recaptcha" | "hcaptcha" | null; // TODO: hcaptcha, custom sitekey: string | null; + secret: string | null; }; }; + login: { + requireCaptcha: boolean; + }; register: { email: { required: boolean; @@ -155,8 +158,12 @@ export const DefaultOptions: DefaultOptions = { enabled: false, service: null, sitekey: null, + secret: null, }, }, + login: { + requireCaptcha: false, + }, register: { email: { required: true,