feat: Add EventHub - Enterprise Event Management Platform#224
feat: Add EventHub - Enterprise Event Management Platform#224devin-ai-integration[bot] wants to merge 1 commit into
Conversation
- Backend: Express.js + TypeScript + Prisma ORM + SQLite - Frontend: React + TypeScript + Material UI v9 + Vite - 5 personas: Admin, Organizer, Governance, Speaker, Audience - JWT authentication with role-based access control - Event discovery, proposal/approval workflow - Campaign scheduling (MS Teams, Viva Engage) - Calendar integration (iCal export) - Twilio SMS notifications - Notification preferences and customization - Admin panel: user management, access matrix, config, audit logs - Seed data with 7 users, 5 groups, 5 sample events
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| if (error.response?.status === 401) { | ||
| localStorage.removeItem('token'); | ||
| localStorage.removeItem('user'); | ||
| window.location.href = '/login'; |
There was a problem hiding this comment.
🔴 Axios 401 interceptor causes page reload on failed login, preventing error message display
The global axios response interceptor redirects to /login via window.location.href on any 401 response, including the one returned by POST /auth/login for invalid credentials. When a user enters wrong credentials on the login page, the flow is: (1) api.post('/auth/login', ...) at frontend/src/context/AuthContext.tsx:35 returns 401, (2) the interceptor fires and sets window.location.href = '/login', triggering a full page reload, (3) the promise rejects and the catch in frontend/src/pages/Login.tsx:19 tries to setError(...), but the page is already reloading. The net result is the user never sees the "Invalid email or password" error — the login page just silently reloads. The same issue affects the register flow for 401 errors.
| if (error.response?.status === 401) { | |
| localStorage.removeItem('token'); | |
| localStorage.removeItem('user'); | |
| window.location.href = '/login'; | |
| if (error.response?.status === 401 && !error.config?.url?.includes('/auth/')) { | |
| localStorage.removeItem('token'); | |
| localStorage.removeItem('user'); | |
| window.location.href = '/login'; | |
| } |
Was this helpful? React with 👍 or 👎 to provide feedback.
| const notification = await prisma.notification.update({ | ||
| where: { id: req.params.id }, | ||
| data: { read: true }, |
There was a problem hiding this comment.
🔴 Missing ownership check on PATCH /notifications/:id/read allows any user to mark others' notifications as read
The PATCH /:id/read endpoint at backend/src/routes/notifications.ts:32-42 updates a notification by its ID without verifying it belongs to the authenticated user (req.user.userId). Any authenticated user who knows or guesses a notification ID can mark another user's notification as read. The Prisma update uses only where: { id: req.params.id } with no userId filter.
| const notification = await prisma.notification.update({ | |
| where: { id: req.params.id }, | |
| data: { read: true }, | |
| const notification = await prisma.notification.findUnique({ where: { id: req.params.id } }); | |
| if (!notification || notification.userId !== req.user!.userId) { | |
| return res.status(404).json({ error: 'Notification not found' }); | |
| } | |
| const updated = await prisma.notification.update({ | |
| where: { id: req.params.id }, | |
| data: { read: true }, | |
| }); |
Was this helpful? React with 👍 or 👎 to provide feedback.
| <Button variant="contained" onClick={handleRegister}>Register</Button> | ||
| )} | ||
| <Button variant="outlined" startIcon={<Download />} | ||
| onClick={() => window.open(`http://localhost:4000/api/calendar/event/${event.id}/ical`, '_blank')}> |
There was a problem hiding this comment.
🔴 Hardcoded localhost:4000 URLs for iCal downloads break in non-local environments
Calendar download links are hardcoded to http://localhost:4000/api/calendar/... in three frontend components (frontend/src/pages/EventDetail.tsx:113, frontend/src/pages/Events.tsx:97, frontend/src/pages/MyEvents.tsx:27) instead of using the configured VITE_API_URL base URL from frontend/src/services/api.ts:3. In any deployed environment, these window.open() calls will try to reach localhost, failing silently.
Prompt for agents
Three frontend files hardcode http://localhost:4000/api/calendar/... for iCal download URLs instead of using the configured API base URL.
Affected locations:
1. frontend/src/pages/EventDetail.tsx line 113: window.open(http://localhost:4000/api/calendar/event/${event.id}/ical)
2. frontend/src/pages/Events.tsx line 97: window.open(http://localhost:4000/api/calendar/event/${event.id}/ical)
3. frontend/src/pages/MyEvents.tsx line 27: window.open(http://localhost:4000/api/calendar/my-events/ical)
The fix is to export the API_BASE constant from frontend/src/services/api.ts (or create a utility function) and use it to construct the calendar URLs dynamically. For example, export const API_BASE from api.ts and use window.open(`${API_BASE}/calendar/event/${event.id}/ical`).
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Adds a complete EventHub web application — an enterprise event management platform with 5 user personas (App Admin, Event Organizer, Governance Team, Speaker, Audience). The application is built as a monorepo with separate
backend/andfrontend/directories.Backend (
backend/): Express.js + TypeScript + Prisma ORM + SQLiteADMIN,ORGANIZER,GOVERNANCE,SPEAKER,AUDIENCE)Frontend (
frontend/): React 19 + TypeScript + Material UI v9 + ViteReview & Testing Checklist for Human
backend/src/middleware/auth.tsfalls back to'eventhub-secret-key-change-in-production'whenJWT_SECRETenv var is missing. Verify this is acceptable for your deployment model.Events.tsx,EventDetail.tsx, andMyEvents.tsxcontain hardcodedhttp://localhost:4000/api/calendar/...URLs for iCal downloads instead of using the configurableVITE_API_URL. These will break in any non-local deployment.backend/src/index.tsusescors()with no origin restrictions. Review whether this is appropriate.catch { /* ignore */ }blocks, meaning users won't see error feedback for many failure scenarios.Recommended test plan:
cd backend && npm install && npx prisma migrate dev && npx prisma db seed && npm run devcd frontend && npm install && npm run devadmin@eventhub.com,organizer@eventhub.com,speaker1@eventhub.com,audience1@eventhub.com— password:password123) and verify role-appropriate pages are visibleNotes
Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/9d986a285a8a44a8a04b6853ece64047