kurulum4
This commit is contained in:
parent
7e222bacbf
commit
812f8dceec
61
frontend/src/app/admin/login/page.tsx
Normal file
61
frontend/src/app/admin/login/page.tsx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
'use client';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
|
||||||
|
export default function AdminLogin() {
|
||||||
|
const [username, setUsername] = useState('');
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const handleLogin = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
// Basic mock authentication
|
||||||
|
if (username && password) {
|
||||||
|
document.cookie = "auth_token=admin_token; path=/; max-age=3600";
|
||||||
|
router.push('/');
|
||||||
|
router.refresh();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen flex items-center justify-center bg-zinc-950 p-4">
|
||||||
|
<div className="w-full max-w-md bg-zinc-900 border border-zinc-800 rounded-2xl shadow-xl p-8">
|
||||||
|
<div className="text-center mb-8">
|
||||||
|
<h1 className="text-2xl font-light text-zinc-100 tracking-tight">ArmoReg <span className="font-semibold">Admin</span></h1>
|
||||||
|
<p className="text-zinc-500 text-sm mt-2">Sign in to central management</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form onSubmit={handleLogin} className="space-y-5">
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-zinc-400 mb-1">Username</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
required
|
||||||
|
value={username}
|
||||||
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
|
className="w-full bg-zinc-950 border border-zinc-800 rounded-lg px-4 py-2.5 text-zinc-100 focus:outline-none focus:border-zinc-600 focus:ring-1 focus:ring-zinc-600 transition-colors"
|
||||||
|
placeholder="admin"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-zinc-400 mb-1">Password</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
required
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
className="w-full bg-zinc-950 border border-zinc-800 rounded-lg px-4 py-2.5 text-zinc-100 focus:outline-none focus:border-zinc-600 focus:ring-1 focus:ring-zinc-600 transition-colors"
|
||||||
|
placeholder="••••••••"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="w-full bg-white text-zinc-950 font-medium rounded-lg px-4 py-2.5 hover:bg-zinc-200 transition-colors mt-2"
|
||||||
|
>
|
||||||
|
Sign In
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
61
frontend/src/app/panel/login/page.tsx
Normal file
61
frontend/src/app/panel/login/page.tsx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
'use client';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
|
||||||
|
export default function TenantLogin() {
|
||||||
|
const [username, setUsername] = useState('');
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const handleLogin = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
// Basic mock authentication
|
||||||
|
if (username && password) {
|
||||||
|
document.cookie = "auth_token=tenant_token; path=/; max-age=3600";
|
||||||
|
router.push('/');
|
||||||
|
router.refresh();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen flex items-center justify-center bg-zinc-50 p-4">
|
||||||
|
<div className="w-full max-w-md bg-white border border-zinc-200 rounded-2xl shadow-xl p-8">
|
||||||
|
<div className="text-center mb-8">
|
||||||
|
<h1 className="text-2xl font-light text-zinc-800 tracking-tight">Customer <span className="font-semibold text-blue-600">Panel</span></h1>
|
||||||
|
<p className="text-zinc-500 text-sm mt-2">Manage your Hotspot & Firewall</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form onSubmit={handleLogin} className="space-y-5">
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-zinc-600 mb-1">Tenant ID / Email</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
required
|
||||||
|
value={username}
|
||||||
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
|
className="w-full bg-white border border-zinc-300 rounded-lg px-4 py-2.5 text-zinc-900 focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-colors"
|
||||||
|
placeholder="customer@domain.com"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-zinc-600 mb-1">Password</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
required
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
className="w-full bg-white border border-zinc-300 rounded-lg px-4 py-2.5 text-zinc-900 focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-colors"
|
||||||
|
placeholder="••••••••"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="w-full bg-blue-600 text-white font-medium rounded-lg px-4 py-2.5 hover:bg-blue-700 transition-colors mt-2 shadow-sm shadow-blue-200"
|
||||||
|
>
|
||||||
|
Sign In
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -3,27 +3,32 @@ import type { NextRequest } from 'next/server';
|
|||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
matcher: [
|
matcher: [
|
||||||
/*
|
|
||||||
* Match all request paths except for the ones starting with:
|
|
||||||
* - api (API routes)
|
|
||||||
* - _next/static (static files)
|
|
||||||
* - _next/image (image optimization files)
|
|
||||||
* - favicon.ico, sitemap.xml, robots.txt (metadata files)
|
|
||||||
*/
|
|
||||||
'/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)',
|
'/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export function middleware(req: NextRequest) {
|
export function middleware(req: NextRequest) {
|
||||||
const url = req.nextUrl;
|
const url = req.nextUrl;
|
||||||
|
|
||||||
// Get hostname (e.g., admin.armoreg.com, panel.armoreg.com, localhost:3000)
|
|
||||||
const hostname = req.headers.get('host') || '';
|
const hostname = req.headers.get('host') || '';
|
||||||
|
|
||||||
// Determine which subdomain we are on
|
// Determine which subdomain we are on
|
||||||
const isAdmin = hostname.includes('admin.armoreg.com') || hostname.startsWith('admin.localhost');
|
const isAdmin = hostname.includes('admin.armoreg.com') || hostname.startsWith('admin.localhost');
|
||||||
const isPanel = hostname.includes('panel.armoreg.com') || hostname.startsWith('panel.localhost');
|
const isPanel = hostname.includes('panel.armoreg.com') || hostname.startsWith('panel.localhost');
|
||||||
|
|
||||||
|
// Simple authentication check via cookie (to be expanded later)
|
||||||
|
const isAuthenticated = req.cookies.has('auth_token');
|
||||||
|
const isLoginPage = url.pathname === '/login';
|
||||||
|
|
||||||
|
// If not authenticated and not on login page, redirect to login
|
||||||
|
if (!isAuthenticated && !isLoginPage) {
|
||||||
|
return NextResponse.redirect(new URL('/login', req.url));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If authenticated and on login page, redirect to root
|
||||||
|
if (isAuthenticated && isLoginPage) {
|
||||||
|
return NextResponse.redirect(new URL('/', req.url));
|
||||||
|
}
|
||||||
|
|
||||||
// Rewrite to the appropriate folder inside /app
|
// Rewrite to the appropriate folder inside /app
|
||||||
if (isAdmin) {
|
if (isAdmin) {
|
||||||
return NextResponse.rewrite(new URL(`/admin${url.pathname}`, req.url));
|
return NextResponse.rewrite(new URL(`/admin${url.pathname}`, req.url));
|
||||||
@ -33,6 +38,5 @@ export function middleware(req: NextRequest) {
|
|||||||
return NextResponse.rewrite(new URL(`/panel${url.pathname}`, req.url));
|
return NextResponse.rewrite(new URL(`/panel${url.pathname}`, req.url));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default fallback (e.g. main landing page or redirect to panel)
|
|
||||||
return NextResponse.next();
|
return NextResponse.next();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user