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