Skip to content

Commit

Permalink
feat: add auth logic
Browse files Browse the repository at this point in the history
  • Loading branch information
amjed-ali-k committed Oct 10, 2023
1 parent a2177c8 commit a08279a
Show file tree
Hide file tree
Showing 15 changed files with 92 additions and 205 deletions.
27 changes: 0 additions & 27 deletions src/app/api/middleware.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/app/api/secure/batches/all/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Branch, Student } from "@prisma/client";
import { getUserId } from "@/components/auth/server";

export async function GET(request: NextRequest) {
const userId = await getUserId();
const userId = await getUserId(request);

const results = await prisma.batch.findMany({
where: {
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/secure/batches/new/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const schema = z.object({
});

export async function GET(request: NextRequest) {
const userId = await getUserId();
const userId = await getUserId(request);
const body = schema.safeParse(await request.json());
if (!body.success) {
const { errors } = body.error;
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/secure/branches/all/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { prisma } from "@/server/db/prisma";
import { getUserId } from "@/components/auth/server";

export async function GET(request: NextRequest) {
const userId = await getUserId();
const userId = await getUserId(request);

const results = await prisma.branch.findMany({
select: {
Expand Down
4 changes: 2 additions & 2 deletions src/app/api/secure/profile/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export async function PUT(request: NextRequest) {
{ status: 400 }
);
}
const userId = await getUserId();
const userId = await getUserId(request);

const res = await prisma.user.upsert({
where: {
Expand Down Expand Up @@ -57,7 +57,7 @@ export async function PUT(request: NextRequest) {
}

export async function GET(request: NextRequest) {
const userId = await getUserId();
const userId = await getUserId(request);

const res = await prisma.user.findUnique({
where: {
Expand Down
4 changes: 2 additions & 2 deletions src/app/api/secure/sbte-result/history/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { z } from "zod";
import { getUserId } from "@/components/auth/server";

export async function GET(request: NextRequest) {
const userId = await getUserId();
const userId = await getUserId(request);

const results = await prisma.examResultFormatHistory.findMany({
where: {
Expand Down Expand Up @@ -50,7 +50,7 @@ export async function DELETE(request: NextRequest) {
{ status: 400 }
);
}
const userId = await getUserId();
const userId = await getUserId(request);

await prisma.examResultFormatHistory.delete({
where: {
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/secure/sbte-result/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export async function POST(request: NextRequest) {
{ status: 400 }
);
}
const userId = await getUserId();
const userId = await getUserId(request);

const myProfile = await prisma.user.findUnique({
where: {
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/secure/sbte-result/single/[resultId]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export async function GET(
request: NextRequest,
{ params }: { params: { resultId: string } }
) {
const userId = await getUserId();
const userId = await getUserId(request);

const results = await prisma.examResultFormatHistory.findUnique({
where: {
Expand Down
24 changes: 24 additions & 0 deletions src/app/dashboard/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,35 @@
"use client";
import Navigation from "@/components/Navigation";
import { useProfile } from "@/lib/swr";
import { useEffect } from "react";
import { usePathname, useRouter } from "next/navigation";
import { useToast } from "@/components/ui/use-toast";

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const { data } = useProfile();
const pathName = usePathname();
const router = useRouter();
const { toast } = useToast();

useEffect(() => {
// check data.college, data.department, data.email, data.phonenumber exists
// if not, redirect to /profile

// if current page is /profile, do nothing
if (pathName === "/dashboard/profile") return;

if (data) {
if (!data.collegeId || !data.designation || !data.phone || !data.name) {
toast({ title: "Please complete your profile first" });
router.replace("/dashboard/profile");
}
}
}, [data, pathName, router, toast]);

return (
<>
<Navigation />
Expand Down
22 changes: 0 additions & 22 deletions src/app/middleware.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/auth/LogOut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function LogoutBtn() {
const logout = async () => {
try {
await hanko?.user.logout();
router.push("/login");
router.push("/auth");
router.refresh();
return;
} catch (error) {
Expand Down
2 changes: 2 additions & 0 deletions src/components/auth/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import { useEffect } from "react";
import { register } from "@teamhanko/hanko-elements";
import { toast } from "../ui/use-toast";

const hankoApi = process.env.NEXT_PUBLIC_HANKO_API_URL!;

export default function HankoProfile() {
useEffect(() => {
register(hankoApi).catch((error) => {
// handle error
toast(error.toString());
});
}, []);

Expand Down
32 changes: 25 additions & 7 deletions src/components/auth/server.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
"use server";
import axios from "axios";
import { hankoApiUrl } from "./vars";
import { createRemoteJWKSet, jwtVerify } from "jose";
import { NextRequest } from "next/server";
import { z } from "zod";

export const getUserId = async () => {
// get user details from Hanko
const {
data: { id },
} = await axios.get<{ id: string }>(`${hankoApiUrl}/me`);
export const fetchUserId = async (hanko: string) => {
const JWKS = createRemoteJWKSet(
new URL(`${hankoApiUrl}/.well-known/jwks.json`)
);

return id;
const verifiedJWT = await jwtVerify(hanko ?? "", JWKS);
return verifiedJWT.payload.sub;
};

export const getUserId = async (req: NextRequest) => {
// const userId = req.headers.get("x-user-id");
const hanko = req.cookies.get("hanko")?.value;
if (!hanko) {
throw new Error("No Hanko cookie found");
}
const userId = await fetchUserId(hanko);
// validate userId is uuid using zod
const schema = z.string().uuid();
const validatedUserId = schema.safeParse(userId);
if (!validatedUserId.success) {
throw new Error("Invalid user id");
}
return validatedUserId.data;
};
31 changes: 31 additions & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { NextResponse, NextRequest } from "next/server";

import { fetchUserId, getUserId } from "@/components/auth/server";

export async function middleware(req: NextRequest) {
try {
const hanko = req.cookies.get("hanko")?.value;
if (!hanko) {
throw new Error("No Hanko cookie found");
}
const userId = await fetchUserId(hanko);

userId && req.headers.set("x-user-id", userId);
return NextResponse.next();
} catch {
if (req.url.startsWith("/api/secure")) {
return NextResponse.json(
{
message: "Unauthenticated",
detail: "Please log in to access this resource.",
},
{ status: 401 }
);
}
return NextResponse.redirect(new URL("/login", req.url));
}
}

export const config = {
matcher: ["/dashboard/:path*", "/api/secure/:path*"],
};
Loading

0 comments on commit a08279a

Please sign in to comment.