Skip to content

Commit df9af68

Browse files
committed
private routes
1 parent 9b6dbaf commit df9af68

File tree

9 files changed

+195
-57
lines changed

9 files changed

+195
-57
lines changed

client/src/App.jsx

Lines changed: 87 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ const enhancedEmployerView = {
3838
]
3939
};
4040

41+
import ProtectedRoute from "./components/ProtectedRoute";
42+
4143
const App = () => {
4244
const [selectedRole, setSelectedRole] = useState(
4345
localStorage.getItem('userRole') ||
@@ -75,7 +77,7 @@ const App = () => {
7577

7678
// Check if Dynamic Labs environment ID is configured
7779
const dynamicEnvId = import.meta.env.VITE_DYNAMIC_ENV_ID;
78-
80+
7981
if (!dynamicEnvId) {
8082
console.error('VITE_DYNAMIC_ENV_ID is not configured. Please set this environment variable.');
8183
return (
@@ -136,32 +138,90 @@ const App = () => {
136138
}}
137139
>
138140
<div>
139-
<Routes>
140-
{/* Common Routes */}
141-
<Route path="/" element={<LandingPage />} />
142-
<Route path="/about-us" element={<AboutPage />} />
143-
<Route path="/user-profile" element={<UserProfile />} />
144-
<Route path="/job-details/:id" element={<JobDetails />} />
145-
146-
{/* Employee Routes */}
147-
<Route path="/employeeDashboard" element={<EmployeeDashboard />} />
148-
<Route path="/employee-profile" element={<EmployeeProfile />} />
149-
<Route path="/employee-jobs" element={<EmployeeJobsPage />} />
150-
151-
{/* Employer Routes */}
152-
<Route path="/employerDashboard" element={<EmployerDashboard />} />
153-
<Route path="/employer-profile" element={<EmployerProfile />} />
154-
<Route path="/job" element={<Job />} />
155-
<Route path="/view-employees" element={<EmployerJobPortal />} />
156-
<Route path="/view-open-contracts" element={<OpenContracts />} />
157-
<Route path="/review-applications" element={<ReviewApplications />} />
158-
<Route path="/review-completed-contracts" element={<ReviewCompletedContracts />} />
159-
<Route path="/dispute" element={<Dispute />} />
160-
<Route path="/closed-contracts" element={<ClosedContracts />} />
161-
162-
{/* 404 - Must be last */}
163-
<Route path="*" element={<h1>404 - Not Found</h1>} />
164-
</Routes>
141+
<Routes>
142+
{/* Public Routes */}
143+
<Route path="/" element={<LandingPage />} />
144+
<Route path="/about-us" element={<AboutPage />} />
145+
146+
{/* Protected Routes */}
147+
<Route path="/user-profile" element={
148+
<ProtectedRoute>
149+
<UserProfile />
150+
</ProtectedRoute>
151+
} />
152+
<Route path="/job-details/:id" element={
153+
<ProtectedRoute>
154+
<JobDetails />
155+
</ProtectedRoute>
156+
} />
157+
158+
{/* Employee Routes */}
159+
<Route path="/employeeDashboard" element={
160+
<ProtectedRoute>
161+
<EmployeeDashboard />
162+
</ProtectedRoute>
163+
} />
164+
<Route path="/employee-profile" element={
165+
<ProtectedRoute>
166+
<EmployeeProfile />
167+
</ProtectedRoute>
168+
} />
169+
<Route path="/employee-jobs" element={
170+
<ProtectedRoute>
171+
<EmployeeJobsPage />
172+
</ProtectedRoute>
173+
} />
174+
175+
{/* Employer Routes */}
176+
<Route path="/employerDashboard" element={
177+
<ProtectedRoute>
178+
<EmployerDashboard />
179+
</ProtectedRoute>
180+
} />
181+
<Route path="/employer-profile" element={
182+
<ProtectedRoute>
183+
<EmployerProfile />
184+
</ProtectedRoute>
185+
} />
186+
<Route path="/job" element={
187+
<ProtectedRoute>
188+
<Job />
189+
</ProtectedRoute>
190+
} />
191+
<Route path="/view-employees" element={
192+
<ProtectedRoute>
193+
<EmployerJobPortal />
194+
</ProtectedRoute>
195+
} />
196+
<Route path="/view-open-contracts" element={
197+
<ProtectedRoute>
198+
<OpenContracts />
199+
</ProtectedRoute>
200+
} />
201+
<Route path="/review-applications" element={
202+
<ProtectedRoute>
203+
<ReviewApplications />
204+
</ProtectedRoute>
205+
} />
206+
<Route path="/review-completed-contracts" element={
207+
<ProtectedRoute>
208+
<ReviewCompletedContracts />
209+
</ProtectedRoute>
210+
} />
211+
<Route path="/dispute" element={
212+
<ProtectedRoute>
213+
<Dispute />
214+
</ProtectedRoute>
215+
} />
216+
<Route path="/closed-contracts" element={
217+
<ProtectedRoute>
218+
<ClosedContracts />
219+
</ProtectedRoute>
220+
} />
221+
222+
{/* 404 - Must be last */}
223+
<Route path="*" element={<h1>404 - Not Found</h1>} />
224+
</Routes>
165225
</div>
166226
</DynamicContextProvider>
167227
);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react';
2+
import { Navigate } from 'react-router-dom';
3+
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
4+
5+
const ProtectedRoute = ({ children }) => {
6+
const { user, isLoading } = useDynamicContext();
7+
8+
if (isLoading) {
9+
return (
10+
<div className="flex items-center justify-center min-h-screen">
11+
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"></div>
12+
</div>
13+
);
14+
}
15+
16+
if (!user) {
17+
return <Navigate to="/" replace />;
18+
}
19+
20+
return children;
21+
};
22+
23+
export default ProtectedRoute;

client/src/services/api.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
2+
import { getAuthToken } from "@dynamic-labs/sdk-react-core";
23

34
class ApiService {
45
// Generic request method
56
async request(endpoint, options = {}) {
67
const url = `${API_BASE_URL}${endpoint}`;
8+
9+
// Get the Dynamic JWT token
10+
const token = getAuthToken();
11+
712
const config = {
813
headers: {
914
'Content-Type': 'application/json',
15+
...(token ? { 'Authorization': `Bearer ${token}` } : {}),
1016
...options.headers,
1117
},
1218
...options,
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const jwt = require('jsonwebtoken');
2+
3+
const verifyToken = (req, res, next) => {
4+
// 1. Get token from header
5+
const authHeader = req.headers['authorization'];
6+
const token = authHeader && authHeader.split(' ')[1]; // "Bearer <TOKEN>"
7+
8+
if (!token) {
9+
return res.status(401).json({
10+
success: false,
11+
message: 'Access denied. No token provided.'
12+
});
13+
}
14+
15+
try {
16+
// 2. Verify the token
17+
// Note: For production with Dynamic, you should verify against their public key (JWKS).
18+
// For now, we are using the local secret or assuming the token structure is valid if we can decode it.
19+
// If you have the Dynamic public key, replace process.env.JWT_SECRET with it.
20+
// If using Dynamic's developer JWTs for testing, the secret might work if configured.
21+
22+
// WARNING: If these are real Dynamic tokens (RS256), verify() with a symmetric secret will fail.
23+
// If we don't have the public key yet, we might need to skip signature verification
24+
// or ask the user for the public key.
25+
// For this step, I will implement standard verification.
26+
27+
const decoded = jwt.verify(token, process.env.JWT_SECRET);
28+
29+
// 3. Attach user info to request
30+
req.user = decoded;
31+
32+
// 4. Proceed to the route
33+
next();
34+
} catch (error) {
35+
console.error('Token verification failed:', error.message);
36+
res.status(403).json({
37+
success: false,
38+
message: 'Invalid token.',
39+
error: error.message
40+
});
41+
}
42+
};
43+
44+
module.exports = verifyToken;

server/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"cors": "^2.8.5",
2121
"dotenv": "^16.3.1",
2222
"helmet": "^7.1.0",
23-
"express-rate-limit": "^7.1.5"
23+
"express-rate-limit": "^7.1.5",
24+
"jsonwebtoken": "^9.0.2"
2425
},
2526
"devDependencies": {
2627
"nodemon": "^3.0.2"

server/routes/employeeRoutes.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
const express = require('express');
22
const EmployeeController = require('../controllers/employeeController');
3+
const verifyToken = require('../middleware/authMiddleware');
34

45
const router = express.Router();
56

67
// Employee routes
7-
router.post('/', EmployeeController.createEmployee);
8-
router.get('/', EmployeeController.getAllEmployees);
9-
router.get('/:id', EmployeeController.getEmployeeById);
10-
router.get('/email/:email', EmployeeController.getEmployeeByEmail);
11-
router.get('/wallet/:wallet_address', EmployeeController.getEmployeeByWallet);
12-
router.put('/:id', EmployeeController.updateEmployee);
8+
router.post('/', verifyToken, EmployeeController.createEmployee);
9+
router.get('/', verifyToken, EmployeeController.getAllEmployees);
10+
router.get('/:id', verifyToken, EmployeeController.getEmployeeById);
11+
router.get('/email/:email', verifyToken, EmployeeController.getEmployeeByEmail);
12+
router.get('/wallet/:wallet_address', verifyToken, EmployeeController.getEmployeeByWallet);
13+
router.put('/:id', verifyToken, EmployeeController.updateEmployee);
1314

1415
module.exports = router;

server/routes/employerRoutes.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
const express = require('express');
22
const EmployerController = require('../controllers/employerController');
3+
const verifyToken = require('../middleware/authMiddleware');
34

45
const router = express.Router();
56

67
// Employer routes
7-
router.post('/', EmployerController.createEmployer);
8-
router.get('/', EmployerController.getAllEmployers);
9-
router.get('/:id', EmployerController.getEmployerById);
10-
router.get('/email/:email', EmployerController.getEmployerByEmail);
11-
router.get('/wallet/:wallet_address', EmployerController.getEmployerByWallet);
12-
router.put('/:id', EmployerController.updateEmployer);
8+
router.post('/', verifyToken, EmployerController.createEmployer);
9+
router.get('/', verifyToken, EmployerController.getAllEmployers);
10+
router.get('/:id', verifyToken, EmployerController.getEmployerById);
11+
router.get('/email/:email', verifyToken, EmployerController.getEmployerByEmail);
12+
router.get('/wallet/:wallet_address', verifyToken, EmployerController.getEmployerByWallet);
13+
router.put('/:id', verifyToken, EmployerController.updateEmployer);
1314

1415
module.exports = router;
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
const express = require('express');
22
const router = express.Router();
33
const jobApplicationController = require('../controllers/jobApplicationController');
4+
const verifyToken = require('../middleware/authMiddleware');
45

56
// Save/Unsave job routes
6-
router.post('/save', jobApplicationController.saveJob);
7-
router.post('/unsave', jobApplicationController.unsaveJob);
7+
router.post('/save', verifyToken, jobApplicationController.saveJob);
8+
router.post('/unsave', verifyToken, jobApplicationController.unsaveJob);
89

910
// Apply to job route
10-
router.post('/apply', jobApplicationController.applyToJob);
11+
router.post('/apply', verifyToken, jobApplicationController.applyToJob);
1112

1213
// Get jobs by status for an employee
13-
router.get('/saved/:employeeId', jobApplicationController.getSavedJobs);
14-
router.get('/applied/:employeeId', jobApplicationController.getAppliedJobs);
15-
router.get('/employee/:employeeId', jobApplicationController.getEmployeeApplications);
14+
router.get('/saved/:employeeId', verifyToken, jobApplicationController.getSavedJobs);
15+
router.get('/applied/:employeeId', verifyToken, jobApplicationController.getAppliedJobs);
16+
router.get('/employee/:employeeId', verifyToken, jobApplicationController.getEmployeeApplications);
1617

1718
// Update application status
18-
router.patch('/:applicationId/status', jobApplicationController.updateApplicationStatus);
19+
router.patch('/:applicationId/status', verifyToken, jobApplicationController.updateApplicationStatus);
1920

2021
module.exports = router;

server/routes/jobRoutes.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
const express = require('express');
22
const JobController = require('../controllers/jobController');
3+
const verifyToken = require('../middleware/authMiddleware');
34

45
const router = express.Router();
56

67
// Job routes
7-
router.post('/', JobController.createJob);
8-
router.get('/', JobController.getAllJobs);
9-
router.get('/employer/:employer_id', JobController.getJobsByEmployer);
10-
router.get('/employer/:employer_id/applications', JobController.getJobsWithApplicationsByEmployer);
11-
router.get('/status/:status', JobController.getJobsByStatus);
12-
router.get('/company/:company_name', JobController.getJobsByCompany);
13-
router.get('/:id/applications', JobController.getJobApplications);
14-
router.get('/:id', JobController.getJobById);
15-
router.put('/:id', JobController.updateJob);
16-
router.patch('/:id/status', JobController.updateJobStatus);
8+
router.post('/', verifyToken, JobController.createJob);
9+
router.get('/', verifyToken, JobController.getAllJobs);
10+
router.get('/employer/:employer_id', verifyToken, JobController.getJobsByEmployer);
11+
router.get('/employer/:employer_id/applications', verifyToken, JobController.getJobsWithApplicationsByEmployer);
12+
router.get('/status/:status', verifyToken, JobController.getJobsByStatus);
13+
router.get('/company/:company_name', verifyToken, JobController.getJobsByCompany);
14+
router.get('/:id/applications', verifyToken, JobController.getJobApplications);
15+
router.get('/:id', verifyToken, JobController.getJobById);
16+
router.put('/:id', verifyToken, JobController.updateJob);
17+
router.patch('/:id/status', verifyToken, JobController.updateJobStatus);
1718

1819
module.exports = router;

0 commit comments

Comments
 (0)