+ Monthly / Yearly Summary +
++ Visual insights into your money habits 📊 +
+diff --git a/analytics-dashboard.js b/analytics-dashboard.js index fee3b281..50780aa4 100644 --- a/analytics-dashboard.js +++ b/analytics-dashboard.js @@ -34,7 +34,7 @@ function formatAnalyticsCurrency(value, options = {}) { // ======================== async function getAuthHeaders() { - const token = localStorage.getItem('authToken'); + const token = localStorage.getItem('token'); return { 'Content-Type': 'application/json', 'Authorization': token ? `Bearer ${token}` : '' @@ -46,7 +46,7 @@ async function getAuthHeaders() { */ async function fetchSpendingTrends(period = 'monthly', months = 6) { try { - const token = localStorage.getItem('authToken'); + const token = localStorage.getItem('token'); if (!token) return { data: [] }; const response = await fetch( @@ -671,7 +671,7 @@ async function loadAnalyticsDashboard() { const dashboardContainer = document.getElementById('analytics-dashboard'); if (!dashboardContainer) return; - const token = localStorage.getItem('authToken'); + const token = localStorage.getItem('token'); if (!token) return; try { diff --git a/api-integration.js b/api-integration.js index eb2d81ca..49e21cfb 100644 --- a/api-integration.js +++ b/api-integration.js @@ -83,7 +83,7 @@ const formatAppCurrency = (value, { showPlus = false, absolute = false } = {}) = // ======================== function getAuthToken() { - return localStorage.getItem('authToken'); + return localStorage.getItem('token'); } async function fetchExpenses(page = 1, limit = 50, workspaceId = null) { diff --git a/auth-integration.js b/auth-integration.js index d1f954ac..510b4b5b 100644 --- a/auth-integration.js +++ b/auth-integration.js @@ -4,7 +4,7 @@ */ var API_BASE_URL = '/api'; -var authToken = localStorage.getItem('authToken'); +var authToken = localStorage.getItem('token'); var currentUser = JSON.parse(localStorage.getItem('currentUser') || 'null'); var currentSessionId = localStorage.getItem('sessionId'); @@ -30,7 +30,7 @@ async function register(userData) { currentUser = data.user; currentSessionId = data.sessionId; - localStorage.setItem('authToken', authToken); + localStorage.setItem('token ', authToken); localStorage.setItem('currentUser', JSON.stringify(currentUser)); localStorage.setItem('sessionId', currentSessionId); @@ -67,7 +67,7 @@ async function login(credentials) { currentUser = data.user; currentSessionId = data.sessionId; - localStorage.setItem('authToken', authToken); + localStorage.setItem('token', authToken); localStorage.setItem('currentUser', JSON.stringify(currentUser)); localStorage.setItem('sessionId', currentSessionId); @@ -95,7 +95,7 @@ async function verify2FA(userId, totpToken, rememberMe = false) { currentUser = data.user; currentSessionId = data.sessionId; - localStorage.setItem('authToken', authToken); + localStorage.setItem('token', authToken); localStorage.setItem('currentUser', JSON.stringify(currentUser)); localStorage.setItem('sessionId', currentSessionId); @@ -119,7 +119,7 @@ async function logout() { authToken = null; currentUser = null; currentSessionId = null; - localStorage.removeItem('authToken'); + localStorage.removeItem('token'); localStorage.removeItem('currentUser'); localStorage.removeItem('sessionId'); localStorage.removeItem('transactions'); diff --git a/budget-goals.js b/budget-goals.js index e2579cdd..3a4aacea 100644 --- a/budget-goals.js +++ b/budget-goals.js @@ -2,7 +2,7 @@ class BudgetGoalsManager { constructor() { this.apiUrl = '/api'; - this.authToken = localStorage.getItem('authToken'); + this.authToken = localStorage.getItem('token'); this.initializeDashboard(); } @@ -199,7 +199,7 @@ class BudgetGoalsManager { // Load dashboard data async loadDashboardData() { - this.authToken = localStorage.getItem('authToken'); + this.authToken = localStorage.getItem('token'); if (!this.authToken) return; try { diff --git a/middleware/authMiddleware.js b/middleware/authMiddleware.js new file mode 100644 index 00000000..904e36ca --- /dev/null +++ b/middleware/authMiddleware.js @@ -0,0 +1,21 @@ +const jwt=require("jsonwebtoken"); + + +const protect=async(req,res,next)=>{ + const authHeader=req.headers.authorization; + + if(!authHeader || !authHeader.startsWith("Bearer")){ + return res.status(401).json({message:"unauthorzed access"}); + } + try{ + const token=authHeader.split(" ")[1]; + const decoded=jwt.verify(token,process.env,JWT_SECRET); + req.user=decoded; + next(); + } + catch(err){ + return res.status(401).json({message:"Invalid token"}); + } + +}; +module.exports=protect; \ No newline at end of file diff --git a/notification-center.js b/notification-center.js index 43ab6532..df04821b 100644 --- a/notification-center.js +++ b/notification-center.js @@ -2,7 +2,7 @@ class NotificationCenter { constructor() { this.apiUrl = 'http://localhost:3000/api'; - this.authToken = localStorage.getItem('authToken'); + this.authToken = localStorage.getItem('token'); this.notifications = []; this.unreadCount = 0; this.socket = null; diff --git a/package-lock.json b/package-lock.json index 1357c778..b0cd562f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "axios": "^1.6.2", "bcryptjs": "^2.4.3", "canvas": "^3.2.1", - "chart.js": "^4.4.1", + "chart.js": "^4.5.1", "chartjs-node-canvas": "^5.0.0", "cors": "^2.8.5", "dotenv": "^16.3.1", @@ -36,6 +36,7 @@ "qrcode": "^1.5.4", "simple-statistics": "^7.8.3", "socket.io": "^4.8.3", + "socket.io-client": "^4.8.3", "twilio": "^5.12.0", "web-push": "^3.6.7", "xero-node": "^13.3.1", @@ -1380,6 +1381,39 @@ "node": ">=10.2.0" } }, + "node_modules/engine.io-client": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.4.tgz", + "integrity": "sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.18.3", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-client/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io-client/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/engine.io-parser": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", @@ -4219,6 +4253,41 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/socket.io-client": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.3.tgz", + "integrity": "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-client/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-client/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/socket.io-parser": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz", @@ -4980,6 +5049,14 @@ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/xss": { "version": "1.0.15", "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.15.tgz", diff --git a/package.json b/package.json index 1b11fdc8..af69eaa8 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "axios": "^1.6.2", "bcryptjs": "^2.4.3", "canvas": "^3.2.1", - "chart.js": "^4.4.1", + "chart.js": "^4.5.1", "chartjs-node-canvas": "^5.0.0", "cors": "^2.8.5", "dotenv": "^16.3.1", @@ -36,6 +36,7 @@ "qrcode": "^1.5.4", "simple-statistics": "^7.8.3", "socket.io": "^4.8.3", + "socket.io-client": "^4.8.3", "twilio": "^5.12.0", "web-push": "^3.6.7", "xero-node": "^13.3.1", diff --git a/public/Community.html b/public/Community.html index e419b7b0..d062883c 100644 --- a/public/Community.html +++ b/public/Community.html @@ -819,7 +819,7 @@
- + - - - - - - - - - - - - - - + + + + + + + + + + + + + + ++ Visual insights into your money habits 📊 +
+