@intranefr/superbackend 1.6.7 → 1.7.8
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.
- package/.beads/.br_history/issues.20260314_212352_900045509.jsonl +0 -0
- package/.beads/.br_history/issues.20260314_212352_900045509.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_087140743.jsonl +1 -0
- package/.beads/.br_history/issues.20260314_212353_087140743.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_285881504.jsonl +2 -0
- package/.beads/.br_history/issues.20260314_212353_285881504.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_473915419.jsonl +3 -0
- package/.beads/.br_history/issues.20260314_212353_473915419.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_659476307.jsonl +4 -0
- package/.beads/.br_history/issues.20260314_212353_659476307.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_869998925.jsonl +5 -0
- package/.beads/.br_history/issues.20260314_212353_869998925.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212354_054785029.jsonl +6 -0
- package/.beads/.br_history/issues.20260314_212354_054785029.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_175893691.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_175893691.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_338509797.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_338509797.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_515443192.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_515443192.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_676417592.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_676417592.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_839182422.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_839182422.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213337_004349113.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213337_004349113.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213337_179824080.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213337_179824080.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213701_705075332.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213701_705075332.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213706_783128702.jsonl +8 -0
- package/.beads/.br_history/issues.20260314_213706_783128702.jsonl.meta.json +1 -0
- package/.beads/config.yaml +4 -0
- package/.beads/issues.jsonl +8 -0
- package/.beads/metadata.json +4 -0
- package/.env.example +8 -0
- package/autochangelog/.env.example +36 -0
- package/autochangelog/README.md +412 -0
- package/autochangelog/config/database.js +27 -0
- package/autochangelog/package.json +47 -0
- package/autochangelog/public/landing.html +581 -0
- package/autochangelog/server.js +104 -0
- package/autochangelog/src/app.js +181 -0
- package/autochangelog/src/config/database.js +26 -0
- package/autochangelog/src/controllers/auth.js +488 -0
- package/autochangelog/src/controllers/changelog.js +682 -0
- package/autochangelog/src/controllers/project.js +580 -0
- package/autochangelog/src/controllers/repository.js +780 -0
- package/autochangelog/src/middleware/auth.js +386 -0
- package/autochangelog/src/models/Changelog.js +443 -0
- package/autochangelog/src/models/Project.js +226 -0
- package/autochangelog/src/models/Repository.js +366 -0
- package/autochangelog/src/models/User.js +223 -0
- package/autochangelog/src/routes/auth.routes.js +32 -0
- package/autochangelog/src/routes/changelog.routes.js +42 -0
- package/autochangelog/src/routes/github-auth.routes.js +102 -0
- package/autochangelog/src/routes/project.routes.js +50 -0
- package/autochangelog/src/routes/repository.routes.js +54 -0
- package/autochangelog/src/services/changelog.js +722 -0
- package/autochangelog/src/services/github.js +243 -0
- package/autochangelog/utils/logger.js +77 -0
- package/autochangelog/views/404.ejs +18 -0
- package/autochangelog/views/dashboard.ejs +596 -0
- package/autochangelog/views/index.ejs +231 -0
- package/autochangelog/views/layouts/main.ejs +44 -0
- package/autochangelog/views/login.ejs +104 -0
- package/autochangelog/views/partials/footer.ejs +20 -0
- package/autochangelog/views/partials/navbar.ejs +51 -0
- package/autochangelog/views/register.ejs +109 -0
- package/autochangelog-cli/README.md +266 -0
- package/autochangelog-cli/bin/autochangelog +120 -0
- package/autochangelog-cli/package.json +46 -0
- package/autochangelog-cli/src/cli/commands/auth.js +291 -0
- package/autochangelog-cli/src/cli/commands/changelog.js +619 -0
- package/autochangelog-cli/src/cli/commands/project.js +427 -0
- package/autochangelog-cli/src/cli/commands/repo.js +557 -0
- package/autochangelog-cli/src/cli/commands/stats.js +706 -0
- package/autochangelog-cli/src/cli/utils/config.js +277 -0
- package/autochangelog-cli/src/cli/utils/errors.js +307 -0
- package/autochangelog-cli/src/cli/utils/logger.js +75 -0
- package/autochangelog-cli/src/cli/utils/output.js +357 -0
- package/package.json +9 -3
- package/plugins/supercli/README.md +108 -0
- package/plugins/supercli/plugin.json +123 -0
- package/server.js +1 -1
- package/src/cli/api.js +380 -0
- package/src/cli/direct/agent-utils.js +61 -0
- package/src/cli/direct/cli-utils.js +112 -0
- package/src/cli/direct/data-seeding.js +307 -0
- package/src/cli/direct/db-admin.js +84 -0
- package/src/cli/direct/db-advanced.js +372 -0
- package/src/cli/direct/db-utils.js +558 -0
- package/src/cli/direct/help.js +195 -0
- package/src/cli/direct/migration.js +107 -0
- package/src/cli/direct/rbac-advanced.js +132 -0
- package/src/cli/direct/resources-additional.js +400 -0
- package/src/cli/direct/resources-cms-advanced.js +173 -0
- package/src/cli/direct/resources-cms.js +247 -0
- package/src/cli/direct/resources-core.js +253 -0
- package/src/cli/direct/resources-execution.js +367 -0
- package/src/cli/direct/resources-health.js +152 -0
- package/src/cli/direct/resources-integrations.js +182 -0
- package/src/cli/direct/resources-logs.js +204 -0
- package/src/cli/direct/resources-org-rbac.js +187 -0
- package/src/cli/direct/resources-system.js +236 -0
- package/src/cli/direct.js +556 -0
- package/src/controllers/admin.controller.js +4 -0
- package/src/controllers/auth.controller.js +148 -1
- package/src/controllers/waitingList.controller.js +130 -1
- package/src/models/RbacRole.js +1 -1
- package/src/models/User.js +39 -5
- package/src/routes/auth.routes.js +6 -0
- package/src/routes/waitingList.routes.js +12 -2
- package/src/routes/waitingListAdmin.routes.js +3 -0
- package/src/services/email.service.js +1 -0
- package/src/services/github.service.js +255 -0
- package/src/services/rateLimiter.service.js +29 -1
- package/src/services/waitingListJson.service.js +32 -3
- package/views/admin-waiting-list.ejs +386 -3
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
const jwt = require("jsonwebtoken");
|
|
2
|
+
const logger = require("../../utils/logger");
|
|
3
|
+
const User = require("../models/User"); // Use local User model directly
|
|
4
|
+
|
|
5
|
+
// Import SuperBackend models via the global registry (for future use)
|
|
6
|
+
const getSuperbackend = () => {
|
|
7
|
+
return globalThis.superbackend || globalThis.saasbackend;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const getUserModel = () => {
|
|
11
|
+
const sb = getSuperbackend();
|
|
12
|
+
return sb?.models?.User || User;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const JWT_SECRET = process.env.JWT_SECRET || process.env.JWT_ACCESS_SECRET;
|
|
16
|
+
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || "7d";
|
|
17
|
+
|
|
18
|
+
// Generate JWT token
|
|
19
|
+
const generateToken = (userId) => {
|
|
20
|
+
return jwt.sign({ userId }, JWT_SECRET, { expiresIn: JWT_EXPIRES_IN });
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Verify JWT token
|
|
24
|
+
const verifyToken = (token) => {
|
|
25
|
+
return jwt.verify(token, JWT_SECRET);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Authentication middleware - uses local User model
|
|
29
|
+
const authenticate = async (req, res, next) => {
|
|
30
|
+
try {
|
|
31
|
+
const authHeader = req.header("Authorization");
|
|
32
|
+
|
|
33
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
34
|
+
return res.status(401).json({
|
|
35
|
+
success: false,
|
|
36
|
+
message: "Access denied. No token provided.",
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const token = authHeader.substring(7); // Remove 'Bearer ' prefix
|
|
41
|
+
|
|
42
|
+
if (!token) {
|
|
43
|
+
return res.status(401).json({
|
|
44
|
+
success: false,
|
|
45
|
+
message: "Access denied. No token provided.",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const decoded = verifyToken(token);
|
|
50
|
+
logger.debug("Decoded userId:", decoded.userId);
|
|
51
|
+
|
|
52
|
+
// Use local User model directly (not SuperBackend's)
|
|
53
|
+
const user = await User.findById(decoded.userId).select("-password");
|
|
54
|
+
logger.debug("User found:", user ? "yes" : "no", user?.email);
|
|
55
|
+
|
|
56
|
+
if (!user) {
|
|
57
|
+
return res.status(401).json({
|
|
58
|
+
success: false,
|
|
59
|
+
message: "Invalid token. User not found.",
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!user.isActive && user.status !== "active") {
|
|
64
|
+
return res.status(401).json({
|
|
65
|
+
success: false,
|
|
66
|
+
message: "Account is inactive.",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
req.user = user;
|
|
71
|
+
next();
|
|
72
|
+
} catch (error) {
|
|
73
|
+
logger.error("Authentication error:", error);
|
|
74
|
+
|
|
75
|
+
if (error.name === "JsonWebTokenError") {
|
|
76
|
+
return res.status(401).json({
|
|
77
|
+
success: false,
|
|
78
|
+
message: "Invalid token.",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (error.name === "TokenExpiredError") {
|
|
83
|
+
return res.status(401).json({
|
|
84
|
+
success: false,
|
|
85
|
+
message: "Token has expired.",
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
res.status(500).json({
|
|
90
|
+
success: false,
|
|
91
|
+
message: "Internal server error.",
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Optional authentication middleware (doesn't fail if no token)
|
|
97
|
+
const optionalAuth = async (req, res, next) => {
|
|
98
|
+
try {
|
|
99
|
+
const authHeader = req.header("Authorization");
|
|
100
|
+
|
|
101
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
102
|
+
return next();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const token = authHeader.substring(7);
|
|
106
|
+
if (!token) {
|
|
107
|
+
return next();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const decoded = verifyToken(token);
|
|
111
|
+
// Use local User model directly
|
|
112
|
+
const user = await User.findById(decoded.userId).select("-password");
|
|
113
|
+
|
|
114
|
+
if (user && (user.isActive || user.status === "active")) {
|
|
115
|
+
req.user = user;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
next();
|
|
119
|
+
} catch (error) {
|
|
120
|
+
// For optional auth, we don't fail on invalid tokens
|
|
121
|
+
next();
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Admin authentication middleware
|
|
126
|
+
const requireAdmin = async (req, res, next) => {
|
|
127
|
+
if (!req.user) {
|
|
128
|
+
return res.status(401).json({
|
|
129
|
+
success: false,
|
|
130
|
+
message: "Access denied. Authentication required.",
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Check if user has admin role via SuperBackend RBAC
|
|
135
|
+
const sb = getSuperbackend();
|
|
136
|
+
if (sb?.helpers?.rbac) {
|
|
137
|
+
const hasAdminRole = await sb.helpers.rbac.checkPermission(
|
|
138
|
+
req.user._id,
|
|
139
|
+
"admin",
|
|
140
|
+
"access",
|
|
141
|
+
);
|
|
142
|
+
if (!hasAdminRole) {
|
|
143
|
+
return res.status(403).json({
|
|
144
|
+
success: false,
|
|
145
|
+
message: "Access denied. Admin privileges required.",
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
next();
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// Check if user owns the resource
|
|
154
|
+
const checkOwnership = (model, idField = "id") => {
|
|
155
|
+
return async (req, res, next) => {
|
|
156
|
+
try {
|
|
157
|
+
if (!req.user) {
|
|
158
|
+
return res.status(401).json({
|
|
159
|
+
success: false,
|
|
160
|
+
message: "Access denied. Authentication required.",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const resourceId = req.params[idField] || req.params.id;
|
|
165
|
+
const Model = require(`../models/${model}`);
|
|
166
|
+
|
|
167
|
+
const resource = await Model.findById(resourceId);
|
|
168
|
+
|
|
169
|
+
if (!resource) {
|
|
170
|
+
return res.status(404).json({
|
|
171
|
+
success: false,
|
|
172
|
+
message: `${model} not found.`,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Check ownership - works with both SuperBackend and local users
|
|
177
|
+
const ownerId =
|
|
178
|
+
resource.ownerId?.toString() || resource.userId?.toString();
|
|
179
|
+
if (ownerId && ownerId !== req.user._id.toString()) {
|
|
180
|
+
return res.status(403).json({
|
|
181
|
+
success: false,
|
|
182
|
+
message: "Access denied. You do not own this resource.",
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Add resource to request for use in controllers
|
|
187
|
+
req.resource = resource;
|
|
188
|
+
next();
|
|
189
|
+
} catch (error) {
|
|
190
|
+
logger.error(`Ownership check error for ${model}:`, error);
|
|
191
|
+
res.status(500).json({
|
|
192
|
+
success: false,
|
|
193
|
+
message: "Internal server error.",
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// Rate limiting middleware
|
|
200
|
+
const rateLimit = require("express-rate-limit");
|
|
201
|
+
|
|
202
|
+
const createRateLimit = (
|
|
203
|
+
windowMs = 15 * 60 * 1000,
|
|
204
|
+
max = 100,
|
|
205
|
+
message = "Too many requests",
|
|
206
|
+
) => {
|
|
207
|
+
return rateLimit({
|
|
208
|
+
windowMs,
|
|
209
|
+
max,
|
|
210
|
+
message: {
|
|
211
|
+
success: false,
|
|
212
|
+
message,
|
|
213
|
+
retryAfter: Math.ceil(windowMs / 1000),
|
|
214
|
+
},
|
|
215
|
+
standardHeaders: true,
|
|
216
|
+
legacyHeaders: false,
|
|
217
|
+
});
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// Specific rate limiters
|
|
221
|
+
const authRateLimit = createRateLimit(
|
|
222
|
+
15 * 60 * 1000, // 15 minutes
|
|
223
|
+
10, // limit each IP to 10 requests per windowMs
|
|
224
|
+
"Too many authentication attempts, please try again later.",
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
const apiRateLimit = createRateLimit(
|
|
228
|
+
15 * 60 * 1000, // 15 minutes
|
|
229
|
+
100, // limit each IP to 100 requests per windowMs
|
|
230
|
+
"Too many API requests, please try again later.",
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
// GitHub webhook authentication middleware
|
|
234
|
+
const verifyGithubWebhook = (req, res, next) => {
|
|
235
|
+
const signature = req.headers["x-hub-signature-256"];
|
|
236
|
+
|
|
237
|
+
if (!signature) {
|
|
238
|
+
return res.status(401).json({
|
|
239
|
+
success: false,
|
|
240
|
+
message: "GitHub webhook signature missing.",
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// This would verify the signature against the webhook secret
|
|
245
|
+
// For now, we'll skip the actual verification
|
|
246
|
+
next();
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// Subscription check middleware - uses SuperBackend billing
|
|
250
|
+
const checkSubscription = (requiredPlan = "free") => {
|
|
251
|
+
return async (req, res, next) => {
|
|
252
|
+
if (!req.user) {
|
|
253
|
+
return res.status(401).json({
|
|
254
|
+
success: false,
|
|
255
|
+
message: "Access denied. Authentication required.",
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Get user's subscription from SuperBackend
|
|
260
|
+
const sb = getSuperbackend();
|
|
261
|
+
let userPlan = "free";
|
|
262
|
+
|
|
263
|
+
if (sb?.services?.globalSettings) {
|
|
264
|
+
// Check if user has an active subscription
|
|
265
|
+
const subscription = await sb.services.globalSettings.getSettingValue(
|
|
266
|
+
`user_subscription_${req.user._id}`,
|
|
267
|
+
"free",
|
|
268
|
+
);
|
|
269
|
+
userPlan = subscription;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const plans = ["free", "pro", "enterprise"];
|
|
273
|
+
|
|
274
|
+
if (plans.indexOf(userPlan) < plans.indexOf(requiredPlan)) {
|
|
275
|
+
return res.status(403).json({
|
|
276
|
+
success: false,
|
|
277
|
+
message: `This feature requires a ${requiredPlan} subscription.`,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
next();
|
|
282
|
+
};
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
// Usage limit check middleware
|
|
286
|
+
const checkUsageLimits = async (req, res, next) => {
|
|
287
|
+
if (!req.user) {
|
|
288
|
+
return next();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
const Project = require("../models/Project");
|
|
293
|
+
const Repository = require("../models/Repository");
|
|
294
|
+
const Changelog = require("../models/Changelog");
|
|
295
|
+
|
|
296
|
+
// Get user's plan limits from SuperBackend or local config
|
|
297
|
+
const sb = getSuperbackend();
|
|
298
|
+
let limits = {
|
|
299
|
+
projectsLimit: 3,
|
|
300
|
+
repositoriesLimit: 5,
|
|
301
|
+
changelogsLimit: 10,
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
if (sb?.services?.globalSettings) {
|
|
305
|
+
const plan = await sb.services.globalSettings.getSettingValue(
|
|
306
|
+
`user_plan_${req.user._id}`,
|
|
307
|
+
"free",
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
// Define limits per plan
|
|
311
|
+
const planLimits = {
|
|
312
|
+
free: { projectsLimit: 3, repositoriesLimit: 5, changelogsLimit: 10 },
|
|
313
|
+
pro: { projectsLimit: 10, repositoriesLimit: 25, changelogsLimit: 100 },
|
|
314
|
+
enterprise: {
|
|
315
|
+
projectsLimit: 100,
|
|
316
|
+
repositoriesLimit: 100,
|
|
317
|
+
changelogsLimit: 1000,
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
limits = planLimits[plan] || planLimits.free;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Update usage counts
|
|
325
|
+
const [projectsCount, repositoriesCount, changelogsCount] =
|
|
326
|
+
await Promise.all([
|
|
327
|
+
Project.countDocuments({ ownerId: req.user._id, status: "active" }),
|
|
328
|
+
Repository.countDocuments({
|
|
329
|
+
projectId: {
|
|
330
|
+
$in: await Project.find({ ownerId: req.user._id }).select("_id"),
|
|
331
|
+
},
|
|
332
|
+
status: "active",
|
|
333
|
+
}),
|
|
334
|
+
Changelog.countDocuments({
|
|
335
|
+
projectId: {
|
|
336
|
+
$in: await Project.find({ ownerId: req.user._id }).select("_id"),
|
|
337
|
+
},
|
|
338
|
+
status: { $in: ["completed", "failed"] },
|
|
339
|
+
}),
|
|
340
|
+
]);
|
|
341
|
+
|
|
342
|
+
// Check limits
|
|
343
|
+
if (projectsCount >= limits.projectsLimit) {
|
|
344
|
+
return res.status(403).json({
|
|
345
|
+
success: false,
|
|
346
|
+
message: `You have reached your project limit of ${limits.projectsLimit}. Upgrade your plan to create more projects.`,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (repositoriesCount >= limits.repositoriesLimit) {
|
|
351
|
+
return res.status(403).json({
|
|
352
|
+
success: false,
|
|
353
|
+
message: `You have reached your repository limit of ${limits.repositoriesLimit}. Upgrade your plan to connect more repositories.`,
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (changelogsCount >= limits.changelogsLimit) {
|
|
358
|
+
return res.status(403).json({
|
|
359
|
+
success: false,
|
|
360
|
+
message: `You have reached your changelog limit of ${limits.changelogsLimit} per month. Upgrade your plan or wait until next month.`,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
next();
|
|
365
|
+
} catch (error) {
|
|
366
|
+
logger.error("Usage limit check error:", error);
|
|
367
|
+
res.status(500).json({
|
|
368
|
+
success: false,
|
|
369
|
+
message: "Internal server error.",
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
module.exports = {
|
|
375
|
+
generateToken,
|
|
376
|
+
verifyToken,
|
|
377
|
+
authenticate,
|
|
378
|
+
optionalAuth,
|
|
379
|
+
requireAdmin,
|
|
380
|
+
checkOwnership,
|
|
381
|
+
authRateLimit,
|
|
382
|
+
apiRateLimit,
|
|
383
|
+
verifyGithubWebhook,
|
|
384
|
+
checkSubscription,
|
|
385
|
+
checkUsageLimits,
|
|
386
|
+
};
|