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,
|