🔒 (security) security improvement
This commit is contained in:
@ -1,17 +1,17 @@
|
||||
import React from "react";
|
||||
|
||||
const SecurityCheckup = () => {
|
||||
return (
|
||||
<div className="flex justify-center">
|
||||
<div className="max-w-[60vh]">
|
||||
<h1 className="mt-[20vh] text-2xl text-center">Please wait...</h1>
|
||||
<p className="mt-4 text-sm text-center text-neutral-400">
|
||||
We want to ensure a secure authentication environment before
|
||||
proceeding for your safety.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SecurityCheckup;
|
||||
import React from "react";
|
||||
|
||||
const SecurityCheckup = () => {
|
||||
return (
|
||||
<div className="flex justify-center">
|
||||
<div className="max-w-[60vh]">
|
||||
<h1 className="mt-[20vh] text-2xl text-center">Please wait...</h1>
|
||||
<p className="mt-4 text-sm text-center text-neutral-400">
|
||||
We want to ensure a secure authentication environment before
|
||||
proceeding for your safety.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SecurityCheckup;
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
import React from "react";
|
||||
|
||||
const SecurityCheckupFailed = () => {
|
||||
return (
|
||||
<div className="flex justify-center">
|
||||
<div className="max-w-[60vh]">
|
||||
<h1 className="mt-[20vh] text-2xl text-center text-red-400">
|
||||
Your browser is not secure
|
||||
</h1>
|
||||
<p className="mt-4 text-sm text-center text-neutral-400">
|
||||
Sorry, we had to stop the authentication process and return you to the
|
||||
home page because your browser environment is not secure.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SecurityCheckupFailed;
|
||||
import React from "react";
|
||||
|
||||
const SecurityCheckupFailed = () => {
|
||||
return (
|
||||
<div className="flex justify-center">
|
||||
<div className="max-w-[60vh]">
|
||||
<h1 className="mt-[20vh] text-2xl text-center text-red-400">
|
||||
Your browser is not secure
|
||||
</h1>
|
||||
<p className="mt-4 text-sm text-center text-neutral-400">
|
||||
Sorry, we had to stop the authentication process and return you to the
|
||||
home page because your browser environment is not secure.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SecurityCheckupFailed;
|
||||
|
||||
@ -1,29 +1,29 @@
|
||||
type BuildMeta = {
|
||||
title?: string;
|
||||
description?: string;
|
||||
image?: string;
|
||||
};
|
||||
|
||||
const appName = process.env.APP_NAME;
|
||||
export const defaultMeta = {
|
||||
title: appName || "Unknown App",
|
||||
description: "Interactive community",
|
||||
};
|
||||
|
||||
export const buildMeta = ({ title, description, image }: BuildMeta) => {
|
||||
return {
|
||||
title: title ? `${title} - ${appName}` : defaultMeta.title,
|
||||
description: description || defaultMeta.description,
|
||||
openGraph: {
|
||||
title,
|
||||
description,
|
||||
images: image ? [image] : ["/default-og.png"],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title,
|
||||
description,
|
||||
images: image ? [image] : ["/default-og.png"],
|
||||
},
|
||||
};
|
||||
};
|
||||
type BuildMeta = {
|
||||
title?: string;
|
||||
description?: string;
|
||||
image?: string;
|
||||
};
|
||||
|
||||
const appName = process.env.APP_NAME;
|
||||
export const defaultMeta = {
|
||||
title: appName || "Unknown App",
|
||||
description: "Interactive community",
|
||||
};
|
||||
|
||||
export const buildMeta = ({ title, description, image }: BuildMeta) => {
|
||||
return {
|
||||
title: title ? `${title} - ${appName}` : defaultMeta.title,
|
||||
description: description || defaultMeta.description,
|
||||
openGraph: {
|
||||
title,
|
||||
description,
|
||||
images: image ? [image] : ["/default-og.png"],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title,
|
||||
description,
|
||||
images: image ? [image] : ["/default-og.png"],
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
export const routes = {
|
||||
home: "/",
|
||||
login: "/login",
|
||||
signup: "/signup",
|
||||
explore: "/explore",
|
||||
trending: "/trending",
|
||||
genres: "/genres",
|
||||
schedule: "/schedule",
|
||||
};
|
||||
export const routes = {
|
||||
home: "/",
|
||||
login: "/login",
|
||||
signup: "/signup",
|
||||
explore: "/explore",
|
||||
trending: "/trending",
|
||||
genres: "/genres",
|
||||
schedule: "/schedule",
|
||||
};
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
export const API_BASE_URL =
|
||||
process.env.MAIN_BACKEND_API_URL ?? "http://localhost";
|
||||
|
||||
const apiFetch = async <T = unknown>(
|
||||
path: string,
|
||||
init?: RequestInit
|
||||
): Promise<T> => {
|
||||
const res = await fetch(`${API_BASE_URL}${path}`, {
|
||||
...init,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...init?.headers,
|
||||
},
|
||||
cache: "no-store",
|
||||
});
|
||||
|
||||
if (!res.ok) throw new Error(await res.text());
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export default apiFetch;
|
||||
export const API_BASE_URL =
|
||||
process.env.MAIN_BACKEND_API_URL ?? "http://localhost";
|
||||
|
||||
const apiFetch = async <T = unknown>(
|
||||
path: string,
|
||||
init?: RequestInit
|
||||
): Promise<T> => {
|
||||
const res = await fetch(`${API_BASE_URL}${path}`, {
|
||||
...init,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...init?.headers,
|
||||
},
|
||||
cache: "no-store",
|
||||
});
|
||||
|
||||
if (!res.ok) throw new Error(await res.text());
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export default apiFetch;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
export const delayButtonClick = (
|
||||
router: ReturnType<typeof useRouter>,
|
||||
href: string,
|
||||
timeout: number = 300
|
||||
) => {
|
||||
setTimeout(() => {
|
||||
router.push(href);
|
||||
}, timeout);
|
||||
};
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
export const delayButtonClick = (
|
||||
router: ReturnType<typeof useRouter>,
|
||||
href: string,
|
||||
timeout: number = 300
|
||||
) => {
|
||||
setTimeout(() => {
|
||||
router.push(href);
|
||||
}, timeout);
|
||||
};
|
||||
|
||||
@ -1,58 +1,58 @@
|
||||
"use client";
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
/**
|
||||
* @function useRunOnce
|
||||
* @description A custom React hook that ensures a function is executed only once
|
||||
* across the entire application, even in React Strict Mode or during
|
||||
* development hot reloads. Maintains a global registry to track
|
||||
* execution status using a unique key.
|
||||
*
|
||||
* Particularly useful for one-time initialization logic, analytics
|
||||
* tracking, or any operation that should not be duplicated.
|
||||
*
|
||||
* @param {string} key - A unique identifier for the process. Used to track execution
|
||||
* across component instances and prevent naming collisions.
|
||||
* Should be descriptive and unique (e.g., "user_analytics_init").
|
||||
* @param {function} fn - The function to be executed once. Should contain the logic
|
||||
* that needs to run only a single time.
|
||||
*
|
||||
* @returns {void}
|
||||
*
|
||||
* @throws {Error} If the provided key is not a string or is empty.
|
||||
* @throws {Error} If the provided function is not callable.
|
||||
*
|
||||
* @example
|
||||
* // One-time asynchronous operation
|
||||
* useRunOnce("async_operation", async () => {
|
||||
* await yourAsyncFunction();
|
||||
* });
|
||||
*
|
||||
* @example
|
||||
* // One-time synchronous operation
|
||||
* useRunOnce("sync_operation", () => {
|
||||
* yourFunction();
|
||||
* });
|
||||
*
|
||||
* @remarks
|
||||
* - The hook uses a global registry, so the same key across different components
|
||||
* will prevent duplicate execution.
|
||||
* - Safe to use in React Strict Mode and development environment with hot reload.
|
||||
* - The function will not execute if another instance with the same key has
|
||||
* already run in the application.
|
||||
*/
|
||||
const registry = new Set<string>();
|
||||
|
||||
export function useRunOnce(key: string, fn: () => void) {
|
||||
const hasRun = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (hasRun.current) return;
|
||||
hasRun.current = true;
|
||||
|
||||
if (registry.has(key)) return;
|
||||
registry.add(key);
|
||||
|
||||
fn();
|
||||
}, [key, fn]);
|
||||
}
|
||||
"use client";
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
/**
|
||||
* @function useRunOnce
|
||||
* @description A custom React hook that ensures a function is executed only once
|
||||
* across the entire application, even in React Strict Mode or during
|
||||
* development hot reloads. Maintains a global registry to track
|
||||
* execution status using a unique key.
|
||||
*
|
||||
* Particularly useful for one-time initialization logic, analytics
|
||||
* tracking, or any operation that should not be duplicated.
|
||||
*
|
||||
* @param {string} key - A unique identifier for the process. Used to track execution
|
||||
* across component instances and prevent naming collisions.
|
||||
* Should be descriptive and unique (e.g., "user_analytics_init").
|
||||
* @param {function} fn - The function to be executed once. Should contain the logic
|
||||
* that needs to run only a single time.
|
||||
*
|
||||
* @returns {void}
|
||||
*
|
||||
* @throws {Error} If the provided key is not a string or is empty.
|
||||
* @throws {Error} If the provided function is not callable.
|
||||
*
|
||||
* @example
|
||||
* // One-time asynchronous operation
|
||||
* useRunOnce("async_operation", async () => {
|
||||
* await yourAsyncFunction();
|
||||
* });
|
||||
*
|
||||
* @example
|
||||
* // One-time synchronous operation
|
||||
* useRunOnce("sync_operation", () => {
|
||||
* yourFunction();
|
||||
* });
|
||||
*
|
||||
* @remarks
|
||||
* - The hook uses a global registry, so the same key across different components
|
||||
* will prevent duplicate execution.
|
||||
* - Safe to use in React Strict Mode and development environment with hot reload.
|
||||
* - The function will not execute if another instance with the same key has
|
||||
* already run in the application.
|
||||
*/
|
||||
const registry = new Set<string>();
|
||||
|
||||
export function useRunOnce(key: string, fn: () => void) {
|
||||
const hasRun = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (hasRun.current) return;
|
||||
hasRun.current = true;
|
||||
|
||||
if (registry.has(key)) return;
|
||||
registry.add(key);
|
||||
|
||||
fn();
|
||||
}, [key, fn]);
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
"use server";
|
||||
|
||||
import ky from "ky";
|
||||
|
||||
export const api = ky.create({
|
||||
prefixUrl: process.env.MAIN_BACKEND_API_URL,
|
||||
credentials: "include",
|
||||
headers: {
|
||||
access_token: process.env.MAIN_BACKEND_API_KEY,
|
||||
},
|
||||
retry: 0,
|
||||
});
|
||||
"use server";
|
||||
|
||||
import ky from "ky";
|
||||
|
||||
export const api = ky.create({
|
||||
prefixUrl: process.env.MAIN_BACKEND_API_URL,
|
||||
credentials: "include",
|
||||
headers: {
|
||||
access_token: process.env.MAIN_BACKEND_API_KEY,
|
||||
},
|
||||
retry: 0,
|
||||
});
|
||||
|
||||
@ -1,34 +1,34 @@
|
||||
"use server";
|
||||
|
||||
import { HTTPError } from "ky";
|
||||
|
||||
export type CallApiErrorHandler = {
|
||||
success?: boolean;
|
||||
status?: number;
|
||||
text?: { message?: string };
|
||||
};
|
||||
|
||||
export const apiErrorHandler = async (
|
||||
error: unknown,
|
||||
safeFail?: CallApiErrorHandler
|
||||
) => {
|
||||
if (error instanceof HTTPError) {
|
||||
return {
|
||||
success: false,
|
||||
status: error.response.status,
|
||||
text: await error.response.json(),
|
||||
};
|
||||
}
|
||||
|
||||
if (safeFail) {
|
||||
return {
|
||||
success: safeFail.success || false,
|
||||
status: safeFail.status || 500,
|
||||
text: {
|
||||
message: safeFail.text?.message || "An unexpected error occurred",
|
||||
},
|
||||
};
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
"use server";
|
||||
|
||||
import { HTTPError } from "ky";
|
||||
|
||||
export type CallApiErrorHandler = {
|
||||
success?: boolean;
|
||||
status?: number;
|
||||
text?: { message?: string };
|
||||
};
|
||||
|
||||
export const apiErrorHandler = async (
|
||||
error: unknown,
|
||||
safeFail?: CallApiErrorHandler
|
||||
) => {
|
||||
if (error instanceof HTTPError) {
|
||||
return {
|
||||
success: false,
|
||||
status: error.response.status,
|
||||
text: await error.response.json(),
|
||||
};
|
||||
}
|
||||
|
||||
if (safeFail) {
|
||||
return {
|
||||
success: safeFail.success || false,
|
||||
status: safeFail.status || 500,
|
||||
text: {
|
||||
message: safeFail.text?.message || "An unexpected error occurred",
|
||||
},
|
||||
};
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
export type ServerRequestCallback = {
|
||||
success: boolean;
|
||||
status: number;
|
||||
text: { message: string };
|
||||
data?: any;
|
||||
error?: unknown;
|
||||
};
|
||||
export type ServerRequestCallback = {
|
||||
success: boolean;
|
||||
status: number;
|
||||
text: { message: string };
|
||||
data?: any;
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user