Updates
This commit is contained in:
@@ -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,
|
||||
},
|
||||
})),
|
||||
);
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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
@@ -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 };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user