diff --git a/apps/admin/app/layout.tsx b/apps/admin/app/layout.tsx
index 7a807d4..8521291 100644
--- a/apps/admin/app/layout.tsx
+++ b/apps/admin/app/layout.tsx
@@ -1,16 +1,107 @@
-import { Geist, Geist_Mono } from "next/font/google"
+import localFont from "next/font/local"
import "@workspace/ui/globals.css"
import { Providers } from "@/components/providers"
-const fontSans = Geist({
- subsets: ["latin"],
+const firaSans = localFont({
+ src: [
+ {
+ path: "../fonts/Fira-sans/FiraSans-Thin.ttf",
+ weight: "100",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-ThinItalic.ttf",
+ weight: "100",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-ExtraLight.ttf",
+ weight: "200",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-ExtraLightItalic.ttf",
+ weight: "200",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Light.ttf",
+ weight: "300",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-LightItalic.ttf",
+ weight: "300",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Regular.ttf",
+ weight: "400",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Italic.ttf",
+ weight: "400",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Medium.ttf",
+ weight: "500",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-MediumItalic.ttf",
+ weight: "500",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-SemiBold.ttf",
+ weight: "600",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-SemiBoldItalic.ttf",
+ weight: "600",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Bold.ttf",
+ weight: "700",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-BoldItalic.ttf",
+ weight: "700",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-ExtraBold.ttf",
+ weight: "800",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-ExtraBoldItalic.ttf",
+ weight: "800",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Black.ttf",
+ weight: "900",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-BlackItalic.ttf",
+ weight: "900",
+ style: "italic",
+ },
+ ],
variable: "--font-sans",
})
-const fontMono = Geist_Mono({
- subsets: ["latin"],
- variable: "--font-mono",
+const marcellus = localFont({
+ src: "../fonts/Marcellus/Marcellus-Regular.ttf",
+ variable: "--font-marcellus",
})
export default function RootLayout({
@@ -21,7 +112,7 @@ export default function RootLayout({
return (
{children}
diff --git a/apps/admin/app/page.tsx b/apps/admin/app/page.tsx
index d338f0c..65031f5 100644
--- a/apps/admin/app/page.tsx
+++ b/apps/admin/app/page.tsx
@@ -1,11 +1,11 @@
import Login from "@/components/login";
import Studs from "@/components/studs";
-import { db, students } from "@workspace/db";
-import { signIn, signOut } from "@workspace/auth";
+import { db, admins } from "@workspace/db";
+import { auth, signIn, signOut } from "@workspace/auth";
async function getStudents() {
"use server";
- const s = await db.select().from(students);
+ const s = await db.select().from(admins);
console.log(s);
}
@@ -20,11 +20,12 @@ async function logOut() {
}
export default async function Page() {
+ const session = await auth()
return (
Hello admins
-
+ {!session?.user && }
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-Black.ttf b/apps/admin/fonts/Fira-sans/FiraSans-Black.ttf
new file mode 100644
index 0000000..3087a31
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-Black.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-BlackItalic.ttf b/apps/admin/fonts/Fira-sans/FiraSans-BlackItalic.ttf
new file mode 100644
index 0000000..9a9ef5e
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-BlackItalic.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-Bold.ttf b/apps/admin/fonts/Fira-sans/FiraSans-Bold.ttf
new file mode 100644
index 0000000..0fb896a
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-Bold.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-BoldItalic.ttf b/apps/admin/fonts/Fira-sans/FiraSans-BoldItalic.ttf
new file mode 100644
index 0000000..e7e936f
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-BoldItalic.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-ExtraBold.ttf b/apps/admin/fonts/Fira-sans/FiraSans-ExtraBold.ttf
new file mode 100644
index 0000000..4b29d6f
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-ExtraBold.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-ExtraBoldItalic.ttf b/apps/admin/fonts/Fira-sans/FiraSans-ExtraBoldItalic.ttf
new file mode 100644
index 0000000..de3b83b
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-ExtraBoldItalic.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-ExtraLight.ttf b/apps/admin/fonts/Fira-sans/FiraSans-ExtraLight.ttf
new file mode 100644
index 0000000..e5755da
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-ExtraLight.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-ExtraLightItalic.ttf b/apps/admin/fonts/Fira-sans/FiraSans-ExtraLightItalic.ttf
new file mode 100644
index 0000000..890524e
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-ExtraLightItalic.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-Italic.ttf b/apps/admin/fonts/Fira-sans/FiraSans-Italic.ttf
new file mode 100644
index 0000000..36efca2
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-Italic.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-Light.ttf b/apps/admin/fonts/Fira-sans/FiraSans-Light.ttf
new file mode 100644
index 0000000..fac4edf
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-Light.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-LightItalic.ttf b/apps/admin/fonts/Fira-sans/FiraSans-LightItalic.ttf
new file mode 100644
index 0000000..1daa0bc
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-LightItalic.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-Medium.ttf b/apps/admin/fonts/Fira-sans/FiraSans-Medium.ttf
new file mode 100644
index 0000000..eeb8f8f
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-Medium.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-MediumItalic.ttf b/apps/admin/fonts/Fira-sans/FiraSans-MediumItalic.ttf
new file mode 100644
index 0000000..328b53b
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-MediumItalic.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-Regular.ttf b/apps/admin/fonts/Fira-sans/FiraSans-Regular.ttf
new file mode 100644
index 0000000..c4cfa59
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-Regular.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-SemiBold.ttf b/apps/admin/fonts/Fira-sans/FiraSans-SemiBold.ttf
new file mode 100644
index 0000000..954a2ca
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-SemiBold.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-SemiBoldItalic.ttf b/apps/admin/fonts/Fira-sans/FiraSans-SemiBoldItalic.ttf
new file mode 100644
index 0000000..55e812c
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-SemiBoldItalic.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-Thin.ttf b/apps/admin/fonts/Fira-sans/FiraSans-Thin.ttf
new file mode 100644
index 0000000..8cb4bad
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-Thin.ttf differ
diff --git a/apps/admin/fonts/Fira-sans/FiraSans-ThinItalic.ttf b/apps/admin/fonts/Fira-sans/FiraSans-ThinItalic.ttf
new file mode 100644
index 0000000..f2dbf59
Binary files /dev/null and b/apps/admin/fonts/Fira-sans/FiraSans-ThinItalic.ttf differ
diff --git a/apps/admin/fonts/Marcellus/Marcellus-Regular.ttf b/apps/admin/fonts/Marcellus/Marcellus-Regular.ttf
new file mode 100644
index 0000000..1be0d9d
Binary files /dev/null and b/apps/admin/fonts/Marcellus/Marcellus-Regular.ttf differ
diff --git a/apps/admin/middleware.ts b/apps/admin/middleware.ts
index b876a27..d084074 100644
--- a/apps/admin/middleware.ts
+++ b/apps/admin/middleware.ts
@@ -1 +1,18 @@
-export { auth as middleware } from "@workspace/auth";
+import { auth } from "@workspace/auth";
+import { NextResponse } from 'next/server';
+
+export default auth((req: any) => {
+ // If the user is unauthenticated or an admin, allow the request.
+ if (!req.auth || req.auth.user?.role === "ADMIN") {
+ return NextResponse.next();
+ }
+
+ // Otherwise, redirect to the student app.
+ const studentUrl = process.env.STUDENT_URL ?? "http://localhost:3000"
+
+ return NextResponse.redirect(new URL(studentUrl, req.url));
+}) as any;
+
+export const config = {
+ matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
+}
\ No newline at end of file
diff --git a/apps/admin/next-auth.d.ts b/apps/admin/next-auth.d.ts
new file mode 100644
index 0000000..0eeed9b
--- /dev/null
+++ b/apps/admin/next-auth.d.ts
@@ -0,0 +1,19 @@
+import "next-auth";
+
+declare module "next-auth" {
+ interface Session {
+ user: {
+ role?: "ADMIN" | "USER";
+ adminId?: number;
+ studentId?: number;
+ [key: string]: any;
+ };
+ }
+}
+declare module "next-auth/jwt" {
+ interface JWT {
+ role?: "ADMIN" | "USER";
+ adminId?: number;
+ studentId?: number;
+ }
+}
\ No newline at end of file
diff --git a/apps/student/app/api/auth/[...nextauth]/route.ts b/apps/student/app/api/auth/[...nextauth]/route.ts
new file mode 100644
index 0000000..ad9858b
--- /dev/null
+++ b/apps/student/app/api/auth/[...nextauth]/route.ts
@@ -0,0 +1,2 @@
+import { handlers } from "@workspace/auth";
+export const { GET, POST } = handlers;
diff --git a/apps/student/app/layout.tsx b/apps/student/app/layout.tsx
index 7a807d4..8521291 100644
--- a/apps/student/app/layout.tsx
+++ b/apps/student/app/layout.tsx
@@ -1,16 +1,107 @@
-import { Geist, Geist_Mono } from "next/font/google"
+import localFont from "next/font/local"
import "@workspace/ui/globals.css"
import { Providers } from "@/components/providers"
-const fontSans = Geist({
- subsets: ["latin"],
+const firaSans = localFont({
+ src: [
+ {
+ path: "../fonts/Fira-sans/FiraSans-Thin.ttf",
+ weight: "100",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-ThinItalic.ttf",
+ weight: "100",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-ExtraLight.ttf",
+ weight: "200",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-ExtraLightItalic.ttf",
+ weight: "200",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Light.ttf",
+ weight: "300",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-LightItalic.ttf",
+ weight: "300",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Regular.ttf",
+ weight: "400",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Italic.ttf",
+ weight: "400",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Medium.ttf",
+ weight: "500",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-MediumItalic.ttf",
+ weight: "500",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-SemiBold.ttf",
+ weight: "600",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-SemiBoldItalic.ttf",
+ weight: "600",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Bold.ttf",
+ weight: "700",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-BoldItalic.ttf",
+ weight: "700",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-ExtraBold.ttf",
+ weight: "800",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-ExtraBoldItalic.ttf",
+ weight: "800",
+ style: "italic",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-Black.ttf",
+ weight: "900",
+ style: "normal",
+ },
+ {
+ path: "../fonts/Fira-sans/FiraSans-BlackItalic.ttf",
+ weight: "900",
+ style: "italic",
+ },
+ ],
variable: "--font-sans",
})
-const fontMono = Geist_Mono({
- subsets: ["latin"],
- variable: "--font-mono",
+const marcellus = localFont({
+ src: "../fonts/Marcellus/Marcellus-Regular.ttf",
+ variable: "--font-marcellus",
})
export default function RootLayout({
@@ -21,7 +112,7 @@ export default function RootLayout({
return (
{children}
diff --git a/apps/student/app/page.tsx b/apps/student/app/page.tsx
index 1018ac5..e09ba3f 100644
--- a/apps/student/app/page.tsx
+++ b/apps/student/app/page.tsx
@@ -1,11 +1,32 @@
-import { Button } from "@workspace/ui/components/button";
+import Login from "@/components/login";
+import Studs from "@/components/studs";
+import { db, admins } from "@workspace/db";
+import { auth, signIn, signOut } from "@workspace/auth";
-export default function Page() {
+async function getStudents() {
+ "use server";
+ const s = await db.select().from(admins);
+ console.log(s);
+}
+
+async function logIn() {
+ "use server";
+ await signIn("google");
+}
+
+async function logOut() {
+ "use server";
+ await signOut();
+}
+
+export default async function Page() {
+ const session = await auth()
return (
Hello students
-
+ {!session?.user && }
+
);
diff --git a/apps/student/components/login.tsx b/apps/student/components/login.tsx
new file mode 100644
index 0000000..7b42ac7
--- /dev/null
+++ b/apps/student/components/login.tsx
@@ -0,0 +1,25 @@
+"use client";
+import { signIn } from "@workspace/auth";
+import { Button } from "@workspace/ui/components/button";
+
+export default function Login({logIn}: {logIn: () => Promise}) {
+ return (
+
+ );
+}
diff --git a/apps/student/components/studs.tsx b/apps/student/components/studs.tsx
new file mode 100644
index 0000000..7e49d2a
--- /dev/null
+++ b/apps/student/components/studs.tsx
@@ -0,0 +1,19 @@
+import { Button } from "@workspace/ui/components/button";
+import { auth } from "@workspace/auth";
+
+export default async function Studs({
+ action,
+ logOut,
+}: {
+ action: () => void;
+ logOut: () => void;
+}) {
+ const session = await auth();
+ if (!session?.user) return null;
+ return (
+
+
+
+
+ );
+}
diff --git a/apps/student/fonts/Fira-sans/FiraSans-Black.ttf b/apps/student/fonts/Fira-sans/FiraSans-Black.ttf
new file mode 100644
index 0000000..3087a31
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-Black.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-BlackItalic.ttf b/apps/student/fonts/Fira-sans/FiraSans-BlackItalic.ttf
new file mode 100644
index 0000000..9a9ef5e
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-BlackItalic.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-Bold.ttf b/apps/student/fonts/Fira-sans/FiraSans-Bold.ttf
new file mode 100644
index 0000000..0fb896a
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-Bold.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-BoldItalic.ttf b/apps/student/fonts/Fira-sans/FiraSans-BoldItalic.ttf
new file mode 100644
index 0000000..e7e936f
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-BoldItalic.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-ExtraBold.ttf b/apps/student/fonts/Fira-sans/FiraSans-ExtraBold.ttf
new file mode 100644
index 0000000..4b29d6f
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-ExtraBold.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-ExtraBoldItalic.ttf b/apps/student/fonts/Fira-sans/FiraSans-ExtraBoldItalic.ttf
new file mode 100644
index 0000000..de3b83b
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-ExtraBoldItalic.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-ExtraLight.ttf b/apps/student/fonts/Fira-sans/FiraSans-ExtraLight.ttf
new file mode 100644
index 0000000..e5755da
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-ExtraLight.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-ExtraLightItalic.ttf b/apps/student/fonts/Fira-sans/FiraSans-ExtraLightItalic.ttf
new file mode 100644
index 0000000..890524e
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-ExtraLightItalic.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-Italic.ttf b/apps/student/fonts/Fira-sans/FiraSans-Italic.ttf
new file mode 100644
index 0000000..36efca2
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-Italic.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-Light.ttf b/apps/student/fonts/Fira-sans/FiraSans-Light.ttf
new file mode 100644
index 0000000..fac4edf
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-Light.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-LightItalic.ttf b/apps/student/fonts/Fira-sans/FiraSans-LightItalic.ttf
new file mode 100644
index 0000000..1daa0bc
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-LightItalic.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-Medium.ttf b/apps/student/fonts/Fira-sans/FiraSans-Medium.ttf
new file mode 100644
index 0000000..eeb8f8f
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-Medium.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-MediumItalic.ttf b/apps/student/fonts/Fira-sans/FiraSans-MediumItalic.ttf
new file mode 100644
index 0000000..328b53b
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-MediumItalic.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-Regular.ttf b/apps/student/fonts/Fira-sans/FiraSans-Regular.ttf
new file mode 100644
index 0000000..c4cfa59
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-Regular.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-SemiBold.ttf b/apps/student/fonts/Fira-sans/FiraSans-SemiBold.ttf
new file mode 100644
index 0000000..954a2ca
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-SemiBold.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-SemiBoldItalic.ttf b/apps/student/fonts/Fira-sans/FiraSans-SemiBoldItalic.ttf
new file mode 100644
index 0000000..55e812c
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-SemiBoldItalic.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-Thin.ttf b/apps/student/fonts/Fira-sans/FiraSans-Thin.ttf
new file mode 100644
index 0000000..8cb4bad
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-Thin.ttf differ
diff --git a/apps/student/fonts/Fira-sans/FiraSans-ThinItalic.ttf b/apps/student/fonts/Fira-sans/FiraSans-ThinItalic.ttf
new file mode 100644
index 0000000..f2dbf59
Binary files /dev/null and b/apps/student/fonts/Fira-sans/FiraSans-ThinItalic.ttf differ
diff --git a/apps/student/fonts/Marcellus/Marcellus-Regular.ttf b/apps/student/fonts/Marcellus/Marcellus-Regular.ttf
new file mode 100644
index 0000000..1be0d9d
Binary files /dev/null and b/apps/student/fonts/Marcellus/Marcellus-Regular.ttf differ
diff --git a/apps/student/middleware.ts b/apps/student/middleware.ts
new file mode 100644
index 0000000..09044e7
--- /dev/null
+++ b/apps/student/middleware.ts
@@ -0,0 +1,18 @@
+import { auth } from "@workspace/auth";
+import { NextResponse } from 'next/server';
+
+export default auth((req: any) => {
+ // If the user is unauthenticated or a student, allow the request.
+ if (!req.auth || req.auth.user?.role === "USER") {
+ return NextResponse.next();
+ }
+
+ // Otherwise, redirect to the admin app.
+ const adminURL = process.env.ADMIN_URL ?? "http://localhost:3001"
+
+ return NextResponse.redirect(new URL(adminURL, req.url));
+}) as any;
+
+export const config = {
+ matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
+}
\ No newline at end of file
diff --git a/apps/student/next-auth.d.ts b/apps/student/next-auth.d.ts
new file mode 100644
index 0000000..8ac7c89
--- /dev/null
+++ b/apps/student/next-auth.d.ts
@@ -0,0 +1,20 @@
+import "next-auth";
+
+declare module "next-auth" {
+ interface Session {
+ user: {
+ role?: "ADMIN" | "USER";
+ adminId?: number;
+ studentId?: number;
+ [key: string]: any;
+ };
+ }
+}
+
+declare module "next-auth/jwt" {
+ interface JWT {
+ role?: "ADMIN" | "USER";
+ adminId?: number;
+ studentId?: number;
+ }
+}
\ No newline at end of file
diff --git a/packages/auth/index.ts b/packages/auth/index.ts
index 8ab8f2c..b4546e6 100644
--- a/packages/auth/index.ts
+++ b/packages/auth/index.ts
@@ -1,9 +1,65 @@
import NextAuth, { type NextAuthConfig } from "next-auth";
import Google from "next-auth/providers/google";
+import { db, admins, students } from "@workspace/db";
+import { eq } from "drizzle-orm";
const authConfig: NextAuthConfig = {
providers: [Google],
- callbacks: {},
+ callbacks: {
+ async jwt({ token, account, user, profile }) {
+ // Only check DB on first sign in
+ if (account && user && user.email) {
+ const admin = await db
+ .select()
+ .from(admins)
+ .where(eq(admins.email, user.email))
+ .limit(1);
+ if (admin.length > 0 && admin[0]) {
+ token.role = "ADMIN";
+ token.adminId = admin[0].id;
+ } else {
+ token.role = "USER";
+ const student = await db
+ .select()
+ .from(students)
+ .where(eq(students.email, user.email))
+ .limit(1);
+ if (student.length > 0 && student[0]) {
+ token.studentId = student[0].id;
+ } else {
+ const nameParts = user.name?.split(" ") ?? [];
+ const firstName = nameParts[0] || "";
+ const lastName = nameParts.slice(1).join(" ") || "";
+ const newStudent = await db
+ .insert(students)
+ .values({
+ email: user.email,
+ firstName: firstName,
+ lastName: lastName,
+ profilePicture: user.image,
+ })
+ .returning({ id: students.id });
+ if (newStudent[0]) {
+ token.studentId = newStudent[0].id;
+ }
+ }
+ }
+ }
+ return token;
+ },
+ async session({ session, token }) {
+ if (token?.role) {
+ session.user.role = token.role as "ADMIN" | "USER";
+ }
+ if (token?.adminId) {
+ session.user.adminId = token.adminId as number;
+ }
+ if (token?.studentId) {
+ session.user.studentId = token.studentId as number;
+ }
+ return session;
+ },
+ },
};
const nextAuth = NextAuth(authConfig);
diff --git a/packages/auth/package.json b/packages/auth/package.json
index 4f2056e..62740d0 100644
--- a/packages/auth/package.json
+++ b/packages/auth/package.json
@@ -12,7 +12,9 @@
"license": "ISC",
"packageManager": "pnpm@10.4.1",
"dependencies": {
- "next-auth": "5.0.0-beta.28"
+ "next-auth": "5.0.0-beta.28",
+ "@workspace/db": "workspace:*",
+ "drizzle-orm": "^0.44.2"
},
"devDependencies": {
"dotenv": "^16.5.0"
diff --git a/packages/auth/types.d.ts b/packages/auth/types.d.ts
new file mode 100644
index 0000000..b4ceb09
--- /dev/null
+++ b/packages/auth/types.d.ts
@@ -0,0 +1,20 @@
+import "next-auth";
+import "next-auth/jwt";
+
+declare module "next-auth" {
+ interface Session {
+ user: {
+ role?: "ADMIN" | "USER";
+ adminId?: number;
+ studentId?: number;
+ [key: string]: any;
+ };
+ }
+}
+declare module "next-auth/jwt" {
+ interface JWT {
+ role?: "ADMIN" | "USER";
+ adminId?: number;
+ studentId?: number;
+ }
+}
\ No newline at end of file
diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx
index e0e289d..0240342 100644
--- a/packages/ui/src/components/button.tsx
+++ b/packages/ui/src/components/button.tsx
@@ -10,11 +10,11 @@ const buttonVariants = cva(
variants: {
variant: {
default:
- "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
+ "bg-primary text-primary-foreground shadow-xs shadow-foreground/20 hover:bg-primary/90",
destructive:
- "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
+ "bg-destructive text-destructive-foreground shadow-xs shadow-foreground/20 hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
outline:
- "bg-background border border-border text-foreground shadow transition-all duration-300 ease-out group relative overflow-hidden hover:bg-muted hover:border-muted-foreground hover:shadow-lg hover:shadow-primary/20 hover:scale-102 active:scale-98 active:shadow-md focus:ring-2 focus:ring-primary focus:ring-offset-2",
+ "bg-background border border-border text-foreground shadow shadow-foreground/20 transition-all duration-300 ease-out group relative overflow-hidden hover:bg-muted hover:border-muted-foreground hover:shadow-lg hover:shadow-primary/20 hover:scale-103 active:scale-98 active:shadow-md focus:ring-2 focus:ring-primary focus:ring-offset-2",
secondary:
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
diff --git a/packages/ui/src/styles/globals.css b/packages/ui/src/styles/globals.css
index a5c6ce3..7f56d18 100644
--- a/packages/ui/src/styles/globals.css
+++ b/packages/ui/src/styles/globals.css
@@ -5,77 +5,82 @@
@import "tw-animate-css";
+@theme {
+ --font-sans: "var(--font-sans)";
+ --font-marcellus: "var(--font-marcellus)";
+}
+
@custom-variant dark (&:is(.dark *));
:root {
- --background: oklch(1 0 0);
- --foreground: oklch(0.145 0 0);
- --card: oklch(1 0 0);
- --card-foreground: oklch(0.145 0 0);
+ --background: oklch(0.9889 0.004 286.33);
+ --foreground: oklch(0.2442 0.006 0.59);
+ --card: oklch(0.97 0.004 286.33);
+ --card-foreground: oklch(0.2442 0.006 0.59);
--popover: oklch(1 0 0);
- --popover-foreground: oklch(0.145 0 0);
- --primary: oklch(0.205 0 0);
- --primary-foreground: oklch(0.985 0 0);
- --secondary: oklch(0.97 0 0);
- --secondary-foreground: oklch(0.205 0 0);
- --muted: oklch(0.97 0 0);
- --muted-foreground: oklch(0.556 0 0);
- --accent: oklch(0.97 0 0);
- --accent-foreground: oklch(0.205 0 0);
- --destructive: oklch(0.577 0.245 27.325);
- --destructive-foreground: oklch(0.577 0.245 27.325);
- --border: oklch(0.922 0 0);
- --input: oklch(0.922 0 0);
- --ring: oklch(0.708 0 0);
- --chart-1: oklch(0.646 0.222 41.116);
- --chart-2: oklch(0.6 0.118 184.704);
- --chart-3: oklch(0.398 0.07 227.392);
- --chart-4: oklch(0.828 0.189 84.429);
- --chart-5: oklch(0.769 0.188 70.08);
+ --popover-foreground: oklch(0.2442 0.006 0.59);
+ --primary: oklch(0.5044 0.184 22.51);
+ --primary-foreground: oklch(0.9889 0.004 286.33);
+ --secondary: oklch(0.4605 0.005 271.31);
+ --secondary-foreground: oklch(0.9889 0.004 286.33);
+ --muted: oklch(0.92 0.003 286.33);
+ --muted-foreground: oklch(0.44 0.004 286.33);
+ --accent: oklch(0.6034 0.234 27.23);
+ --accent-foreground: oklch(0.9889 0.004 286.33);
+ --destructive: oklch(0.55 0.18 27.23);
+ --destructive-foreground: oklch(0.9889 0.004 286.33);
+ --border: oklch(0.88 0.003 286.33);
+ --input: oklch(0.97 0.004 286.33);
+ --ring: oklch(0.6034 0.234 27.23);
+ --chart-1: oklch(0.5044 0.184 22.51);
+ --chart-2: oklch(0.6034 0.234 27.23);
+ --chart-3: oklch(0.4605 0.005 271.31);
+ --chart-4: oklch(0.7 0.15 120);
+ --chart-5: oklch(0.7 0.15 300);
--radius: 0.625rem;
- --sidebar: oklch(0.985 0 0);
- --sidebar-foreground: oklch(0.145 0 0);
- --sidebar-primary: oklch(0.205 0 0);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.97 0 0);
- --sidebar-accent-foreground: oklch(0.205 0 0);
- --sidebar-border: oklch(0.922 0 0);
- --sidebar-ring: oklch(0.708 0 0);
+ --sidebar: oklch(0.97 0.004 286.33);
+ --sidebar-foreground: oklch(0.2442 0.006 0.59);
+ --sidebar-primary: oklch(0.5044 0.184 22.51);
+ --sidebar-primary-foreground: oklch(0.9889 0.004 286.33);
+ --sidebar-accent: oklch(0.6034 0.234 27.23);
+ --sidebar-accent-foreground: oklch(0.9889 0.004 286.33);
+ --sidebar-border: oklch(0.88 0.003 286.33);
+ --sidebar-ring: oklch(0.6034 0.234 27.23);
}
.dark {
- --background: oklch(0.145 0 0);
- --foreground: oklch(0.985 0 0);
- --card: oklch(0.145 0 0);
- --card-foreground: oklch(0.985 0 0);
- --popover: oklch(0.145 0 0);
- --popover-foreground: oklch(0.985 0 0);
- --primary: oklch(0.985 0 0);
- --primary-foreground: oklch(0.205 0 0);
- --secondary: oklch(0.269 0 0);
- --secondary-foreground: oklch(0.985 0 0);
- --muted: oklch(0.269 0 0);
- --muted-foreground: oklch(0.708 0 0);
- --accent: oklch(0.269 0 0);
- --accent-foreground: oklch(0.985 0 0);
- --destructive: oklch(0.396 0.141 25.723);
- --destructive-foreground: oklch(0.637 0.237 25.331);
- --border: oklch(0.269 0 0);
- --input: oklch(0.269 0 0);
- --ring: oklch(0.556 0 0);
- --chart-1: oklch(0.488 0.243 264.376);
- --chart-2: oklch(0.696 0.17 162.48);
- --chart-3: oklch(0.769 0.188 70.08);
- --chart-4: oklch(0.627 0.265 303.9);
- --chart-5: oklch(0.645 0.246 16.439);
- --sidebar: oklch(0.205 0 0);
- --sidebar-foreground: oklch(0.985 0 0);
- --sidebar-primary: oklch(0.488 0.243 264.376);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.269 0 0);
- --sidebar-accent-foreground: oklch(0.985 0 0);
- --sidebar-border: oklch(0.269 0 0);
- --sidebar-ring: oklch(0.439 0 0);
+ --background: oklch(0.18 0.01 286.33);
+ --foreground: oklch(0.9889 0.004 286.33);
+ --card: oklch(0.22 0.01 286.33);
+ --card-foreground: oklch(0.9889 0.004 286.33);
+ --popover: oklch(0.22 0.01 286.33);
+ --popover-foreground: oklch(0.9889 0.004 286.33);
+ --primary: oklch(0.7044 0.184 22.51);
+ --primary-foreground: oklch(0.18 0.01 286.33);
+ --secondary: oklch(0.36 0.005 271.31);
+ --secondary-foreground: oklch(0.9889 0.004 286.33);
+ --muted: oklch(0.25 0.01 286.33);
+ --muted-foreground: oklch(0.7 0.01 286.33);
+ --accent: oklch(0.8034 0.234 27.23);
+ --accent-foreground: oklch(0.18 0.01 286.33);
+ --destructive: oklch(0.65 0.18 27.23);
+ --destructive-foreground: oklch(0.18 0.01 286.33);
+ --border: oklch(0.25 0.01 286.33);
+ --input: oklch(0.22 0.01 286.33);
+ --ring: oklch(0.8034 0.234 27.23);
+ --chart-1: oklch(0.7044 0.184 22.51);
+ --chart-2: oklch(0.8034 0.234 27.23);
+ --chart-3: oklch(0.36 0.005 271.31);
+ --chart-4: oklch(0.7 0.15 120);
+ --chart-5: oklch(0.7 0.15 300);
+ --sidebar: oklch(0.22 0.01 286.33);
+ --sidebar-foreground: oklch(0.9889 0.004 286.33);
+ --sidebar-primary: oklch(0.7044 0.184 22.51);
+ --sidebar-primary-foreground: oklch(0.18 0.01 286.33);
+ --sidebar-accent: oklch(0.8034 0.234 27.23);
+ --sidebar-accent-foreground: oklch(0.18 0.01 286.33);
+ --sidebar-border: oklch(0.25 0.01 286.33);
+ --sidebar-ring: oklch(0.8034 0.234 27.23);
}
@theme inline {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ff0cf5d..df903bd 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -130,6 +130,12 @@ importers:
packages/auth:
dependencies:
+ '@workspace/db':
+ specifier: workspace:*
+ version: link:../db
+ drizzle-orm:
+ specifier: ^0.44.2
+ version: 0.44.2(@neondatabase/serverless@1.0.1)(@types/pg@8.15.4)
next-auth:
specifier: 5.0.0-beta.28
version: 5.0.0-beta.28(next@15.3.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)