From 30dda22f1d7b93e585f6f381a6767f49f794ec21 Mon Sep 17 00:00:00 2001 From: LyTrv-20 Date: Sat, 8 Nov 2025 18:11:09 -0600 Subject: [PATCH 1/6] authentication w jwt....? --- backend/middleware/auth.ts | 44 +++++++++++++++++++++++++------------- backend/server.ts | 5 ----- frontend/src/main.tsx | 6 +++++- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/backend/middleware/auth.ts b/backend/middleware/auth.ts index 76f1a5a..09928b2 100644 --- a/backend/middleware/auth.ts +++ b/backend/middleware/auth.ts @@ -1,10 +1,10 @@ import { Response, NextFunction } from 'express'; import { AuthenticatedRequest } from '../types/index.js'; -import { clerkMiddleware, getAuth } from '@clerk/express'; +import { clerkMiddleware, getAuth, requireAuth } from '@clerk/express'; // Helper const isAdmin = (role?: string) => role === 'ADMIN'; - +const jwt = require('jsonwebtoken'); //Hyk dunno if this is needed here but leaving for now export default clerkMiddleware(); @@ -12,21 +12,34 @@ export default clerkMiddleware(); * TODO: Replace with Clerk's requireAuth() middleware * This should verify that a valid Clerk session exists */ -export const authenticateToken = async ( - req: AuthenticatedRequest, - res: Response, - next: NextFunction -): Promise => { - const auth = getAuth(req); +export const authenticateToken = [ + requireAuth(), + (req: AuthenticatedRequest, res: Response, next: NextFunction) => { + const header = req.headers['authorization']; - //requireAuth() cant be used here - if (!auth.userId || !auth.sessionId) { - res.status(401).json({ error: 'Unauthenticated' }); - return; - } + if (!header || !header.startsWith('Bearer ')) { + return res.status(401).json({ error: 'No token provided' }); + } - next(); -}; + const auth = getAuth(req); + + //requireAuth() cant be used here + if (!auth.userId || !auth.sessionId) { + res.status(401).json({ error: 'Unauthenticated' }); + return; + } + + try { + const decoded = jwt.verify(header.split(' ')[1], process.env.CLERK_SECRET_KEY!); + // Optionally attach the decoded payload to the request for later use + (req as any).user = decoded; // Or use a more specific type for req + next(); // Token is valid, proceed to the next middleware/route handler + } catch (err) { + console.error('JWT verification error:', err); // Log the actual error for debugging + return res.status(401).json({ error: 'Invalid token' }); // Token is invalid + } + }, +]; /** * TODO: Implement role-based authorization @@ -37,6 +50,7 @@ export const requireAdmin = async ( res: Response, next: NextFunction ): Promise => { + const auth = getAuth(req); if (!isAdmin(req.user?.role)) { res.status(403).json({ error: 'Admin access required' }); return; diff --git a/backend/server.ts b/backend/server.ts index ddf2162..0daac17 100644 --- a/backend/server.ts +++ b/backend/server.ts @@ -1,14 +1,9 @@ import dotenv from 'dotenv'; import app from './app'; -import { clerkMiddleware } from '@clerk/express'; dotenv.config(); const PORT = 8000; -//clerk middleware -//TODO: check the location (docs says in index.ts but it feels incorrect) -app.use(clerkMiddleware()); - app.post('/placeholder'); app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index e37e78a..1aaa9b8 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -13,7 +13,11 @@ if (!PUBLISHABLE_KEY) { createRoot(document.getElementById('root')!).render( - + From b77b7e940e01a57bb1355cad3213ef83a3eae5ce Mon Sep 17 00:00:00 2001 From: LyTrv-20 Date: Sat, 15 Nov 2025 16:49:06 -0600 Subject: [PATCH 2/6] front end, still need quill --- frontend/package-lock.json | 8 +- frontend/package.json | 2 +- frontend/src/components/AdminRoute.tsx | 16 ++-- .../src/pages/Admin/AlertsPage/Alerts.tsx | 63 +++++++++++++++- .../pages/Admin/AlertsPage/Create-Alert.tsx | 65 ++++++++++++++++ frontend/src/routes/AppRoutes.tsx | 9 +++ package-lock.json | 74 ++++++++++++++++++- package.json | 5 ++ 8 files changed, 226 insertions(+), 16 deletions(-) create mode 100644 frontend/src/pages/Admin/AlertsPage/Create-Alert.tsx create mode 100644 package.json diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 38ee643..fd7a099 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -27,7 +27,7 @@ "@vitejs/plugin-react": "^5.0.3", "autoprefixer": "^10.4.21", "cross-env": "^10.1.0", - "daisyui": "^5.4.3", + "daisyui": "^5.5.4", "eslint": "^9.36.0", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-react": "^7.37.5", @@ -3396,9 +3396,9 @@ "license": "MIT" }, "node_modules/daisyui": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.4.3.tgz", - "integrity": "sha512-dfDCJnN4utErGoWfElgdEE252FtfHV9Mxj5Dq1+JzUq3nVkluWdF3JYykP0Xy/y/yArnPXYztO1tLNCow3kjmg==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.5.4.tgz", + "integrity": "sha512-opuf6YHsGxOqWtPXEHFCGDC0HxNIYW6DgXB9GRNfFJL4garzEoHCEWqcuvMTjFK2Al2aHgHYFrpqLxd5x2qopQ==", "dev": true, "license": "MIT", "funding": { diff --git a/frontend/package.json b/frontend/package.json index a72d7df..1e7ca7c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -30,7 +30,7 @@ "@vitejs/plugin-react": "^5.0.3", "autoprefixer": "^10.4.21", "cross-env": "^10.1.0", - "daisyui": "^5.4.3", + "daisyui": "^5.5.4", "eslint": "^9.36.0", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-react": "^7.37.5", diff --git a/frontend/src/components/AdminRoute.tsx b/frontend/src/components/AdminRoute.tsx index 0633c43..7f4b345 100644 --- a/frontend/src/components/AdminRoute.tsx +++ b/frontend/src/components/AdminRoute.tsx @@ -16,15 +16,15 @@ const AdminRoute = ({ children }: AdminRouteProps) => { if (!isLoaded) return; if (!isSignedIn) { - navigate('/login'); + // navigate('/login'); return; } const userRole = user?.publicMetadata?.role as string | undefined; - if (userRole !== 'ADMIN') { - navigate('/'); - return; - } + // if (userRole !== 'ADMIN') { + // navigate('/'); + // return; + // } }, [isLoaded, isSignedIn, user, navigate]); if (!isLoaded) { @@ -35,9 +35,9 @@ const AdminRoute = ({ children }: AdminRouteProps) => { ); } - if (!isSignedIn || user?.publicMetadata?.role !== 'ADMIN') { - return null; - } + // if (!isSignedIn || user?.publicMetadata?.role !== 'ADMIN') { + // return null; + // } return <>{children}; }; diff --git a/frontend/src/pages/Admin/AlertsPage/Alerts.tsx b/frontend/src/pages/Admin/AlertsPage/Alerts.tsx index 61a5124..af2e9d7 100644 --- a/frontend/src/pages/Admin/AlertsPage/Alerts.tsx +++ b/frontend/src/pages/Admin/AlertsPage/Alerts.tsx @@ -1,11 +1,70 @@ +import { useState } from 'react'; import AdminSidebar from '../../../components/AdminSidebar'; const AdminAlerts = () => { + const alerts: any[] = [ + { + title: 'Title', + content: 'content aspodfiejpaosdifjepoijdfpoeis', + date: new Date('2024-06-01T10:00:00Z'), + }, + { + title: 'Title', + content: 'content aspodfiejpaosdifjepoijdfpoeis', + date: new Date('2024-06-01T10:00:00Z'), + }, + { + title: 'Title', + content: 'content aspodfiejpaosdifjepoijdfpoeis', + date: new Date('2024-06-01T10:00:00Z'), + }, + ]; // TODO: Fetch alerts from backend + + const tags: string[] = ['Tag1', 'Tag2', 'Tag3']; // TODO: add preset tags later + filtering + return (
-
-

Alerts

+
+
+

Alerts

+ + Create New + +
+ +
+ {tags.map(tag => ( + + ))} +
+ +
+ {alerts.map((alert, index) => { + return ( + +
+
+

{alert.title}

+

{alert.date.toDateString()}

+
+

{alert.content}

+
+
+ ); + })} +
); diff --git a/frontend/src/pages/Admin/AlertsPage/Create-Alert.tsx b/frontend/src/pages/Admin/AlertsPage/Create-Alert.tsx new file mode 100644 index 0000000..a981980 --- /dev/null +++ b/frontend/src/pages/Admin/AlertsPage/Create-Alert.tsx @@ -0,0 +1,65 @@ +import React, { useState } from 'react'; +import AdminSidebar from '../../../components/AdminSidebar'; +import Quill from 'quill'; + +const CreateAlert = () => { + const [loading, setLoading] = useState(false); //TODO: handle loading in the form submission + + return ( +
+ +
+ + + + + + +

Create Alert

+ +
+
+ + +
+
+ + {/* + */} +
+ +
+ {/* TODO: handle drafts */} + + +
+
+
+
+ ); +}; + +export default CreateAlert; diff --git a/frontend/src/routes/AppRoutes.tsx b/frontend/src/routes/AppRoutes.tsx index e8e1aa7..f5ce3f4 100644 --- a/frontend/src/routes/AppRoutes.tsx +++ b/frontend/src/routes/AppRoutes.tsx @@ -26,6 +26,7 @@ import AdminAlerts from '../pages/Admin/AlertsPage/Alerts'; import AdminSurveys from '../pages/Admin/SurveysPage/Surveys'; import Blog from '../pages/BlogPage/Blog'; import BlogsPage from '../pages/BlogsPage/Blogs'; +import CreateAlert from '../pages/Admin/AlertsPage/Create-Alert'; const AppRoutes = () => { return ( @@ -148,6 +149,14 @@ const AppRoutes = () => { } /> + + + + } + /> =8.2.3" + } + }, + "node_modules/quill-delta": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", + "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", + "license": "MIT", + "dependencies": { + "fast-diff": "^1.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + } + } } diff --git a/package.json b/package.json new file mode 100644 index 0000000..e2aea57 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "quill": "^2.0.3" + } +} From 461b1df8cec9f2656f66c00cd0bd0ca04d2ff1ec Mon Sep 17 00:00:00 2001 From: LyTrv-20 Date: Tue, 18 Nov 2025 22:46:13 -0600 Subject: [PATCH 3/6] add quill --- frontend/package-lock.json | 77 ++++++++++++++++++- frontend/package.json | 1 + frontend/src/components/QuillEditor.tsx | 31 ++++++++ frontend/src/index.css | 31 ++++++++ .../src/pages/Admin/AlertsPage/Alerts.tsx | 45 ++++++----- .../pages/Admin/AlertsPage/Create-Alert.tsx | 34 +++++--- 6 files changed, 189 insertions(+), 30 deletions(-) create mode 100644 frontend/src/components/QuillEditor.tsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index fd7a099..89eacc7 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -16,6 +16,7 @@ "react": "^19.1.1", "react-dom": "^19.1.1", "react-icons": "^5.5.0", + "react-quill-new": "^3.6.0", "react-router-dom": "^7.9.3" }, "devDependencies": { @@ -4079,6 +4080,12 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4090,7 +4097,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true, "license": "Apache-2.0" }, "node_modules/fast-glob": { @@ -5484,12 +5490,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "license": "MIT" }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -5848,6 +5873,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parchment": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz", + "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==", + "license": "BSD-3-Clause" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6064,6 +6095,35 @@ ], "license": "MIT" }, + "node_modules/quill": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz", + "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==", + "license": "BSD-3-Clause", + "dependencies": { + "eventemitter3": "^5.0.1", + "lodash-es": "^4.17.21", + "parchment": "^3.0.0", + "quill-delta": "^5.1.0" + }, + "engines": { + "npm": ">=8.2.3" + } + }, + "node_modules/quill-delta": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", + "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", + "license": "MIT", + "dependencies": { + "fast-diff": "^1.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/react": { "version": "19.1.1", "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", @@ -6101,6 +6161,21 @@ "dev": true, "license": "MIT" }, + "node_modules/react-quill-new": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/react-quill-new/-/react-quill-new-3.6.0.tgz", + "integrity": "sha512-weU6YfB2+7Cujw5Hjgmi0aN/qJd3B6ADWrxgUJMp2MO3tEvKX5kfB0sg3P0UdOVfU0z8icsKFzlnEIpeW1mLhw==", + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21", + "quill": "~2.0.2" + }, + "peerDependencies": { + "quill-delta": "^5.1.0", + "react": "^16 || ^17 || ^18 || ^19", + "react-dom": "^16 || ^17 || ^18 || ^19" + } + }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 1e7ca7c..a1b559c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -19,6 +19,7 @@ "react": "^19.1.1", "react-dom": "^19.1.1", "react-icons": "^5.5.0", + "react-quill-new": "^3.6.0", "react-router-dom": "^7.9.3" }, "devDependencies": { diff --git a/frontend/src/components/QuillEditor.tsx b/frontend/src/components/QuillEditor.tsx new file mode 100644 index 0000000..1d027e8 --- /dev/null +++ b/frontend/src/components/QuillEditor.tsx @@ -0,0 +1,31 @@ +import { useEffect, useRef } from 'react'; +import Quill from 'quill'; +import 'quill/dist/quill.snow.css'; + +const QuillEditor = () => { + const editorWrapperRef = useRef(null); + const didInit = useRef(false); + + useEffect(() => { + if (didInit.current) return; + didInit.current = true; + + if (!editorWrapperRef.current) return; + + // Create Quill + new Quill(editorWrapperRef.current, { + modules: { + toolbar: true, + }, + theme: 'snow', + }); + }, []); + + return ( +
+
+
+ ); +}; + +export default QuillEditor; diff --git a/frontend/src/index.css b/frontend/src/index.css index e7e50ba..f05c870 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -50,3 +50,34 @@ body { .animate-fadeIn { animation: fadeIn 0.2s ease-out; } + +.ql-toolbar.ql-snow { + border-bottom: 1px !important; + border-top: none !important; + border-right: none !important; + border-left: none !important; + border-color: gray !important; +} + +.ql-container.ql-snow { + border: none !important; + height: 100% !important; + display: flex !important; +} + +.ql-container { + height: 100% !important; + display: flex !important; + flex-direction: column !important; +} + +.ql-editor { + flex: 1 1 auto !important; + overflow-y: auto !important; + padding: 0 !important; + min-height: 0 !important; +} + +.ql-tooltip { + z-index: 9999 !important; +} diff --git a/frontend/src/pages/Admin/AlertsPage/Alerts.tsx b/frontend/src/pages/Admin/AlertsPage/Alerts.tsx index af2e9d7..eb260cd 100644 --- a/frontend/src/pages/Admin/AlertsPage/Alerts.tsx +++ b/frontend/src/pages/Admin/AlertsPage/Alerts.tsx @@ -1,4 +1,10 @@ -import { useState } from 'react'; +import { + useState, + type JSXElementConstructor, + type ReactElement, + type ReactNode, + type ReactPortal, +} from 'react'; import AdminSidebar from '../../../components/AdminSidebar'; const AdminAlerts = () => { @@ -7,21 +13,22 @@ const AdminAlerts = () => { title: 'Title', content: 'content aspodfiejpaosdifjepoijdfpoeis', date: new Date('2024-06-01T10:00:00Z'), + tags: ['Tag1', 'Tag2'], }, { title: 'Title', content: 'content aspodfiejpaosdifjepoijdfpoeis', date: new Date('2024-06-01T10:00:00Z'), + tags: ['Tag3'], }, { title: 'Title', content: 'content aspodfiejpaosdifjepoijdfpoeis', date: new Date('2024-06-01T10:00:00Z'), + tags: [], }, ]; // TODO: Fetch alerts from backend - const tags: string[] = ['Tag1', 'Tag2', 'Tag3']; // TODO: add preset tags later + filtering - return (
@@ -36,28 +43,30 @@ const AdminAlerts = () => {
-
- {tags.map(tag => ( - - ))} -
- -
+
{alerts.map((alert, index) => { return (
-

{alert.title}

-

{alert.date.toDateString()}

+
+

{alert.title}

+
+ {alert.tags.map((tag: string) => { + return ( +
+ {tag.toLowerCase()} +
+ ); + })} +
+
+

+ {alert.date.toDateString()} +

{alert.content}

diff --git a/frontend/src/pages/Admin/AlertsPage/Create-Alert.tsx b/frontend/src/pages/Admin/AlertsPage/Create-Alert.tsx index a981980..96edc90 100644 --- a/frontend/src/pages/Admin/AlertsPage/Create-Alert.tsx +++ b/frontend/src/pages/Admin/AlertsPage/Create-Alert.tsx @@ -1,10 +1,18 @@ -import React, { useState } from 'react'; +import React, { forwardRef, useEffect, useRef, useLayoutEffect, useState } from 'react'; import AdminSidebar from '../../../components/AdminSidebar'; -import Quill from 'quill'; +import ReactQuill from 'react-quill-new'; +import 'react-quill-new/dist/quill.snow.css'; +import QuillEditor from '../../../components/QuillEditor'; const CreateAlert = () => { const [loading, setLoading] = useState(false); //TODO: handle loading in the form submission + const [value, setValue] = useState(''); + const handleChange = (content: string) => { + setValue(content); + }; + + const tags: string[] = ['Tag1', 'Tag2', 'Tag3']; // TODO: add preset tags later return (
@@ -31,17 +39,21 @@ const CreateAlert = () => { className='p-4 h-12 bg-white border-[1px] border-[#717171] rounded-[10px]' />
+ +
+ {tags.map(tag => ( + + ))} +
+
- {/* - */} +
From efa0276d1ba6c5bde6ea1683cd01b609423bf1b1 Mon Sep 17 00:00:00 2001 From: LyTrv-20 Date: Tue, 18 Nov 2025 23:44:52 -0600 Subject: [PATCH 4/6] formatted(?) + revert to normal auth --- frontend/src/components/AdminRoute.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/AdminRoute.tsx b/frontend/src/components/AdminRoute.tsx index 7f4b345..0633c43 100644 --- a/frontend/src/components/AdminRoute.tsx +++ b/frontend/src/components/AdminRoute.tsx @@ -16,15 +16,15 @@ const AdminRoute = ({ children }: AdminRouteProps) => { if (!isLoaded) return; if (!isSignedIn) { - // navigate('/login'); + navigate('/login'); return; } const userRole = user?.publicMetadata?.role as string | undefined; - // if (userRole !== 'ADMIN') { - // navigate('/'); - // return; - // } + if (userRole !== 'ADMIN') { + navigate('/'); + return; + } }, [isLoaded, isSignedIn, user, navigate]); if (!isLoaded) { @@ -35,9 +35,9 @@ const AdminRoute = ({ children }: AdminRouteProps) => { ); } - // if (!isSignedIn || user?.publicMetadata?.role !== 'ADMIN') { - // return null; - // } + if (!isSignedIn || user?.publicMetadata?.role !== 'ADMIN') { + return null; + } return <>{children}; }; From 8fa5c487a9e943a9b858d762d0339eea06afe09f Mon Sep 17 00:00:00 2001 From: LyTrv-20 Date: Tue, 18 Nov 2025 23:48:49 -0600 Subject: [PATCH 5/6] fix middleware + format --- backend/middleware/auth.ts | 61 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/backend/middleware/auth.ts b/backend/middleware/auth.ts index 44e9664..5b1e8b3 100644 --- a/backend/middleware/auth.ts +++ b/backend/middleware/auth.ts @@ -17,7 +17,63 @@ export const authenticateToken = async ( return; } - next(); + const token = authHeader.substring(7); + + const verifiedToken = await verifyToken(token, { + secretKey: process.env.CLERK_SECRET_KEY!, + clockSkewInMs: 5000, + }); + + console.log('Token verification result:', { + userId: verifiedToken.sub, + sessionId: verifiedToken.sid, + path: req.path, + method: req.method, + }); + + const adminUser = await prisma.adminUser.findUnique({ + where: { clerkId: verifiedToken.sub }, + }); + + if (adminUser) { + console.log('Admin user lookup:', { + clerkId: verifiedToken.sub, + found: true, + }); + + req.user = { + id: adminUser.id, + clerkId: adminUser.clerkId, + role: 'ADMIN', + email: adminUser.email, + name: adminUser.name, + }; + } else { + const organization = await prisma.organization.findUnique({ + where: { clerkId: verifiedToken.sub }, + }); + + console.log('Organization lookup:', { + clerkId: verifiedToken.sub, + found: !!organization, + role: organization?.role, + }); + + if (organization) { + req.user = { + id: organization.id, + clerkId: organization.clerkId, + role: organization.role, + email: organization.email, + name: organization.name, + }; + } + } + next(); + } catch (error: any) { + console.error('Token verification error:', error.message); + res.status(401).json({ error: 'Invalid or expired token' }); + } }; export const requireAdmin = async ( @@ -25,10 +81,9 @@ export const requireAdmin = async ( res: Response, next: NextFunction ): Promise => { - const auth = getAuth(req); if (!isAdmin(req.user?.role)) { res.status(403).json({ error: 'Admin access required' }); return; } next(); -}; +}; \ No newline at end of file From f1e439ff950cc9a7b139c1f5cea58adbf98dde82 Mon Sep 17 00:00:00 2001 From: LyTrv-20 Date: Tue, 18 Nov 2025 23:50:32 -0600 Subject: [PATCH 6/6] FORMATT --- backend/middleware/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/middleware/auth.ts b/backend/middleware/auth.ts index 5b1e8b3..0cf3401 100644 --- a/backend/middleware/auth.ts +++ b/backend/middleware/auth.ts @@ -86,4 +86,4 @@ export const requireAdmin = async ( return; } next(); -}; \ No newline at end of file +};