Skip to content

Commit cfda25f

Browse files
committed
middle ware and profile
1 parent 803cec9 commit cfda25f

5 files changed

Lines changed: 160 additions & 33 deletions

File tree

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// pages/api/set-auth-cookie/route.ts
2+
import type { NextApiRequest, NextApiResponse } from 'next';
3+
import { getAuth } from 'firebase-admin/auth';
4+
import { initializeApp, getApps, cert } from 'firebase-admin/app';
5+
import { serialize } from 'cookie';
6+
7+
const serviceAccount = {
8+
// Replace these with your service account values
9+
projectId: process.env.FIREBASE_PROJECT_ID,
10+
privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
11+
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
12+
};
13+
14+
if (!getApps().length) {
15+
initializeApp({
16+
credential: cert(serviceAccount as any),
17+
});
18+
}
19+
20+
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
21+
if (req.method !== 'POST') return res.status(405).end();
22+
23+
const { idToken } = req.body;
24+
if (!idToken) return res.status(400).json({ error: 'ID token required' });
25+
26+
try {
27+
const decodedToken = await getAuth().verifyIdToken(idToken);
28+
29+
// Set secure HttpOnly cookie
30+
const cookie = serialize('authToken', idToken, {
31+
httpOnly: true,
32+
secure: process.env.NODE_ENV === 'production',
33+
maxAge: 60 * 60 * 24, // 1 day
34+
path: '/',
35+
sameSite: 'lax',
36+
});
37+
38+
res.setHeader('Set-Cookie', cookie);
39+
res.status(200).json({ success: true });
40+
} catch (err) {
41+
console.error(err);
42+
res.status(401).json({ error: 'Invalid token' });
43+
}
44+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"use client";
2+
3+
import { useRouter } from "next/navigation";
4+
import { ArrowLeft, ChevronDown } from "lucide-react";
5+
import { useState } from "react";
6+
7+
export default function EditProfile() {
8+
const router = useRouter();
9+
const [sem, setSem] = useState("");
10+
const [dept, setDept] = useState("");
11+
const [course, setCourse] = useState("");
12+
13+
return (
14+
<div className="min-h-screen bg-white flex flex-col items-center p-4 md:p-8">
15+
<div className="w-full max-w-md">
16+
<button onClick={() => router.back()} className="mb-4">
17+
<ArrowLeft className="text-gray-700" />
18+
</button>
19+
20+
<h1 className="text-2xl font-semibold text-center mb-1">Profile</h1>
21+
<p className="text-center text-gray-500 mb-6">Edit Profile</p>
22+
23+
<div className="flex flex-col items-center mb-6">
24+
<div className="w-24 h-24 bg-gray-300 rounded-full flex items-center justify-center text-sm text-gray-600 mb-2">
25+
Upload Image
26+
</div>
27+
</div>
28+
29+
<div className="space-y-4">
30+
<input
31+
type="text"
32+
placeholder="Enter Your Sem"
33+
value={sem}
34+
onChange={(e) => setSem(e.target.value)}
35+
className="w-full px-4 py-2 border rounded-md outline-none focus:ring-2 ring-gray-300"
36+
/>
37+
<input
38+
type="text"
39+
placeholder="Enter Your Department"
40+
value={dept}
41+
onChange={(e) => setDept(e.target.value)}
42+
className="w-full px-4 py-2 border rounded-md outline-none focus:ring-2 ring-gray-300"
43+
/>
44+
<div className="relative">
45+
<select
46+
value={course}
47+
onChange={(e) => setCourse(e.target.value)}
48+
className="w-full appearance-none px-4 py-2 border rounded-md outline-none focus:ring-2 ring-gray-300"
49+
>
50+
<option value="">Select Your Course</option>
51+
<option value="btech">B.Tech</option>
52+
<option value="mtech">M.Tech</option>
53+
<option value="mba">MBA</option>
54+
</select>
55+
<ChevronDown className="absolute right-3 top-3 text-gray-500 pointer-events-none" />
56+
</div>
57+
<button className="w-full py-2 bg-gray-700 text-white rounded-md hover:bg-gray-800 transition">
58+
Confirm
59+
</button>
60+
</div>
61+
</div>
62+
</div>
63+
);
64+
}

src/app/profile/page.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"use client";
2+
3+
import { useRouter } from "next/navigation";
4+
import { ArrowLeft } from "lucide-react";
5+
6+
export default function Profile() {
7+
const router = useRouter();
8+
9+
return (
10+
<div className="min-h-screen bg-white flex flex-col items-center p-4 md:p-8">
11+
<div className="w-full max-w-md">
12+
<button onClick={() => router.back()} className="mb-4">
13+
<ArrowLeft className="text-gray-700" />
14+
</button>
15+
16+
<h1 className="text-2xl font-semibold text-center mb-1">Profile</h1>
17+
<div className="w-24 h-1 bg-gray-300 mx-auto rounded-full mb-6"></div>
18+
19+
<div className="flex flex-col items-center">
20+
<div className="w-24 h-24 bg-gray-300 rounded-full mb-4" />
21+
22+
<h2 className="text-lg font-medium">Name</h2>
23+
<p className="text-sm text-gray-500">Sem - Dept</p>
24+
25+
<button
26+
onClick={() => router.push("/profile/editProfile")}
27+
className="mt-6 px-6 py-2 border border-gray-600 rounded-md hover:bg-gray-100 transition"
28+
>
29+
Edit Profile
30+
</button>
31+
</div>
32+
</div>
33+
</div>
34+
);
35+
}

src/components/topNavbar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const Header: React.FC<{
2020
? `S${semester}, `
2121
: "";
2222
const handleUsrProfileClick = () => {
23-
router.push("/login");
23+
router.push("/profile");
2424
};
2525

2626
return (

src/middleware.ts

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,27 @@
1-
// middleware.ts
2-
import { NextResponse } from 'next/server'
3-
import type { NextRequest } from 'next/server'
1+
import { NextResponse } from 'next/server';
2+
import type { NextRequest } from 'next/server';
43

54
export function middleware(request: NextRequest) {
6-
const { pathname } = request.nextUrl
7-
const token = request.cookies.get('authToken')?.value
5+
const { pathname } = request.nextUrl;
6+
const token = request.cookies.get('authToken')?.value;
87

9-
// Define public routes that don't need authentication
10-
const publicRoutes = [ '/auth']
11-
12-
// Check if the current path is a public route
13-
const isPublicRoute = publicRoutes.includes(pathname) ||
14-
publicRoutes.some(route => pathname.startsWith(route + '/'))
8+
// Public routes that don't require auth
9+
const publicRoutes = ['/auth'];
10+
const isPublicRoute =
11+
publicRoutes.includes(pathname) ||
12+
publicRoutes.some((route) => pathname.startsWith(route + '/'));
1513

16-
// If user has no token and trying to access protected route
17-
if (!token && !isPublicRoute) {
18-
console.log(`Redirecting ${pathname} to /auth - no token`)
19-
return NextResponse.redirect(new URL('/auth', request.url))
20-
}
14+
// If no token and trying to access protected route
15+
// if (!token && !isPublicRoute) {
16+
// console.log(`Redirecting ${pathname} to /auth - no token`);
17+
// return NextResponse.redirect(new URL('/auth', request.url));
18+
// }
2119

22-
// If user has token and trying to access auth page, redirect to home
23-
if (token && pathname === '/auth') {
24-
console.log(`Redirecting from /auth to / - user has token`)
25-
return NextResponse.redirect(new URL('/', request.url))
26-
}
27-
28-
return NextResponse.next()
20+
return NextResponse.next();
2921
}
3022

3123
export const config = {
3224
matcher: [
33-
/*
34-
* Match all request paths except for the ones starting with:
35-
* - api (API routes)
36-
* - _next/static (static files)
37-
* - _next/image (image optimization files)
38-
* - favicon.ico (favicon file)
39-
* - public files (images, etc.)
40-
*/
4125
'/((?!api|_next/static|_next/image|favicon.ico|images|.*\\..*).*)',
4226
],
43-
}
27+
};

0 commit comments

Comments
 (0)