alpe-temp 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/backend-project/package-lock.json +131 -0
  2. package/backend-project/package.json +3 -1
  3. package/backend-project/src/app.js +33 -55
  4. package/backend-project/src/config/app.config.js +1 -49
  5. package/backend-project/src/config/env.js +2 -10
  6. package/backend-project/src/middleware/auth.middleware.js +3 -26
  7. package/backend-project/src/modules/auth/auth.controller.js +15 -19
  8. package/backend-project/src/modules/auth/auth.routes.js +4 -8
  9. package/backend-project/src/modules/auth/auth.service.js +9 -31
  10. package/backend-project/src/modules/auth/user.model.js +10 -33
  11. package/backend-project/src/modules/department/department.controller.js +0 -4
  12. package/backend-project/src/modules/department/department.model.js +1 -4
  13. package/backend-project/src/modules/department/department.routes.js +0 -1
  14. package/backend-project/src/modules/department/department.service.js +1 -9
  15. package/backend-project/src/modules/employee/employee.controller.js +2 -10
  16. package/backend-project/src/modules/employee/employee.model.js +15 -9
  17. package/backend-project/src/modules/employee/employee.routes.js +4 -6
  18. package/backend-project/src/modules/employee/employee.service.js +20 -5
  19. package/backend-project/src/modules/position/position.controller.js +50 -0
  20. package/backend-project/src/modules/position/position.model.js +8 -0
  21. package/backend-project/src/modules/position/position.routes.js +14 -0
  22. package/backend-project/src/modules/position/position.service.js +21 -0
  23. package/backend-project/src/modules/reports/reports.controller.js +16 -28
  24. package/backend-project/src/modules/reports/reports.routes.js +2 -2
  25. package/backend-project/src/seed.js +69 -15
  26. package/backend-project/src/utils/token.js +1 -27
  27. package/frontend-project/dist/assets/index-BXwcQ8Za.css +1 -0
  28. package/frontend-project/dist/assets/index-Bo0aORq7.js +20 -0
  29. package/frontend-project/dist/index.html +3 -3
  30. package/frontend-project/index.html +1 -1
  31. package/frontend-project/src/App.css +1 -0
  32. package/frontend-project/src/Auth/Login.jsx +75 -0
  33. package/frontend-project/src/Auth/Register.jsx +92 -0
  34. package/frontend-project/src/Intro.jsx +28 -0
  35. package/frontend-project/src/LayOut.jsx +25 -0
  36. package/frontend-project/src/api/ApiClient.js +51 -0
  37. package/frontend-project/src/assets/hero.png +0 -0
  38. package/frontend-project/src/assets/react.svg +1 -0
  39. package/frontend-project/src/assets/vite.svg +1 -0
  40. package/frontend-project/src/components/Aside.jsx +9 -0
  41. package/frontend-project/src/components/Button.jsx +100 -0
  42. package/frontend-project/src/components/Card.jsx +104 -0
  43. package/frontend-project/src/components/FormField.jsx +129 -0
  44. package/frontend-project/src/components/Modal.jsx +106 -0
  45. package/frontend-project/src/components/Table.jsx +127 -0
  46. package/frontend-project/src/components/Toast.jsx +64 -0
  47. package/frontend-project/src/components/index.js +14 -0
  48. package/frontend-project/src/config.js +66 -0
  49. package/frontend-project/src/design.js +115 -0
  50. package/frontend-project/src/index.css +60 -0
  51. package/frontend-project/src/layouts/BottomNav.jsx +73 -0
  52. package/frontend-project/src/layouts/TopNav.jsx +71 -0
  53. package/frontend-project/src/layouts/useShell.js +30 -0
  54. package/frontend-project/src/main.jsx +40 -0
  55. package/frontend-project/src/pages/Department.jsx +151 -0
  56. package/frontend-project/src/pages/Employee.jsx +292 -0
  57. package/frontend-project/src/pages/Home.jsx +79 -0
  58. package/frontend-project/src/pages/Position.jsx +161 -0
  59. package/frontend-project/src/pages/Profile.jsx +9 -0
  60. package/frontend-project/src/pages/Register.jsx +57 -0
  61. package/frontend-project/src/pages/Reports.jsx +104 -0
  62. package/frontend-project/src/pages/Salary.jsx +264 -0
  63. package/frontend-project/src/themes.js +175 -0
  64. package/package.json +4 -2
  65. package/server-test-err.txt +0 -0
  66. package/server-test-out.txt +0 -0
  67. package/backend-project/src/modules/_example/example.controller.js +0 -82
  68. package/backend-project/src/modules/_example/example.model.js +0 -47
  69. package/backend-project/src/modules/_example/example.routes.js +0 -43
  70. package/backend-project/src/modules/_example/example.service.js +0 -58
  71. package/backend-project/src/modules/excel/excel.controller.js +0 -61
  72. package/backend-project/src/modules/excel/excel.routes.js +0 -13
  73. package/backend-project/src/modules/excel/excel.service.js +0 -303
  74. package/backend-project/src/modules/salary/salary.controller.js +0 -70
  75. package/backend-project/src/modules/salary/salary.model.js +0 -23
  76. package/backend-project/src/modules/salary/salary.routes.js +0 -16
  77. package/backend-project/src/modules/salary/salary.service.js +0 -44
  78. package/frontend-project/dist/assets/index-B08ICGra.js +0 -20
  79. package/frontend-project/dist/assets/index-D_cqT2Z6.css +0 -1
@@ -9,10 +9,12 @@
9
9
  "version": "1.0.0",
10
10
  "dependencies": {
11
11
  "bcryptjs": "^2.4.3",
12
+ "connect-mongo": "^6.0.0",
12
13
  "cors": "^2.8.5",
13
14
  "dotenv": "^16.4.5",
14
15
  "exceljs": "^4.4.0",
15
16
  "express": "^4.19.2",
17
+ "express-session": "^1.19.0",
16
18
  "helmet": "^7.1.0",
17
19
  "jsonwebtoken": "^9.0.2",
18
20
  "mongoose": "^8.5.0",
@@ -183,6 +185,18 @@
183
185
  "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
184
186
  "license": "MIT"
185
187
  },
188
+ "node_modules/asn1.js": {
189
+ "version": "5.4.1",
190
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
191
+ "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
192
+ "license": "MIT",
193
+ "dependencies": {
194
+ "bn.js": "^4.0.0",
195
+ "inherits": "^2.0.1",
196
+ "minimalistic-assert": "^1.0.0",
197
+ "safer-buffer": "^2.1.0"
198
+ }
199
+ },
186
200
  "node_modules/async": {
187
201
  "version": "3.2.6",
188
202
  "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
@@ -273,6 +287,12 @@
273
287
  "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==",
274
288
  "license": "MIT"
275
289
  },
290
+ "node_modules/bn.js": {
291
+ "version": "4.12.3",
292
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz",
293
+ "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==",
294
+ "license": "MIT"
295
+ },
276
296
  "node_modules/body-parser": {
277
297
  "version": "1.20.5",
278
298
  "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
@@ -481,6 +501,46 @@
481
501
  "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
482
502
  "license": "MIT"
483
503
  },
504
+ "node_modules/connect-mongo": {
505
+ "version": "6.0.0",
506
+ "resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-6.0.0.tgz",
507
+ "integrity": "sha512-mHxfnTiWk7ZtxmHdcrFBKlr7fCtgGoFpx/oe9jFW0yb2NinagsxEeuol78nUWMpnWyYK0nnuXMlU9wrgUjTE6g==",
508
+ "license": "MIT",
509
+ "dependencies": {
510
+ "debug": "^4.4.3",
511
+ "kruptein": "3.0.8"
512
+ },
513
+ "engines": {
514
+ "node": ">=20.8.0"
515
+ },
516
+ "peerDependencies": {
517
+ "express-session": "^1.17.1",
518
+ "mongodb": ">=5.0.0"
519
+ }
520
+ },
521
+ "node_modules/connect-mongo/node_modules/debug": {
522
+ "version": "4.4.3",
523
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
524
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
525
+ "license": "MIT",
526
+ "dependencies": {
527
+ "ms": "^2.1.3"
528
+ },
529
+ "engines": {
530
+ "node": ">=6.0"
531
+ },
532
+ "peerDependenciesMeta": {
533
+ "supports-color": {
534
+ "optional": true
535
+ }
536
+ }
537
+ },
538
+ "node_modules/connect-mongo/node_modules/ms": {
539
+ "version": "2.1.3",
540
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
541
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
542
+ "license": "MIT"
543
+ },
484
544
  "node_modules/content-disposition": {
485
545
  "version": "0.5.4",
486
546
  "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@@ -818,6 +878,29 @@
818
878
  "url": "https://opencollective.com/express"
819
879
  }
820
880
  },
881
+ "node_modules/express-session": {
882
+ "version": "1.19.0",
883
+ "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.19.0.tgz",
884
+ "integrity": "sha512-0csaMkGq+vaiZTmSMMGkfdCOabYv192VbytFypcvI0MANrp+4i/7yEkJ0sbAEhycQjntaKGzYfjfXQyVb7BHMA==",
885
+ "license": "MIT",
886
+ "dependencies": {
887
+ "cookie": "~0.7.2",
888
+ "cookie-signature": "~1.0.7",
889
+ "debug": "~2.6.9",
890
+ "depd": "~2.0.0",
891
+ "on-headers": "~1.1.0",
892
+ "parseurl": "~1.3.3",
893
+ "safe-buffer": "~5.2.1",
894
+ "uid-safe": "~2.1.5"
895
+ },
896
+ "engines": {
897
+ "node": ">= 0.8.0"
898
+ },
899
+ "funding": {
900
+ "type": "opencollective",
901
+ "url": "https://opencollective.com/express"
902
+ }
903
+ },
821
904
  "node_modules/fast-csv": {
822
905
  "version": "4.3.6",
823
906
  "resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz",
@@ -1307,6 +1390,18 @@
1307
1390
  "node": ">=12.0.0"
1308
1391
  }
1309
1392
  },
1393
+ "node_modules/kruptein": {
1394
+ "version": "3.0.8",
1395
+ "resolved": "https://registry.npmjs.org/kruptein/-/kruptein-3.0.8.tgz",
1396
+ "integrity": "sha512-0CyalFA0Cjp3jnziMp0u1uLZW2/ouhQ0mEMfYlroBXNe86na1RwAuwBcdRAegeWZNMfQy/G5fN47g/Axjtqrfw==",
1397
+ "license": "MIT",
1398
+ "dependencies": {
1399
+ "asn1.js": "^5.4.1"
1400
+ },
1401
+ "engines": {
1402
+ "node": ">8"
1403
+ }
1404
+ },
1310
1405
  "node_modules/lazystream": {
1311
1406
  "version": "1.0.1",
1312
1407
  "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
@@ -1548,6 +1643,12 @@
1548
1643
  "node": ">= 0.6"
1549
1644
  }
1550
1645
  },
1646
+ "node_modules/minimalistic-assert": {
1647
+ "version": "1.0.1",
1648
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
1649
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
1650
+ "license": "ISC"
1651
+ },
1551
1652
  "node_modules/minimatch": {
1552
1653
  "version": "3.1.5",
1553
1654
  "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
@@ -1859,6 +1960,15 @@
1859
1960
  "node": ">= 0.8"
1860
1961
  }
1861
1962
  },
1963
+ "node_modules/on-headers": {
1964
+ "version": "1.1.0",
1965
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
1966
+ "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
1967
+ "license": "MIT",
1968
+ "engines": {
1969
+ "node": ">= 0.8"
1970
+ }
1971
+ },
1862
1972
  "node_modules/once": {
1863
1973
  "version": "1.4.0",
1864
1974
  "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -1961,6 +2071,15 @@
1961
2071
  "url": "https://github.com/sponsors/ljharb"
1962
2072
  }
1963
2073
  },
2074
+ "node_modules/random-bytes": {
2075
+ "version": "1.0.0",
2076
+ "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
2077
+ "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==",
2078
+ "license": "MIT",
2079
+ "engines": {
2080
+ "node": ">= 0.8"
2081
+ }
2082
+ },
1964
2083
  "node_modules/range-parser": {
1965
2084
  "version": "1.2.1",
1966
2085
  "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -2384,6 +2503,18 @@
2384
2503
  "node": ">= 0.6"
2385
2504
  }
2386
2505
  },
2506
+ "node_modules/uid-safe": {
2507
+ "version": "2.1.5",
2508
+ "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
2509
+ "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
2510
+ "license": "MIT",
2511
+ "dependencies": {
2512
+ "random-bytes": "~1.0.0"
2513
+ },
2514
+ "engines": {
2515
+ "node": ">= 0.8"
2516
+ }
2517
+ },
2387
2518
  "node_modules/undefsafe": {
2388
2519
  "version": "2.0.5",
2389
2520
  "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
@@ -10,13 +10,15 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "bcryptjs": "^2.4.3",
13
+ "connect-mongo": "^6.0.0",
13
14
  "cors": "^2.8.5",
14
15
  "dotenv": "^16.4.5",
15
16
  "exceljs": "^4.4.0",
16
17
  "express": "^4.19.2",
17
- "mongoose": "^8.5.0",
18
+ "express-session": "^1.19.0",
18
19
  "helmet": "^7.1.0",
19
20
  "jsonwebtoken": "^9.0.2",
21
+ "mongoose": "^8.5.0",
20
22
  "uuid": "^10.0.0"
21
23
  },
22
24
  "devDependencies": {
@@ -1,39 +1,37 @@
1
- // ═══════════════════════════════════════════════════════════════════════════
2
- // 🚀 APP — Express application setup
3
- // ═══════════════════════════════════════════════════════════════════════════
4
- //
5
- // WHAT THIS FILE DOES:
6
- // - Creates the Express app
7
- // - Adds middleware (security, CORS, JSON parsing)
8
- // - Registers all API module routes
9
- // - Exports the app for server.js to use
10
- //
11
- // HOW TO ADD A NEW MODULE:
12
- // 1. Add its routes to src/config/app.config.js (registeredRoutes array)
13
- // 2. Add a use() line below (see the PATTERN section)
14
- // 3. Done! Your new API is live.
15
- //
16
- // ═══════════════════════════════════════════════════════════════════════════
17
-
18
1
  const express = require('express');
19
- const path = require('path');
20
- const helmet = require('helmet');
21
- const cors = require('cors');
22
- const db = require('./config/db');
23
- const cfg = require('./config/app.config');
24
-
2
+ const path = require('path');
3
+ const helmet = require('helmet');
4
+ const cors = require('cors');
5
+ const session = require('express-session');
6
+ const { MongoStore } = require('connect-mongo');
7
+ const db = require('./config/db');
8
+ const cfg = require('./config/app.config');
9
+ const env = require('./config/env');
25
10
  const { errorHandler, notFoundHandler } = require('./middleware/error.middleware');
26
11
 
27
12
  const app = express();
28
13
 
29
- // ─── GLOBAL MIDDLEWARE (applied to every request) ────────────────────────────
30
- app.use(helmet()); // security headers
31
- app.use(cors()); // allow cross-origin requests
32
- app.use(express.json({ limit: '10mb' })); // parse JSON bodies
14
+ app.use(helmet({ contentSecurityPolicy: false }));
15
+ app.use(cors({
16
+ origin: process.env.NODE_ENV === 'production' ? false : 'http://localhost:5173',
17
+ credentials: true,
18
+ }));
19
+ app.use(express.json({ limit: '10mb' }));
33
20
  app.use(express.urlencoded({ extended: true }));
34
21
 
35
- // ─── HEALTH CHECK ────────────────────────────────────────────────────────────
36
- // Every scenario needs a health endpoint for deployment monitoring.
22
+ app.use(session({
23
+ secret: env.SESSION_SECRET,
24
+ resave: false,
25
+ saveUninitialized: false,
26
+ store: MongoStore.create({ mongoUrl: env.MONGODB_URI, collectionName: 'sessions' }),
27
+ cookie: {
28
+ httpOnly: true,
29
+ secure: false,
30
+ sameSite: 'lax',
31
+ maxAge: 24 * 60 * 60 * 1000,
32
+ },
33
+ }));
34
+
37
35
  app.get('/health', (_req, res) =>
38
36
  res.json({
39
37
  status: 'ok',
@@ -42,28 +40,12 @@ app.get('/health', (_req, res) =>
42
40
  })
43
41
  );
44
42
 
45
- // ╔═══════════════════════════════════════════════════════════════════════════╗
46
- // ║ 📌 PATTERN: Register a new module ║
47
- // ║ ║
48
- // ║ Step 1. In app.config.js, add to registeredRoutes: ║
49
- // ║ { name: 'products', routes: require('./modules/product/product.routes') } ║
50
- // ║ ║
51
- // ║ Step 2. Add one line below: ║
52
- // ║ app.use('/api/products', require('./modules/product/product.routes')); ║
53
- // ╚═══════════════════════════════════════════════════════════════════════════╝
54
-
55
- // ─── MODULE ROUTES ───────────────────────────────────────────────────────────
56
- // Each line starts a new API group under /api/...
57
- // The route file inside each module handles its own sub-routes.
58
- //
59
- app.use('/api/auth', require('./modules/auth/auth.routes'));
60
- app.use('/api/excel', require('./modules/excel/excel.routes'));
61
- app.use('/api/employees', require('./modules/employee/employee.routes'));
43
+ app.use('/api/auth', require('./modules/auth/auth.routes'));
44
+ app.use('/api/employees', require('./modules/employee/employee.routes'));
62
45
  app.use('/api/departments', require('./modules/department/department.routes'));
63
- app.use('/api/salaries', require('./modules/salary/salary.routes'));
64
- app.use('/api/reports', require('./modules/reports/reports.routes'));
46
+ app.use('/api/positions', require('./modules/position/position.routes'));
47
+ app.use('/api/reports', require('./modules/reports/reports.routes'));
65
48
 
66
- // ─── FRONTEND SPA (serves built React app) ────────────────────────────────────
67
49
  const distPath = path.join(__dirname, '..', '..', 'frontend-project', 'dist');
68
50
  app.use(express.static(distPath));
69
51
 
@@ -72,13 +54,9 @@ app.get('*', (req, res, next) => {
72
54
  res.sendFile(path.join(distPath, 'index.html'));
73
55
  });
74
56
 
75
- // ─── ERROR HANDLING (must be last) ───────────────────────────────────────────
76
- // These catch any errors from routes above.
77
- app.use(notFoundHandler); // handles 404 - route not found
78
- app.use(errorHandler); // handles 500 - server errors
57
+ app.use(notFoundHandler);
58
+ app.use(errorHandler);
79
59
 
80
- // ─── DATABASE CONNECTION ─────────────────────────────────────────────────────
81
- // Called by server.js (not here) so the app is testable without a DB.
82
60
  app.connectDB = () => db.connect();
83
61
 
84
62
  module.exports = app;
@@ -1,72 +1,24 @@
1
- // ═══════════════════════════════════════════════════════════════════════════
2
- // ⚙️ APP CONFIG — One place to control the whole backend
3
- // ═══════════════════════════════════════════════════════════════════════════
4
- //
5
- // WHAT THIS FILE DOES:
6
- // - Loads environment variables from .env (via env.js)
7
- // - Lists every registered module (so you can add/remove features)
8
- // - Exports everything in one easy-to-find object
9
- //
10
- // HOW TO ADD A NEW FEATURE (e.g. "Products"):
11
- // 1. Create folder: src/modules/product/
12
- // 2. Copy files from src/modules/_example/ (rename to product.*)
13
- // 3. Import routes below in this file (see REGISTERED MODULES)
14
- // 4. Add route line in app.js (see instructions there)
15
- //
16
- // ═══════════════════════════════════════════════════════════════════════════
17
-
18
1
  const env = require('./env');
19
2
 
20
- // ─── SERVER SETTINGS ─────────────────────────────────────────────────────────
21
3
  const server = {
22
4
  PORT: env.PORT,
23
5
  NODE_ENV: env.NODE_ENV,
24
6
  };
25
7
 
26
- // ─── DATABASE ────────────────────────────────────────────────────────────────
27
8
  const database = {
28
9
  URI: env.MONGODB_URI,
29
10
  };
30
11
 
31
- // ─── JWT AUTHENTICATION ──────────────────────────────────────────────────────
32
- const jwt = {
33
- SECRET: env.JWT_SECRET,
34
- EXPIRES_IN: env.JWT_EXPIRES_IN,
35
- REFRESH_SECRET: env.JWT_REFRESH_SECRET,
36
- REFRESH_EXPIRES_IN: env.JWT_REFRESH_EXPIRES_IN,
37
- };
38
-
39
- // ─── BCRYPT ──────────────────────────────────────────────────────────────────
40
- const bcrypt = {
41
- ROUNDS: env.BCRYPT_ROUNDS,
42
- };
43
-
44
- // ─── REGISTERED MODULES ──────────────────────────────────────────────────────
45
- // 🔵 To ADD a new module:
46
- // 1. Import its routes: const productRoutes = require('../modules/product/product.routes');
47
- // 2. Add to the list: { name: 'products', routes: productRoutes }
48
- //
49
- // 🔴 To REMOVE a module:
50
- // Just delete its line from this array (and the import above).
51
- //
52
- // Every module in this list automatically gets:
53
- // - Route registration in app.js
54
- // - Listed in the /health endpoint for debugging
55
- //
56
12
  const registeredRoutes = [
57
13
  { name: 'auth', routes: require('../modules/auth/auth.routes') },
58
14
  { name: 'employees', routes: require('../modules/employee/employee.routes') },
59
15
  { name: 'departments', routes: require('../modules/department/department.routes') },
60
- { name: 'salaries', routes: require('../modules/salary/salary.routes') },
16
+ { name: 'positions', routes: require('../modules/position/position.routes') },
61
17
  { name: 'reports', routes: require('../modules/reports/reports.routes') },
62
- { name: 'excel', routes: require('../modules/excel/excel.routes') },
63
18
  ];
64
19
 
65
- // ─── EXPORT EVERYTHING ───────────────────────────────────────────────────────
66
20
  module.exports = {
67
21
  server,
68
22
  database,
69
- jwt,
70
- bcrypt,
71
23
  registeredRoutes,
72
24
  };
@@ -3,17 +3,9 @@ require('dotenv').config();
3
3
  const env = {
4
4
  PORT: process.env.PORT || 3000,
5
5
  NODE_ENV: process.env.NODE_ENV || 'development',
6
-
7
- MONGODB_URI: process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/auth_db',
8
-
9
- JWT_SECRET: process.env.JWT_SECRET || 'change-this-secret-in-production',
10
- JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '7d',
11
- JWT_REFRESH_SECRET: process.env.JWT_REFRESH_SECRET || 'change-this-refresh-secret',
12
- JWT_REFRESH_EXPIRES_IN: process.env.JWT_REFRESH_EXPIRES_IN || '30d',
13
-
6
+ MONGODB_URI: process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/HRMS',
7
+ SESSION_SECRET: process.env.SESSION_SECRET || 'hrms-session-secret-change-in-production',
14
8
  BCRYPT_ROUNDS: parseInt(process.env.BCRYPT_ROUNDS || '12', 10),
15
-
16
- EXCEL_OUTPUT_DIR: process.env.EXCEL_OUTPUT_DIR || './exports',
17
9
  };
18
10
 
19
11
  module.exports = env;
@@ -1,33 +1,10 @@
1
- const { verifyAccessToken } = require('../utils/token');
2
1
  const res_ = require('../utils/response');
3
2
 
4
- /**
5
- * authenticate — verifies the Bearer token and attaches `req.user`.
6
- */
7
3
  const authenticate = (req, res, next) => {
8
- const header = req.headers.authorization || '';
9
- const token = header.startsWith('Bearer ') ? header.slice(7) : null;
10
-
11
- if (!token) return res_.unauthorized(res, 'No token provided');
12
-
13
- try {
14
- req.user = verifyAccessToken(token);
15
- return next();
16
- } catch (err) {
17
- const message = err.name === 'TokenExpiredError' ? 'Token expired' : 'Invalid token';
18
- return res_.unauthorized(res, message);
19
- }
20
- };
21
-
22
- /**
23
- * authorize — gates a route to specific roles.
24
- * Usage: router.delete('/admin', authenticate, authorize('admin'), handler)
25
- */
26
- const authorize = (...roles) => (req, res, next) => {
27
- if (!roles.includes(req.user?.role)) {
28
- return res_.forbidden(res, 'Insufficient permissions');
4
+ if (!req.session || !req.session.userId) {
5
+ return res_.unauthorized(res, 'Please log in first');
29
6
  }
30
7
  return next();
31
8
  };
32
9
 
33
- module.exports = { authenticate, authorize };
10
+ module.exports = { authenticate };
@@ -2,10 +2,10 @@ const AuthService = require('./auth.service');
2
2
  const res_ = require('../../utils/response');
3
3
 
4
4
  const AuthController = {
5
- async signup(req, res) {
5
+ async register(req, res) {
6
6
  try {
7
- const result = await AuthService.signup(req.body);
8
- return res_.created(res, result, 'Account created successfully');
7
+ const user = await AuthService.createUser(req.body);
8
+ return res_.created(res, user, 'User account created');
9
9
  } catch (err) {
10
10
  return res_.error(res, err.message, err.statusCode || 500);
11
11
  }
@@ -13,17 +13,10 @@ const AuthController = {
13
13
 
14
14
  async login(req, res) {
15
15
  try {
16
- const result = await AuthService.login(req.body);
17
- return res_.success(res, result, 'Login successful');
18
- } catch (err) {
19
- return res_.error(res, err.message, err.statusCode || 500);
20
- }
21
- },
22
-
23
- async refresh(req, res) {
24
- try {
25
- const result = await AuthService.refresh(req.body.refreshToken);
26
- return res_.success(res, result, 'Tokens refreshed');
16
+ const user = await AuthService.login(req.body);
17
+ req.session.userId = user.id;
18
+ req.session.userName = user.userName;
19
+ return res_.success(res, { user }, 'Login successful');
27
20
  } catch (err) {
28
21
  return res_.error(res, err.message, err.statusCode || 500);
29
22
  }
@@ -31,16 +24,19 @@ const AuthController = {
31
24
 
32
25
  async me(req, res) {
33
26
  try {
34
- const user = await AuthService.me(req.user.id);
35
- return res_.success(res, user);
27
+ const user = await AuthService.me(req.session.userId);
28
+ return res_.success(res, { user });
36
29
  } catch (err) {
37
30
  return res_.error(res, err.message, err.statusCode || 500);
38
31
  }
39
32
  },
40
33
 
41
- logout(_req, res) {
42
- // JWT logout is client-side. Add a token blocklist here for server-side invalidation.
43
- return res_.success(res, null, 'Logged out successfully');
34
+ async logout(req, res) {
35
+ req.session.destroy((err) => {
36
+ if (err) return res_.error(res, 'Logout failed', 500);
37
+ res.clearCookie('connect.sid');
38
+ return res_.success(res, null, 'Logged out successfully');
39
+ });
44
40
  },
45
41
  };
46
42
 
@@ -4,13 +4,9 @@ const { authenticate } = require('../../middleware/auth.middleware');
4
4
 
5
5
  const router = Router();
6
6
 
7
- // Public routes
8
- router.post('/signup', AuthController.signup);
9
- router.post('/login', AuthController.login);
10
- router.post('/refresh', AuthController.refresh);
11
-
12
- // Protected routes
13
- router.get('/me', authenticate, AuthController.me);
14
- router.post('/logout', authenticate, AuthController.logout);
7
+ router.post('/register', AuthController.register);
8
+ router.post('/login', AuthController.login);
9
+ router.get('/me', authenticate, AuthController.me);
10
+ router.post('/logout', authenticate, AuthController.logout);
15
11
 
16
12
  module.exports = router;
@@ -1,7 +1,6 @@
1
1
  const bcrypt = require('bcryptjs');
2
2
  const User = require('./user.model');
3
3
  const env = require('../../config/env');
4
- const { generateTokens, verifyRefreshToken } = require('../../utils/token');
5
4
 
6
5
  const fail = (message, statusCode) => {
7
6
  const err = new Error(message);
@@ -10,45 +9,24 @@ const fail = (message, statusCode) => {
10
9
  };
11
10
 
12
11
  const AuthService = {
13
- async signup({ name, email, password }) {
14
- const existing = await User.findOne({ email: email.toLowerCase() });
15
- if (existing) fail('Email is already registered', 409);
16
-
12
+ async createUser({ userName, password }) {
13
+ const existing = await User.findOne({ userName });
14
+ if (existing) fail('Username is already taken', 409);
17
15
  const hashed = await bcrypt.hash(password, env.BCRYPT_ROUNDS);
18
- const user = await User.create({ name, email, password: hashed });
19
- const tokens = generateTokens(user.toSafeObject());
20
-
21
- return { user: user.toSafeObject(), ...tokens };
16
+ const user = await User.create({ userName, password: hashed });
17
+ return user.toSafeObject();
22
18
  },
23
19
 
24
- async login({ email, password }) {
25
- const user = await User.findOne({ email: email.toLowerCase() });
20
+ async login({ userName, password }) {
21
+ const user = await User.findOne({ userName }).populate('employee');
26
22
  if (!user) fail('Invalid credentials', 401);
27
-
28
23
  const valid = await bcrypt.compare(password, user.password);
29
24
  if (!valid) fail('Invalid credentials', 401);
30
-
31
- const tokens = generateTokens(user.toSafeObject());
32
- return { user: user.toSafeObject(), ...tokens };
33
- },
34
-
35
- async refresh(refreshToken) {
36
- let payload;
37
- try {
38
- payload = verifyRefreshToken(refreshToken);
39
- } catch {
40
- fail('Invalid or expired refresh token', 401);
41
- }
42
-
43
- const user = await User.findById(payload.id);
44
- if (!user) fail('User not found', 401);
45
-
46
- const tokens = generateTokens(user.toSafeObject());
47
- return { user: user.toSafeObject(), ...tokens };
25
+ return user.toSafeObject();
48
26
  },
49
27
 
50
28
  async me(userId) {
51
- const user = await User.findById(userId);
29
+ const user = await User.findById(userId).populate('employee');
52
30
  if (!user) fail('User not found', 404);
53
31
  return user.toSafeObject();
54
32
  },