Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implemented admin login/signup #442

Merged
merged 3 commits into from
Nov 4, 2024

Conversation

Sourabh782
Copy link
Contributor

@Sourabh782 Sourabh782 commented Oct 31, 2024

Fixes #212

hello @RamakrushnaBiswal i have implemented the changes:

  1. created admin login and signup
  2. made "/admin" route protected, only users logged in as admin will be able to access "/admin"
  3. created a global context to keep track of user
BoardGame.Cafe.-.Google.Chrome.2024-10-31.17-19-24.mp4

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced admin login and signup components for enhanced authentication.
    • Added user role information in login responses for both admin and customer logins.
    • Implemented a ProtectedRoute component to restrict access to admin routes based on user roles.
    • Added a user context for managing user authentication state across the application.
  • Bug Fixes

    • Enhanced error handling in various components, including login and password reset functionalities.
  • Improvements

    • Updated the Admin component to dynamically display the logged-in user's name.
    • Improved cookie management for user authentication and session handling.
    • Added functionality to toggle password visibility and display password strength during signup.
    • Enhanced routing configuration for better access control and user experience.
  • Styling

    • Enhanced visual presentation of signup forms and background images for better user experience.

Copy link

vercel bot commented Oct 31, 2024

@Sourabh782 is attempting to deploy a commit to the bunty's projects Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

coderabbitai bot commented Oct 31, 2024

Walkthrough

The pull request introduces enhancements to the admin and customer login functionalities. Key changes include the addition of authToken cookies for admin logins, the inclusion of user roles in response objects, and the creation of new components for admin login and signup. The routing structure is updated to include protected routes for admin access, ensuring that only authenticated users can access certain pages. Overall, the modifications improve user authentication, error handling, and the dynamic rendering of user information.

Changes

File Change Summary
backend/controller/admin.controller.js Modified loginAdmin to set authToken cookie and include role in the response object.
backend/controller/customer.controller.js Updated loginCustomer to include role in the response and enhanced error handling in resetPassword.
frontend/src/components/Pages/Admin.jsx Added dynamic user greeting and improved error handling in fetchData and handleDelete functions.
frontend/src/components/Pages/AdminLogin.jsx Introduced a new component for admin login with state management and error handling.
frontend/src/components/Pages/AdminSignup.jsx Introduced a new component for admin signup with input validation and error handling.
frontend/src/components/Pages/Login.jsx Modified error handling and cookie management logic in handleSubmit.
frontend/src/components/Pages/Signup.jsx Adjusted styling for the signup form background without changing functionality.
frontend/src/components/Pages/VerifyOtp.jsx Changed method of accessing API_URL for environment variables.
frontend/src/components/Shared/Navbar.jsx Enhanced logout functionality by removing authenticatedUser cookie.
frontend/src/context/userContext.jsx Created a new context for user authentication management.
frontend/src/main.jsx Wrapped RouterProvider in UserProvider for user context access.
frontend/src/router/ProtectedRoute.jsx Introduced ProtectedRoute component to manage route protection based on user roles.
frontend/src/router/index.jsx Added new routes for admin login and signup, and modified the admin route to use ProtectedRoute.

Sequence Diagram(s)

sequenceDiagram
    participant Admin
    participant Server
    participant CookieManager
    participant UserContext

    Admin->>Server: Submit login credentials
    Server->>CookieManager: Set authToken cookie
    Server->>Admin: Return response with role
    Admin->>UserContext: Update user state with role
Loading

Assessment against linked issues

Objective Addressed Explanation
Create admin login and signup pages (#212)

Possibly related PRs

Suggested labels

enhancement, level3, gssoc-ext, hacktoberfest accepted

Suggested reviewers

  • RamakrushnaBiswal

Poem

In the land of code, where bunnies play,
Admins can log in, and users can stay.
With cookies and roles, all set to explore,
A hop to the dashboard, and so much more! 🐇✨
Error handling's tight, the UI's a delight,
Let's celebrate changes, all through the night!


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

Thank you for submitting your pull request! 🙌 We'll review it as soon as possible. In the meantime, please ensure that your changes align with our CONTRIBUTING.md. If there are any specific instructions or feedback regarding your PR, we'll provide them here. Thanks again for your contribution! 😊

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 28

🧹 Outside diff range and nitpick comments (24)
frontend/src/router/ProtectedRoute.jsx (3)

5-9: Add prop types validation

Add PropTypes or TypeScript types to validate the children prop and improve code maintainability.

+import PropTypes from 'prop-types';
+
 const ProtectedRoute = ({ children }) => {
   // ... component logic
 };
+
+ProtectedRoute.propTypes = {
+  children: PropTypes.node.isRequired,
+};

5-5: Add JSDoc documentation

Add documentation to explain the component's purpose, props, and usage.

+/**
+ * A route wrapper that protects admin-only routes.
+ * Redirects to admin login if the user is not authenticated as an admin.
+ *
+ * @param {Object} props
+ * @param {React.ReactNode} props.children - The components to render if access is granted
+ * @returns {React.ReactElement} The protected route
+ */
 const ProtectedRoute = ({ children }) => {

1-11: Consider implementing error boundaries

The component should be wrapped in an error boundary to gracefully handle runtime errors.

Would you like me to provide an example implementation of an error boundary component?

frontend/src/context/userContext.jsx (1)

1-20: Consider enhancing user context for role-based authentication.

Given that this PR implements admin authentication, the context should explicitly handle user roles and permissions.

Consider these enhancements:

  1. Add role-based access control (RBAC)
  2. Include admin-specific methods in the context
  3. Add role validation utilities

Example structure:

export const UserContext = createContext({
  user: null,
  setUser: () => {},
  isAdmin: () => false,
  hasPermission: (permission) => false,
});
frontend/src/router/index.jsx (1)

42-51: Consider restructuring admin routes for better scalability.

As you add more admin features, consider organizing admin-related routes in a separate router configuration file (e.g., adminRoutes.jsx). This would improve maintainability and make it easier to manage admin-specific route protection.

Example structure:

// adminRoutes.jsx
const adminRoutes = [
  {
    path: "/admin",
    element: <ProtectedRoute><Admin /></ProtectedRoute>
  },
  {
    path: "/admin-login",
    element: <AdminLogin />
  },
  {
    path: "/admin-signup",
    element: <AdminSignup />
  }
];

// index.jsx
import { adminRoutes } from './adminRoutes';
// ... then spread adminRoutes in your route configuration
backend/controller/admin.controller.js (1)

Line range hint 1-93: Consider implementing additional security measures

The current implementation could benefit from several security enhancements:

  1. Add rate limiting to prevent brute force attacks:
const rateLimit = require('express-rate-limit');

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5 // limit each IP to 5 login attempts per windowMs
});

// Apply to login route
app.use('/api/admin/login', loginLimiter);
  1. Validate JWT_SECRET at startup:
if (!process.env.JWT_SECRET || process.env.JWT_SECRET.length < 32) {
  throw new Error('JWT_SECRET must be at least 32 characters long');
}
  1. Consider using a more generic error message for invalid credentials:
- return res.status(401).json({ error: "Invalid email or password" });
+ return res.status(401).json({ error: "Invalid credentials" });
  1. Add password complexity validation to the schema:
- password: z.string().min(6, "Password must be at least 6 characters long"),
+ password: z.string()
+   .min(8, "Password must be at least 8 characters long")
+   .regex(/[A-Z]/, "Password must contain at least one uppercase letter")
+   .regex(/[a-z]/, "Password must contain at least one lowercase letter")
+   .regex(/[0-9]/, "Password must contain at least one number")
+   .regex(/[^A-Za-z0-9]/, "Password must contain at least one special character"),
frontend/src/components/Pages/Login.jsx (1)

Line range hint 1-156: Enhance admin login functionality.

Given that this PR implements admin login/signup, consider these improvements:

  1. Add a toggle or separate section for admin login
  2. Implement role-based navigation after successful login
  3. Add visual indicators for admin login mode

Example implementation for role-based navigation:

       if (!response.ok) {
         throw new Error(result.message || 'Login failed');
       }
+      // Role-based navigation
+      if (result.user.role === 'admin') {
+        navigate('/admin/dashboard');
+      } else {
+        navigate('/');
+      }
-      navigate('/');

Would you like me to provide a complete implementation for the admin-specific UI enhancements?

backend/controller/customer.controller.js (6)

Line range hint 89-94: Security: Reduce JWT payload information.

The JWT payload contains sensitive user information that isn't necessary for authentication purposes.

Consider minimizing the JWT payload to only essential claims:

 const payload = {
   sub: customer._id, 
-  name: customer.name, // Optional
-  role: "customer", // Optional
-  email: customer.email, // Optional
 };

Line range hint 127-131: Security: Strengthen cookie configuration.

While HttpOnly and Secure flags are correctly set, the cookie configuration could be enhanced.

Add SameSite attribute and domain restriction:

 res.cookie("authToken", token, {
   maxAge: 1000 * 60 * 60,
   httpOnly: true,               
   secure: true,                
+  sameSite: 'strict',
+  domain: process.env.COOKIE_DOMAIN
 });

Line range hint 102-104: Security: Use generic error messages.

Current error messages could enable user enumeration attacks by differentiating between non-existent accounts and wrong passwords.

Standardize error messages:

 if (!customer) {
-  return res.status(401).json({ error: "Invalid email or password" });
+  return res.status(401).json({ error: "Invalid credentials" });
 }
 if (!customer.isVerified) {
-  return res.status(403).json({ error: "Account not verified. Please verify your email." });
+  return res.status(401).json({ error: "Invalid credentials" });
 }

Also applies to: 108-110


Line range hint 95-146: Architecture: Consider removing session-based authentication.

The code currently maintains both JWT and session-based authentication, which could lead to inconsistent auth states and increased complexity.

Consider:

  1. Choosing either JWT or session-based auth, not both
  2. If keeping both, ensure proper synchronization between them
  3. Document the reason for maintaining dual authentication mechanisms

Would you like me to provide an example implementation using only JWT-based authentication?


Line range hint 1-146: Security: Implement rate limiting.

The authentication endpoints should implement rate limiting to prevent brute force attacks.

Consider adding rate limiting middleware using express-rate-limit:

const rateLimit = require('express-rate-limit');

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // 5 attempts
  message: { error: 'Too many login attempts. Please try again later.' }
});

// Apply to routes
router.post('/login', loginLimiter, loginCustomer);

Line range hint 8-12: Security: Strengthen password requirements.

Current password validation only checks for minimum length of 6 characters.

Enhance the password schema to require stronger passwords:

 const customerSchema = z.object({
   name: z.string().min(1, "Name is required"),
   email: z.string().email("Invalid email address"),
-  password: z.string().min(6, "Password must be at least 6 characters long"),
+  password: z.string()
+    .min(8, "Password must be at least 8 characters long")
+    .regex(/[A-Z]/, "Password must contain at least one uppercase letter")
+    .regex(/[a-z]/, "Password must contain at least one lowercase letter")
+    .regex(/[0-9]/, "Password must contain at least one number")
+    .regex(/[^A-Za-z0-9]/, "Password must contain at least one special character"),
 });
frontend/src/components/Pages/Admin/AdminLogin.jsx (1)

1-150: Consider implementing rate limiting and monitoring.

While the basic admin login functionality is implemented, consider these architectural improvements:

  1. Implement rate limiting to prevent brute force attacks
  2. Add logging for security monitoring
  3. Consider implementing 2FA for admin accounts

Would you like assistance in implementing any of these security enhancements?

frontend/src/components/Pages/Admin/AdminSignup.jsx (1)

1-182: Consider implementing form state management library.

For a complex form with validation, consider using a form management library like Formik or React Hook Form. This would provide:

  • Better validation handling
  • Reduced boilerplate
  • Built-in accessibility features
  • More robust error handling

Would you like examples of implementing this component using a form management library?

frontend/src/components/Shared/Navbar.jsx (4)

Line range hint 19-21: Add role-based UI elements for admin users.

The navbar should reflect different navigation options for admin users to align with the PR's admin functionality implementation.

Consider adding admin-specific menu items:

 const menuItems = [
   { name: 'HOME', path: '/' },
   { name: 'EVENTS', path: '/events' },
   { name: 'MENU', path: '/menu' },
   { name: 'RESERVATION', path: '/reservation' },
   { name: 'BOARDGAMES', path: '/boardgame' },
   { name: 'MEMBERSHIP', path: '/membership' },
+  // Conditionally render admin menu items
+  ...(Cookies.get('authenticatedUser') === 'admin' ? [
+    { name: 'ADMIN DASHBOARD', path: '/admin' },
+    { name: 'MANAGE USERS', path: '/admin/users' }
+  ] : [])
 ];

Line range hint 11-15: Implement proper state management for user roles.

The current implementation doesn't track user roles effectively. Consider using the global context mentioned in the PR objectives.

Add role-based state management:

 const [token, setToken] = useState(Cookies.get('authToken'));
+const [userRole, setUserRole] = useState(Cookies.get('authenticatedUser'));
 const location = useLocation();
 const navigate = useNavigate();

Then update the useEffect:

 useEffect(() => {
   setToken(Cookies.get('authToken'));
+  setUserRole(Cookies.get('authenticatedUser'));
 });

Line range hint 54-61: Enhance logout error handling.

The logout process should handle API errors and network failures gracefully.

Implement proper error handling:

 const handleLogout = async () => {
+  try {
     const response = await fetch(`${API_URL}/api/user/logout`, {
       method: 'POST',
       headers: {
         'Content-Type': 'application/json',
       },
     })
+    if (!response.ok) {
+      throw new Error('Logout failed');
+    }
     Cookies.remove('authToken');
     Cookies.remove("authenticatedUser");
     setToken(null);
     setIsModalOpen(false);
     setIsMenuOpen(false);
     navigate('/login');
+  } catch (error) {
+    console.error('Logout failed:', error);
+    // Show error notification to user
+  }
 };

Token validation is properly implemented in the backend but needs improvement in the frontend

While the backend properly validates tokens using JWT verification (including expiration checks), the frontend Navbar component only checks for token presence without validating its state. To improve security:

  • Add a check in the useEffect hook to validate the token's existence and set the login state accordingly
  • Consider implementing an interceptor or authentication context to handle token validation consistently
  • Add error handling for expired or invalid tokens

Example improvement for the useEffect:

useEffect(() => {
  const token = Cookies.get('authToken');
  setToken(token);
  setisloggedIn(!!token);
}, []);
🔗 Analysis chain

Line range hint 42-52: Verify token validation on component mount.

The current implementation only checks for token presence but doesn't validate its authenticity.

Let's verify the token validation implementation:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for token validation logic in the codebase
echo "Searching for token validation implementations..."
rg -l "validateToken|verifyToken|checkToken" --type js --type jsx

# Search for JWT verification utilities
echo "Searching for JWT verification utilities..."
rg -l "jwt.verify|verify\(token" --type js --type jsx

Length of output: 385


Script:

#!/bin/bash
# Search for token validation logic in the codebase with correct file type
echo "Searching for token validation implementations..."
rg -l "validateToken|verifyToken|checkToken|jwt\.verify" .

# Look for useEffect hooks that might contain token validation
echo "Searching for useEffect implementations in Navbar..."
rg -A 10 "useEffect\(" frontend/src/components/Shared/Navbar.jsx

# Search for authentication-related utilities
echo "Searching for auth utilities..."
fd -e js -e jsx auth

Length of output: 1017


Script:

#!/bin/bash
# Check the token validation implementation in auth middleware
echo "Checking auth middleware implementation..."
cat backend/middlewares/authCustomer.js

# Check if there's any token validation in the Navbar component
echo "Checking token handling in Navbar..."
rg -C 5 "setToken|authToken" frontend/src/components/Shared/Navbar.jsx

Length of output: 2300

frontend/src/components/Pages/Admin.jsx (5)

Line range hint 38-40: Remove unused Admin object definition.

The Admin object with hardcoded name is now redundant since we're using the useUser hook to get the user's name dynamically. This should be removed to prevent confusion and potential bugs.

-  const Admin = {
-    name: 'AdminName',
-  };

Line range hint 13-31: Enhance error handling and add loading state management.

The current implementation could benefit from the following improvements:

  1. Add loading state management for better UX
  2. Include authentication token in API requests
  3. Use antd's message system for user-friendly error notifications
 const Admin = () => {
+  const [loading, setLoading] = useState(false);
   // ...
   const fetchData = async () => {
+    setLoading(true);
     try {
       const response = await fetch(
         `${import.meta.env.VITE_BACKEND_URL}/api/event/all`,
         {
           method: 'GET',
           headers: {
             'Content-Type': 'application/json',
+            'Authorization': `Bearer ${localStorage.getItem('authToken')}`,
           },
         }
       );
+      if (!response.ok) {
+        throw new Error('Failed to fetch events');
+      }
       const data = await response.json();
       setEvents(data);
     } catch (error) {
       setError(error.message);
+      message.error('Failed to fetch events: ' + error.message);
       console.error('Error fetching events:', error);
+    } finally {
+      setLoading(false);
     }
   };

Line range hint 94-116: Fix critical issues in event deletion logic.

There are several issues that need to be addressed:

  1. The success message is shown when !response.ok (incorrect logic)
  2. Using GET method for deletion violates REST principles
  3. Missing user confirmation before deletion
   const handleDelete = async (eventId) => {
+    if (!confirm('Are you sure you want to delete this event?')) {
+      return;
+    }
     try {
       const response = await fetch(
         `${import.meta.env.VITE_BACKEND_URL}/api/event/delete?id=${eventId}`,
         {
-          method: 'get',
+          method: 'DELETE',
           headers: {
             'Content-Type': 'application/json',
+            'Authorization': `Bearer ${localStorage.getItem('authToken')}`,
           },
         }
       );
       const data = await response.json();
-      if (!response.ok) {
+      if (response.ok) {
         message.success('Event deleted successfully');
-        navigate('/admin');
+        // Filter out the deleted event from the list
+        setEvents((prevEvents) =>
+          prevEvents.filter((event) => event._id !== eventId)
+        );
+      } else {
+        throw new Error(data.message || 'Failed to delete event');
       }
-
-      // Filter out the deleted event from the list
-      setEvents((prevEvents) =>
-        prevEvents.filter((event) => event._id !== eventId)
-      );
     } catch (error) {
       console.error('Error deleting event:', error);
+      message.error('Failed to delete event: ' + error.message);
       setError(error.message);
     }
   };

Line range hint 65-89: Enhance event creation validation and error handling.

The event creation logic needs additional validation and improved error handling:

  1. Validate that start time is before end time
  2. Add date validation (no past dates)
  3. Improve success flow
   const handleSubmit = async (e) => {
     e.preventDefault();
+    // Validate times
+    const [startHour, startMin] = formData.startTime.split(':').map(Number);
+    const [endHour, endMin] = formData.endTime.split(':').map(Number);
+    if (startHour > endHour || (startHour === endHour && startMin >= endMin)) {
+      message.error('Start time must be before end time');
+      return;
+    }
+
+    // Validate date
+    const eventDate = new Date(formData.date);
+    if (eventDate < new Date().setHours(0, 0, 0, 0)) {
+      message.error('Cannot create events in the past');
+      return;
+    }
+
     const formattedTime = `${formatTime(formData.startTime)} - ${formatTime(formData.endTime)}`;
     const { title, description, ageRange, date } = formData;
     const event = { title, description, ageRange, date, time: formattedTime };
-    console.log(event);
+
     try {
       const response = await fetch(
         `${import.meta.env.VITE_BACKEND_URL}/api/event/create`,
         {
           method: 'POST',
           headers: {
             'Content-Type': 'application/json',
+            'Authorization': `Bearer ${localStorage.getItem('authToken')}`,
           },
           body: JSON.stringify(event),
         }
       );
       const data = await response.json();
+      if (!response.ok) {
+        throw new Error(data.message || 'Failed to create event');
+      }
-      if (response.ok) {
-        message.success('Event added successfully');
-        navigate('/admin');
-        fetchData();
-      }
-      console.log(data);
+      message.success('Event added successfully');
+      setFormData({
+        title: '',
+        description: '',
+        ageRange: '',
+        startTime: '',
+        endTime: '',
+        date: '',
+      });
+      fetchData();
     } catch (error) {
       console.error('Error adding event:', error);
-      message.error('Error adding event');
+      message.error('Failed to create event: ' + error.message);
     }
   };

Line range hint 245-268: Improve UI accessibility and performance.

The event listing section needs several improvements:

  1. Add loading states
  2. Optimize images
  3. Enhance accessibility
   <div className="event-list">
+    {loading && <div className="text-center"><Spin size="large" /></div>}
     {error && <p className="text-red-500">{error}</p>}
-    {events.map((event) => (
+    {!loading && events.map((event) => (
       <div
         key={event._id}
+        role="article"
+        aria-label={`Event: ${event.title}`}
         className="grid grid-cols-1 md:grid-cols-2 gap-10 lg:grid-cols-1 xl:grid-cols-2 md:px-6 lg:px-4 xl:px-0"
       >
         <div className="w-full m-10 mx-auto lg:mx-0 md:mx-0">
           <img
             src={event.image}
             alt={event.title}
             loading='lazy'
+            width="800"
+            height="400"
             className="h-[400px] w-full"
           />
         </div>
         <div className="w-full lg:m-10 md:m-10">
           <h1 className="text-4xl font-semibold">{event.title}</h1>
           <button
             onClick={() => handleDelete(event._id)}
+            aria-label={`Delete event: ${event.title}`}
             className="btn btn-primary bg-[#f81b1b] p-4 rounded-xl text-md font-medium mt-4 hover:scale-110 transition text-white"
           >
             Remove Event
           </button>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e9f5e02 and 13f97d4.

📒 Files selected for processing (13)
  • backend/controller/admin.controller.js (1 hunks)
  • backend/controller/customer.controller.js (1 hunks)
  • frontend/src/components/Pages/Admin.jsx (2 hunks)
  • frontend/src/components/Pages/Admin/AdminLogin.jsx (1 hunks)
  • frontend/src/components/Pages/Admin/AdminSignup.jsx (1 hunks)
  • frontend/src/components/Pages/Login.jsx (1 hunks)
  • frontend/src/components/Pages/Signup.jsx (1 hunks)
  • frontend/src/components/Pages/VerifyOtp.jsx (1 hunks)
  • frontend/src/components/Shared/Navbar.jsx (1 hunks)
  • frontend/src/context/userContext.jsx (1 hunks)
  • frontend/src/main.jsx (1 hunks)
  • frontend/src/router/ProtectedRoute.jsx (1 hunks)
  • frontend/src/router/index.jsx (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • frontend/src/components/Pages/Signup.jsx
🔇 Additional comments (8)
frontend/src/router/ProtectedRoute.jsx (1)

8-8: Verify route protection implementation

Let's verify that this protected route is properly integrated with the router configuration.

✅ Verification successful

Let me gather more information about how ProtectedRoute is being used in the router configuration.


Route protection is correctly implemented

The ProtectedRoute component is properly integrated in the router configuration:

  • It's correctly imported and used to protect the /admin route
  • The component redirects to /admin-login for non-admin users, which exists as a valid route
  • The protection is specifically applied to the admin dashboard while keeping other routes accessible
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of ProtectedRoute in router configuration
rg -l "ProtectedRoute" "frontend/src/router/"

# Check if admin routes are properly protected
ast-grep --pattern 'Route $_ element={<ProtectedRoute>$$$</ProtectedRoute>}'

Length of output: 191


Script:

#!/bin/bash
# Check the router configuration in index.jsx
cat frontend/src/router/index.jsx

# Also check for any admin-related routes
rg -A 5 "admin" frontend/src/router/index.jsx

Length of output: 3089

frontend/src/main.jsx (1)

6-6: LGTM! Clean implementation of global user context.

The UserProvider is correctly positioned at the root level, ensuring user context is available throughout the application. This implementation aligns well with the PR objectives for admin authentication.

Also applies to: 10-12

frontend/src/router/index.jsx (2)

25-27: LGTM! Imports are properly organized.

The new imports for admin authentication components follow the existing naming conventions and organization pattern.


42-49: Protected route implementation looks good, but verify the protection logic.

The admin route is correctly wrapped with the ProtectedRoute component, implementing the required access control.

Let's verify the ProtectedRoute implementation:

#!/bin/bash
# Description: Verify ProtectedRoute implementation for proper role checking

# Check ProtectedRoute implementation
echo "Checking ProtectedRoute implementation..."
ast-grep --pattern 'export $_ function ProtectedRoute' -A 10

# Look for role checking logic
echo "Checking for role verification..."
rg -l "role.*admin" --type jsx
frontend/src/components/Pages/VerifyOtp.jsx (1)

Line range hint 22-45: Verify integration with admin authentication flow.

The OTP verification logic appears to be generic and not specifically integrated with the admin authentication flow mentioned in the PR objectives. Please verify:

  1. Is this component meant to be shared between admin and regular user flows?
  2. Should there be admin-specific handling in the verification process?

Let's check how this component is used in the admin flow:

backend/controller/customer.controller.js (1)

146-146: LGTM: Role addition aligns with PR objectives.

The addition of the role field in the response object is consistent with the PR's goal of implementing role-based authentication.

frontend/src/components/Pages/Admin/AdminLogin.jsx (1)

1-9: LGTM! Dependencies are well organized.

The imports are appropriate for the component's functionality, showing good separation of concerns with context usage.

frontend/src/components/Pages/Admin/AdminSignup.jsx (1)

66-66: Clarify OTP implementation status.

The commented-out OTP alert suggests incomplete implementation of a security feature.

Let's check if OTP verification is implemented elsewhere:

Would you like help implementing the OTP verification flow?

✅ Verification successful

OTP implementation is fully functional - commented alert can be removed

The OTP verification system is completely implemented with:

  • Frontend components for OTP verification (VerifyOtp.jsx and verifyRegisterOtp.jsx)
  • Backend routes and controllers handling OTP generation, verification, and email delivery
  • Proper email verification flow with 6-digit OTP and 5-minute expiry

The commented-out alert in AdminSignup.jsx can be safely removed as it's redundant with the existing implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for OTP-related code
rg -i "otp" --type js --type jsx

Length of output: 60


Script:

#!/bin/bash
# Search for OTP-related code with ripgrep, using all text files
rg -i "otp" -t txt -t js -t ts -t tsx

# Also search for email verification related code since OTP is often used for email verification
rg -i "email.*verif|verif.*email" -t txt -t js -t ts -t tsx

# Look for authentication or verification related files
fd -e js -e jsx -e ts -e tsx . | grep -i "auth\|verif"

Length of output: 499


Script:

#!/bin/bash
# Check the content of OTP verification related files
cat frontend/src/components/Pages/VerifyOtp.jsx frontend/src/components/Pages/verifyRegisterOtp.jsx

# Check the content of email verification file
cat frontend/src/components/Pages/EmailVerify.jsx

# Look for OTP related routes or API endpoints
rg -i "otp" --type js backend/

Length of output: 14007

const ProtectedRoute = ({ children }) => {
const {user} = useUser();

return user.role == "admin" ? children : <Navigate to="/admin-login" />;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix security vulnerability in role comparison

The loose equality operator (==) can lead to unexpected type coercion. Use strict equality (===) for role comparison.

-  return user.role == "admin" ? children : <Navigate to="/admin-login" />;
+  return user.role === "admin" ? children : <Navigate to="/admin-login" />;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return user.role == "admin" ? children : <Navigate to="/admin-login" />;
return user.role === "admin" ? children : <Navigate to="/admin-login" />;

Comment on lines 5 to 9
const ProtectedRoute = ({ children }) => {
const {user} = useUser();

return user.role == "admin" ? children : <Navigate to="/admin-login" />;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add null checks and loading state handling

The component doesn't handle cases where the user object might be null/undefined or when authentication is still loading. This could lead to runtime errors.

-const ProtectedRoute = ({ children }) => {
-  const {user} = useUser();
+const ProtectedRoute = ({ children }) => {
+  const { user, isLoading } = useUser();
+
+  if (isLoading) {
+    return <div>Loading...</div>; // Consider using a proper loading component
+  }
+
+  if (!user) {
+    return <Navigate to="/admin-login" />;
+  }
 
-  return user.role === "admin" ? children : <Navigate to="/admin-login" />;
+  return user.role === "admin" ? children : <Navigate to="/admin-login" />;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const ProtectedRoute = ({ children }) => {
const {user} = useUser();
return user.role == "admin" ? children : <Navigate to="/admin-login" />;
};
const ProtectedRoute = ({ children }) => {
const { user, isLoading } = useUser();
if (isLoading) {
return <div>Loading...</div>; // Consider using a proper loading component
}
if (!user) {
return <Navigate to="/admin-login" />;
}
return user.role === "admin" ? children : <Navigate to="/admin-login" />;
};

Comment on lines 8 to 14
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<RouterProvider router={router} />
<UserProvider>
<RouterProvider router={router} />
</UserProvider>
</React.StrictMode>
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding error boundaries for improved reliability.

To prevent authentication-related errors from crashing the entire application, consider wrapping the UserProvider with an error boundary component.

Here's a suggested implementation:

+ import { ErrorBoundary } from 'react-error-boundary';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
+   <ErrorBoundary fallback={<div>Something went wrong with authentication. Please refresh.</div>}>
      <UserProvider>
        <RouterProvider router={router} />
      </UserProvider>
+   </ErrorBoundary>
  </React.StrictMode>
);

Committable suggestion was skipped due to low confidence.

Comment on lines 1 to 4
import React, { createContext, useState, useContext } from 'react';
import Cookies from 'js-cookie';

const UserContext = createContext();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding a default value and exporting the context.

The context creation could be improved for better maintainability and type safety.

 import React, { createContext, useState, useContext } from 'react';
 import Cookies from 'js-cookie';

-const UserContext = createContext();
+export const UserContext = createContext({
+  user: null,
+  setUser: () => {},
+});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import React, { createContext, useState, useContext } from 'react';
import Cookies from 'js-cookie';
const UserContext = createContext();
import React, { createContext, useState, useContext } from 'react';
import Cookies from 'js-cookie';
export const UserContext = createContext({
user: null,
setUser: () => {},
});

);
};

export const useUser = () => useContext(UserContext);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add context validation in useUser hook.

The custom hook should validate context usage and provide helpful error messages.

-export const useUser = () => useContext(UserContext);
+export const useUser = () => {
+  const context = useContext(UserContext);
+  if (context === undefined) {
+    throw new Error('useUser must be used within a UserProvider');
+  }
+  return context;
+};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const useUser = () => useContext(UserContext);
export const useUser = () => {
const context = useContext(UserContext);
if (context === undefined) {
throw new Error('useUser must be used within a UserProvider');
}
return context;
};

Comment on lines +87 to +90
const getPasswordStrengthText = (score) => {
const strengthLevels = ['Very Weak', 'Weak', 'Okay', 'Good', 'Strong'];
return strengthLevels[score];
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance password strength feedback.

The current strength indicators could be more informative to help users create better passwords.

Consider enhancing the feedback:

 const getPasswordStrengthText = (score) => {
-  const strengthLevels = ['Very Weak', 'Weak', 'Okay', 'Good', 'Strong'];
+  const strengthLevels = [
+    'Very Weak - Add more characters',
+    'Weak - Try adding numbers',
+    'Okay - Consider special characters',
+    'Good - Length is important too',
+    'Strong - Excellent password!'
+  ];
   return strengthLevels[score];
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getPasswordStrengthText = (score) => {
const strengthLevels = ['Very Weak', 'Weak', 'Okay', 'Good', 'Strong'];
return strengthLevels[score];
};
const getPasswordStrengthText = (score) => {
const strengthLevels = [
'Very Weak - Add more characters',
'Weak - Try adding numbers',
'Okay - Consider special characters',
'Good - Length is important too',
'Strong - Excellent password!'
];
return strengthLevels[score];
};

Comment on lines +51 to +64
try {
const response = await fetch(`${API_URL}/api/admin/register`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
const result = await response.json();

if (!response.ok) {
setIsLoading(false);
setError(result.error);
return;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Enhance API request security.

The API request lacks CSRF protection and rate limiting considerations.

Consider these security enhancements:

 try {
   const response = await fetch(`${API_URL}/api/admin/register`, {
     method: 'POST',
     headers: { 
       'Content-Type': 'application/json',
+      'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
     },
     credentials: 'include',
     body: JSON.stringify(data),
   });

Committable suggestion was skipped due to low confidence.

Comment on lines 166 to 170
<a href={`${API_URL}/api/user/auth/google`} className="w-full">
<button className="button-confirm w-full h-10 rounded-md border-2 border-black bg-beige text-[17px] font-semibold shadow-[4px_4px_0px_0px_black] hover:text-green-300">
Sign up with Google
</button>
</a>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Enhance Google authentication security and UX.

The Google authentication link lacks CSRF protection and loading state handling.

Consider these improvements:

-<a href={`${API_URL}/api/user/auth/google`} className="w-full">
+<a 
+  href={`${API_URL}/api/user/auth/google?csrf=${document.querySelector('meta[name="csrf-token"]').content}`}
+  className="w-full"
+  onClick={(e) => {
+    e.preventDefault();
+    setIsLoading(true);
+    window.location.href = e.target.href;
+  }}
+>
   <button className="button-confirm w-full h-10 rounded-md border-2 border-black bg-beige text-[17px] font-semibold shadow-[4px_4px_0px_0px_black] hover:text-green-300">
-    Sign up with Google
+    {isLoading ? 'Redirecting...' : 'Sign up with Google'}
   </button>
 </a>

Committable suggestion was skipped due to low confidence.

Comment on lines 45 to 49
if (!data.email.includes('@')) {
setError('Please enter a valid email address');
setIsLoading(false);
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Enhance email validation security.

The current email validation is too basic and could allow invalid email formats.

Consider using a proper email validation regex or a validation library:

-if (!data.email.includes('@')) {
+const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+if (!emailRegex.test(data.email)) {
  setError('Please enter a valid email address');
  setIsLoading(false);
  return;
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!data.email.includes('@')) {
setError('Please enter a valid email address');
setIsLoading(false);
return;
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(data.email)) {
setError('Please enter a valid email address');
setIsLoading(false);
return;
}

@@ -55,6 +55,7 @@ const Navbar = () => {
})

Cookies.remove('authToken');
Cookies.remove("authenticatedUser");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Enhance cookie removal security during logout.

While adding authenticatedUser cookie removal is good, consider these security improvements:

  1. Set secure attributes when removing cookies
  2. Clear all auth-related cookies in one operation

Apply this enhancement:

-    Cookies.remove("authenticatedUser");
+    Cookies.remove("authToken", { secure: true, sameSite: 'strict' });
+    Cookies.remove("authenticatedUser", { secure: true, sameSite: 'strict' });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Cookies.remove("authenticatedUser");
Cookies.remove("authToken", { secure: true, sameSite: 'strict' });
Cookies.remove("authenticatedUser", { secure: true, sameSite: 'strict' });

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (1)
frontend/src/router/index.jsx (1)

43-52: Consider implementing additional security measures

While the current implementation provides basic protection, consider these additional security measures:

  1. Implement rate limiting for admin login attempts
  2. Add CSRF protection for admin routes
  3. Consider implementing session management for admin sessions
  4. Add audit logging for admin actions
  5. Consider implementing 2FA for admin accounts

These measures would enhance the security of the admin functionality.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 13f97d4 and 51ea0da.

📒 Files selected for processing (4)
  • backend/controller/customer.controller.js (1 hunks)
  • frontend/src/components/Pages/Login.jsx (2 hunks)
  • frontend/src/components/Shared/Navbar.jsx (1 hunks)
  • frontend/src/router/index.jsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • backend/controller/customer.controller.js
  • frontend/src/components/Pages/Login.jsx
  • frontend/src/components/Shared/Navbar.jsx
🔇 Additional comments (1)
frontend/src/router/index.jsx (1)

25-27: LGTM: Required imports added correctly

The new imports are properly structured and align with the PR objectives for implementing admin authentication.

Comment on lines +43 to +50
<Route
path="/admin"
element={
<ProtectedRoute>
<Admin />
</ProtectedRoute>
}
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Security concern: Loose equality check in admin role validation

The ProtectedRoute implementation has a potential security issue using loose equality (==) instead of strict equality (===) when checking the admin role. While it works, it's not following security best practices and could lead to unexpected behavior.

  • frontend/src/router/ProtectedRoute.jsx: Change user.role == "admin" to user.role === "admin"
🔗 Analysis chain

Verify ProtectedRoute implementation for admin role check

The admin route is now protected, which is good. Let's verify the implementation of the ProtectedRoute component.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify ProtectedRoute implementation for admin authentication

# Check ProtectedRoute component implementation
echo "Checking ProtectedRoute implementation..."
rg -A 10 "function ProtectedRoute|const ProtectedRoute" frontend/src/router/

# Check for admin role validation in ProtectedRoute
echo "Checking admin role validation..."
rg -A 5 "role.*admin|isAdmin" frontend/src/router/ProtectedRoute

# Check for proper redirection logic
echo "Checking redirect implementation..."
rg -A 3 "navigate|redirect" frontend/src/router/ProtectedRoute

Length of output: 1066


Script:

#!/bin/bash
# Let's verify the actual path of ProtectedRoute component and its implementation
echo "Finding ProtectedRoute component location..."
fd -e jsx -e js ProtectedRoute

# Once found, let's check its content
echo "Checking component implementation..."
rg -A 10 "function ProtectedRoute|const ProtectedRoute"

# Let's also check for any admin role checks in the entire frontend
echo "Checking admin role validations..."
rg -A 5 "role.*admin|isAdmin" frontend/src/

Length of output: 1157

Comment on lines +51 to +52
<Route path="/admin-login" element={<AdminLogin />} />
<Route path="/admin-signup" element={<AdminSignup />} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Admin authentication implementation needs role-based security enhancements

The current implementation has several security concerns:

  • No explicit admin role validation in the authentication flow
  • Common user context is used for both admin and regular users without role distinction
  • Admin authentication endpoints (/api/admin/login and /api/admin/register) exist but no role-based guards
  • Google OAuth integration lacks admin-specific handling

Required changes:

  • Add admin role validation in the authentication response
  • Implement separate admin context or extend user context with role information
  • Add route guards to prevent regular users from accessing admin routes
  • Remove Google OAuth from admin authentication as it bypasses admin validation
🔗 Analysis chain

Verify admin-specific authentication handling

The routes are correctly added, but we need to ensure proper admin-specific authentication handling in the components.


Let me gather more information about the admin authentication implementation.

This will help us verify if there's proper admin-specific authentication logic and role validation in place.


Let me check the actual implementation of the admin components and user context to verify the authentication handling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify admin-specific authentication implementation

# Check admin role handling in login/signup
echo "Checking admin role handling in authentication..."
rg -A 5 "role.*admin|isAdmin" frontend/src/components/Pages/Admin/Admin{Login,Signup}.jsx

# Check for proper error handling
echo "Checking error handling..."
rg -A 5 "catch|error" frontend/src/components/Pages/Admin/Admin{Login,Signup}.jsx

# Check for proper state management
echo "Checking authentication state management..."
rg -A 5 "useState|useContext|useAuth" frontend/src/components/Pages/Admin/Admin{Login,Signup}.jsx

Length of output: 7706


Script:

#!/bin/bash
# Check admin-specific API endpoints and authentication logic
echo "Checking admin API endpoints and authentication..."
rg -A 5 "admin.*login|admin.*signup|admin.*auth" frontend/src/api/

# Check admin role validation in components
echo "Checking admin role validation..."
rg -A 5 "admin.*role|role.*admin|isAdmin" frontend/src/api/

# Check admin authentication state handling
echo "Checking admin auth state..."
rg -A 5 "useUser|AuthContext|admin.*context" frontend/src/context/

Length of output: 661


Script:

#!/bin/bash
# Check admin component implementations
echo "Checking AdminLogin implementation..."
cat frontend/src/components/Pages/Admin/AdminLogin.jsx

echo "Checking AdminSignup implementation..."
cat frontend/src/components/Pages/Admin/AdminSignup.jsx

# Check user context implementation
echo "Checking UserContext implementation..."
cat frontend/src/context/userContext.jsx

Length of output: 12474

@RamakrushnaBiswal
Copy link
Owner

@Sourabh782 resolve the code rabbit suggetions

@Sourabh782
Copy link
Contributor Author

@Sourabh782 resolve the code rabbit suggetions

okk implementing

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🧹 Outside diff range and nitpick comments (7)
frontend/src/router/ProtectedRoute.jsx (1)

1-3: Remove unused Route import

The Route component is imported but never used in this file.

import React from 'react';
-import { Route, Navigate } from 'react-router-dom';
+import { Navigate } from 'react-router-dom';
import { useUser } from '../context/userContext';
frontend/src/context/userContext.jsx (1)

1-35: Consider enhancing the authentication architecture.

While the current implementation provides basic authentication, consider adding these architectural improvements:

  1. Implement a refresh token mechanism to handle token expiration
  2. Add session management utilities (e.g., idle timeout, force logout)
  3. Create role-based access control (RBAC) utilities to centralize permission checks

Would you like assistance in implementing any of these architectural improvements?

frontend/src/components/Pages/Admin/AdminLogin.jsx (1)

65-67: Consider enhancing scroll behavior.

The current scroll implementation could be improved for a smoother user experience.

 useEffect(() => {
-  window.scrollTo(0, 0);
+  window.scrollTo({
+    top: 0,
+    behavior: 'smooth'
+  });
 }, []);
frontend/src/components/Pages/Admin.jsx (4)

Line range hint 37-39: Remove redundant Admin object.

The Admin object is no longer needed since we're now using the useUser hook to get the user's name dynamically.

-  const Admin = {
-    name: 'AdminName',
-  };

Line range hint 95-116: Fix critical bug in handleDelete function.

There are several issues in the delete event handler:

  1. Success message is shown when the response is NOT ok (incorrect condition)
  2. Navigation occurs on failure
  3. Error handling could be improved with user feedback

Apply this fix:

  const handleDelete = async (eventId) => {
    try {
      const response = await fetch(
        `${import.meta.env.VITE_BACKEND_URL}/api/event/delete?id=${eventId}`,
        {
-         method: 'get',
+         method: 'DELETE',
          headers: {
            'Content-Type': 'application/json',
          },
        }
      );
      const data = await response.json();
-     if (!response.ok) {
+     if (response.ok) {
        message.success('Event deleted successfully');
-       navigate('/admin');
+       // Filter out the deleted event from the list
+       setEvents((prevEvents) =>
+         prevEvents.filter((event) => event._id !== eventId)
+       );
+     } else {
+       message.error(data.message || 'Failed to delete event');
      }
-
-     // Filter out the deleted event from the list
-     setEvents((prevEvents) =>
-       prevEvents.filter((event) => event._id !== eventId)
-     );
    } catch (error) {
      console.error('Error deleting event:', error);
-     setError(error.message);
+     message.error('Error deleting event: ' + error.message);
    }
  };

Line range hint 66-89: Enhance form submission handling and user feedback.

The form submission could benefit from better user feedback and validation:

  1. Add loading state during submission
  2. Improve input validation
  3. Consistent error handling

Consider implementing these improvements:

  const handleSubmit = async (e) => {
    e.preventDefault();
+   // Add form validation
+   if (new Date(formData.date) < new Date()) {
+     message.error('Event date cannot be in the past');
+     return;
+   }
+   
+   // Add loading state
+   const [isSubmitting, setIsSubmitting] = useState(false);
+   setIsSubmitting(true);
+   
    const formattedTime = `${formatTime(formData.startTime)} - ${formatTime(formData.endTime)}`;
    const { title, description, ageRange, date } = formData;
    const event = { title, description, ageRange, date, time: formattedTime };
-   console.log(event);
    try {
      const response = await fetch(
        `${import.meta.env.VITE_BACKEND_URL}/api/event/create`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(event),
        }
      );
      const data = await response.json();
      if (response.ok) {
        message.success('Event added successfully');
-       navigate('/admin');
        fetchData();
+       setFormData({
+         title: '',
+         description: '',
+         ageRange: '',
+         startTime: '',
+         endTime: '',
+         date: '',
+       });
+     } else {
+       message.error(data.message || 'Failed to add event');
      }
-     console.log(data);
    } catch (error) {
      console.error('Error adding event:', error);
      message.error('Error adding event: ' + error.message);
+   } finally {
+     setIsSubmitting(false);
    }
  };

Also update the submit button to show loading state:

  <button
    type="submit"
+   disabled={isSubmitting}
    className="w-full bg-blue-500 text-white font-bold py-2 px-4 rounded-md hover:bg-blue-600 disabled:bg-gray-400"
  >
-   Submit
+   {isSubmitting ? 'Submitting...' : 'Submit'}
  </button>

Security improvements needed for Admin component API interactions

The verification reveals several security gaps that need to be addressed:

  1. Missing Authorization headers in Admin component API calls while other components like Dashboard implement them properly
  2. No CSRF protection implemented across the application
  3. No rate limiting for form submissions
  4. Admin route protection relies on client-side role check that could be bypassed

Required changes:

  • Add Authorization: Bearer ${token} header to all API calls in Admin.jsx
  • Implement CSRF token validation
  • Add request throttling for form submissions
  • Move role-based access control to the backend
const fetchData = async () => {
  try {
    const response = await fetch(
      `${import.meta.env.VITE_BACKEND_URL}/api/event/all`,
      {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
+         'Authorization': `Bearer ${user?.token}`,
+         'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
        },
      }
    );
🔗 Analysis chain

Line range hint 14-31: Address security concerns in API interactions.

Several security improvements are recommended for the admin panel:

  1. Add CSRF protection to API calls
  2. Implement rate limiting for form submissions
  3. Add authorization token to API requests
  4. Validate file uploads (if implemented later)

Consider these security enhancements:

+ const authToken = localStorage.getItem('adminToken');
  const fetchData = async () => {
    try {
      const response = await fetch(
        `${import.meta.env.VITE_BACKEND_URL}/api/event/all`,
        {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
+           'Authorization': `Bearer ${authToken}`,
+           'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
          },
        }
      );

Apply similar changes to handleSubmit and handleDelete functions. Also consider implementing request throttling on the frontend to prevent rapid-fire submissions.

Let's verify the current security measures:

Also applies to: 66-89, 95-116

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for proper authorization headers in API calls
rg -A 5 "fetch\(" frontend/src/
# Check for CSRF protection
rg -l "csrf" frontend/src/

Length of output: 8723


Script:

#!/bin/bash
# Check for authentication token usage in API calls
rg -A 5 "Authorization.*Bearer" frontend/src/

# Check for any authentication-related code in Admin component
rg -A 10 "localStorage.getItem.*Token|useAuth" frontend/src/components/Pages/Admin.jsx

# Check if there's any rate limiting implementation
rg -A 5 "rate|throttle|limit" frontend/src/components/Pages/Admin.jsx

# Check for any authentication hooks or context
fd -e jsx -e js -e ts -e tsx -p "auth|protect" frontend/src/

Length of output: 732


Script:

#!/bin/bash
# Check the implementation of ProtectedRoute
cat frontend/src/router/ProtectedRoute.jsx

# Check if there's any authentication context provider
rg -l "AuthContext|AuthProvider" frontend/src/

# Check how admin routes are protected in router configuration
rg -A 10 "path.*admin" frontend/src/

Length of output: 1685

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 51ea0da and 7c09828.

📒 Files selected for processing (7)
  • backend/controller/admin.controller.js (1 hunks)
  • frontend/src/components/Pages/Admin.jsx (3 hunks)
  • frontend/src/components/Pages/Admin/AdminLogin.jsx (1 hunks)
  • frontend/src/components/Pages/Admin/AdminSignup.jsx (1 hunks)
  • frontend/src/components/Pages/Login.jsx (2 hunks)
  • frontend/src/context/userContext.jsx (1 hunks)
  • frontend/src/router/ProtectedRoute.jsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/controller/admin.controller.js
  • frontend/src/components/Pages/Login.jsx
🔇 Additional comments (2)
frontend/src/router/ProtectedRoute.jsx (1)

5-13: Verify authentication token validity

The current implementation doesn't verify if the user's authentication token is still valid. An expired token could lead to unauthorized access.

Consider implementing token validation in the useUser hook:

  1. Check token expiration
  2. Implement token refresh mechanism
  3. Clear user data and redirect on token expiration
frontend/src/components/Pages/Admin.jsx (1)

4-4: LGTM: User context integration.

The integration of the user context is well implemented with proper import and hook usage.

Also applies to: 10-11

Comment on lines +5 to +6
const ProtectedRoute = ({ children }) => {
const {user} = useUser();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add prop validation

Consider adding PropTypes or TypeScript to validate the children prop and improve type safety.

+import PropTypes from 'prop-types';
 import React from 'react';
 
 const ProtectedRoute = ({ children }) => {
   const {user} = useUser();
   // ... rest of the component
 };
 
+ProtectedRoute.propTypes = {
+  children: PropTypes.node.isRequired,
+};
 
 export default ProtectedRoute;

Committable suggestion skipped: line range outside the PR's diff.

return <Navigate to="/admin-login" />;
}

return user.role === "admin" ? children : <Navigate to="/admin-login" />;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance role checking and configuration

Consider the following improvements for better maintainability and flexibility:

  1. Extract magic strings to constants
  2. Make redirect path configurable via props
  3. Add case-insensitive role comparison
+const ADMIN_ROLE = 'admin';
+const DEFAULT_REDIRECT = '/admin-login';
 
-const ProtectedRoute = ({ children }) => {
+const ProtectedRoute = ({ children, redirectPath = DEFAULT_REDIRECT }) => {
   const {user} = useUser();
 
   if (!user) {
-    return <Navigate to="/admin-login" />;
+    return <Navigate to={redirectPath} />;
   }
 
-  return user.role === "admin" ? children : <Navigate to="/admin-login" />;
+  return user.role?.toLowerCase() === ADMIN_ROLE ? 
+    children : 
+    <Navigate to={redirectPath} />;
 };

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +9 to +27
export const UserProvider = ({ children }) => {
const data = Cookies.get("authenticatedUser");

let userData = null;
try {
userData = data ? JSON.parse(data) : null;
} catch (error) {
console.error('Invalid user data in cookie:', error);
Cookies.remove("authenticatedUser");
}

const [user, setUser] = useState(userData);

return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Enhance security measures in UserProvider implementation.

The current implementation needs additional security measures to protect against common web vulnerabilities:

  1. Add cookie security options when setting cookies
  2. Validate user data structure before setting state
  3. Implement CSRF protection

Here's how to enhance the implementation:

 export const UserProvider = ({ children }) => {
   const data = Cookies.get("authenticatedUser");
 
   let userData = null;
   try {
     userData = data ? JSON.parse(data) : null;
+    // Validate user data structure
+    if (userData && !isValidUserData(userData)) {
+      throw new Error('Invalid user data structure');
+    }
   } catch (error) {
     console.error('Invalid user data in cookie:', error);
     Cookies.remove("authenticatedUser");
   }
   
   const [user, setUser] = useState(userData);
 
+  // Wrap setUser to ensure cookie options
+  const setUserWithCookie = (newUser) => {
+    setUser(newUser);
+    if (newUser) {
+      Cookies.set("authenticatedUser", JSON.stringify(newUser), {
+        secure: true,
+        sameSite: 'strict',
+        expires: 1, // 1 day
+      });
+    } else {
+      Cookies.remove("authenticatedUser");
+    }
+  }
 
   return (
-    <UserContext.Provider value={{ user, setUser }}>
+    <UserContext.Provider value={{ user, setUser: setUserWithCookie }}>
       {children}
     </UserContext.Provider>
   );
 };
 
+// Add this helper function
+function isValidUserData(data) {
+  return (
+    data &&
+    typeof data === 'object' &&
+    typeof data.id === 'string' &&
+    typeof data.role === 'string' &&
+    ['admin', 'user'].includes(data.role)
+  );
+}

Committable suggestion skipped: line range outside the PR's diff.

</button>
</Link>

{error && <p className="text-red-500 mt-2">{error}</p>}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve error message accessibility and visibility.

The error message display could be enhanced for better accessibility and user experience.

-{error && <p className="text-red-500 mt-2">{error}</p>}
+{error && (
+  <div
+    role="alert"
+    aria-live="polite"
+    className="p-3 bg-red-100 border border-red-400 text-red-700 rounded relative"
+  >
+    <span className="block sm:inline">{error}</span>
+  </div>
+)}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{error && <p className="text-red-500 mt-2">{error}</p>}
{error && (
<div
role="alert"
aria-live="polite"
className="p-3 bg-red-100 border border-red-400 text-red-700 rounded relative"
>
<span className="block sm:inline">{error}</span>
</div>
)}

Comment on lines +49 to +51
if (!response.ok) {
throw new Error(result.message || 'Login failed');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance error handling with more specific error messages.

The current error handling could be more informative by providing specific error messages based on different error scenarios.

 if (!response.ok) {
-  throw new Error(result.message || 'Login failed');
+  const errorMessage = {
+    401: 'Invalid email or password',
+    403: 'Account not verified',
+    429: 'Too many login attempts. Please try again later',
+  }[response.status] || result.message || 'Login failed';
+  throw new Error(errorMessage);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!response.ok) {
throw new Error(result.message || 'Login failed');
}
if (!response.ok) {
const errorMessage = {
401: 'Invalid email or password',
403: 'Account not verified',
429: 'Too many login attempts. Please try again later',
}[response.status] || result.message || 'Login failed';
throw new Error(errorMessage);
}

Comment on lines +25 to +50
const handleSubmit = async (e) => {
e.preventDefault();
setIsLoading(true);

// Input validation
if (!data.email || !data.password || !data.name) {
setError('Please fill in all fields');
setIsLoading(false);
return;
}
if (data.password.length < 8) {
setError('Password must be at least 8 characters long');
setIsLoading(false);
return;
}
if (data.name.length < 3) {
setError('Name must be at least 3 characters long');
setIsLoading(false);
return;
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(data.email)) {
setError('Please enter a valid email address');
setIsLoading(false);
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Centralize validation logic for better maintainability.

The validation logic is scattered throughout the handleSubmit function. Consider extracting it into a separate utility function.

const validateFormData = (data) => {
  const errors = [];
  if (!data.email || !data.password || !data.name) {
    errors.push('Please fill in all fields');
  }
  if (data.password.length < 8) {
    errors.push('Password must be at least 8 characters long');
  }
  if (data.name.length < 3) {
    errors.push('Name must be at least 3 characters long');
  }
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  if (!emailRegex.test(data.email)) {
    errors.push('Please enter a valid email address');
  }
  return errors;
};

Comment on lines +52 to +76
try {
const response = await fetch(`${API_URL}/api/admin/register`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
const result = await response.json();

if (!response.ok) {
setIsLoading(false);
setError(result.error);
return;
}


// alert('OTP sent to your email. Verify to complete registration.');
navigate('/admin-login');

} catch (error) {
setError(error.message);
console.error('Error:', error);
} finally {
setIsLoading(false); // Ensure loading state is reset after request
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Implement rate limiting for failed signup attempts.

As this is an admin signup endpoint, it should be protected against brute force attempts.

Consider implementing a client-side attempt counter:

const MAX_ATTEMPTS = 3;
const LOCKOUT_TIME = 15 * 60 * 1000; // 15 minutes

const [attempts, setAttempts] = useState(0);
const [lockoutUntil, setLockoutUntil] = useState(null);

// In handleSubmit, before API call:
if (lockoutUntil && Date.now() < lockoutUntil) {
  setError(`Too many attempts. Please try again in ${Math.ceil((lockoutUntil - Date.now()) / 60000)} minutes`);
  return;
}

// After failed attempt:
if (!response.ok) {
  setAttempts(prev => {
    if (prev + 1 >= MAX_ATTEMPTS) {
      setLockoutUntil(Date.now() + LOCKOUT_TIME);
      return 0;
    }
    return prev + 1;
  });
}

Comment on lines +79 to +81
useEffect(() => {
window.scrollTo(0, 0);
}, []);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance scroll behavior accessibility.

The current scroll implementation might interfere with assistive technologies.

Consider using a more accessible approach:

useEffect(() => {
  // Announce page load to screen readers
  const pageTitle = document.title;
  document.title = "Admin Signup - " + pageTitle;
  
  // Smooth scroll to top
  window.scrollTo({
    top: 0,
    behavior: 'smooth'
  });
  
  return () => {
    document.title = pageTitle;
  };
}, []);

Comment on lines +172 to +177
<button
className="button-confirm w-full h-10 rounded-md border-2 border-black bg-beige text-[17px] font-semibold shadow-[4px_4px_0px_0px_black] mb-2 hover:text-green-300"
onClick={handleSubmit}
>
{isLoading ? 'Loading...' : "Let's go →"}
</button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance loading state and form submission feedback.

The current loading state only updates the button text. Consider providing more comprehensive feedback.

 <button
   className="button-confirm w-full h-10 rounded-md border-2 border-black bg-beige text-[17px] font-semibold shadow-[4px_4px_0px_0px_black] mb-2 hover:text-green-300"
   onClick={handleSubmit}
+  disabled={isLoading}
 >
-  {isLoading ? 'Loading...' : "Let's go →"}
+  {isLoading ? (
+    <span className="flex items-center justify-center">
+      <svg className="animate-spin h-5 w-5 mr-3" viewBox="0 0 24 24">
+        <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
+        <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
+      </svg>
+      Creating account...
+    </span>
+  ) : (
+    "Let's go →"
+  )}
 </button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button
className="button-confirm w-full h-10 rounded-md border-2 border-black bg-beige text-[17px] font-semibold shadow-[4px_4px_0px_0px_black] mb-2 hover:text-green-300"
onClick={handleSubmit}
>
{isLoading ? 'Loading...' : "Let's go →"}
</button>
<button
className="button-confirm w-full h-10 rounded-md border-2 border-black bg-beige text-[17px] font-semibold shadow-[4px_4px_0px_0px_black] mb-2 hover:text-green-300"
onClick={handleSubmit}
disabled={isLoading}
>
{isLoading ? (
<span className="flex items-center justify-center">
<svg className="animate-spin h-5 w-5 mr-3" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
</svg>
Creating account...
</span>
) : (
"Let's go →"
)}
</button>

Comment on lines +270 to 271
{events.length > 0 && events.map((event) => (
<div
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance UI with loading and empty states.

The events rendering could be improved with better handling of different states.

Consider implementing these improvements:

+ const [isLoading, setIsLoading] = useState(true);

  const fetchData = async () => {
+   setIsLoading(true);
    try {
      const response = await fetch(...);
      const data = await response.json();
      setEvents(data);
    } catch (error) {
      setError(error.message);
    } finally {
+     setIsLoading(false);
    }
  };

- {events.length > 0 && events.map((event) => (
+ {isLoading ? (
+   <div className="flex justify-center items-center h-40">
+     <span className="loading loading-spinner loading-lg"></span>
+   </div>
+ ) : error ? (
+   <div className="text-red-500 text-center">
+     <p>Error loading events: {error}</p>
+     <button 
+       onClick={fetchData}
+       className="mt-4 bg-blue-500 text-white px-4 py-2 rounded"
+     >
+       Retry
+     </button>
+   </div>
+ ) : events.length === 0 ? (
+   <div className="text-center text-gray-500">
+     <p>No events found</p>
+   </div>
+ ) : (
+   events.map((event) => (

Committable suggestion skipped: line range outside the PR's diff.

@Sourabh782
Copy link
Contributor Author

@RamakrushnaBiswal can you now check?

Copy link

vercel bot commented Nov 4, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
play-cafe ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 4, 2024 4:46am

@RamakrushnaBiswal RamakrushnaBiswal added enhancement New feature or request level3 for 45 points gssoc-ext gssoc-extd program hacktoberfest accepted hacktoberfest-accepted repo labels Nov 4, 2024
@RamakrushnaBiswal RamakrushnaBiswal merged commit 3a4fa96 into RamakrushnaBiswal:main Nov 4, 2024
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request gssoc-ext gssoc-extd program hacktoberfest accepted hacktoberfest-accepted repo level3 for 45 points
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create Admin Creation and Login Pages
2 participants