summary refs log tree commit diff
path: root/src/api/util/utility
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/util/utility')
-rw-r--r--src/api/util/utility/RandomInviteID.ts7
-rw-r--r--src/api/util/utility/String.ts2
-rw-r--r--src/api/util/utility/captcha.ts46
-rw-r--r--src/api/util/utility/ipAddress.ts6
-rw-r--r--src/api/util/utility/passwordStrength.ts10
5 files changed, 60 insertions, 11 deletions
diff --git a/src/api/util/utility/RandomInviteID.ts b/src/api/util/utility/RandomInviteID.ts
index 7ea344e0..feebfd3d 100644
--- a/src/api/util/utility/RandomInviteID.ts
+++ b/src/api/util/utility/RandomInviteID.ts
@@ -22,11 +22,10 @@ export function snowflakeBasedInvite() {
 	// snowflakes hold ~10.75 characters worth of entropy;
 	// safe to generate a 8-char invite out of them
 	let str = "";
-	for (let i=0; i < 10; i++) {
-		
+	for (let i = 0; i < 10; i++) {
 		str.concat(chars.charAt(Number(snowflake % base)));
 		snowflake = snowflake / base;
 	}
-	
-	return str.substr(3,8).split("").reverse().join("");
+
+	return str.substr(3, 8).split("").reverse().join("");
 }
diff --git a/src/api/util/utility/String.ts b/src/api/util/utility/String.ts
index 982b7e11..a2e491e4 100644
--- a/src/api/util/utility/String.ts
+++ b/src/api/util/utility/String.ts
@@ -1,6 +1,6 @@
+import { FieldErrors } from "@fosscord/util";
 import { Request } from "express";
 import { ntob } from "./Base64";
-import { FieldErrors } from "@fosscord/util";
 
 export function checkLength(str: string, min: number, max: number, key: string, req: Request) {
 	if (str.length < min || str.length > max) {
diff --git a/src/api/util/utility/captcha.ts b/src/api/util/utility/captcha.ts
new file mode 100644
index 00000000..739647d2
--- /dev/null
+++ b/src/api/util/utility/captcha.ts
@@ -0,0 +1,46 @@
+import { Config } from "@fosscord/util";
+import fetch from "node-fetch";
+
+export interface hcaptchaResponse {
+	success: boolean;
+	challenge_ts: string;
+	hostname: string;
+	credit: boolean;
+	"error-codes": string[];
+	score: number;	// enterprise only
+	score_reason: string[];	// enterprise only
+}
+
+export interface recaptchaResponse {
+	success: boolean;
+	score: number; // between 0 - 1
+	action: string;
+	challenge_ts: string;
+	hostname: string;
+	"error-codes"?: string[];
+}
+
+const verifyEndpoints = {
+	hcaptcha: "https://hcaptcha.com/siteverify",
+	recaptcha: "https://www.google.com/recaptcha/api/siteverify",
+}
+
+export async function verifyCaptcha(response: string, ip?: string) {
+	const { security } = Config.get();
+	const { service, secret, sitekey } = security.captcha;
+
+	if (!service) throw new Error("Cannot verify captcha without service");
+
+	const res = await fetch(verifyEndpoints[service], {
+		method: "POST",
+		headers: {
+			"Content-Type": "application/x-www-form-urlencoded",
+		},
+		body: `response=${encodeURIComponent(response)}`
+			+ `&secret=${encodeURIComponent(secret!)}`
+			+ `&sitekey=${encodeURIComponent(sitekey!)}`
+			+ (ip ? `&remoteip=${encodeURIComponent(ip!)}` : ""),
+	});
+
+	return await res.json() as hcaptchaResponse | recaptchaResponse;
+}
\ No newline at end of file
diff --git a/src/api/util/utility/ipAddress.ts b/src/api/util/utility/ipAddress.ts
index 8d986b26..c96feb9e 100644
--- a/src/api/util/utility/ipAddress.ts
+++ b/src/api/util/utility/ipAddress.ts
@@ -78,7 +78,11 @@ export function isProxy(data: typeof exampleData) {
 
 export function getIpAdress(req: Request): string {
 	// @ts-ignore
-	return req.headers[Config.get().security.forwadedFor] || req.socket.remoteAddress;
+	return (
+		req.headers[Config.get().security.forwadedFor as string] ||
+		req.headers[Config.get().security.forwadedFor?.toLowerCase() as string] ||
+		req.socket.remoteAddress
+	);
 }
 
 export function distanceBetweenLocations(loc1: any, loc2: any): number {
diff --git a/src/api/util/utility/passwordStrength.ts b/src/api/util/utility/passwordStrength.ts
index 8eca63b8..ff83d3df 100644
--- a/src/api/util/utility/passwordStrength.ts
+++ b/src/api/util/utility/passwordStrength.ts
@@ -44,16 +44,16 @@ export function checkPassword(password: string): number {
 	if (password.length == password.count(reNUMBER) || password.length === password.count(reUPPERCASELETTER)) {
 		strength = 0;
 	}
-	
+
 	let entropyMap: { [key: string]: number } = {};
 	for (let i = 0; i < password.length; i++) {
 		if (entropyMap[password[i]]) entropyMap[password[i]]++;
 		else entropyMap[password[i]] = 1;
 	}
-	
+
 	let entropies = Object.values(entropyMap);
-	
-	entropies.map(x => (x / entropyMap.length));
-	strength += entropies.reduceRight((a: number, x: number) => a - (x * Math.log2(x))) / Math.log2(password.length);	
+
+	entropies.map((x) => x / entropyMap.length);
+	strength += entropies.reduceRight((a: number, x: number) => a - x * Math.log2(x)) / Math.log2(password.length);
 	return strength;
 }