@@ -21,7 +28,7 @@ export default function Page() {
{Object.entries(info).map(([key, value]) => (
{key} |
- {value?.toString()} |
+ {value} |
))}
diff --git a/frontend/app/(routes)/groups/[id]/page.tsx b/frontend/app/groups/[id]/page.tsx
similarity index 93%
rename from frontend/app/(routes)/groups/[id]/page.tsx
rename to frontend/app/groups/[id]/page.tsx
index b200e28..4fff8b9 100644
--- a/frontend/app/(routes)/groups/[id]/page.tsx
+++ b/frontend/app/groups/[id]/page.tsx
@@ -1,7 +1,5 @@
import { Navbar } from '@/components/navbar';
-export const dynamic = 'force-dynamic';
-
export default function Page({ params }: { params: { id: string } }) {
return (
<>
diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx
index 5cfa6bc..06f8f18 100644
--- a/frontend/app/layout.tsx
+++ b/frontend/app/layout.tsx
@@ -3,6 +3,9 @@ import './globals.css';
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
+import { getBackend } from './actions';
+import { Providers } from './providers';
+
const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
@@ -10,14 +13,20 @@ export const metadata: Metadata = {
description: 'Generated by create next app',
};
-export default function RootLayout({
+export const dynamic = 'force-dynamic';
+
+export default async function RootLayoutServer({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
+ 'use server';
+ const apiBasePath = await getBackend({ preferredNetwork: 'public' });
return (
- {children}
+
+ {children}
+
);
}
diff --git a/frontend/app/login/jwt/route.ts b/frontend/app/login/jwt/route.ts
new file mode 100644
index 0000000..0cc2cc1
--- /dev/null
+++ b/frontend/app/login/jwt/route.ts
@@ -0,0 +1,18 @@
+import { type NextRequest, NextResponse } from 'next/server';
+
+export function GET(req: NextRequest): NextResponse {
+ const oAuthToken = req.nextUrl.searchParams.get('jwt');
+ if (oAuthToken) {
+ const response = NextResponse.redirect(new URL('/', req.url));
+ response.cookies.set({
+ name: 'jwt',
+ value: oAuthToken.toString(),
+ maxAge: 60 * 60 * 24 * 7,
+ secure: process.env.NODE_ENV === 'production',
+ });
+
+ return response;
+ }
+
+ return NextResponse.next();
+}
diff --git a/frontend/app/login/page.tsx b/frontend/app/login/page.tsx
new file mode 100644
index 0000000..142521c
--- /dev/null
+++ b/frontend/app/login/page.tsx
@@ -0,0 +1,16 @@
+'use client';
+
+import { useEffect } from 'react';
+
+import { useApi } from '@/hooks/use-api';
+
+export default function Page() {
+ const pek = useApi();
+ const url = pek?.loginPath;
+
+ useEffect(() => {
+ if (url) window.location.href = url;
+ }, [url]);
+
+ Redirecting to {url ?? 'backend/login'}
;
+}
diff --git a/frontend/app/(routes)/page.tsx b/frontend/app/page.tsx
similarity index 84%
rename from frontend/app/(routes)/page.tsx
rename to frontend/app/page.tsx
index ab9c0f0..6e28876 100644
--- a/frontend/app/(routes)/page.tsx
+++ b/frontend/app/page.tsx
@@ -1,11 +1,13 @@
-import { Navbar } from '@/components/navbar';
-import { PekApi } from '@/pek-api';
+import Link from 'next/link';
-export const dynamic = 'force-dynamic';
+import { ClientSideProfile } from '@/components/client-side-profile';
+import { Navbar } from '@/components/navbar';
+import { ServerSideProfile } from '@/components/server-side-profile';
+import { ServerPekApi } from '@/network/server-api';
export default async function Home() {
- const api = new PekApi();
- const ping = await api.ping();
+ const pek = await ServerPekApi.getDefault();
+ const ping = await pek.ping();
return (
<>
@@ -43,6 +45,9 @@ export default async function Home() {
Egy random személy profilja
+ Login
+
+
>
);
diff --git a/frontend/app/(routes)/profiles/[id]/page.tsx b/frontend/app/profiles/[id]/page.tsx
similarity index 93%
rename from frontend/app/(routes)/profiles/[id]/page.tsx
rename to frontend/app/profiles/[id]/page.tsx
index 83b4cdf..289f86a 100644
--- a/frontend/app/(routes)/profiles/[id]/page.tsx
+++ b/frontend/app/profiles/[id]/page.tsx
@@ -1,7 +1,5 @@
import { Navbar } from '@/components/navbar';
-export const dynamic = 'force-dynamic';
-
export default function Page({ params }: { params: { id: string } }) {
return (
<>
diff --git a/frontend/app/providers.tsx b/frontend/app/providers.tsx
new file mode 100644
index 0000000..1483b7f
--- /dev/null
+++ b/frontend/app/providers.tsx
@@ -0,0 +1,17 @@
+'use client';
+
+import { createContext, useEffect } from 'react';
+
+import { ClientPekApi } from '@/network/client-api';
+
+export const ClientApiContext = createContext(null);
+
+export function Providers({ children, apiBasePath }: Readonly<{ children: React.ReactNode; apiBasePath: string }>) {
+ const apiInstance = new ClientPekApi(apiBasePath);
+ useEffect(() => {
+ if (typeof window !== 'undefined') (window as any).pekApi = apiInstance;
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [apiBasePath]);
+
+ return {children};
+}
diff --git a/frontend/components/client-side-profile.tsx b/frontend/components/client-side-profile.tsx
new file mode 100644
index 0000000..d4ba762
--- /dev/null
+++ b/frontend/components/client-side-profile.tsx
@@ -0,0 +1,25 @@
+'use client';
+
+import { useContext, useEffect, useState } from 'react';
+
+import { ClientApiContext } from '@/app/providers';
+import { type UserDto } from '@/pek';
+
+export function ClientSideProfile() {
+ const pek = useContext(ClientApiContext);
+ const [user, setUser] = useState(null);
+
+ useEffect(() => {
+ if (!pek) return;
+ pek
+ .me()
+ .then(setUser)
+ .catch(() => {});
+ }, [pek]);
+
+ if (!user) {
+ return null;
+ }
+
+ return {user.name}
;
+}
diff --git a/frontend/components/server-side-profile.tsx b/frontend/components/server-side-profile.tsx
new file mode 100644
index 0000000..c66ea18
--- /dev/null
+++ b/frontend/components/server-side-profile.tsx
@@ -0,0 +1,13 @@
+import { ServerPekApi } from '@/network/server-api';
+import { type UserDto } from '@/pek';
+
+export async function ServerSideProfile() {
+ const pek = await ServerPekApi.getDefault();
+ let user: UserDto;
+ try {
+ user = await pek.me();
+ } catch (e) {
+ return null;
+ }
+ return {user.name}
;
+}
diff --git a/frontend/hooks/use-api.ts b/frontend/hooks/use-api.ts
new file mode 100644
index 0000000..5f018d5
--- /dev/null
+++ b/frontend/hooks/use-api.ts
@@ -0,0 +1,8 @@
+'use client';
+import { useContext } from 'react';
+
+import { ClientApiContext } from '@/app/providers';
+
+export function useApi() {
+ return useContext(ClientApiContext);
+}
diff --git a/frontend/network/abstract-api.ts b/frontend/network/abstract-api.ts
new file mode 100644
index 0000000..5774ae1
--- /dev/null
+++ b/frontend/network/abstract-api.ts
@@ -0,0 +1,28 @@
+import { AxiosInstance } from 'axios';
+
+import { Configuration, DefaultApi, UserDto } from '@/pek';
+
+export class AbstractPekApi {
+ constructor(
+ public readonly basePath: string,
+ public readonly axios?: AxiosInstance
+ ) {}
+
+ get loginPath() {
+ return `${this.basePath}/api/v4/auth/login`;
+ }
+
+ private get api(): DefaultApi {
+ return new DefaultApi(new Configuration({ basePath: this.basePath }), this.basePath, this.axios);
+ }
+
+ async ping(): Promise {
+ const { data } = await this.api.pingControllerSend();
+ return data.ping;
+ }
+
+ async me(): Promise {
+ const { data } = await this.api.authControllerMe();
+ return data;
+ }
+}
diff --git a/frontend/network/client-api.ts b/frontend/network/client-api.ts
new file mode 100644
index 0000000..caa640a
--- /dev/null
+++ b/frontend/network/client-api.ts
@@ -0,0 +1,20 @@
+'use client';
+import axios from 'axios';
+import Cookies from 'js-cookie';
+
+import { AbstractPekApi } from './abstract-api';
+
+export const clientAxios = axios.create();
+clientAxios.interceptors.request.use((config) => {
+ const jwt = Cookies.get('jwt');
+ if (jwt) {
+ config.headers.Authorization = `Bearer ${jwt}`;
+ }
+ return config;
+});
+
+export class ClientPekApi extends AbstractPekApi {
+ constructor(basePath: string) {
+ super(basePath, clientAxios);
+ }
+}
diff --git a/frontend/network/server-api.ts b/frontend/network/server-api.ts
new file mode 100644
index 0000000..2e14963
--- /dev/null
+++ b/frontend/network/server-api.ts
@@ -0,0 +1,26 @@
+import axios from 'axios';
+import { cookies } from 'next/headers';
+
+import { getBackend } from '@/app/actions';
+
+import { AbstractPekApi } from './abstract-api';
+
+export const serverAxios = axios.create();
+serverAxios.interceptors.request.use((config) => {
+ const jwt = cookies().get('jwt');
+ if (jwt) {
+ config.headers.Authorization = `Bearer ${jwt.value}`;
+ }
+ return config;
+});
+
+export class ServerPekApi extends AbstractPekApi {
+ constructor(basePath: string) {
+ super(basePath, serverAxios);
+ }
+
+ static async getDefault(): Promise {
+ const basePath = await getBackend({ preferredNetwork: 'private' });
+ return new ServerPekApi(basePath);
+ }
+}
diff --git a/frontend/package.json b/frontend/package.json
index 141009e..2295094 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -17,6 +17,7 @@
"axios": "^1.7.6",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
+ "js-cookie": "^3.0.5",
"lucide-react": "^0.414.0",
"next": "14.2.5",
"react": "^18",
@@ -25,6 +26,7 @@
"tailwindcss-animate": "^1.0.7"
},
"devDependencies": {
+ "@types/js-cookie": "^3.0.6",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
diff --git a/frontend/pages/api/[[...slug]].ts b/frontend/pages/api/[[...slug]].ts
index 792ebb8..2d4377d 100644
--- a/frontend/pages/api/[[...slug]].ts
+++ b/frontend/pages/api/[[...slug]].ts
@@ -1,7 +1,11 @@
-import { bootstrap } from 'backend/dist/app.js';
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(req: NextApiRequest, res: NextApiResponse): Promise {
+ if (process.env.VERCEL_ENV !== 'preview') {
+ res.status(404).end();
+ return;
+ }
+ const { bootstrap } = await import('backend/dist/app.js');
const { app } = await bootstrap();
const server = (await app.init()).getHttpAdapter().getInstance();
diff --git a/frontend/pek-api.ts b/frontend/pek-api.ts
deleted file mode 100644
index cb28391..0000000
--- a/frontend/pek-api.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Configuration, DefaultApi } from '../pek-client';
-
-export function getBasePath(): string {
- if (process.env.NEXT_PUBLIC_API_URL) {
- return process.env.NEXT_PUBLIC_API_URL;
- }
- if (process.env.VERCEL_ENV === 'preview') {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- if VERCEL_ENV is preview, VERCEL_URL is set
- return `https://${process.env.VERCEL_URL!}`;
- }
- return 'http://localhost:3000';
-}
-
-export class PekApi {
- private get api(): DefaultApi {
- return new DefaultApi(new Configuration({ basePath: getBasePath() }));
- }
-
- async ping(): Promise {
- const { data } = await this.api.pingControllerSend();
- return data.ping;
- }
-}
diff --git a/package.json b/package.json
index 25988b6..dc579ad 100644
--- a/package.json
+++ b/package.json
@@ -5,13 +5,13 @@
"frontend"
],
"scripts": {
- "dev": "concurrently \"yarn workspace backend run build:watch\" \"yarn workspace frontend run dev\" \"yarn run watch:openapi\"",
+ "dev": "concurrently --names \"backend,frontend,openapi\" -c \"bgBlue.bold,bgGreen.bold,bgYellow.bold\" \"yarn workspace backend run start:dev\" \"yarn workspace frontend run dev\" \"yarn run watch:openapi\"",
"build": "yarn workspace backend run build && yarn workspace frontend run build",
"lint": "yarn workspace backend run lint && yarn workspace frontend run lint",
"lint:fix": "yarn workspace backend run lint:fix && yarn workspace frontend run lint:fix",
"format:fix": "npx prettier -c --write .",
"generate": "npx @openapitools/openapi-generator-cli generate -i ./backend/openapi.yaml -g typescript-axios -o ./pek-client",
- "watch:openapi": "nodemon --watch backend/openapi.yaml --exec \"yarn generate\""
+ "watch:openapi": "nodemon --on-change-only --watch backend/openapi.yaml --exec \"yarn generate\""
},
"devDependencies": {
"@openapitools/openapi-generator-cli": "^2.13.4",
diff --git a/pek-client/api.ts b/pek-client/api.ts
index 1c6b885..1d45773 100644
--- a/pek-client/api.ts
+++ b/pek-client/api.ts
@@ -36,6 +36,19 @@ export interface Ping {
*/
'ping': string;
}
+/**
+ *
+ * @export
+ * @interface UserDto
+ */
+export interface UserDto {
+ /**
+ *
+ * @type {string}
+ * @memberof UserDto
+ */
+ 'name': string;
+}
/**
* DefaultApi - axios parameter creator
@@ -43,6 +56,102 @@ export interface Ping {
*/
export const DefaultApiAxiosParamCreator = function (configuration?: Configuration) {
return {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ authControllerLogin: async (options: RawAxiosRequestConfig = {}): Promise => {
+ const localVarPath = `/api/v4/auth/login`;
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+ let baseOptions;
+ if (configuration) {
+ baseOptions = configuration.baseOptions;
+ }
+
+ const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+ const localVarHeaderParameter = {} as any;
+ const localVarQueryParameter = {} as any;
+
+
+
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+ localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+ return {
+ url: toPathString(localVarUrlObj),
+ options: localVarRequestOptions,
+ };
+ },
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ authControllerMe: async (options: RawAxiosRequestConfig = {}): Promise => {
+ const localVarPath = `/api/v4/auth/me`;
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+ let baseOptions;
+ if (configuration) {
+ baseOptions = configuration.baseOptions;
+ }
+
+ const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+ const localVarHeaderParameter = {} as any;
+ const localVarQueryParameter = {} as any;
+
+
+
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+ localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+ return {
+ url: toPathString(localVarUrlObj),
+ options: localVarRequestOptions,
+ };
+ },
+ /**
+ *
+ * @param {any} code
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ authControllerOauthRedirect: async (code: any, options: RawAxiosRequestConfig = {}): Promise => {
+ // verify required parameter 'code' is not null or undefined
+ assertParamExists('authControllerOauthRedirect', 'code', code)
+ const localVarPath = `/api/v4/auth/callback`;
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+ let baseOptions;
+ if (configuration) {
+ baseOptions = configuration.baseOptions;
+ }
+
+ const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+ const localVarHeaderParameter = {} as any;
+ const localVarQueryParameter = {} as any;
+
+ if (code !== undefined) {
+ for (const [key, value] of Object.entries(code)) {
+ localVarQueryParameter[key] = value;
+ }
+ }
+
+
+
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+ localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+ return {
+ url: toPathString(localVarUrlObj),
+ options: localVarRequestOptions,
+ };
+ },
/**
* # Health check endpoint
This endpoint is a simple health check API designed to confirm that the server is operational. When accessed, it returns a straightforward response indicating that the service is up and running.
* @summary
@@ -83,6 +192,40 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
export const DefaultApiFp = function(configuration?: Configuration) {
const localVarAxiosParamCreator = DefaultApiAxiosParamCreator(configuration)
return {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async authControllerLogin(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
+ const localVarAxiosArgs = await localVarAxiosParamCreator.authControllerLogin(options);
+ const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+ const localVarOperationServerBasePath = operationServerMap['DefaultApi.authControllerLogin']?.[localVarOperationServerIndex]?.url;
+ return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+ },
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async authControllerMe(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
+ const localVarAxiosArgs = await localVarAxiosParamCreator.authControllerMe(options);
+ const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+ const localVarOperationServerBasePath = operationServerMap['DefaultApi.authControllerMe']?.[localVarOperationServerIndex]?.url;
+ return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+ },
+ /**
+ *
+ * @param {any} code
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async authControllerOauthRedirect(code: any, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
+ const localVarAxiosArgs = await localVarAxiosParamCreator.authControllerOauthRedirect(code, options);
+ const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+ const localVarOperationServerBasePath = operationServerMap['DefaultApi.authControllerOauthRedirect']?.[localVarOperationServerIndex]?.url;
+ return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+ },
/**
* # Health check endpoint
This endpoint is a simple health check API designed to confirm that the server is operational. When accessed, it returns a straightforward response indicating that the service is up and running.
* @summary
@@ -105,6 +248,31 @@ export const DefaultApiFp = function(configuration?: Configuration) {
export const DefaultApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
const localVarFp = DefaultApiFp(configuration)
return {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ authControllerLogin(options?: any): AxiosPromise {
+ return localVarFp.authControllerLogin(options).then((request) => request(axios, basePath));
+ },
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ authControllerMe(options?: any): AxiosPromise {
+ return localVarFp.authControllerMe(options).then((request) => request(axios, basePath));
+ },
+ /**
+ *
+ * @param {any} code
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ authControllerOauthRedirect(code: any, options?: any): AxiosPromise {
+ return localVarFp.authControllerOauthRedirect(code, options).then((request) => request(axios, basePath));
+ },
/**
* # Health check endpoint
This endpoint is a simple health check API designed to confirm that the server is operational. When accessed, it returns a straightforward response indicating that the service is up and running.
* @summary
@@ -124,6 +292,37 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa
* @extends {BaseAPI}
*/
export class DefaultApi extends BaseAPI {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof DefaultApi
+ */
+ public authControllerLogin(options?: RawAxiosRequestConfig) {
+ return DefaultApiFp(this.configuration).authControllerLogin(options).then((request) => request(this.axios, this.basePath));
+ }
+
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof DefaultApi
+ */
+ public authControllerMe(options?: RawAxiosRequestConfig) {
+ return DefaultApiFp(this.configuration).authControllerMe(options).then((request) => request(this.axios, this.basePath));
+ }
+
+ /**
+ *
+ * @param {any} code
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof DefaultApi
+ */
+ public authControllerOauthRedirect(code: any, options?: RawAxiosRequestConfig) {
+ return DefaultApiFp(this.configuration).authControllerOauthRedirect(code, options).then((request) => request(this.axios, this.basePath));
+ }
+
/**
* # Health check endpoint
This endpoint is a simple health check API designed to confirm that the server is operational. When accessed, it returns a straightforward response indicating that the service is up and running.
* @summary
diff --git a/yarn.lock b/yarn.lock
index 4f7c9d9..f469feb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -925,6 +925,16 @@ __metadata:
languageName: node
linkType: hard
+"@kir-dev/passport-authsch@npm:^2.0.3":
+ version: 2.0.4
+ resolution: "@kir-dev/passport-authsch@npm:2.0.4"
+ dependencies:
+ axios: "npm:^1.7.4"
+ passport-strategy: "npm:^1.0.0"
+ checksum: 10c0/2faa19e997b509dc59be2e33b6323f9a71f78bf6f887641a3e95f890968940907b4412c1b3d8fde17c5db680b1e4d4da6966505cf5198cfb12ff14f8f08fc0a6
+ languageName: node
+ linkType: hard
+
"@ljharb/through@npm:^2.3.12":
version: 2.3.13
resolution: "@ljharb/through@npm:2.3.13"
@@ -1113,6 +1123,18 @@ __metadata:
languageName: node
linkType: hard
+"@nestjs/jwt@npm:^10.2.0":
+ version: 10.2.0
+ resolution: "@nestjs/jwt@npm:10.2.0"
+ dependencies:
+ "@types/jsonwebtoken": "npm:9.0.5"
+ jsonwebtoken: "npm:9.0.2"
+ peerDependencies:
+ "@nestjs/common": ^8.0.0 || ^9.0.0 || ^10.0.0
+ checksum: 10c0/81c5cbcb459122b175ad6b50dad83aab7d5dc3beb6122a56c7f985cc1c7838cd1c5eae9d630e95550b95a03e183502a183029e36ba51879c638bd0bad086c056
+ languageName: node
+ linkType: hard
+
"@nestjs/mapped-types@npm:2.0.5":
version: 2.0.5
resolution: "@nestjs/mapped-types@npm:2.0.5"
@@ -1130,6 +1152,16 @@ __metadata:
languageName: node
linkType: hard
+"@nestjs/passport@npm:^10.0.3":
+ version: 10.0.3
+ resolution: "@nestjs/passport@npm:10.0.3"
+ peerDependencies:
+ "@nestjs/common": ^8.0.0 || ^9.0.0 || ^10.0.0
+ passport: ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0
+ checksum: 10c0/9e8a6103407852951625e75d0abd82a0f9786d4f27fc7036731ccbac39cbdb4e597a7313e53a266bb1fe1ec36c5193365abeb3264f5d285ba0aaeb23ee8e3f1b
+ languageName: node
+ linkType: hard
+
"@nestjs/platform-express@npm:^10.0.0":
version: 10.4.1
resolution: "@nestjs/platform-express@npm:10.4.1"
@@ -1919,7 +1951,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/express@npm:^4.17.21":
+"@types/express@npm:*, @types/express@npm:^4.17.21":
version: 4.17.21
resolution: "@types/express@npm:4.17.21"
dependencies:
@@ -1982,6 +2014,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/js-cookie@npm:^3.0.6":
+ version: 3.0.6
+ resolution: "@types/js-cookie@npm:3.0.6"
+ checksum: 10c0/173afaf5ea9d86c22395b9d2a00b6adb0006dcfef165d6dcb0395cdc32f5a5dcf9c3c60f97194119963a15849b8f85121e1ae730b03e40bc0c29b84396ba22f9
+ languageName: node
+ linkType: hard
+
"@types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9":
version: 7.0.15
resolution: "@types/json-schema@npm:7.0.15"
@@ -1996,6 +2035,24 @@ __metadata:
languageName: node
linkType: hard
+"@types/jsonwebtoken@npm:*":
+ version: 9.0.6
+ resolution: "@types/jsonwebtoken@npm:9.0.6"
+ dependencies:
+ "@types/node": "npm:*"
+ checksum: 10c0/9c29e3896e5fb6056e54d87514643e59e0cfb966ae25171a107776270195bba955f0373e98c8ed6450c145b18984f5df9cf0fcac360f382cec3c7c4d3510b202
+ languageName: node
+ linkType: hard
+
+"@types/jsonwebtoken@npm:9.0.5":
+ version: 9.0.5
+ resolution: "@types/jsonwebtoken@npm:9.0.5"
+ dependencies:
+ "@types/node": "npm:*"
+ checksum: 10c0/c582b8420586f3b9550f7e34992cb32be300bc953636f3b087ed9c180ce7ea5c2e4b35090be2d57f0d3168cc3ca1074932907caa2afe09f4e9c84cf5c0daefa8
+ languageName: node
+ linkType: hard
+
"@types/methods@npm:^1.1.4":
version: 1.1.4
resolution: "@types/methods@npm:1.1.4"
@@ -2035,6 +2092,35 @@ __metadata:
languageName: node
linkType: hard
+"@types/passport-jwt@npm:^4.0.1":
+ version: 4.0.1
+ resolution: "@types/passport-jwt@npm:4.0.1"
+ dependencies:
+ "@types/jsonwebtoken": "npm:*"
+ "@types/passport-strategy": "npm:*"
+ checksum: 10c0/0ced0eaa7bb379d674821108d9bc6758223f1a5f2b9790ec78d3eaaccce6a58a424cf8ed22b53d813740ec53d929e21d92cf794ef0fb30c732866750763c0d7a
+ languageName: node
+ linkType: hard
+
+"@types/passport-strategy@npm:*":
+ version: 0.2.38
+ resolution: "@types/passport-strategy@npm:0.2.38"
+ dependencies:
+ "@types/express": "npm:*"
+ "@types/passport": "npm:*"
+ checksum: 10c0/d7d2b1782a0845bd8914250aa9213a23c8d9c2225db46d854b77f2bf0129a789f46d4a5e9ad336eca277fc7e0a051c0a2942da5c864e7c6710763f102d9d4295
+ languageName: node
+ linkType: hard
+
+"@types/passport@npm:*":
+ version: 1.0.16
+ resolution: "@types/passport@npm:1.0.16"
+ dependencies:
+ "@types/express": "npm:*"
+ checksum: 10c0/7120c1186c8c67e3818683b5b6a4439d102f67da93cc1c7d8f32484f7bf10e8438dd5de0bf571910b23d06caa43dd1ad501933b48618bfaf54e63219500993fe
+ languageName: node
+ linkType: hard
+
"@types/prop-types@npm:*":
version: 15.7.12
resolution: "@types/prop-types@npm:15.7.12"
@@ -3074,7 +3160,7 @@ __metadata:
languageName: node
linkType: hard
-"axios@npm:^1.7.6":
+"axios@npm:^1.7.4, axios@npm:^1.7.6":
version: 1.7.6
resolution: "axios@npm:1.7.6"
dependencies:
@@ -3177,9 +3263,12 @@ __metadata:
version: 0.0.0-use.local
resolution: "backend@workspace:backend"
dependencies:
+ "@kir-dev/passport-authsch": "npm:^2.0.3"
"@nestjs/cli": "npm:^10.0.0"
"@nestjs/common": "npm:^10.0.0"
"@nestjs/core": "npm:^10.0.0"
+ "@nestjs/jwt": "npm:^10.2.0"
+ "@nestjs/passport": "npm:^10.0.3"
"@nestjs/platform-express": "npm:^10.0.0"
"@nestjs/schematics": "npm:^10.0.0"
"@nestjs/swagger": "npm:^7.4.0"
@@ -3188,16 +3277,21 @@ __metadata:
"@types/express": "npm:^4.17.21"
"@types/jest": "npm:^29.5.2"
"@types/node": "npm:^20.3.1"
+ "@types/passport-jwt": "npm:^4.0.1"
"@types/supertest": "npm:^6.0.0"
"@typescript-eslint/eslint-plugin": "npm:^7.0.0"
"@typescript-eslint/parser": "npm:^7.0.0"
"@vercel/style-guide": "npm:^6.0.0"
+ dotenv: "npm:^16.4.5"
+ env-var: "npm:^7.5.0"
eslint: "npm:^8.42.0"
eslint-config-prettier: "npm:^9.0.0"
eslint-plugin-prettier: "npm:^5.0.0"
express: "npm:^4.19.2"
jest: "npm:^29.5.0"
nestjs-prisma: "npm:^0.23.0"
+ passport: "npm:^0.7.0"
+ passport-jwt: "npm:^4.0.1"
prettier: "npm:^3.0.0"
prisma: "npm:^5.17.0"
reflect-metadata: "npm:^0.2.0"
@@ -3326,6 +3420,13 @@ __metadata:
languageName: node
linkType: hard
+"buffer-equal-constant-time@npm:1.0.1":
+ version: 1.0.1
+ resolution: "buffer-equal-constant-time@npm:1.0.1"
+ checksum: 10c0/fb2294e64d23c573d0dd1f1e7a466c3e978fe94a4e0f8183937912ca374619773bef8e2aceb854129d2efecbbc515bbd0cc78d2734a3e3031edb0888531bbc8e
+ languageName: node
+ linkType: hard
+
"buffer-from@npm:^1.0.0":
version: 1.1.2
resolution: "buffer-from@npm:1.1.2"
@@ -4231,6 +4332,13 @@ __metadata:
languageName: node
linkType: hard
+"dotenv@npm:^16.4.5":
+ version: 16.4.5
+ resolution: "dotenv@npm:16.4.5"
+ checksum: 10c0/48d92870076832af0418b13acd6e5a5a3e83bb00df690d9812e94b24aff62b88ade955ac99a05501305b8dc8f1b0ee7638b18493deb6fe93d680e5220936292f
+ languageName: node
+ linkType: hard
+
"eastasianwidth@npm:^0.2.0":
version: 0.2.0
resolution: "eastasianwidth@npm:0.2.0"
@@ -4250,6 +4358,15 @@ __metadata:
languageName: node
linkType: hard
+"ecdsa-sig-formatter@npm:1.0.11":
+ version: 1.0.11
+ resolution: "ecdsa-sig-formatter@npm:1.0.11"
+ dependencies:
+ safe-buffer: "npm:^5.0.1"
+ checksum: 10c0/ebfbf19d4b8be938f4dd4a83b8788385da353d63307ede301a9252f9f7f88672e76f2191618fd8edfc2f24679236064176fab0b78131b161ee73daa37125408c
+ languageName: node
+ linkType: hard
+
"ee-first@npm:1.1.1":
version: 1.1.1
resolution: "ee-first@npm:1.1.1"
@@ -4329,6 +4446,13 @@ __metadata:
languageName: node
linkType: hard
+"env-var@npm:^7.5.0":
+ version: 7.5.0
+ resolution: "env-var@npm:7.5.0"
+ checksum: 10c0/7eb93446417b2a1caaec213ffa1a28686a23d18f9364c9c007c113bedabf4632f8890a95b23022f3ac59351807f8ed27fce3ea68f85462406d7d19b2f6c75e88
+ languageName: node
+ linkType: hard
+
"err-code@npm:^2.0.2":
version: 2.0.3
resolution: "err-code@npm:2.0.3"
@@ -5377,6 +5501,7 @@ __metadata:
dependencies:
"@radix-ui/react-navigation-menu": "npm:^1.2.0"
"@radix-ui/react-slot": "npm:^1.1.0"
+ "@types/js-cookie": "npm:^3.0.6"
"@types/node": "npm:^20"
"@types/react": "npm:^18"
"@types/react-dom": "npm:^18"
@@ -5388,6 +5513,7 @@ __metadata:
eslint: "npm:^8.0.0"
eslint-config-next: "npm:14.2.5"
eslint-plugin-react: "npm:^7.35.0"
+ js-cookie: "npm:^3.0.5"
lucide-react: "npm:^0.414.0"
next: "npm:14.2.5"
postcss: "npm:^8.4.39"
@@ -6972,6 +7098,13 @@ __metadata:
languageName: node
linkType: hard
+"js-cookie@npm:^3.0.5":
+ version: 3.0.5
+ resolution: "js-cookie@npm:3.0.5"
+ checksum: 10c0/04a0e560407b4489daac3a63e231d35f4e86f78bff9d792011391b49c59f721b513411cd75714c418049c8dc9750b20fcddad1ca5a2ca616c3aca4874cce5b3a
+ languageName: node
+ linkType: hard
+
"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0":
version: 4.0.0
resolution: "js-tokens@npm:4.0.0"
@@ -7125,6 +7258,24 @@ __metadata:
languageName: node
linkType: hard
+"jsonwebtoken@npm:9.0.2, jsonwebtoken@npm:^9.0.0":
+ version: 9.0.2
+ resolution: "jsonwebtoken@npm:9.0.2"
+ dependencies:
+ jws: "npm:^3.2.2"
+ lodash.includes: "npm:^4.3.0"
+ lodash.isboolean: "npm:^3.0.3"
+ lodash.isinteger: "npm:^4.0.4"
+ lodash.isnumber: "npm:^3.0.3"
+ lodash.isplainobject: "npm:^4.0.6"
+ lodash.isstring: "npm:^4.0.1"
+ lodash.once: "npm:^4.0.0"
+ ms: "npm:^2.1.1"
+ semver: "npm:^7.5.4"
+ checksum: 10c0/d287a29814895e866db2e5a0209ce730cbc158441a0e5a70d5e940eb0d28ab7498c6bf45029cc8b479639bca94056e9a7f254e2cdb92a2f5750c7f358657a131
+ languageName: node
+ linkType: hard
+
"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.5":
version: 3.3.5
resolution: "jsx-ast-utils@npm:3.3.5"
@@ -7137,6 +7288,27 @@ __metadata:
languageName: node
linkType: hard
+"jwa@npm:^1.4.1":
+ version: 1.4.1
+ resolution: "jwa@npm:1.4.1"
+ dependencies:
+ buffer-equal-constant-time: "npm:1.0.1"
+ ecdsa-sig-formatter: "npm:1.0.11"
+ safe-buffer: "npm:^5.0.1"
+ checksum: 10c0/5c533540bf38702e73cf14765805a94027c66a0aa8b16bc3e89d8d905e61a4ce2791e87e21be97d1293a5ee9d4f3e5e47737e671768265ca4f25706db551d5e9
+ languageName: node
+ linkType: hard
+
+"jws@npm:^3.2.2":
+ version: 3.2.2
+ resolution: "jws@npm:3.2.2"
+ dependencies:
+ jwa: "npm:^1.4.1"
+ safe-buffer: "npm:^5.0.1"
+ checksum: 10c0/e770704533d92df358adad7d1261fdecad4d7b66fa153ba80d047e03ca0f1f73007ce5ed3fbc04d2eba09ba6e7e6e645f351e08e5ab51614df1b0aa4f384dfff
+ languageName: node
+ linkType: hard
+
"keyv@npm:^4.5.3":
version: 4.5.4
resolution: "keyv@npm:4.5.4"
@@ -7232,6 +7404,48 @@ __metadata:
languageName: node
linkType: hard
+"lodash.includes@npm:^4.3.0":
+ version: 4.3.0
+ resolution: "lodash.includes@npm:4.3.0"
+ checksum: 10c0/7ca498b9b75bf602d04e48c0adb842dfc7d90f77bcb2a91a2b2be34a723ad24bc1c8b3683ec6b2552a90f216c723cdea530ddb11a3320e08fa38265703978f4b
+ languageName: node
+ linkType: hard
+
+"lodash.isboolean@npm:^3.0.3":
+ version: 3.0.3
+ resolution: "lodash.isboolean@npm:3.0.3"
+ checksum: 10c0/0aac604c1ef7e72f9a6b798e5b676606042401dd58e49f051df3cc1e3adb497b3d7695635a5cbec4ae5f66456b951fdabe7d6b387055f13267cde521f10ec7f7
+ languageName: node
+ linkType: hard
+
+"lodash.isinteger@npm:^4.0.4":
+ version: 4.0.4
+ resolution: "lodash.isinteger@npm:4.0.4"
+ checksum: 10c0/4c3e023a2373bf65bf366d3b8605b97ec830bca702a926939bcaa53f8e02789b6a176e7f166b082f9365bfec4121bfeb52e86e9040cb8d450e64c858583f61b7
+ languageName: node
+ linkType: hard
+
+"lodash.isnumber@npm:^3.0.3":
+ version: 3.0.3
+ resolution: "lodash.isnumber@npm:3.0.3"
+ checksum: 10c0/2d01530513a1ee4f72dd79528444db4e6360588adcb0e2ff663db2b3f642d4bb3d687051ae1115751ca9082db4fdef675160071226ca6bbf5f0c123dbf0aa12d
+ languageName: node
+ linkType: hard
+
+"lodash.isplainobject@npm:^4.0.6":
+ version: 4.0.6
+ resolution: "lodash.isplainobject@npm:4.0.6"
+ checksum: 10c0/afd70b5c450d1e09f32a737bed06ff85b873ecd3d3d3400458725283e3f2e0bb6bf48e67dbe7a309eb371a822b16a26cca4a63c8c52db3fc7dc9d5f9dd324cbb
+ languageName: node
+ linkType: hard
+
+"lodash.isstring@npm:^4.0.1":
+ version: 4.0.1
+ resolution: "lodash.isstring@npm:4.0.1"
+ checksum: 10c0/09eaf980a283f9eef58ef95b30ec7fee61df4d6bf4aba3b5f096869cc58f24c9da17900febc8ffd67819b4e29de29793190e88dc96983db92d84c95fa85d1c92
+ languageName: node
+ linkType: hard
+
"lodash.memoize@npm:^4.1.2":
version: 4.1.2
resolution: "lodash.memoize@npm:4.1.2"
@@ -7246,6 +7460,13 @@ __metadata:
languageName: node
linkType: hard
+"lodash.once@npm:^4.0.0":
+ version: 4.1.1
+ resolution: "lodash.once@npm:4.1.1"
+ checksum: 10c0/46a9a0a66c45dd812fcc016e46605d85ad599fe87d71a02f6736220554b52ffbe82e79a483ad40f52a8a95755b0d1077fba259da8bfb6694a7abbf4a48f1fc04
+ languageName: node
+ linkType: hard
+
"lodash@npm:4.17.21, lodash@npm:^4.17.21":
version: 4.17.21
resolution: "lodash@npm:4.17.21"
@@ -8152,6 +8373,34 @@ __metadata:
languageName: node
linkType: hard
+"passport-jwt@npm:^4.0.1":
+ version: 4.0.1
+ resolution: "passport-jwt@npm:4.0.1"
+ dependencies:
+ jsonwebtoken: "npm:^9.0.0"
+ passport-strategy: "npm:^1.0.0"
+ checksum: 10c0/d7e2b472d399f596a1db31310f8e63d10777ab7468b9a378c964156e5f0a772598b007417356ead578cfdaf60dc2bba39a55f0033ca865186fdb2a2b198e2e7e
+ languageName: node
+ linkType: hard
+
+"passport-strategy@npm:1.x.x, passport-strategy@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "passport-strategy@npm:1.0.0"
+ checksum: 10c0/cf4cd32e1bf2538a239651581292fbb91ccc83973cde47089f00d2014c24bed63d3e65af21da8ddef649a8896e089eb9c3ac9ca639f36c797654ae9ee4ed65e1
+ languageName: node
+ linkType: hard
+
+"passport@npm:^0.7.0":
+ version: 0.7.0
+ resolution: "passport@npm:0.7.0"
+ dependencies:
+ passport-strategy: "npm:1.x.x"
+ pause: "npm:0.0.1"
+ utils-merge: "npm:^1.0.1"
+ checksum: 10c0/08c940b86e4adbfe43e753f8097300a5a9d1ce9a3aa002d7b12d27770943a1a87202c54597c0f04dbfd4117d67de76303433577512fc19c7e364fec37b0d3fc5
+ languageName: node
+ linkType: hard
+
"path-exists@npm:^4.0.0":
version: 4.0.0
resolution: "path-exists@npm:4.0.0"
@@ -8211,6 +8460,13 @@ __metadata:
languageName: node
linkType: hard
+"pause@npm:0.0.1":
+ version: 0.0.1
+ resolution: "pause@npm:0.0.1"
+ checksum: 10c0/f362655dfa7f44b946302c5a033148852ed5d05f744bd848b1c7eae6a543f743e79c7751ee896ba519fd802affdf239a358bb2ea5ca1b1c1e4e916279f83ab75
+ languageName: node
+ linkType: hard
+
"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1":
version: 1.0.1
resolution: "picocolors@npm:1.0.1"
@@ -8964,7 +9220,7 @@ __metadata:
languageName: node
linkType: hard
-"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0":
+"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0":
version: 5.2.1
resolution: "safe-buffer@npm:5.2.1"
checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3
@@ -10362,7 +10618,7 @@ __metadata:
languageName: node
linkType: hard
-"utils-merge@npm:1.0.1":
+"utils-merge@npm:1.0.1, utils-merge@npm:^1.0.1":
version: 1.0.1
resolution: "utils-merge@npm:1.0.1"
checksum: 10c0/02ba649de1b7ca8854bfe20a82f1dfbdda3fb57a22ab4a8972a63a34553cf7aa51bc9081cf7e001b035b88186d23689d69e71b510e610a09a4c66f68aa95b672