updated fetchers
This commit is contained in:
38
ServicesWeb/customer/src/fetchers/base.ts
Normal file
38
ServicesWeb/customer/src/fetchers/base.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { ApiResponse, CookieObject } from "./types";
|
||||
import NextCrypto from "next-crypto";
|
||||
|
||||
const tokenSecretEnv = process.env.TOKENSECRET_90;
|
||||
const tokenSecret = tokenSecretEnv || "e781d1b0-9418-40b3-9940-385abf81a0b7";
|
||||
const nextCrypto = new NextCrypto(tokenSecret);
|
||||
|
||||
const cookieObject: CookieObject = {
|
||||
httpOnly: true,
|
||||
path: "/",
|
||||
sameSite: "none",
|
||||
secure: true,
|
||||
maxAge: 3600,
|
||||
priority: "high",
|
||||
};
|
||||
|
||||
const DEFAULT_TIMEOUT: number = 10000; // 10 seconds
|
||||
const defaultHeaders: Record<string, string> = {
|
||||
accept: "application/json",
|
||||
language: "tr",
|
||||
domain: "evyos.com.tr",
|
||||
tz: "GMT+3",
|
||||
"Content-type": "application/json",
|
||||
};
|
||||
const DEFAULT_RESPONSE: ApiResponse = {
|
||||
error: "Hata tipi belirtilmedi",
|
||||
status: 500,
|
||||
data: {},
|
||||
};
|
||||
|
||||
export {
|
||||
DEFAULT_TIMEOUT,
|
||||
DEFAULT_RESPONSE,
|
||||
defaultHeaders,
|
||||
tokenSecret,
|
||||
cookieObject,
|
||||
nextCrypto,
|
||||
};
|
||||
127
ServicesWeb/customer/src/fetchers/fecther.ts
Normal file
127
ServicesWeb/customer/src/fetchers/fecther.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
"use server";
|
||||
import { DEFAULT_RESPONSE, defaultHeaders, DEFAULT_TIMEOUT } from "./base";
|
||||
import { FetchOptions, HttpMethod, ApiResponse } from "./types";
|
||||
import { retrieveAccessToken } from "./mutual/cookies/token";
|
||||
|
||||
/**
|
||||
* Creates a promise that rejects after a specified timeout
|
||||
* @param ms Timeout in milliseconds
|
||||
* @param controller AbortController to abort the fetch request
|
||||
* @returns A promise that rejects after the timeout
|
||||
*/
|
||||
const createTimeoutPromise = (
|
||||
ms: number,
|
||||
controller: AbortController
|
||||
): Promise<never> => {
|
||||
return new Promise((_, reject) => {
|
||||
setTimeout(() => {
|
||||
controller.abort();
|
||||
reject(new Error(`Request timed out after ${ms}ms`));
|
||||
}, ms);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Core fetch function with timeout and error handling
|
||||
* @param url The URL to fetch
|
||||
* @param options Fetch options
|
||||
* @param headers Request headers
|
||||
* @param payload Request payload
|
||||
* @returns API response
|
||||
*/
|
||||
async function coreFetch<T>(
|
||||
url: string,
|
||||
options: FetchOptions = {},
|
||||
headers: Record<string, string> = defaultHeaders,
|
||||
payload?: any
|
||||
): Promise<ApiResponse<T>> {
|
||||
const { method = "POST", cache = false, timeout = DEFAULT_TIMEOUT } = options;
|
||||
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const fetchOptions: RequestInit = {
|
||||
method,
|
||||
headers,
|
||||
cache: cache ? "force-cache" : "no-cache",
|
||||
signal: controller.signal,
|
||||
};
|
||||
|
||||
if (method !== "GET" && payload) {
|
||||
fetchOptions.body = JSON.stringify(
|
||||
payload.payload ? payload.payload : payload
|
||||
);
|
||||
}
|
||||
const timeoutPromise = createTimeoutPromise(timeout, controller);
|
||||
const response = await Promise.race([
|
||||
fetch(url, fetchOptions),
|
||||
timeoutPromise,
|
||||
]);
|
||||
const responseData = await response.json();
|
||||
return {
|
||||
status: response.status,
|
||||
data: responseData || ({} as T),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`API Error (${url}):`, error);
|
||||
return {
|
||||
...DEFAULT_RESPONSE,
|
||||
error: error instanceof Error ? error.message : "Network error",
|
||||
} as ApiResponse<T>;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data without authentication
|
||||
*/
|
||||
async function fetchData<T>(
|
||||
endpoint: string,
|
||||
payload?: any,
|
||||
method: HttpMethod = "POST",
|
||||
cache: boolean = false,
|
||||
timeout: number = DEFAULT_TIMEOUT
|
||||
): Promise<ApiResponse<T>> {
|
||||
return coreFetch<T>(
|
||||
endpoint,
|
||||
{ method, cache, timeout },
|
||||
defaultHeaders,
|
||||
payload
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data with authentication token
|
||||
*/
|
||||
async function fetchDataWithToken<T>(
|
||||
endpoint: string,
|
||||
payload?: any,
|
||||
method: HttpMethod = "POST",
|
||||
cache: boolean = false,
|
||||
timeout: number = DEFAULT_TIMEOUT
|
||||
): Promise<ApiResponse<T>> {
|
||||
const accessToken = await retrieveAccessToken();
|
||||
const headers = { ...defaultHeaders, "eys-acs-tkn": accessToken };
|
||||
return coreFetch<T>(endpoint, { method, cache, timeout }, headers, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update data with authentication token and UUID
|
||||
*/
|
||||
async function updateDataWithToken<T>(
|
||||
endpoint: string,
|
||||
uuid: string,
|
||||
payload?: any,
|
||||
method: HttpMethod = "POST",
|
||||
cache: boolean = false,
|
||||
timeout: number = DEFAULT_TIMEOUT
|
||||
): Promise<ApiResponse<T>> {
|
||||
const accessToken = await retrieveAccessToken();
|
||||
const headers = { ...defaultHeaders, "eys-acs-tkn": accessToken };
|
||||
return coreFetch<T>(
|
||||
`${endpoint}/${uuid}`,
|
||||
{ method, cache, timeout },
|
||||
headers,
|
||||
payload
|
||||
);
|
||||
}
|
||||
|
||||
export { fetchData, fetchDataWithToken, updateDataWithToken };
|
||||
36
ServicesWeb/customer/src/fetchers/index.ts
Normal file
36
ServicesWeb/customer/src/fetchers/index.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { formatServiceUrl } from "./utils";
|
||||
|
||||
const baseUrlAuth = formatServiceUrl(
|
||||
process.env.NEXT_PUBLIC_AUTH_SERVICE_URL || "auth_service:8001"
|
||||
);
|
||||
const baseUrlRestriction = formatServiceUrl(
|
||||
process.env.NEXT_PUBLIC_RESTRICTION_SERVICE_URL || "restriction_service:8002"
|
||||
);
|
||||
const baseUrlApplication = formatServiceUrl(
|
||||
process.env.NEXT_PUBLIC_MANAGEMENT_SERVICE_URL || "management_service:8003"
|
||||
);
|
||||
const baseUrlAccount = formatServiceUrl(
|
||||
process.env.NEXT_PUBLIC_ACCOUNT_SERVICE_URL || "account_service:8004"
|
||||
);
|
||||
const baseUrlBuilding = formatServiceUrl(
|
||||
process.env.NEXT_PUBLIC_BUILDING_SERVICE_URL || "building_service:8006"
|
||||
);
|
||||
const baseUrlPeople = formatServiceUrl(
|
||||
process.env.NEXT_PUBLIC_VALIDATION_SERVICE_URL || "validation_service:8009"
|
||||
);
|
||||
|
||||
const urlCheckToken = `${baseUrlAuth}/authentication/token/check`;
|
||||
const urlPageValid = `${baseUrlRestriction}/restrictions/page/valid`;
|
||||
const urlSiteUrls = `${baseUrlRestriction}/restrictions/sites/list`;
|
||||
|
||||
export {
|
||||
baseUrlAuth,
|
||||
baseUrlPeople,
|
||||
baseUrlApplication,
|
||||
baseUrlAccount,
|
||||
baseUrlBuilding,
|
||||
baseUrlRestriction,
|
||||
urlCheckToken,
|
||||
urlPageValid,
|
||||
urlSiteUrls,
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
'use server';
|
||||
import { cookies } from "next/headers";
|
||||
import { cookieObject } from "@/fetchers/base";
|
||||
import { ResponseCookie } from "next/dist/compiled/@edge-runtime/cookies";
|
||||
|
||||
/**
|
||||
* Server action to delete all access cookies at once
|
||||
* This is a direct server action that can be called from server components
|
||||
*/
|
||||
export async function deleteAllCookies() {
|
||||
try {
|
||||
const cookieStore = await cookies();
|
||||
if (cookieStore.has("eys-zzz")) { cookieStore.delete({ name: "eys-zzz", ...cookieObject } as ResponseCookie); }
|
||||
if (cookieStore.has("eys-yyy")) { cookieStore.delete({ name: "eys-yyy", ...cookieObject } as ResponseCookie); }
|
||||
if (cookieStore.has("eys-sel")) { cookieStore.delete({ name: "eys-sel", ...cookieObject } as ResponseCookie); }
|
||||
return true;
|
||||
} catch (error) { console.error("Error in deleteAllCookies:", error); return false }
|
||||
}
|
||||
49
ServicesWeb/customer/src/fetchers/mutual/cookies/token.tsx
Normal file
49
ServicesWeb/customer/src/fetchers/mutual/cookies/token.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { cookies } from "next/headers";
|
||||
import { fetchDataWithToken } from "@/fetchers/fecther";
|
||||
import { urlCheckToken, urlPageValid, urlSiteUrls } from "@/fetchers/index";
|
||||
import { nextCrypto } from "@/fetchers/base";
|
||||
import { AuthError } from "@/validations/mutual/context/validations";
|
||||
import { fetchResponseStatus } from "@/fetchers/utils";
|
||||
|
||||
async function checkAccessTokenIsValid() {
|
||||
try {
|
||||
const response = await fetchDataWithToken(urlCheckToken, {}, "GET", false);
|
||||
return fetchResponseStatus(response);
|
||||
} catch (error) { throw new AuthError("No access token found") }
|
||||
}
|
||||
|
||||
async function retrievePageList() {
|
||||
const response: any = await fetchDataWithToken(urlSiteUrls, {}, "GET", false);
|
||||
return fetchResponseStatus(response) ? response.data?.sites : null;
|
||||
}
|
||||
|
||||
async function retrieveApplicationbyUrl(pageUrl: string) {
|
||||
const response: any = await fetchDataWithToken(urlPageValid, { page_url: pageUrl }, "POST", false);
|
||||
return fetchResponseStatus(response) ? response.data?.application : null;
|
||||
}
|
||||
|
||||
async function retrieveAccessToken() {
|
||||
const cookieStore = await cookies();
|
||||
try {
|
||||
const encrpytAccessToken = cookieStore.get("eys-zzz")?.value || "";
|
||||
return await nextCrypto.decrypt(encrpytAccessToken) || "";
|
||||
}
|
||||
catch (error) { throw new AuthError("No access token found") }
|
||||
}
|
||||
|
||||
async function retrieveAccessObjects() {
|
||||
const cookieStore = await cookies();
|
||||
try {
|
||||
const encrpytAccessObject = cookieStore.get("eys-yyy")?.value || "";
|
||||
return await nextCrypto.decrypt(encrpytAccessObject) || "";
|
||||
}
|
||||
catch (error) { throw new AuthError("No access objects found") }
|
||||
}
|
||||
|
||||
export {
|
||||
checkAccessTokenIsValid,
|
||||
retrieveAccessToken,
|
||||
retrieveAccessObjects,
|
||||
retrieveApplicationbyUrl,
|
||||
retrievePageList,
|
||||
};
|
||||
24
ServicesWeb/customer/src/fetchers/types.ts
Normal file
24
ServicesWeb/customer/src/fetchers/types.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
||||
|
||||
interface ApiResponse<T = any> {
|
||||
status: number;
|
||||
data: T;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface FetchOptions {
|
||||
method?: HttpMethod;
|
||||
cache?: boolean;
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
interface CookieObject {
|
||||
httpOnly: boolean;
|
||||
path: string;
|
||||
sameSite: string;
|
||||
secure: boolean;
|
||||
maxAge: number;
|
||||
priority: string;
|
||||
}
|
||||
|
||||
export type { HttpMethod, ApiResponse, FetchOptions, CookieObject };
|
||||
10
ServicesWeb/customer/src/fetchers/utils.ts
Normal file
10
ServicesWeb/customer/src/fetchers/utils.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
const formatServiceUrl = (url: string) => {
|
||||
if (!url) return "";
|
||||
return url.startsWith("http") ? url : `http://${url}`;
|
||||
};
|
||||
|
||||
function fetchResponseStatus(response: any) {
|
||||
return 199 < response?.status && response?.status < 300;
|
||||
}
|
||||
|
||||
export { formatServiceUrl, fetchResponseStatus };
|
||||
Reference in New Issue
Block a user