From 8cab872b7d860ef29ed0a5f1708556757e5c24d0 Mon Sep 17 00:00:00 2001 From: Lea Date: Wed, 17 Jan 2024 00:45:48 +0100 Subject: [PATCH] meowmeowmeowmeowmeowmeow --- package.json | 1 + pnpm-lock.yaml | 11 ++++ src/app/admin/users/page.tsx | 45 +++++++++++++++ src/app/layout.tsx | 15 +++-- src/app/page.tsx | 30 +--------- src/lib/actions.ts | 17 ++++++ src/lib/components/AuthWrapper.tsx | 22 ++++++-- src/lib/components/ThemeWrapper.tsx | 1 + src/lib/components/ui/NavigationPanel.tsx | 67 +++++++++++++++++++++++ src/lib/db.ts | 2 +- src/lib/util.ts | 9 ++- 11 files changed, 177 insertions(+), 43 deletions(-) create mode 100644 src/app/admin/users/page.tsx create mode 100644 src/lib/actions.ts create mode 100644 src/lib/components/ui/NavigationPanel.tsx diff --git a/package.json b/package.json index 26b35e7..9982854 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@radix-ui/themes": "^2.0.3", "@types/bcryptjs": "^2.4.6", "bcryptjs": "^2.4.3", + "lucide-react": "^0.311.0", "next": "14.0.4", "next-auth": "^4.24.5", "react": "^18", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 55a15b3..42fccc9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ dependencies: bcryptjs: specifier: ^2.4.3 version: 2.4.3 + lucide-react: + specifier: ^0.311.0 + version: 0.311.0(react@18.2.0) next: specifier: 14.0.4 version: 14.0.4(react-dom@18.2.0)(react@18.2.0) @@ -3307,6 +3310,14 @@ packages: dependencies: yallist: 4.0.0 + /lucide-react@0.311.0(react@18.2.0): + resolution: {integrity: sha512-kyMc6YyVepMVnmZT2X1sl7iyf7w6l8YdhEVKmcBLiT0lMlXqcPGsr2/drYP1/VaGf7DmBJ4/CjQAmOpDd8R8uw==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + /make-fetch-happen@9.1.0: resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==} engines: {node: '>= 10'} diff --git a/src/app/admin/users/page.tsx b/src/app/admin/users/page.tsx new file mode 100644 index 0000000..cad4753 --- /dev/null +++ b/src/app/admin/users/page.tsx @@ -0,0 +1,45 @@ +import { fetchAllUsers } from "@/lib/actions"; +import { sha256sum } from "@/lib/util"; +import { Avatar, Button, Flex, Heading, Table, Text } from "@radix-ui/themes"; + +export default async function Users() { + const data = await fetchAllUsers(); + + return ( + <> + Users + + + + + + Email + Actions + + + + + {data.map((email) => ( + + + + + {email} + + + + + + + ))} + + + + + ); +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ab283c8..8fdd036 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -4,6 +4,8 @@ import ThemeWrapper from '@/lib/components/ThemeWrapper'; import './globals.css'; import AuthWrapper from '@/lib/components/AuthWrapper'; import { getServerSession } from 'next-auth'; +import NavigationPanel from '@/lib/components/ui/NavigationPanel'; +import { Flex } from '@radix-ui/themes'; const inter = Inter({ subsets: ['latin'] }); @@ -20,11 +22,14 @@ export default async function RootLayout({ return ( - - - {children} - - + + + +
+
{children}
+
+
+
); diff --git a/src/app/page.tsx b/src/app/page.tsx index 23024ff..8f5dd1c 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,39 +1,11 @@ "use client"; -import { Avatar, Card, Flex, Heading, Text, Box, Button } from '@radix-ui/themes'; -import { useSession } from 'next-auth/react'; -import Link from 'next/link'; +import { Heading } from '@radix-ui/themes'; export default function Home() { - const session = useSession().data; - return ( <> Welcome back. - - {session?.user && ( - - - - - - {session.user.email} - - - - - )} - - - - ); } diff --git a/src/lib/actions.ts b/src/lib/actions.ts new file mode 100644 index 0000000..dc1effa --- /dev/null +++ b/src/lib/actions.ts @@ -0,0 +1,17 @@ +"use server"; + +import { database } from "./db"; +import { isAdmin } from "./util"; + +export async function fetchAllUsers(): Promise { + return new Promise((resolve, reject) => { + if (!isAdmin) return reject("Unauthenticated"); + + const db = database(); + db.all("SELECT key FROM passwords", (err, res: any) => { + if (err) return reject(err); + + resolve(res.map((row: any) => row.key)); + }); + }); +} diff --git a/src/lib/components/AuthWrapper.tsx b/src/lib/components/AuthWrapper.tsx index 279459e..356831b 100644 --- a/src/lib/components/AuthWrapper.tsx +++ b/src/lib/components/AuthWrapper.tsx @@ -1,7 +1,8 @@ "use client"; +import { Button, Flex, Heading } from "@radix-ui/themes"; import { Session } from "next-auth"; -import { SessionProvider } from "next-auth/react"; +import { SessionProvider, signIn } from "next-auth/react"; export default function AuthWrapper({ children, @@ -10,9 +11,18 @@ export default function AuthWrapper({ children: React.ReactNode, session: Session | null, }) { - return ( - - {children} - - ); + if (session?.user) { + return ( + + {children} + + ); + } else { + return ( + + Unauthenticated + + + ); + } } \ No newline at end of file diff --git a/src/lib/components/ThemeWrapper.tsx b/src/lib/components/ThemeWrapper.tsx index 281089b..78bb99a 100644 --- a/src/lib/components/ThemeWrapper.tsx +++ b/src/lib/components/ThemeWrapper.tsx @@ -13,6 +13,7 @@ export default function ThemeWrapper({ // Automatically respond to theme changes useEffect(() => { + console.log("meow"); setDark(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches); const onThemeChange = (event: MediaQueryListEvent) => { diff --git a/src/lib/components/ui/NavigationPanel.tsx b/src/lib/components/ui/NavigationPanel.tsx new file mode 100644 index 0000000..6bb353c --- /dev/null +++ b/src/lib/components/ui/NavigationPanel.tsx @@ -0,0 +1,67 @@ +"use client"; + +import { isAdmin } from "@/lib/util"; +import { Avatar, Box, Button, Card, Flex, IconButton, Popover, Text } from "@radix-ui/themes"; +import { BookUserIcon, HomeIcon } from "lucide-react"; +import { signOut, useSession } from "next-auth/react"; +import Link from "next/link"; + +export default function NavigationPanel() { + const session = useSession(); + + return ( + + + {session.data?.user + && ( + + + + + + + + + + + + + {session.data.user.email} + + + + + + ° + + + + + )} + + + + + + + + {isAdmin(session.data) && ( + + + + + + )} + + + ); +} \ No newline at end of file diff --git a/src/lib/db.ts b/src/lib/db.ts index 6312432..394cde5 100644 --- a/src/lib/db.ts +++ b/src/lib/db.ts @@ -6,7 +6,7 @@ if (!CREDENTIALS_DB_PATH) { throw "$CREDENTIALS_DB_PATH not provided; unable to connect to database"; } -const database = () => new sqlite.Database(CREDENTIALS_DB_PATH!); +export const database = () => new sqlite.Database(CREDENTIALS_DB_PATH!); export function validateCredentials(email: string, password: string) { const db = database(); diff --git a/src/lib/util.ts b/src/lib/util.ts index a8898a7..addfb0b 100644 --- a/src/lib/util.ts +++ b/src/lib/util.ts @@ -1,7 +1,12 @@ -import crypto from 'node:crypto'; +import { Session } from 'next-auth'; +import crypto from 'crypto'; export function sha256sum(input: any) { const hash = crypto.createHash('sha256'); hash.update(input); return hash.digest('hex'); -} \ No newline at end of file +} + +export function isAdmin(session: Session | null) { + return session?.user?.email == "lea@amogus.cloud"; // todo +}