Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9adabb6f5d | ||
|
|
9f031a6757 | ||
|
|
342e17aed2 | ||
|
|
428b6f58d8 | ||
|
|
af20fcb1dc | ||
|
|
f069b84f87 | ||
|
|
60159970aa | ||
|
|
dcadef92b6 | ||
|
|
3f195e1765 | ||
|
|
7df2789153 | ||
| 4252478e73 |
@@ -1,10 +1,13 @@
|
||||
FROM node:20-alpine AS builder
|
||||
ARG NODE_ENV=production
|
||||
ENV NODE_ENV=development
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json* ./
|
||||
COPY packages/shared/package.json ./packages/shared/
|
||||
RUN npm install
|
||||
COPY packages/shared/ ./packages/shared/
|
||||
COPY . .
|
||||
ENV NODE_ENV=production
|
||||
RUN npx next build
|
||||
|
||||
FROM node:20-alpine AS runner
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { NextConfig } from 'next';
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
transpilePackages: ['@fiberops/shared'],
|
||||
output: 'standalone',
|
||||
};
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@fiberops/shared",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"lint": "tsc --noEmit",
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "node",
|
||||
"lib": ["ES2022"],
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
|
||||
41
src/app/impersonate/page.tsx
Normal file
41
src/app/impersonate/page.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, Suspense } from 'react';
|
||||
import { useRouter, useSearchParams } from 'next/navigation';
|
||||
|
||||
function ImpersonateHandler() {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
useEffect(() => {
|
||||
const token = searchParams.get('token');
|
||||
const userStr = searchParams.get('user');
|
||||
const tenantStr = searchParams.get('tenant');
|
||||
|
||||
if (token && userStr && tenantStr) {
|
||||
localStorage.setItem('accessToken', token);
|
||||
localStorage.setItem('user', userStr);
|
||||
localStorage.setItem('tenant', tenantStr);
|
||||
localStorage.setItem('is_impersonating', 'true');
|
||||
router.push('/dashboard');
|
||||
} else {
|
||||
router.push('/login');
|
||||
}
|
||||
}, [router, searchParams]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default function ImpersonatePage() {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-surface-50 dark:bg-surface-900">
|
||||
<div className="text-center">
|
||||
<div className="w-10 h-10 border-4 border-primary-500 border-t-transparent rounded-full animate-spin mx-auto mb-4"></div>
|
||||
<p className="text-surface-600 dark:text-surface-400">Loading impersonation session...</p>
|
||||
</div>
|
||||
<Suspense fallback={null}>
|
||||
<ImpersonateHandler />
|
||||
</Suspense>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
10
src/app/not-found.tsx
Normal file
10
src/app/not-found.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<h1>404 - Page Not Found</h1>
|
||||
<p>The page you are looking for does not exist.</p>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user