This commit is contained in:
2026-03-09 06:16:36 +01:00
parent ef54906d9a
commit 40dacc0b62
52 changed files with 1922 additions and 143 deletions
+93
View File
@@ -0,0 +1,93 @@
import { CookieOptions } from "@moduletrace/datasquirel/dist/package-shared/types";
import dayjs, { type Dayjs } from "dayjs";
import * as http from "http";
import { NextApiResponse } from "next";
type FinalCookieOpts = Omit<CookieOptions, "expires"> & { expires?: Dayjs };
type Cookie = { name: string; value: string; options: FinalCookieOpts };
export function setCookie(
res: http.ServerResponse | NextApiResponse,
cookies: Cookie[],
): void {
const AllCookieParts: string[][] = [];
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i];
const { name, options, value } = cookie;
const cookieParts: string[] = [
`${encodeURIComponent(name)}=${encodeURIComponent(value)}`,
];
if (options.expires) {
cookieParts.push(
`Expires=${options.expires.toDate().toUTCString()}`,
);
}
if (options.maxAge !== undefined) {
cookieParts.push(`Max-Age=${options.maxAge}`);
}
if (options.path) {
cookieParts.push(`Path=${options.path}`);
}
if (options.domain) {
cookieParts.push(`Domain=${options.domain}`);
}
if (options.secure) {
cookieParts.push("Secure");
}
if (options.httpOnly) {
cookieParts.push("HttpOnly");
}
AllCookieParts.push(cookieParts);
}
const final_cookie_string = AllCookieParts.map((ck) => ck.join("; "));
res.setHeader("Set-Cookie", final_cookie_string);
}
export function getCookie(
req: http.IncomingMessage,
name: string,
): string | null {
const cookieHeader = req.headers.cookie;
if (!cookieHeader) return null;
const cookies = cookieHeader
.split(";")
.reduce((acc: { [key: string]: string }, cookie: string) => {
const [key, val] = cookie.trim().split("=").map(decodeURIComponent);
acc[key] = val;
return acc;
}, {});
return cookies[name] || null;
}
export function updateCookie(
res: http.ServerResponse,
cookies: Cookie[],
): void {
setCookie(res, cookies);
}
export function deleteCookie(
res: http.ServerResponse,
cookies: Cookie[],
): void {
setCookie(
res,
cookies.map((ck) => ({
...ck,
value: "",
options: {
...ck.options,
expires: dayjs().subtract(1, "day"),
maxAge: 0,
},
})),
);
}
+140
View File
@@ -0,0 +1,140 @@
import { NextApiResponse } from "next";
import { ServerResponse } from "http";
import NSQLite from "@moduletrace/nsqlite";
import { NSQLITE_TEST_DB_USERS, NSQLiteTables } from "../db/types";
import { User } from "../types";
import { AppData } from "../data/app-data";
import { setCookie } from "./cookies-actions";
import { EJSON } from "../exports/client-exports";
import encrypt from "@moduletrace/datasquirel/dist/package-shared/functions/dsql/encrypt";
import { APIResponseObject } from "@moduletrace/datasquirel/dist/package-shared/types";
import hashPassword from "@moduletrace/datasquirel/dist/package-shared/functions/dsql/hashPassword";
import dayjs from "dayjs";
type Params = {
res: NextApiResponse | ServerResponse;
user_id?: string | number;
password?: string;
email_or_username?: string;
};
export default async function loginUser({
res,
user_id,
password,
email_or_username,
}: Params): Promise<APIResponseObject> {
let fetched_user: NSQLITE_TEST_DB_USERS | undefined;
if (user_id) {
const user_res = await NSQLite.select<
NSQLITE_TEST_DB_USERS,
(typeof NSQLiteTables)[number]
>({
table: "users",
targetId: user_id,
});
if (!user_res.singleRes?.id) {
throw new Error(`Couldn't Find user for login`);
}
fetched_user = user_res.singleRes;
}
if (email_or_username) {
const user_res = await NSQLite.select<
NSQLITE_TEST_DB_USERS,
(typeof NSQLiteTables)[number]
>({
table: "users",
query: {
query: {
email: {
value: email_or_username,
},
username: {
value: email_or_username,
},
},
searchOperator: "OR",
},
});
if (!user_res.singleRes?.id) {
throw new Error(`Couldn't Find user for login`);
}
fetched_user = user_res.singleRes;
}
if (!fetched_user) {
return {
success: false,
msg: `User Not Found!`,
};
}
if (password) {
const hashed_password = hashPassword({ password });
if (hashed_password !== fetched_user.password) {
return {
success: false,
msg: `Invalid Password.`,
};
}
}
const now = Date.now();
const csrf_k =
Math.random().toString(36).substring(2) +
"-" +
Math.random().toString(36).substring(2);
const logged_in_user_payload: User = {
first_name: fetched_user.first_name!,
last_name: fetched_user.last_name!,
date: now,
email: fetched_user.email!,
csrf_k,
id: fetched_user.id!,
logged_in_status: true,
image: fetched_user.image,
image_thumbnail: fetched_user.image,
};
const payload_string = EJSON.stringify(logged_in_user_payload);
const encrypted_payload = encrypt({ data: payload_string || "" });
const expiration_date = dayjs(Date.now()).add(7, "days");
expiration_date.add(7, "days");
setCookie(res, [
{
name: AppData["AuthCookieName"],
value: encrypted_payload || "",
options: {
secure: process.env.DOMAIN !== "localhost",
path: "/",
expires: expiration_date,
domain: process.env.DOMAIN,
},
},
{
name: AppData["AuthCSRFCookieName"],
value: csrf_k,
options: {
path: "/",
expires: expiration_date,
domain: process.env.DOMAIN,
},
},
]);
return {
success: true,
singleRes: logged_in_user_payload,
};
}
+21
View File
@@ -0,0 +1,21 @@
export default function parsePageUrl(url?: string, admin?: boolean) {
if (!url) return null;
let finalAdminUrlArray = url?.match(/_next/)
? null
: url
?.split("?")[0]
.split("#")[0]
.split("/")
.filter((item) => item !== "");
if (admin) {
finalAdminUrlArray?.splice(1, 1);
}
const finalAdminUrl = finalAdminUrlArray
? "/" + finalAdminUrlArray?.join("/") || ""
: null;
return finalAdminUrl;
}
+56 -6
View File
@@ -1,12 +1,62 @@
import datasquirel from "@moduletrace/datasquirel";
import { NextApiRequest } from "next";
import { User } from "../types";
import { IncomingMessage } from "http";
import { AppData } from "../data/app-data";
import { getCookie } from "./cookies-actions";
import { APIResponseObject } from "@moduletrace/datasquirel/dist/package-shared/types";
import decrypt from "@moduletrace/datasquirel/dist/package-shared/functions/dsql/decrypt";
import { EJSON } from "../exports/client-exports";
type Params = {
req: NextApiRequest;
req:
| NextApiRequest
| (IncomingMessage & { cookies: Partial<{ [key: string]: string }> });
};
export default async function userAuth({ req }: Params) {
const auth = datasquirel.user.auth.auth({ req });
const user = auth.payload;
return { user };
export default async function userAuth({
req,
}: Params): Promise<APIResponseObject<User>> {
try {
const key = getCookie(req, AppData["AuthCookieName"]);
if (!key) {
return {
success: false,
msg: `No ${AppData["AuthCookieName"]} found in request object.`,
};
}
const decrypted_key = decrypt({ encryptedString: key });
const decrypted_object = EJSON.parse(decrypted_key) as User | undefined;
if (!decrypted_object?.id) {
return {
success: false,
msg: `Invalid Auth Key`,
};
}
const csrf = getCookie(req, AppData["AuthCSRFCookieName"]);
if (!csrf) {
return {
success: false,
msg: `No ${AppData["AuthCSRFCookieName"]} found in request object.`,
};
}
if (csrf !== decrypted_object.csrf_k) {
return {
success: false,
msg: `CSRF mismatch`,
};
}
return {
success: true,
singleRes: decrypted_object,
};
} catch (error) {
return { success: false };
}
}