로그인 테스트 작업중
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { cmsPostFectch } from "@/components/lib/api";
|
||||
|
||||
export const isLogin = async () => {
|
||||
const headers = {
|
||||
accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"X-Site-Id": "WR",
|
||||
"Access-Control-Expose-Headers" : ["Authorization","refresh-token","token-id"]
|
||||
};
|
||||
const param = { userId: "tuser10003", password: "test1234!" };
|
||||
await cmsPostFectch("/user-service/login",param,headers);
|
||||
};
|
||||
|
||||
// export type LoginState = {
|
||||
// login: {} as any;
|
||||
// };
|
||||
|
||||
// export type loginType = LoginState & LoginActions;
|
||||
|
||||
// export const loginState: LoginState = {
|
||||
// login: {},
|
||||
// };
|
||||
|
||||
// export type LoginActions = {
|
||||
// isLogin: () => void;
|
||||
// };
|
||||
|
||||
// export const loginActionExport: (set: any) => LoginActions = (set: any) => {
|
||||
// return {
|
||||
// isLogin: async () => {},
|
||||
// };
|
||||
// };
|
||||
@@ -96,6 +96,8 @@ import {
|
||||
} from "./ruseFcltMng/fcltSttn/rswtSttn";
|
||||
import { rainStatActionsExport, rainStatExport, type rainStatState, type rainStatType } from "./stats/rainStat";
|
||||
import { rswtStatActionsExport, rswtStatExport, type rswtStatState, type rswtStatType } from "./stats/rswtStat";
|
||||
//import { isLogin } from "./common/login";
|
||||
import { LoginApi } from "@/src/entities/auth";
|
||||
|
||||
export type WrStore = comCodeType &
|
||||
pubFacType &
|
||||
@@ -188,6 +190,7 @@ export const StoreZus = (
|
||||
getMiddleRegionCd(set);
|
||||
getUnitWaterShedCd(set);
|
||||
getEnvPartCd(set);
|
||||
LoginApi.login({userId: "tuser10003", password: "test1234!"})
|
||||
return {
|
||||
...initState,
|
||||
...comFcltSearchAction(set),
|
||||
|
||||
@@ -108,6 +108,24 @@ export const postFectch = async (url: string, params: any, type?: string) => {
|
||||
return await response.json();
|
||||
};
|
||||
|
||||
export const cmsPostFectch = async (url: string, params: any,headers:any) => {
|
||||
const response = fetch(url, {
|
||||
method: "POST",
|
||||
headers:headers ,
|
||||
body: JSON.stringify(params),
|
||||
}).then((res) =>
|
||||
{
|
||||
console.log(' res ' , res)
|
||||
console.log(' access-token ' , res.headers.get('access-token'))
|
||||
console.log(' refresh-token ' , res.headers.get('refresh-token'))
|
||||
console.log(' token-id ' , res.headers.get('token-id'))
|
||||
|
||||
})
|
||||
|
||||
|
||||
return await response;
|
||||
};
|
||||
|
||||
export const putFectch = async (url: string, params: any,type?:string) => {
|
||||
const div =
|
||||
type === fetchType.COMMON
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import {
|
||||
initValInUsage,
|
||||
initValOutUsage,
|
||||
subTotalObj,
|
||||
totalObj,
|
||||
type PrfType,
|
||||
type PrfUsageSummary,
|
||||
} from "@/app/store/prfmncReg/pbnstPrfmncReg/type";
|
||||
|
||||
export const getTablePrfData = (prfList: PrfType[]) => {
|
||||
const inUsageData = structuredClone(initValInUsage);
|
||||
const outUsageData = structuredClone(initValOutUsage);
|
||||
const inSubtotal = structuredClone(subTotalObj);
|
||||
const outSubtotal = structuredClone(subTotalObj);
|
||||
|
||||
if (prfList) {
|
||||
prfList?.forEach((prfItem) => {
|
||||
const month = Number(prfItem?.ym?.slice(4)); // "MM"
|
||||
const monthKey = `${month}월`;
|
||||
|
||||
inUsageData.forEach((inData: PrfUsageSummary) => {
|
||||
const usageKey = inData.usage as keyof PrfType;
|
||||
const value = (prfItem[usageKey] as number) ?? 0;
|
||||
|
||||
(inData[monthKey as keyof PrfUsageSummary] as number) = value;
|
||||
inData.total += value;
|
||||
|
||||
if (inSubtotal&& usageKey !== "subtotal" as keyof PrfType) {
|
||||
(inSubtotal[monthKey as keyof PrfUsageSummary] as number) =
|
||||
((inSubtotal[monthKey as keyof PrfUsageSummary] as number) ?? 0) +
|
||||
value;
|
||||
inSubtotal.total += value;
|
||||
}
|
||||
});
|
||||
|
||||
outUsageData.forEach((outData: PrfUsageSummary) => {
|
||||
const usageKey = outData.usage as keyof PrfType;
|
||||
const value = (prfItem[usageKey] as number) ?? 0; // Type assertion for prfItem[usageKey]
|
||||
|
||||
(outData[monthKey as keyof PrfUsageSummary] as number) = value;
|
||||
outData.total += value;
|
||||
|
||||
if (outSubtotal && usageKey !== "subtotal" as keyof PrfType) {
|
||||
(outSubtotal [monthKey as keyof PrfUsageSummary] as number) =
|
||||
((outSubtotal[monthKey as keyof PrfUsageSummary] as number) ?? 0) + value;
|
||||
outSubtotal.total += value;
|
||||
} // End of if (outSubtotal && usageKey !== "subtotal")
|
||||
}); // End of outUsageData.forEach
|
||||
});
|
||||
(inSubtotal as any)["구분"] = "장내용수";
|
||||
(outSubtotal as any)["구분"] = "장내용수";
|
||||
|
||||
|
||||
inUsageData.push(inSubtotal);
|
||||
outUsageData.push(outSubtotal);
|
||||
const usageTotalObj: { [key: string]: any } = structuredClone(totalObj);
|
||||
for (const key in usageTotalObj) {
|
||||
if (["usage", "gubun", "edit"].includes(key)) continue;
|
||||
const val =
|
||||
(Number((inSubtotal as any)[key]) || 0) +
|
||||
(Number((outSubtotal as any)[key]) || 0);
|
||||
|
||||
(usageTotalObj as any)[key] = val;
|
||||
}
|
||||
const tableData = [...inUsageData, ...outUsageData, usageTotalObj];
|
||||
|
||||
return {
|
||||
inPrf: inUsageData,
|
||||
outPrf: outUsageData,
|
||||
totalPrf: tableData,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// const usageKey = inData.usage as keyof PrfType;
|
||||
// const value = (prfItem[usageKey] as number) ?? 0;
|
||||
|
||||
// (inData[monthKey as keyof PrfUsageSummary] as number) = value;
|
||||
// inData.total += value;
|
||||
|
||||
// if (inSubtotal&& usageKey !== "subtotal" as keyof PrfType) {
|
||||
// (inSubtotal[monthKey as keyof PrfUsageSummary] as number) =
|
||||
// ((inSubtotal[monthKey as keyof PrfUsageSummary] as number) ?? 0) +
|
||||
// value;
|
||||
// inSubtotal.total += value;
|
||||
// }
|
||||
+38
-16
@@ -1,10 +1,10 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { CS_URL } from "./components/lib/config";
|
||||
//import { CLAIM_NAME, AUTH_USER_ID } from "./src/shared/config";
|
||||
import { CLAIM_NAME, AUTH_USER_ID } from "./src/shared/config";
|
||||
|
||||
const CLAIM_NAME = "Authorization";
|
||||
const AUTH_USER_ID = "token-id";
|
||||
const serverApiUrl = CS_URL;
|
||||
// const CLAIM_NAME = "Authorization";
|
||||
// const AUTH_USER_ID = "token-id";
|
||||
const serverApiUrl = CS_URL;
|
||||
const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || "";
|
||||
const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || "";
|
||||
const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
|
||||
@@ -14,28 +14,38 @@ export function middleware(req: NextRequest) {
|
||||
console.log(`[Middleware] Request URL: ${req.url}`);
|
||||
const searchParams = req.nextUrl.searchParams;
|
||||
|
||||
// if (pathname.startsWith("/server")) {
|
||||
// const queryParams = searchParams.toString();
|
||||
// const newUrl = `${serverApiUrl}${pathname.replace("/server", "")}${
|
||||
// queryParams ? `?${queryParams}` : ""
|
||||
// }`;
|
||||
// console.log(`[Middleware] Rewriting from '/server' path to: ${newUrl}`);
|
||||
// return NextResponse.rewrite(new URL(newUrl));
|
||||
// }
|
||||
|
||||
if (pathname.startsWith("/server")) {
|
||||
const queryParams = searchParams.toString();
|
||||
const decodedParams = Array.from(searchParams.entries())
|
||||
.map(([key, value]) => `${key}=${decodeURIComponent(value)}`)
|
||||
.join("&");
|
||||
|
||||
console.log(' sesesesesesevereveraserwereqwrewbrtkehjwrtg server')
|
||||
const newUrl = `${serverApiUrl}${pathname.replace("/server", "")}${
|
||||
queryParams ? `?${queryParams}` : ""
|
||||
decodedParams ? `?${decodedParams}` : ""
|
||||
}`;
|
||||
console.log(`[Middleware] Rewriting from '/server' path to: ${newUrl}`);
|
||||
return NextResponse.rewrite(new URL(newUrl));
|
||||
}
|
||||
|
||||
|
||||
if (pathname.startsWith("/attach-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const token =
|
||||
"eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhMGVjN2EwNy03NTJhLTRmN2YtODlhNi04NTRlNjNkMmUzYTAiLCJhdXRob3JpdGllcyI6IlJPTEVfQURNSU4sUk9MRV9BTk9OWU1PVVMiLCJtbmdyWW4iOiJZIiwiZXhwIjoxNzQ4ODQ4NDkxfQ.ZiYpKxAMyyoPuUquxsWxfQbMBzYN4tsa7itZ49_OEsdGvbUUmKzrIV6Or7VVbEjtAqhh7W97nqB5EP6GRzFC9Q";
|
||||
const userId = "a0ec7a07-752a-4f7f-89a6-854e63d2e3a0";
|
||||
//const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
//const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
// const token =
|
||||
// "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhMGVjN2EwNy03NTJhLTRmN2YtODlhNi04NTRlNjNkMmUzYTAiLCJhdXRob3JpdGllcyI6IlJPTEVfQURNSU4sUk9MRV9BTk9OWU1PVVMiLCJtbmdyWW4iOiJZIiwiZXhwIjoxNzUyMTM1OTk3fQ.itGY6M6mC2iwKvEpXw2KS6354T_B_OFz4hD26ResIgwJhpwiDJCMuSXD-rZ3AarmAIKd0udpCuJR7UlvFMN2ww";
|
||||
// const userId = "a0ec7a07-752a-4f7f-89a6-854e63d2e3a0";
|
||||
const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
const newUrl = `${serverApiUrl}${pathname}`;
|
||||
|
||||
console.log("serverApiUrl ", serverApiUrl);
|
||||
console.log("pathname ", pathname);
|
||||
//wr:dev: pathname /attach-service/api/v1/tus/upload/5e60b70a-956e-40c3-be5a-cdd3100bf8ad
|
||||
|
||||
//http://dev.onasys.co.kr:8000/attach-service/api/v1/tus/upload/5e60b70a-956e-40c3-be5a-cdd3100bf8ad
|
||||
if (token) requestHeaders.set(CLAIM_NAME, token);
|
||||
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
|
||||
@@ -48,6 +58,18 @@ export function middleware(req: NextRequest) {
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/user-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const newUrl = `${serverApiUrl}${pathname}`;
|
||||
|
||||
console.log(
|
||||
`[Middleware] Rewriting from '/user-service' path to: ${newUrl}`
|
||||
);
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/geoserver")) {
|
||||
let queryParams = searchParams.toString();
|
||||
const typename = searchParams.get("TYPENAME");
|
||||
@@ -103,5 +125,5 @@ export function middleware(req: NextRequest) {
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ["/server/:path*", "/attach-service/:path*", "/geoserver/:path*", "/sewerage-service/:path*"],
|
||||
matcher: ["/server/:path*", "/user-service/:path*", "/attach-service/:path*", "/geoserver/:path*", "/sewerage-service/:path*"],
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"i18next": "^25.3.2",
|
||||
"js-cookie": "^3.0.5",
|
||||
"lucide-react": "^0.474.0",
|
||||
"moment": "^2.30.1",
|
||||
"next": "15.1.7",
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
import type { LoginService, ILogin } from "../model/login-interface";
|
||||
import { tokenManager } from "../lib/token-manager";
|
||||
import {PROXY_HOST, ACCESS_TOKEN, AUTH_USER_ID,SITE_ID, CLAIM_NAME, ENDPOINT, JWT_EXPIRATION_TIME } from "../../../shared/config";
|
||||
|
||||
export class LoginApiService implements LoginService {
|
||||
private static instance: LoginApiService;
|
||||
|
||||
private constructor() {}
|
||||
|
||||
public static getInstance(): LoginApiService {
|
||||
if (!LoginApiService.instance) {
|
||||
LoginApiService.instance = new LoginApiService();
|
||||
}
|
||||
return LoginApiService.instance;
|
||||
}
|
||||
|
||||
public async login(payload: ILogin): Promise<void> {
|
||||
try {
|
||||
console.log(' ENDPOINT.USER_SERVICE.LOGIN ', ENDPOINT.USER_SERVICE.LOGIN)
|
||||
const response = await fetch( PROXY_HOST+ ENDPOINT.USER_SERVICE.LOGIN, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
userId: payload.userId,
|
||||
password: payload.password,
|
||||
}),
|
||||
});
|
||||
// const data = response.headers.get(ACCESS_TOKEN);
|
||||
const accessToken = response.headers.get(ACCESS_TOKEN);
|
||||
const tokenId = response.headers.get(AUTH_USER_ID);
|
||||
|
||||
console.log('accessToken ', accessToken)
|
||||
console.log('tokenId ', tokenId)
|
||||
|
||||
if (!accessToken || !tokenId) {
|
||||
throw new Error("Missing required authentication tokens");
|
||||
}
|
||||
|
||||
tokenManager.setToken(CLAIM_NAME, accessToken);
|
||||
tokenManager.setToken(AUTH_USER_ID, tokenId);
|
||||
tokenManager.setToken("site-id-key", SITE_ID);
|
||||
tokenManager.setupRefreshTimer(
|
||||
() => this.silentRefresh(),
|
||||
JWT_EXPIRATION_TIME,
|
||||
);
|
||||
} catch (error) {
|
||||
|
||||
console.log(' login err ' , error)
|
||||
throw new Error(`Login failed: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async silentRefresh(): Promise<void> {
|
||||
console.log(' silentRefresh ')
|
||||
|
||||
try {
|
||||
const response = await fetch(PROXY_HOST+
|
||||
`${ENDPOINT.USER_SERVICE.SILENT_REFRESH}`,
|
||||
{ method: "PUT" },
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
const accessToken = data[ACCESS_TOKEN];
|
||||
const tokenId = data[AUTH_USER_ID];
|
||||
|
||||
if (!accessToken || !tokenId) {
|
||||
throw new Error("Missing required authentication tokens");
|
||||
}
|
||||
|
||||
tokenManager.setToken(CLAIM_NAME, accessToken);
|
||||
tokenManager.setToken(AUTH_USER_ID, tokenId);
|
||||
} catch (error) {
|
||||
tokenManager.clearAuthToken();
|
||||
throw new Error(`Silent refresh failed: ${error}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const LoginApi = LoginApiService.getInstance();
|
||||
@@ -0,0 +1,2 @@
|
||||
export { LoginApi } from "./api/login-service";
|
||||
//export { AuthWrapper } from "./lib/auth-wrapper";
|
||||
@@ -0,0 +1,45 @@
|
||||
// "use client";
|
||||
|
||||
// import { useEffect } from "react";
|
||||
// import { useRouter } from "next/navigation";
|
||||
// import { LoginApi } from "../api/login-service";
|
||||
|
||||
// const AuthWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
// const router = useRouter();
|
||||
// const { userInfo, setUserInfo } = useUserStore((state) => state);
|
||||
|
||||
// async function authCheck() {
|
||||
// const userId = getCookie(AUTH_USER_ID);
|
||||
// if (!userId) {
|
||||
// throw new Error("Missing required authentication tokens");
|
||||
// }
|
||||
|
||||
// const response = await client.get<IUserInfo>(
|
||||
// `${ENDPOINT.USER_SERVICE.USERS}/info/me`,
|
||||
// );
|
||||
// if (!userInfo) setUserInfo(response.data);
|
||||
// }
|
||||
|
||||
// useEffect(() => {
|
||||
// (async () => {
|
||||
// try {
|
||||
// await authCheck();
|
||||
// } catch (error) {
|
||||
// console.error(error);
|
||||
|
||||
// try {
|
||||
// await LoginApi.silentRefresh();
|
||||
// await authCheck();
|
||||
// } catch (refreshError) {
|
||||
// console.error("Token refresh failed:", refreshError);
|
||||
// setUserInfo(null);
|
||||
// router.push("/auth/login");
|
||||
// }
|
||||
// }
|
||||
// })();
|
||||
// }, []);
|
||||
|
||||
// return <>{children}</>;
|
||||
// };
|
||||
|
||||
// export { AuthWrapper };
|
||||
@@ -0,0 +1,59 @@
|
||||
import { AUTH_USER_ID, CLAIM_NAME } from "@/src/shared/config";
|
||||
import { getCookie, removeCookie, setCookie } from "@/src/shared/lib/cookie";
|
||||
|
||||
export class TokenManager {
|
||||
private static instance: TokenManager;
|
||||
private refreshTimer: NodeJS.Timeout | null = null;
|
||||
|
||||
private constructor() {}
|
||||
|
||||
public static getInstance(): TokenManager {
|
||||
if (!TokenManager.instance) {
|
||||
TokenManager.instance = new TokenManager();
|
||||
}
|
||||
return TokenManager.instance;
|
||||
}
|
||||
|
||||
public getToken(key: string): string | undefined {
|
||||
return getCookie(key);
|
||||
}
|
||||
|
||||
public setToken(key: string, value: string): void {
|
||||
setCookie(key, value, {
|
||||
secure: window.location.protocol === "https:",
|
||||
sameSite: "lax",
|
||||
});
|
||||
}
|
||||
|
||||
public removeToken(key: string): void {
|
||||
removeCookie(key);
|
||||
}
|
||||
|
||||
public setupRefreshTimer(
|
||||
callback: () => Promise<void>,
|
||||
expirationTime: number,
|
||||
): void {
|
||||
if (this.refreshTimer) {
|
||||
clearTimeout(this.refreshTimer);
|
||||
}
|
||||
|
||||
this.refreshTimer = setTimeout(() => {
|
||||
callback().catch((error) => {
|
||||
console.error("Silent refresh failed:", error);
|
||||
this.clearAuthToken();
|
||||
});
|
||||
}, expirationTime - 60000);
|
||||
}
|
||||
|
||||
public clearAuthToken(): void {
|
||||
if (this.refreshTimer) {
|
||||
clearTimeout(this.refreshTimer);
|
||||
this.refreshTimer = null;
|
||||
}
|
||||
|
||||
this.removeToken(CLAIM_NAME);
|
||||
this.removeToken(AUTH_USER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
export const tokenManager = TokenManager.getInstance();
|
||||
@@ -0,0 +1,9 @@
|
||||
export interface ILogin {
|
||||
userId: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface LoginService {
|
||||
login(payload: ILogin): Promise<void>;
|
||||
silentRefresh(): Promise<void>;
|
||||
}
|
||||
@@ -12,3 +12,4 @@ export const AUTH_USER_ID = process.env.NEXT_PUBLIC_AUTH_USER_ID || "token-id";
|
||||
export const SERVER_SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
|
||||
export function getCookie(name: string): string | undefined {
|
||||
if (typeof window === "undefined") {
|
||||
return undefined;
|
||||
}
|
||||
return Cookies.get(name);
|
||||
}
|
||||
|
||||
export function setCookie(
|
||||
name: string,
|
||||
value: string,
|
||||
options?: Cookies.CookieAttributes,
|
||||
): void {
|
||||
if (typeof window === "undefined") {
|
||||
return;
|
||||
}
|
||||
Cookies.set(name, value, options);
|
||||
}
|
||||
|
||||
export function removeCookie(
|
||||
name: string,
|
||||
options?: Cookies.CookieAttributes,
|
||||
): void {
|
||||
if (typeof window === "undefined") {
|
||||
return;
|
||||
}
|
||||
Cookies.remove(name, options);
|
||||
}
|
||||
Reference in New Issue
Block a user