@intranefr/superbackend 1.4.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.
- package/.commiat +4 -0
- package/.env.example +47 -0
- package/README.md +110 -0
- package/index.js +94 -0
- package/package.json +67 -0
- package/public/css/styles.css +139 -0
- package/public/js/animations.js +41 -0
- package/sdk/error-tracking/browser/package.json +16 -0
- package/sdk/error-tracking/browser/src/core.js +270 -0
- package/sdk/error-tracking/browser/src/embed.js +18 -0
- package/sdk/error-tracking/browser/src/index.js +1 -0
- package/server.js +5 -0
- package/src/admin/endpointRegistry.js +300 -0
- package/src/controllers/admin.controller.js +321 -0
- package/src/controllers/adminAssets.controller.js +530 -0
- package/src/controllers/adminAssetsStorage.controller.js +260 -0
- package/src/controllers/adminEjsVirtual.controller.js +354 -0
- package/src/controllers/adminFeatureFlags.controller.js +155 -0
- package/src/controllers/adminHeadless.controller.js +1071 -0
- package/src/controllers/adminI18n.controller.js +604 -0
- package/src/controllers/adminJsonConfigs.controller.js +97 -0
- package/src/controllers/adminLlm.controller.js +273 -0
- package/src/controllers/adminMigration.controller.js +257 -0
- package/src/controllers/adminSeoConfig.controller.js +515 -0
- package/src/controllers/adminStats.controller.js +121 -0
- package/src/controllers/adminUploadNamespaces.controller.js +208 -0
- package/src/controllers/assets.controller.js +248 -0
- package/src/controllers/auth.controller.js +93 -0
- package/src/controllers/billing.controller.js +223 -0
- package/src/controllers/featureFlags.controller.js +35 -0
- package/src/controllers/forms.controller.js +217 -0
- package/src/controllers/globalSettings.controller.js +252 -0
- package/src/controllers/headlessCrud.controller.js +126 -0
- package/src/controllers/i18n.controller.js +12 -0
- package/src/controllers/invite.controller.js +249 -0
- package/src/controllers/jsonConfigs.controller.js +19 -0
- package/src/controllers/metrics.controller.js +149 -0
- package/src/controllers/notificationAdmin.controller.js +264 -0
- package/src/controllers/notifications.controller.js +131 -0
- package/src/controllers/org.controller.js +357 -0
- package/src/controllers/orgAdmin.controller.js +491 -0
- package/src/controllers/stripeAdmin.controller.js +410 -0
- package/src/controllers/user.controller.js +361 -0
- package/src/controllers/userAdmin.controller.js +277 -0
- package/src/controllers/waitingList.controller.js +167 -0
- package/src/controllers/webhook.controller.js +200 -0
- package/src/middleware/auth.js +66 -0
- package/src/middleware/errorCapture.js +170 -0
- package/src/middleware/headlessApiTokenAuth.js +57 -0
- package/src/middleware/org.js +108 -0
- package/src/middleware.js +901 -0
- package/src/models/ActionEvent.js +31 -0
- package/src/models/ActivityLog.js +41 -0
- package/src/models/Asset.js +84 -0
- package/src/models/AuditEvent.js +93 -0
- package/src/models/EmailLog.js +28 -0
- package/src/models/ErrorAggregate.js +72 -0
- package/src/models/FormSubmission.js +41 -0
- package/src/models/GlobalSetting.js +38 -0
- package/src/models/HeadlessApiToken.js +24 -0
- package/src/models/HeadlessModelDefinition.js +41 -0
- package/src/models/I18nEntry.js +77 -0
- package/src/models/I18nLocale.js +33 -0
- package/src/models/Invite.js +70 -0
- package/src/models/JsonConfig.js +46 -0
- package/src/models/Notification.js +60 -0
- package/src/models/Organization.js +57 -0
- package/src/models/OrganizationMember.js +43 -0
- package/src/models/StripeCatalogItem.js +77 -0
- package/src/models/StripeWebhookEvent.js +57 -0
- package/src/models/User.js +89 -0
- package/src/models/VirtualEjsFile.js +60 -0
- package/src/models/VirtualEjsFileVersion.js +43 -0
- package/src/models/VirtualEjsGroupChange.js +32 -0
- package/src/models/WaitingList.js +41 -0
- package/src/models/Webhook.js +63 -0
- package/src/models/Workflow.js +29 -0
- package/src/models/WorkflowExecution.js +12 -0
- package/src/routes/admin.routes.js +26 -0
- package/src/routes/adminAssets.routes.js +28 -0
- package/src/routes/adminAssetsStorage.routes.js +13 -0
- package/src/routes/adminAudit.routes.js +196 -0
- package/src/routes/adminEjsVirtual.routes.js +17 -0
- package/src/routes/adminErrors.routes.js +164 -0
- package/src/routes/adminFeatureFlags.routes.js +12 -0
- package/src/routes/adminHeadless.routes.js +38 -0
- package/src/routes/adminI18n.routes.js +22 -0
- package/src/routes/adminJsonConfigs.routes.js +15 -0
- package/src/routes/adminLlm.routes.js +12 -0
- package/src/routes/adminMigration.routes.js +81 -0
- package/src/routes/adminSeoConfig.routes.js +20 -0
- package/src/routes/adminUploadNamespaces.routes.js +13 -0
- package/src/routes/assets.routes.js +21 -0
- package/src/routes/auth.routes.js +12 -0
- package/src/routes/billing.routes.js +11 -0
- package/src/routes/errorTracking.routes.js +31 -0
- package/src/routes/featureFlags.routes.js +9 -0
- package/src/routes/forms.routes.js +9 -0
- package/src/routes/formsAdmin.routes.js +13 -0
- package/src/routes/globalSettings.routes.js +18 -0
- package/src/routes/headless.routes.js +15 -0
- package/src/routes/i18n.routes.js +8 -0
- package/src/routes/invite.routes.js +9 -0
- package/src/routes/jsonConfigs.routes.js +8 -0
- package/src/routes/log.routes.js +111 -0
- package/src/routes/metrics.routes.js +9 -0
- package/src/routes/notificationAdmin.routes.js +15 -0
- package/src/routes/notifications.routes.js +12 -0
- package/src/routes/org.routes.js +31 -0
- package/src/routes/orgAdmin.routes.js +20 -0
- package/src/routes/publicAssets.routes.js +7 -0
- package/src/routes/stripeAdmin.routes.js +20 -0
- package/src/routes/user.routes.js +22 -0
- package/src/routes/userAdmin.routes.js +15 -0
- package/src/routes/waitingList.routes.js +13 -0
- package/src/routes/waitingListAdmin.routes.js +9 -0
- package/src/routes/webhook.routes.js +32 -0
- package/src/routes/workflowWebhook.routes.js +54 -0
- package/src/routes/workflows.routes.js +110 -0
- package/src/services/assets.service.js +110 -0
- package/src/services/audit.service.js +62 -0
- package/src/services/auditLogger.js +165 -0
- package/src/services/ejsVirtual.service.js +614 -0
- package/src/services/email.service.js +351 -0
- package/src/services/errorLogger.js +221 -0
- package/src/services/featureFlags.service.js +202 -0
- package/src/services/forms.service.js +214 -0
- package/src/services/globalSettings.service.js +49 -0
- package/src/services/headlessApiTokens.service.js +158 -0
- package/src/services/headlessCrypto.service.js +31 -0
- package/src/services/headlessModels.service.js +356 -0
- package/src/services/i18n.service.js +314 -0
- package/src/services/i18nInferredKeys.service.js +337 -0
- package/src/services/jsonConfigs.service.js +392 -0
- package/src/services/llm.service.js +749 -0
- package/src/services/migration.service.js +581 -0
- package/src/services/migrationAssets/fsLocal.js +58 -0
- package/src/services/migrationAssets/index.js +134 -0
- package/src/services/migrationAssets/s3.js +75 -0
- package/src/services/migrationAssets/sftp.js +92 -0
- package/src/services/notification.service.js +212 -0
- package/src/services/objectStorage.service.js +514 -0
- package/src/services/seoConfig.service.js +402 -0
- package/src/services/storage.js +150 -0
- package/src/services/stripe.service.js +185 -0
- package/src/services/stripeHelper.service.js +264 -0
- package/src/services/uploadNamespaces.service.js +326 -0
- package/src/services/webhook.service.js +157 -0
- package/src/services/workflow.service.js +271 -0
- package/src/utils/asyncHandler.js +5 -0
- package/src/utils/encryption.js +80 -0
- package/src/utils/jwt.js +40 -0
- package/src/utils/orgRoles.js +156 -0
- package/src/utils/validation.js +26 -0
- package/src/utils/webhookRetry.js +93 -0
- package/views/admin-assets.ejs +444 -0
- package/views/admin-audit.ejs +283 -0
- package/views/admin-coolify-deploy.ejs +207 -0
- package/views/admin-dashboard-home.ejs +291 -0
- package/views/admin-dashboard.ejs +397 -0
- package/views/admin-ejs-virtual.ejs +280 -0
- package/views/admin-errors.ejs +368 -0
- package/views/admin-feature-flags.ejs +390 -0
- package/views/admin-forms.ejs +526 -0
- package/views/admin-global-settings.ejs +436 -0
- package/views/admin-headless.ejs +2020 -0
- package/views/admin-i18n-locales.ejs +221 -0
- package/views/admin-i18n.ejs +728 -0
- package/views/admin-json-configs.ejs +410 -0
- package/views/admin-llm.ejs +884 -0
- package/views/admin-metrics.ejs +274 -0
- package/views/admin-migration.ejs +814 -0
- package/views/admin-notifications.ejs +430 -0
- package/views/admin-organizations.ejs +984 -0
- package/views/admin-seo-config.ejs +673 -0
- package/views/admin-stripe-pricing.ejs +558 -0
- package/views/admin-test.ejs +342 -0
- package/views/admin-users.ejs +452 -0
- package/views/admin-waiting-list.ejs +547 -0
- package/views/admin-webhooks.ejs +329 -0
- package/views/admin-workflows.ejs +310 -0
- package/views/partials/admin-assets-script.ejs +2022 -0
- package/views/partials/admin-test-sidebar.ejs +14 -0
- package/views/partials/dashboard/nav-items.ejs +66 -0
- package/views/partials/dashboard/palette.ejs +63 -0
- package/views/partials/dashboard/sidebar.ejs +21 -0
- package/views/partials/dashboard/tab-bar.ejs +26 -0
- package/views/partials/footer.ejs +3 -0
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
const User = require('../models/User');
|
|
2
|
+
const StripeWebhookEvent = require('../models/StripeWebhookEvent');
|
|
3
|
+
const asyncHandler = require('../utils/asyncHandler');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
|
|
7
|
+
const { generateAccessToken, generateRefreshToken } = require('../utils/jwt');
|
|
8
|
+
const { retryFailedWebhooks, processWebhookEvent } = require('../utils/webhookRetry');
|
|
9
|
+
|
|
10
|
+
// Get all users
|
|
11
|
+
const getUsers = asyncHandler(async (req, res) => {
|
|
12
|
+
const users = await User.find()
|
|
13
|
+
.select('-passwordHash')
|
|
14
|
+
.sort({ createdAt: -1 })
|
|
15
|
+
.limit(100);
|
|
16
|
+
|
|
17
|
+
res.json(users.map(u => u.toJSON()));
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Get single user
|
|
21
|
+
const getUser = asyncHandler(async (req, res) => {
|
|
22
|
+
const user = await User.findById(req.params.id);
|
|
23
|
+
|
|
24
|
+
if (!user) {
|
|
25
|
+
return res.status(404).json({ error: 'User not found' });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
res.json({ user: user.toJSON() });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Update user subscription
|
|
32
|
+
const updateUserSubscription = asyncHandler(async (req, res) => {
|
|
33
|
+
const { subscriptionStatus } = req.body;
|
|
34
|
+
const user = await User.findById(req.params.id);
|
|
35
|
+
|
|
36
|
+
if (!user) {
|
|
37
|
+
return res.status(404).json({ error: 'User not found' });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (subscriptionStatus) {
|
|
41
|
+
user.subscriptionStatus = subscriptionStatus;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
await user.save();
|
|
45
|
+
|
|
46
|
+
res.json({ user: user.toJSON() });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Update user password
|
|
50
|
+
const updateUserPassword = asyncHandler(async (req, res) => {
|
|
51
|
+
const { passwordHash } = req.body;
|
|
52
|
+
const bcrypt = require('bcryptjs');
|
|
53
|
+
const user = await User.findById(req.params.id);
|
|
54
|
+
|
|
55
|
+
if (!user) {
|
|
56
|
+
return res.status(404).json({ error: 'User not found' });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!passwordHash) {
|
|
60
|
+
return res.status(400).json({ error: 'Password is required' });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Detect if the provided password is already a bcrypt hash
|
|
64
|
+
const isBcryptHash = /^\$2[aby]\$\d{2}\$/.test(passwordHash);
|
|
65
|
+
if (isBcryptHash) {
|
|
66
|
+
return res.status(400).json({
|
|
67
|
+
error: 'Invalid password format',
|
|
68
|
+
message: 'The password appears to be already hashed. Please provide a plaintext password instead.',
|
|
69
|
+
hint: 'Bcrypt hashes start with $2a$, $2b$, or $2y$ followed by a cost parameter (e.g., $2a$10$...)'
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
// Set plaintext password and let pre-save hook hash it
|
|
75
|
+
user.passwordHash = passwordHash;
|
|
76
|
+
await user.save();
|
|
77
|
+
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error('Save error:', error);
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
res.json({ user: user.toJSON() });
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Reconcile user subscription
|
|
87
|
+
const reconcileUser = asyncHandler(async (req, res) => {
|
|
88
|
+
const user = await User.findById(req.params.id);
|
|
89
|
+
|
|
90
|
+
if (!user) {
|
|
91
|
+
return res.status(404).json({ error: 'User not found' });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!user.stripeCustomerId) {
|
|
95
|
+
return res.json({ status: 'success', message: 'No Stripe customer found' });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const subscriptions = await stripe.subscriptions.list({
|
|
99
|
+
customer: user.stripeCustomerId,
|
|
100
|
+
limit: 1
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (subscriptions.data.length > 0) {
|
|
104
|
+
const subscription = subscriptions.data[0];
|
|
105
|
+
user.stripeSubscriptionId = subscription.id;
|
|
106
|
+
user.subscriptionStatus = subscription.status === 'active' ? 'active' : subscription.status;
|
|
107
|
+
await user.save();
|
|
108
|
+
} else {
|
|
109
|
+
// No active subscription found. Check for successful one-off (payment) checkouts
|
|
110
|
+
const sessions = await stripe.checkout.sessions.list({
|
|
111
|
+
customer: user.stripeCustomerId,
|
|
112
|
+
limit: 10
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const lifetimeSession = sessions.data.find((session) => {
|
|
116
|
+
const mode = session.metadata?.billingMode || session.mode;
|
|
117
|
+
return (
|
|
118
|
+
mode === 'payment' &&
|
|
119
|
+
session.payment_status === 'paid'
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
if (lifetimeSession) {
|
|
124
|
+
user.subscriptionStatus = 'active';
|
|
125
|
+
} else {
|
|
126
|
+
user.subscriptionStatus = 'none';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
await user.save();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
res.json({ status: 'success', user: user.toJSON() });
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Generate JWT for testing
|
|
136
|
+
const generateToken = asyncHandler(async (req, res) => {
|
|
137
|
+
const { userId } = req.body;
|
|
138
|
+
|
|
139
|
+
if (!userId) {
|
|
140
|
+
return res.status(400).json({ error: 'userId is required' });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const user = await User.findById(userId);
|
|
144
|
+
if (!user) {
|
|
145
|
+
return res.status(404).json({ error: 'User not found' });
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const token = generateAccessToken(user._id);
|
|
149
|
+
const refreshToken = generateRefreshToken(user._id);
|
|
150
|
+
|
|
151
|
+
res.json({ token, refreshToken, userId: user._id });
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Get all webhook events
|
|
155
|
+
const getWebhookEvents = asyncHandler(async (req, res) => {
|
|
156
|
+
const { limit = 50, offset = 0, eventType, status } = req.query;
|
|
157
|
+
|
|
158
|
+
const filter = {};
|
|
159
|
+
if (eventType) filter.eventType = eventType;
|
|
160
|
+
if (status) filter.status = status;
|
|
161
|
+
|
|
162
|
+
const events = await StripeWebhookEvent.find(filter)
|
|
163
|
+
.sort({ receivedAt: -1 })
|
|
164
|
+
.skip(parseInt(offset))
|
|
165
|
+
.limit(parseInt(limit));
|
|
166
|
+
|
|
167
|
+
const total = await StripeWebhookEvent.countDocuments(filter);
|
|
168
|
+
|
|
169
|
+
res.json({
|
|
170
|
+
events,
|
|
171
|
+
pagination: {
|
|
172
|
+
total,
|
|
173
|
+
limit: parseInt(limit),
|
|
174
|
+
offset: parseInt(offset)
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Get single webhook event
|
|
180
|
+
const getWebhookEvent = asyncHandler(async (req, res) => {
|
|
181
|
+
const event = await StripeWebhookEvent.findOne({ stripeEventId: req.params.id });
|
|
182
|
+
|
|
183
|
+
if (!event) {
|
|
184
|
+
return res.status(404).json({ error: 'Webhook event not found' });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
res.json({ event });
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Retry failed webhook events
|
|
191
|
+
const retryFailedWebhookEvents = asyncHandler(async (req, res) => {
|
|
192
|
+
const { limit = 10, maxRetries = 3 } = req.body;
|
|
193
|
+
|
|
194
|
+
const results = await retryFailedWebhooks({ limit, maxRetries });
|
|
195
|
+
|
|
196
|
+
res.json({
|
|
197
|
+
status: 'success',
|
|
198
|
+
results
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Retry single webhook event
|
|
203
|
+
const retrySingleWebhookEvent = asyncHandler(async (req, res) => {
|
|
204
|
+
const event = await StripeWebhookEvent.findOne({ stripeEventId: req.params.id });
|
|
205
|
+
|
|
206
|
+
if (!event) {
|
|
207
|
+
return res.status(404).json({ error: 'Webhook event not found' });
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (event.status === 'processed') {
|
|
211
|
+
return res.status(400).json({ error: 'Event already processed' });
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
await processWebhookEvent(event);
|
|
216
|
+
|
|
217
|
+
event.status = 'processed';
|
|
218
|
+
event.processedAt = new Date();
|
|
219
|
+
await event.save();
|
|
220
|
+
|
|
221
|
+
res.json({
|
|
222
|
+
status: 'success',
|
|
223
|
+
message: 'Event processed successfully',
|
|
224
|
+
event
|
|
225
|
+
});
|
|
226
|
+
} catch (err) {
|
|
227
|
+
event.retryCount++;
|
|
228
|
+
event.processingErrors.push({
|
|
229
|
+
message: err.message,
|
|
230
|
+
timestamp: new Date()
|
|
231
|
+
});
|
|
232
|
+
await event.save();
|
|
233
|
+
|
|
234
|
+
res.status(500).json({
|
|
235
|
+
status: 'error',
|
|
236
|
+
message: err.message,
|
|
237
|
+
event
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Get webhook statistics
|
|
243
|
+
const getWebhookStats = asyncHandler(async (req, res) => {
|
|
244
|
+
const stats = await StripeWebhookEvent.aggregate([
|
|
245
|
+
{
|
|
246
|
+
$group: {
|
|
247
|
+
_id: '$status',
|
|
248
|
+
count: { $sum: 1 }
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
]);
|
|
252
|
+
|
|
253
|
+
const eventTypeStats = await StripeWebhookEvent.aggregate([
|
|
254
|
+
{
|
|
255
|
+
$group: {
|
|
256
|
+
_id: '$eventType',
|
|
257
|
+
count: { $sum: 1 },
|
|
258
|
+
failedCount: {
|
|
259
|
+
$sum: { $cond: [{ $eq: ['$status', 'failed'] }, 1, 0] }
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
{ $sort: { count: -1 } }
|
|
264
|
+
]);
|
|
265
|
+
|
|
266
|
+
const recentFailures = await StripeWebhookEvent.find({ status: 'failed' })
|
|
267
|
+
.sort({ receivedAt: -1 })
|
|
268
|
+
.limit(10)
|
|
269
|
+
.select('stripeEventId eventType receivedAt retryCount processingErrors');
|
|
270
|
+
|
|
271
|
+
res.json({
|
|
272
|
+
statusStats: stats,
|
|
273
|
+
eventTypeStats,
|
|
274
|
+
recentFailures
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// Coolify Headless Deploy provisioning
|
|
279
|
+
const provisionCoolifyDeploy = asyncHandler(async (req, res) => {
|
|
280
|
+
try {
|
|
281
|
+
const { overwrite } = req.body;
|
|
282
|
+
const managePath = path.join(process.cwd(), "manage.sh");
|
|
283
|
+
const exists = fs.existsSync(managePath);
|
|
284
|
+
|
|
285
|
+
if (exists && !overwrite) {
|
|
286
|
+
return res.json({
|
|
287
|
+
success: false,
|
|
288
|
+
requiresConfirmation: true,
|
|
289
|
+
message: "Script already exists. Do you want to overwrite it?",
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// In ref-saasbackend, manage.sh already exists in the root of the repository
|
|
294
|
+
// If it didn't, we would write it here. For this case, we'll just success.
|
|
295
|
+
res.json({
|
|
296
|
+
success: true,
|
|
297
|
+
message: exists
|
|
298
|
+
? "Coolify Headless Deploy script (manage.sh) was already there."
|
|
299
|
+
: "Coolify Headless Deploy script (manage.sh) is ready in the root directory.",
|
|
300
|
+
path: managePath,
|
|
301
|
+
});
|
|
302
|
+
} catch (error) {
|
|
303
|
+
console.error("❌ Error provisioning script:", error);
|
|
304
|
+
res.status(500).json({ error: error.message });
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
module.exports = {
|
|
309
|
+
getUsers,
|
|
310
|
+
getUser,
|
|
311
|
+
updateUserSubscription,
|
|
312
|
+
updateUserPassword,
|
|
313
|
+
reconcileUser,
|
|
314
|
+
generateToken,
|
|
315
|
+
getWebhookEvents,
|
|
316
|
+
getWebhookEvent,
|
|
317
|
+
retryFailedWebhookEvents,
|
|
318
|
+
retrySingleWebhookEvent,
|
|
319
|
+
getWebhookStats,
|
|
320
|
+
provisionCoolifyDeploy
|
|
321
|
+
};
|