-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
198 lines (166 loc) · 5.44 KB
/
Copy pathserver.js
File metadata and controls
198 lines (166 loc) · 5.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
const express = require("express");
const app = express();
const cors = require("cors");
const cookieParser = require("cookie-parser");
const helmet = require("helmet");
const rateLimit = require("express-rate-limit");
// mongoose/mongodb
const mongoose = require("mongoose");
// dotenv
require("dotenv").config();
// port
const PORT = process.env.PORT || 4000;
// path
const path = require("path");
// import routes
const root = require("./routes/root");
const taskRoutes = require("./routes/taskRoutes");
const eventRoutes = require("./routes/eventRoutes");
const budgetRoutes = require("./routes/budgetRoutes");
const expenseRoutes = require("./routes/expenseRoutes");
const clientRoutes = require("./routes/clientRoutes");
const vendorRoutes = require("./routes/vendorRoutes");
const authRoutes = require("./routes/authRoutes");
const organizationRoutes = require("./routes/organizationRoutes");
const userRoutes = require("./routes/userRoutes");
// connect to MongoDB
mongoose.connect(process.env.DATABASE_URI, {
maxPoolSize: 10,
});
require("dotenv").config();
// cors
app.use(
cors({
// origin: "http://localhost:5173",
origin: "https://planit.traceykadenyi.com",
credentials: true,
methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
}),
);
// cookie-parser
app.use(cookieParser());
// Security headers
app.use(helmet());
// ========== RATE LIMITING SETUP ==========
// More permissive rate limiting for refresh token
const refreshTokenLimiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1 minute
max: 30, // 30 refresh attempts per minute (more permissive)
message: "Too many token refresh attempts. Please slow down.",
handler: (req, res) => {
res.status(429).json({
status: "error",
message:
"Too many token refresh attempts. Please wait a moment before trying again.",
});
},
});
// Aggressive rate limiting for sensitive auth routes
const authLimiter = rateLimit({
windowMs: 5 * 60 * 1000, // CHANGE TO 15 AFTER DEVELOPMENT
max: 100, // CHANGE TO 10 AFTER DEVELOPMENT
handler: (req, res) => {
res.status(429).json({
status: "error",
message:
"Too many login attempts. Please wait 15 minutes before trying again.",
});
},
});
// Add this before your routes
// let requestCounts = {};
// app.use((req, res, next) => {
// const path = req.path;
// const ip = req.ip;
// if (!requestCounts[ip]) {
// requestCounts[ip] = {};
// }
// if (!requestCounts[ip][path]) {
// requestCounts[ip][path] = 0;
// }
// requestCounts[ip][path]++;
// // Log refresh token requests
// if (path.includes('refresh-token')) {
// console.log(`Refresh token request #${requestCounts[ip][path]} from ${ip} at ${new Date().toISOString()}`);
// }
// next();
// });
// Add a debug endpoint to see counts
app.get("/api/debug/rate-limit-status", (req, res) => {
res.json({
requestCounts,
totalRefreshTokens: Object.values(requestCounts).reduce((acc, ipData) => {
return acc + (ipData["/api/auth/refresh-token"] || 0);
}, 0),
timestamp: new Date().toISOString(),
});
});
// General rate limiting for all other API routes
// const generalLimiter = rateLimit({
// windowMs: 15 * 60 * 1000, // 15 minutes
// max: 100, // limit each IP to 100 requests per windowMs
// message: "Too many requests from this IP, please try again later.",
// // Skip refresh-token since we have a separate limiter for it
// skip: (req) => req.originalUrl === "/api/auth/refresh-token",
// });
// app.use("/api/", generalLimiter);
// Apply refresh token limiter specifically to refresh-token endpoint
app.use("/api/auth/refresh-token", refreshTokenLimiter);
app.use("/api/auth/login", authLimiter);
app.use("/api/auth/signup", authLimiter);
// ========== END RATE LIMITING SETUP ==========
app.use(express.json());
// middleware to handle static files
app.use(express.static(path.join(__dirname, "public")));
// Add this before your other routes in server.js
app.get("/api/debug-cookies-set", (req, res) => {
console.log("Setting debug cookie...");
res.cookie("debugCookie", "test-value", {
httpOnly: true,
secure: false,
sameSite: "lax",
maxAge: 24 * 60 * 60 * 1000,
});
res.json({ message: "Debug cookie should be set" });
});
app.get("/api/debug-cookies-check", (req, res) => {
console.log("Received cookies:", req.cookies);
res.json({
receivedCookies: req.cookies,
headers: req.headers,
});
});
// use routes
app.use("/", root);
app.use("/api/auth", authRoutes);
app.use("/api/users", userRoutes);
app.use("/api/organization", organizationRoutes);
app.use("/api/tasks", taskRoutes);
app.use("/api/events", eventRoutes);
app.use("/api/budget", budgetRoutes);
app.use("/api/expenses", expenseRoutes);
app.use("/api/clients", clientRoutes);
app.use("/api/vendors", vendorRoutes);
// ERROR HANDLING MIDDLEWARE (important for auth)
app.use((error, req, res, next) => {
console.error(error.stack);
res.status(500).json({
message: "Something went wrong!",
error:
process.env.NODE_ENV === "development"
? error.message
: "Internal server error",
});
});
// // Fallback for undefined routes
app.all(/.*/, (req, res) => {
res.status(404).json({ message: "Route not found" });
});
// start server
mongoose.connection.once("open", () => {
console.log("connected to MongoDB");
app.listen(PORT, () => {
console.log(`server listening on port ${PORT}`);
});
});