229 lines
6.0 KiB
Markdown
229 lines
6.0 KiB
Markdown
# Authentication
|
|
|
|
## Function 1: Basic Layout (Header, Footer, Navbar, SidebarAdmin)
|
|
|
|
### Objective
|
|
Create a foundational layout for the entire system and structure content rendering by route.
|
|
|
|
#### Detailed Tasks
|
|
- Create directory:
|
|
```
|
|
src/components/layouts/
|
|
```
|
|
- Include:
|
|
+ Header.jsx
|
|
+ Footer.jsx
|
|
+ Navbar.jsx
|
|
+ SidebarAdmin.jsx
|
|
+ LayoutMain.jsx
|
|
- Use <Outlet /> in LayoutMain to render dynamic content.
|
|
- Navbar changes based on login status:
|
|
+ If not logged in → display "Login / Register" button.
|
|
+ If logged in → display avatar, user name and "Logout" button.
|
|
- SidebarAdmin only displays with role = admin.
|
|
|
|
### Expected Results
|
|
1. Overall layout displays stably.
|
|
2. Navbar displays dynamic content based on user status.
|
|
3. Responsive interface, compatible with desktop/mobile.
|
|
|
|
---
|
|
|
|
## Function 2: Routing Configuration (react-router-dom)
|
|
|
|
### Objective
|
|
Set up a standard routing system with role-based route protection.
|
|
|
|
#### Detailed Tasks
|
|
- Main route structure:
|
|
```
|
|
<Route path="/" element={<LayoutMain />}>
|
|
<Route index element={<HomePage />} />
|
|
<Route path="rooms" element={<RoomListPage />} />
|
|
<Route path="bookings" element={<BookingListPage />} />
|
|
</Route>
|
|
|
|
<Route path="/login" element={<LoginPage />} />
|
|
<Route path="/register" element={<RegisterPage />} />
|
|
<Route path="/forgot-password" element={<ForgotPasswordPage />} />
|
|
<Route path="/reset-password/:token" element={<ResetPasswordPage />} />
|
|
|
|
<Route path="/dashboard" element={<ProtectedRoute><Dashboard /></ProtectedRoute>} />
|
|
<Route path="/admin/*" element={<AdminRoute><AdminModule /></AdminRoute>} />
|
|
```
|
|
- Use ProtectedRoute and AdminRoute to check:
|
|
+ isAuthenticated
|
|
+ role === "admin"
|
|
|
|
### Expected Results
|
|
1. Unauthenticated users are redirected to /login.
|
|
2. AdminRoute only allows admin access.
|
|
3. All routes work smoothly, no redirect loop errors.
|
|
|
|
---
|
|
|
|
## Function 3: useAuthStore (Zustand Store)
|
|
|
|
### Objective
|
|
Manage global authentication state (token, userInfo, role).
|
|
|
|
#### Detailed Tasks
|
|
- Create src/stores/useAuthStore.js
|
|
- Structure:
|
|
```
|
|
const useAuthStore = create((set) => ({
|
|
token: localStorage.getItem("token") || null,
|
|
userInfo: JSON.parse(localStorage.getItem("userInfo")) || null,
|
|
isAuthenticated: !!localStorage.getItem("token"),
|
|
|
|
login: async (credentials) => { ... },
|
|
logout: () => { ... },
|
|
setUser: (user) => { ... },
|
|
resetPassword: async (payload) => { ... },
|
|
}));
|
|
```
|
|
- When login succeeds:
|
|
+ Save token + userInfo to localStorage.
|
|
- When logout:
|
|
+ Clear localStorage and reset state.
|
|
|
|
### Expected Results
|
|
1. All user information is managed centrally.
|
|
2. Maintain login after page reload.
|
|
3. Easy access to userInfo in any component.
|
|
|
|
---
|
|
|
|
## Function 4: Login Form
|
|
|
|
### Objective
|
|
Allow users to log into the system.
|
|
|
|
#### Detailed Tasks
|
|
- Create LoginPage.jsx
|
|
- Use React Hook Form + Yup validation:
|
|
+ Valid email
|
|
+ Password ≥ 8 characters
|
|
- API:
|
|
```
|
|
POST /api/auth/login
|
|
```
|
|
- After successful login:
|
|
+ Save token to localStorage.
|
|
+ Call setUser() to update Zustand.
|
|
+ Redirect to /dashboard.
|
|
+ Send email POST /api/notify/login-success.
|
|
- Enhanced UX:
|
|
+ Loading button when submitting form.
|
|
+ "Show/Hide password".
|
|
+ "Remember me" → save for 7 days.
|
|
|
|
### Expected Results
|
|
1. Login works smoothly, displays clear error messages.
|
|
2. Email is sent when login succeeds.
|
|
3. Redirect correctly based on user role.
|
|
|
|
---
|
|
|
|
## Function 5: Register Form
|
|
|
|
### Objective
|
|
Allow users to register a new account.
|
|
|
|
#### Detailed Tasks
|
|
- Create RegisterPage.jsx
|
|
- Use React Hook Form + Yup validation:
|
|
+ Full name not empty
|
|
+ Valid email
|
|
+ Password ≥ 8 characters, contains special characters
|
|
- API:
|
|
```
|
|
POST /api/auth/register
|
|
```
|
|
- After successful registration:
|
|
+ Display toast "Registration successful, please login".
|
|
+ Redirect to /login.
|
|
|
|
### Expected Results
|
|
1. Users can create new accounts successfully.
|
|
2. Strict validation, smooth UX.
|
|
3. Interface consistent with login form.
|
|
|
|
---
|
|
|
|
## Function 6: Forgot Password
|
|
|
|
### Objective
|
|
Provide functionality to send password reset email.
|
|
|
|
#### Detailed Tasks
|
|
- Create ForgotPasswordPage.jsx
|
|
- API:
|
|
```
|
|
POST /api/auth/forgot-password
|
|
```
|
|
- After successful send:
|
|
+ Display message "Please check your email to reset password."
|
|
+ Backend sends reset link with token:
|
|
```
|
|
https://domain.com/reset-password/:token
|
|
```
|
|
|
|
### Expected Results
|
|
1. Email sent successfully.
|
|
2. Clear UX, with loading and error messages.
|
|
3. User-friendly interface.
|
|
|
|
---
|
|
|
|
## Function 7: Reset Password
|
|
|
|
### Objective
|
|
Allow users to change password through email link.
|
|
|
|
#### Detailed Tasks
|
|
- Create ResetPasswordPage.jsx
|
|
- Validation:
|
|
+ New password ≥ 8 characters, contains special characters
|
|
+ Confirm password matches
|
|
- API:
|
|
```
|
|
POST /api/auth/reset-password
|
|
```
|
|
- After successful password change:
|
|
+ Send confirmation email POST /api/notify/reset-success.
|
|
+ Redirect to /login.
|
|
|
|
### Expected Results
|
|
1. Password updated successfully.
|
|
2. Success notification email sent.
|
|
3. Protect expired token (invalid token → redirect to forgot-password).
|
|
|
|
---
|
|
|
|
## Function 8: Permissions & Route Protection (ProtectedRoute / AdminRoute)
|
|
|
|
### Objective
|
|
Block unauthorized access and protect important routes.
|
|
|
|
#### Detailed Tasks
|
|
- Create ProtectedRoute.jsx component:
|
|
```
|
|
const ProtectedRoute = ({ children }) => {
|
|
const { isAuthenticated } = useAuthStore();
|
|
const location = useLocation();
|
|
return isAuthenticated ? children : <Navigate to="/login" state={{ from: location }} replace />;
|
|
};
|
|
```
|
|
|
|
- Create AdminRoute.jsx:
|
|
```
|
|
const AdminRoute = ({ children }) => {
|
|
const { userInfo } = useAuthStore();
|
|
return userInfo?.role === "admin" ? children : <Navigate to="/" replace />;
|
|
};
|
|
```
|
|
### Expected Results
|
|
1. Only valid users can access important routes.
|
|
2. AdminRoute ensures security for admin module.
|