diff --git a/ServicesWeb/customer/src/fetchers/base.ts b/ServicesWeb/customer/src/fetchers/base.ts new file mode 100644 index 0000000..6a24785 --- /dev/null +++ b/ServicesWeb/customer/src/fetchers/base.ts @@ -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 = { + 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, +}; diff --git a/ServicesWeb/customer/src/fetchers/fecther.ts b/ServicesWeb/customer/src/fetchers/fecther.ts new file mode 100644 index 0000000..5d7409f --- /dev/null +++ b/ServicesWeb/customer/src/fetchers/fecther.ts @@ -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 => { + 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( + url: string, + options: FetchOptions = {}, + headers: Record = defaultHeaders, + payload?: any +): Promise> { + 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; + } +} + +/** + * Fetch data without authentication + */ +async function fetchData( + endpoint: string, + payload?: any, + method: HttpMethod = "POST", + cache: boolean = false, + timeout: number = DEFAULT_TIMEOUT +): Promise> { + return coreFetch( + endpoint, + { method, cache, timeout }, + defaultHeaders, + payload + ); +} + +/** + * Fetch data with authentication token + */ +async function fetchDataWithToken( + endpoint: string, + payload?: any, + method: HttpMethod = "POST", + cache: boolean = false, + timeout: number = DEFAULT_TIMEOUT +): Promise> { + const accessToken = await retrieveAccessToken(); + const headers = { ...defaultHeaders, "eys-acs-tkn": accessToken }; + return coreFetch(endpoint, { method, cache, timeout }, headers, payload); +} + +/** + * Update data with authentication token and UUID + */ +async function updateDataWithToken( + endpoint: string, + uuid: string, + payload?: any, + method: HttpMethod = "POST", + cache: boolean = false, + timeout: number = DEFAULT_TIMEOUT +): Promise> { + const accessToken = await retrieveAccessToken(); + const headers = { ...defaultHeaders, "eys-acs-tkn": accessToken }; + return coreFetch( + `${endpoint}/${uuid}`, + { method, cache, timeout }, + headers, + payload + ); +} + +export { fetchData, fetchDataWithToken, updateDataWithToken }; diff --git a/ServicesWeb/customer/src/fetchers/index.ts b/ServicesWeb/customer/src/fetchers/index.ts new file mode 100644 index 0000000..eb695db --- /dev/null +++ b/ServicesWeb/customer/src/fetchers/index.ts @@ -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, +}; diff --git a/ServicesWeb/customer/src/fetchers/mutual/cookies/cookie-actions.tsx b/ServicesWeb/customer/src/fetchers/mutual/cookies/cookie-actions.tsx new file mode 100644 index 0000000..7f60665 --- /dev/null +++ b/ServicesWeb/customer/src/fetchers/mutual/cookies/cookie-actions.tsx @@ -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 } +} diff --git a/ServicesWeb/customer/src/fetchers/mutual/cookies/token.tsx b/ServicesWeb/customer/src/fetchers/mutual/cookies/token.tsx new file mode 100644 index 0000000..58f55f7 --- /dev/null +++ b/ServicesWeb/customer/src/fetchers/mutual/cookies/token.tsx @@ -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, +}; diff --git a/ServicesWeb/customer/src/fetchers/types.ts b/ServicesWeb/customer/src/fetchers/types.ts new file mode 100644 index 0000000..8d547ab --- /dev/null +++ b/ServicesWeb/customer/src/fetchers/types.ts @@ -0,0 +1,24 @@ +type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH"; + +interface ApiResponse { + 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 }; diff --git a/ServicesWeb/customer/src/fetchers/utils.ts b/ServicesWeb/customer/src/fetchers/utils.ts new file mode 100644 index 0000000..4d7c87c --- /dev/null +++ b/ServicesWeb/customer/src/fetchers/utils.ts @@ -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 }; diff --git a/ServicesWeb/customer/src/validations/mutual/context/validations.ts b/ServicesWeb/customer/src/validations/mutual/context/validations.ts new file mode 100644 index 0000000..3d1cfe3 --- /dev/null +++ b/ServicesWeb/customer/src/validations/mutual/context/validations.ts @@ -0,0 +1,193 @@ +// From Redis objects +export class AuthError extends Error { + constructor(message: string) { + super(message); + this.name = 'AuthError'; + } +} + +interface ClientOnline { + lastLogin: Date; + lastLogout: Date; + lastAction: Date; + lastPage: string; + userType: string; + lang: string; + timezone: string; +} + +interface ClientPageConfig { + mode: string; + textFont: number; + theme: string; +} + +interface ClientHeader { + header: any[]; + activeDomain: string; + listOfDomains: string[]; + connections: any[]; +} + +interface ClientMenu { + selectionList: string[]; + activeSelection: string; +} + +interface ClientSelection { + selectionList: any[]; + activeSelection: Record; +} + +interface ClientUser { + uuid: string; + avatar: string; + email: string; + phone_number: string; + user_tag: string; + password_expiry_begins: string; + person: { + uuid: string; + firstname: string; + surname: string; + middle_name: string; + sex_code: string; + person_tag: string; + country_code: string; + birth_date: string; + }; +} + +interface ClientSettings { + lastOnline: Date; + token: string; +} + +interface LinkList { + linkList: any[]; +} + +interface ClientRedisToken { + online: ClientOnline; + pageConfig: ClientPageConfig; + menu: ClientMenu; + header: ClientHeader; + selection: ClientSelection; + user: ClientUser; + settings: ClientSettings; + chatRoom: LinkList; + notifications: LinkList; + messages: LinkList; +} + +const defaultClientOnline: ClientOnline = { + lastLogin: new Date(), + lastLogout: new Date(), + lastAction: new Date(), + lastPage: "/dashboard", + userType: "employee", + lang: "tr", + timezone: "GMT+3", +}; + +const defaultClientPageConfig: ClientPageConfig = { + mode: "light", + textFont: 14, + theme: "default", +}; + +const defaultClientMenu: ClientMenu = { + selectionList: [], + activeSelection: "/dashboard", +}; + +const defaultClientHeader: ClientHeader = { + header: [], + activeDomain: "", + listOfDomains: [], + connections: [], +}; + +const defaultClientSelection: ClientSelection = { + selectionList: [], + activeSelection: {}, +}; + +const defaultClientUser: ClientUser = { + uuid: "", + avatar: "", + email: "", + phone_number: "", + user_tag: "", + password_expiry_begins: new Date().toISOString(), + person: { + uuid: "", + firstname: "", + surname: "", + middle_name: "", + sex_code: "", + person_tag: "", + country_code: "", + birth_date: "", + }, +}; + +const defaultClientSettings: ClientSettings = { + lastOnline: new Date(), + token: "", +}; + +const defaultLinkList: LinkList = { + linkList: [], +}; + +const defaultClientRedisToken: ClientRedisToken = { + online: defaultClientOnline, + pageConfig: defaultClientPageConfig, + menu: defaultClientMenu, + header: defaultClientHeader, + selection: defaultClientSelection, + user: defaultClientUser, + settings: defaultClientSettings, + chatRoom: defaultLinkList, + notifications: defaultLinkList, + messages: defaultLinkList, +}; + +const generateRedisKey = (userType: string, uuId: string) => { + const userTypeToUpper = userType.toUpperCase(); + if (!userTypeToUpper || !uuId) throw new Error("Invalid user type or uuId"); + return `CLIENT:${userTypeToUpper}:${uuId}`; +}; + +const readRedisKey = (redisKey: string) => { + if (redisKey.split(":").length !== 2) throw new Error("Invalid redis key"); + const userTypeToUpper = redisKey.split(":")[1]; + const uuId = redisKey.split(":")[2]; + if (!userTypeToUpper || !uuId) throw new Error("Invalid user type or uuId"); + return { userType: userTypeToUpper.toLowerCase(), uuId }; +}; + +export { + defaultClientOnline, + defaultClientPageConfig, + defaultClientMenu, + defaultClientHeader, + defaultClientSelection, + defaultClientUser, + defaultClientSettings, + defaultLinkList, + defaultClientRedisToken, +}; +export type { + ClientOnline, + ClientPageConfig, + ClientMenu, + ClientHeader, + ClientSelection, + ClientUser, + ClientSettings, + LinkList, + ClientRedisToken, +}; +export { generateRedisKey, readRedisKey }; diff --git a/ServicesWeb/customer/src/validations/mutual/fecther/validations.ts b/ServicesWeb/customer/src/validations/mutual/fecther/validations.ts new file mode 100644 index 0000000..394dd2d --- /dev/null +++ b/ServicesWeb/customer/src/validations/mutual/fecther/validations.ts @@ -0,0 +1,44 @@ +interface FetcherRequest { + url: string; + isNoCache: boolean; +} + +interface PostFetcherRequest extends FetcherRequest { + body: Record; +} + +interface GetFetcherRequest extends FetcherRequest { + url: string; +} + +interface DeleteFetcherRequest extends GetFetcherRequest {} +interface PutFetcherRequest extends PostFetcherRequest {} +interface PatchFetcherRequest extends PostFetcherRequest {} + +interface FetcherRespose { + success: boolean; +} +interface PaginationResponse { + onPage: number; + onPageCount: number; + totalPage: number; + totalCount: number; + next: boolean; + back: boolean; +} + +interface FetcherDataResponse extends FetcherRespose { + data: Record | null; + pagination?: PaginationResponse; +} + +export type { + FetcherRequest, + PostFetcherRequest, + GetFetcherRequest, + DeleteFetcherRequest, + PutFetcherRequest, + PatchFetcherRequest, + FetcherRespose, + FetcherDataResponse, +}; diff --git a/ServicesWeb/management/src/fetchers/base.ts b/ServicesWeb/management/src/fetchers/base.ts new file mode 100644 index 0000000..6a24785 --- /dev/null +++ b/ServicesWeb/management/src/fetchers/base.ts @@ -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 = { + 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, +}; diff --git a/ServicesWeb/management/src/fetchers/fecther.ts b/ServicesWeb/management/src/fetchers/fecther.ts new file mode 100644 index 0000000..5d7409f --- /dev/null +++ b/ServicesWeb/management/src/fetchers/fecther.ts @@ -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 => { + 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( + url: string, + options: FetchOptions = {}, + headers: Record = defaultHeaders, + payload?: any +): Promise> { + 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; + } +} + +/** + * Fetch data without authentication + */ +async function fetchData( + endpoint: string, + payload?: any, + method: HttpMethod = "POST", + cache: boolean = false, + timeout: number = DEFAULT_TIMEOUT +): Promise> { + return coreFetch( + endpoint, + { method, cache, timeout }, + defaultHeaders, + payload + ); +} + +/** + * Fetch data with authentication token + */ +async function fetchDataWithToken( + endpoint: string, + payload?: any, + method: HttpMethod = "POST", + cache: boolean = false, + timeout: number = DEFAULT_TIMEOUT +): Promise> { + const accessToken = await retrieveAccessToken(); + const headers = { ...defaultHeaders, "eys-acs-tkn": accessToken }; + return coreFetch(endpoint, { method, cache, timeout }, headers, payload); +} + +/** + * Update data with authentication token and UUID + */ +async function updateDataWithToken( + endpoint: string, + uuid: string, + payload?: any, + method: HttpMethod = "POST", + cache: boolean = false, + timeout: number = DEFAULT_TIMEOUT +): Promise> { + const accessToken = await retrieveAccessToken(); + const headers = { ...defaultHeaders, "eys-acs-tkn": accessToken }; + return coreFetch( + `${endpoint}/${uuid}`, + { method, cache, timeout }, + headers, + payload + ); +} + +export { fetchData, fetchDataWithToken, updateDataWithToken }; diff --git a/ServicesWeb/management/src/fetchers/index.ts b/ServicesWeb/management/src/fetchers/index.ts new file mode 100644 index 0000000..eb695db --- /dev/null +++ b/ServicesWeb/management/src/fetchers/index.ts @@ -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, +}; diff --git a/ServicesWeb/management/src/fetchers/mutual/cookies/cookie-actions.tsx b/ServicesWeb/management/src/fetchers/mutual/cookies/cookie-actions.tsx new file mode 100644 index 0000000..7f60665 --- /dev/null +++ b/ServicesWeb/management/src/fetchers/mutual/cookies/cookie-actions.tsx @@ -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 } +} diff --git a/ServicesWeb/management/src/fetchers/mutual/cookies/token.tsx b/ServicesWeb/management/src/fetchers/mutual/cookies/token.tsx new file mode 100644 index 0000000..58f55f7 --- /dev/null +++ b/ServicesWeb/management/src/fetchers/mutual/cookies/token.tsx @@ -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, +}; diff --git a/ServicesWeb/management/src/fetchers/types.ts b/ServicesWeb/management/src/fetchers/types.ts new file mode 100644 index 0000000..8d547ab --- /dev/null +++ b/ServicesWeb/management/src/fetchers/types.ts @@ -0,0 +1,24 @@ +type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH"; + +interface ApiResponse { + 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 }; diff --git a/ServicesWeb/management/src/fetchers/utils.ts b/ServicesWeb/management/src/fetchers/utils.ts new file mode 100644 index 0000000..4d7c87c --- /dev/null +++ b/ServicesWeb/management/src/fetchers/utils.ts @@ -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 }; diff --git a/docs/frontDocs/MutualComponents.md b/docs/frontDocs/MutualComponents.md index 27a4ca3..529ff37 100644 --- a/docs/frontDocs/MutualComponents.md +++ b/docs/frontDocs/MutualComponents.md @@ -2,11 +2,11 @@ ## Contexts -- [Component Contexts](./docs/contexts/component_contexts.md) -- [Component Menu](./docs/contexts/component_menu.md) -- [Component User](./docs/contexts/component_user.md) -- [Component Online](./docs/contexts/component_online.md) -- [Component Selection](./docs/contexts/component_selection.md) +- [Component Contexts](./contexts/component_contexts.md) +- [Component Menu](./contexts/component_menu.md) +- [Component User](./contexts/component_user.md) +- [Component Online](./contexts/component_online.md) +- [Component Selection](./contexts/component_selection.md) ## Language Selection