nodebb-plugin-calendar-onekite 11.1.75 → 11.1.77
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/lib/admin.js +30 -13
- package/lib/api.js +29 -13
- package/library.js +18 -11
- package/package.json +1 -1
- package/plugin.json +2 -3
package/lib/admin.js
CHANGED
|
@@ -21,27 +21,39 @@ function formatFR(tsOrIso) {
|
|
|
21
21
|
async function sendEmail(template, toEmail, subject, data) {
|
|
22
22
|
if (!toEmail) return;
|
|
23
23
|
try {
|
|
24
|
+
const dataWithSubject = Object.assign({}, data || {}, subject ? { subject, _subject: subject } : {});
|
|
25
|
+
|
|
26
|
+
// Same compatibility strategy as lib/api.js
|
|
27
|
+
const attempts = [];
|
|
24
28
|
if (typeof emailer.sendToEmail === 'function') {
|
|
25
|
-
if (emailer.sendToEmail.length
|
|
26
|
-
|
|
29
|
+
if (emailer.sendToEmail.length === 3) {
|
|
30
|
+
attempts.push(() => emailer.sendToEmail(template, toEmail, dataWithSubject));
|
|
27
31
|
} else {
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
attempts.push(() => emailer.sendToEmail(template, toEmail, subject, dataWithSubject));
|
|
33
|
+
attempts.push(() => emailer.sendToEmail(template, toEmail, dataWithSubject, subject));
|
|
34
|
+
attempts.push(() => emailer.sendToEmail(template, toEmail, dataWithSubject));
|
|
30
35
|
}
|
|
31
|
-
return;
|
|
32
36
|
}
|
|
33
37
|
if (typeof emailer.send === 'function') {
|
|
34
|
-
if (emailer.send.length >= 4) {
|
|
35
|
-
await emailer.send(template, toEmail, subject, data);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
38
|
if (emailer.send.length === 3) {
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
attempts.push(() => emailer.send(template, toEmail, dataWithSubject));
|
|
40
|
+
} else {
|
|
41
|
+
attempts.push(() => emailer.send(template, toEmail, subject, dataWithSubject));
|
|
42
|
+
attempts.push(() => emailer.send(template, toEmail, dataWithSubject, subject));
|
|
43
|
+
attempts.push(() => emailer.send(template, toEmail, dataWithSubject));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let lastErr = null;
|
|
48
|
+
for (const fn of attempts) {
|
|
49
|
+
try {
|
|
50
|
+
await fn();
|
|
41
51
|
return;
|
|
52
|
+
} catch (e) {
|
|
53
|
+
lastErr = e;
|
|
42
54
|
}
|
|
43
|
-
await emailer.send(template, toEmail, subject, data);
|
|
44
55
|
}
|
|
56
|
+
if (lastErr) throw lastErr;
|
|
45
57
|
} catch (err) {
|
|
46
58
|
console.warn('[calendar-onekite] Failed to send email', { template, toEmail, err: String(err && err.message || err) });
|
|
47
59
|
}
|
|
@@ -86,7 +98,12 @@ admin.getSettings = async function (req, res) {
|
|
|
86
98
|
};
|
|
87
99
|
|
|
88
100
|
admin.saveSettings = async function (req, res) {
|
|
89
|
-
|
|
101
|
+
// Merge instead of overwrite so a missing/empty body (eg. due to body parser
|
|
102
|
+
// differences across NodeBB versions) does not wipe existing settings.
|
|
103
|
+
const current = (await meta.settings.get('calendar-onekite')) || {};
|
|
104
|
+
const incoming = req.body && typeof req.body === 'object' ? req.body : {};
|
|
105
|
+
const merged = Object.assign({}, current, incoming);
|
|
106
|
+
await meta.settings.set('calendar-onekite', merged);
|
|
90
107
|
res.json({ ok: true });
|
|
91
108
|
};
|
|
92
109
|
|
package/lib/api.js
CHANGED
|
@@ -15,27 +15,43 @@ const helloasso = require('./helloasso');
|
|
|
15
15
|
async function sendEmail(template, toEmail, subject, data) {
|
|
16
16
|
if (!toEmail) return;
|
|
17
17
|
const emailer = require.main.require('./src/emailer');
|
|
18
|
-
const dataWithSubject = Object.assign({}, data || {}, subject ? { subject } : {});
|
|
18
|
+
const dataWithSubject = Object.assign({}, data || {}, subject ? { subject, _subject: subject } : {});
|
|
19
19
|
try {
|
|
20
|
-
// NodeBB
|
|
20
|
+
// NodeBB Emailer signatures vary across versions/plugins.
|
|
21
|
+
// IMPORTANT: some implementations accept (template, email, data) and will NOT throw if we pass a string as `data`,
|
|
22
|
+
// which can lead to "sent but empty subject". So we prefer the (template, email, data) call first when arity hints it.
|
|
23
|
+
const attempts = [];
|
|
24
|
+
|
|
21
25
|
if (typeof emailer.sendToEmail === 'function') {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
if (emailer.sendToEmail.length === 3) {
|
|
27
|
+
attempts.push(() => emailer.sendToEmail(template, toEmail, dataWithSubject));
|
|
28
|
+
} else {
|
|
29
|
+
// Try the common forms that include subject
|
|
30
|
+
attempts.push(() => emailer.sendToEmail(template, toEmail, subject, dataWithSubject));
|
|
31
|
+
attempts.push(() => emailer.sendToEmail(template, toEmail, dataWithSubject, subject));
|
|
32
|
+
attempts.push(() => emailer.sendToEmail(template, toEmail, dataWithSubject));
|
|
26
33
|
}
|
|
27
|
-
// Fallback
|
|
28
|
-
await emailer.sendToEmail(template, toEmail, subject, data);
|
|
29
|
-
return;
|
|
30
34
|
}
|
|
31
35
|
if (typeof emailer.send === 'function') {
|
|
32
|
-
if (emailer.send.length
|
|
33
|
-
|
|
36
|
+
if (emailer.send.length === 3) {
|
|
37
|
+
attempts.push(() => emailer.send(template, toEmail, dataWithSubject));
|
|
38
|
+
} else {
|
|
39
|
+
attempts.push(() => emailer.send(template, toEmail, subject, dataWithSubject));
|
|
40
|
+
attempts.push(() => emailer.send(template, toEmail, dataWithSubject, subject));
|
|
41
|
+
attempts.push(() => emailer.send(template, toEmail, dataWithSubject));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let lastErr = null;
|
|
46
|
+
for (const fn of attempts) {
|
|
47
|
+
try {
|
|
48
|
+
await fn();
|
|
34
49
|
return;
|
|
50
|
+
} catch (e) {
|
|
51
|
+
lastErr = e;
|
|
35
52
|
}
|
|
36
|
-
await emailer.send(template, toEmail, subject, data);
|
|
37
|
-
return;
|
|
38
53
|
}
|
|
54
|
+
if (lastErr) throw lastErr;
|
|
39
55
|
} catch (err) {
|
|
40
56
|
// eslint-disable-next-line no-console
|
|
41
57
|
console.warn('[calendar-onekite] Failed to send email', { template, toEmail, err: String((err && err.message) || err) });
|
package/library.js
CHANGED
|
@@ -126,6 +126,13 @@ Plugin.renderMiniWidget = async function (hookData, callback) {
|
|
|
126
126
|
Plugin.init = async function (params) {
|
|
127
127
|
const { router, middleware } = params;
|
|
128
128
|
|
|
129
|
+
// Parse JSON bodies for our API routes.
|
|
130
|
+
// NodeBB core parses bodies for many built-in routes, but custom plugin
|
|
131
|
+
// routes are not guaranteed to have body parsing enabled across versions.
|
|
132
|
+
const jsonBody = bodyParser.json({
|
|
133
|
+
type: ['application/json', 'application/*+json'],
|
|
134
|
+
});
|
|
135
|
+
|
|
129
136
|
// Build middleware arrays safely and always spread them into Express route methods.
|
|
130
137
|
// Express will throw if any callback is undefined, so we filter strictly.
|
|
131
138
|
const publicExpose = mw(middleware && middleware.exposeUid);
|
|
@@ -173,12 +180,12 @@ Plugin.init = async function (params) {
|
|
|
173
180
|
});
|
|
174
181
|
|
|
175
182
|
['/api/v3/plugins/calendar-onekite/reservations', '/api/plugins/calendar-onekite/reservations'].forEach((p) => {
|
|
176
|
-
router.post(p, ...publicAuth, api.createReservation);
|
|
183
|
+
router.post(p, jsonBody, ...publicAuth, api.createReservation);
|
|
177
184
|
});
|
|
178
185
|
|
|
179
186
|
// Special events (other colour) - created/deleted by configured groups
|
|
180
187
|
['/api/v3/plugins/calendar-onekite/special-events', '/api/plugins/calendar-onekite/special-events'].forEach((p) => {
|
|
181
|
-
router.post(p, ...publicAuth, api.createSpecialEvent);
|
|
188
|
+
router.post(p, jsonBody, ...publicAuth, api.createSpecialEvent);
|
|
182
189
|
});
|
|
183
190
|
['/api/v3/plugins/calendar-onekite/special-events/:eid', '/api/plugins/calendar-onekite/special-events/:eid'].forEach((p) => {
|
|
184
191
|
router.delete(p, ...publicAuth, api.deleteSpecialEvent);
|
|
@@ -186,14 +193,14 @@ Plugin.init = async function (params) {
|
|
|
186
193
|
|
|
187
194
|
// Validator actions from the calendar popup (requires login + validatorGroups)
|
|
188
195
|
['/api/v3/plugins/calendar-onekite/reservations/:rid/approve', '/api/plugins/calendar-onekite/reservations/:rid/approve'].forEach((p) => {
|
|
189
|
-
router.put(p, ...publicAuth, api.approveReservation);
|
|
196
|
+
router.put(p, jsonBody, ...publicAuth, api.approveReservation);
|
|
190
197
|
});
|
|
191
198
|
['/api/v3/plugins/calendar-onekite/reservations/:rid/refuse', '/api/plugins/calendar-onekite/reservations/:rid/refuse'].forEach((p) => {
|
|
192
|
-
router.put(p, ...publicAuth, api.refuseReservation);
|
|
199
|
+
router.put(p, jsonBody, ...publicAuth, api.refuseReservation);
|
|
193
200
|
});
|
|
194
201
|
// Cancellation by requester (or staff): owner can cancel even if not in validator group
|
|
195
202
|
['/api/v3/plugins/calendar-onekite/reservations/:rid/cancel', '/api/plugins/calendar-onekite/reservations/:rid/cancel'].forEach((p) => {
|
|
196
|
-
router.put(p, ...publicAuth, api.cancelReservation);
|
|
203
|
+
router.put(p, jsonBody, ...publicAuth, api.cancelReservation);
|
|
197
204
|
});
|
|
198
205
|
|
|
199
206
|
|
|
@@ -202,21 +209,21 @@ Plugin.init = async function (params) {
|
|
|
202
209
|
|
|
203
210
|
adminBases.forEach((base) => {
|
|
204
211
|
router.get(`${base}/settings`, ...adminMws, admin.getSettings);
|
|
205
|
-
router.put(`${base}/settings`, ...adminMws, admin.saveSettings);
|
|
212
|
+
router.put(`${base}/settings`, jsonBody, ...adminMws, admin.saveSettings);
|
|
206
213
|
|
|
207
214
|
router.get(`${base}/pending`, ...adminMws, admin.listPending);
|
|
208
|
-
router.put(`${base}/reservations/:rid/approve`, ...adminMws, admin.approveReservation);
|
|
209
|
-
router.put(`${base}/reservations/:rid/refuse`, ...adminMws, admin.refuseReservation);
|
|
215
|
+
router.put(`${base}/reservations/:rid/approve`, jsonBody, ...adminMws, admin.approveReservation);
|
|
216
|
+
router.put(`${base}/reservations/:rid/refuse`, jsonBody, ...adminMws, admin.refuseReservation);
|
|
210
217
|
|
|
211
|
-
router.post(`${base}/purge`, ...adminMws, admin.purgeByYear);
|
|
218
|
+
router.post(`${base}/purge`, jsonBody, ...adminMws, admin.purgeByYear);
|
|
212
219
|
router.get(`${base}/debug`, ...adminMws, admin.debugHelloAsso);
|
|
213
220
|
// Accounting / exports
|
|
214
221
|
router.get(`${base}/accounting`, ...adminMws, admin.getAccounting);
|
|
215
222
|
router.get(`${base}/accounting.csv`, ...adminMws, admin.exportAccountingCsv);
|
|
216
|
-
router.post(`${base}/accounting/purge`, ...adminMws, admin.purgeAccounting);
|
|
223
|
+
router.post(`${base}/accounting/purge`, jsonBody, ...adminMws, admin.purgeAccounting);
|
|
217
224
|
|
|
218
225
|
// Purge special events by year
|
|
219
|
-
router.post(`${base}/special-events/purge`, ...adminMws, admin.purgeSpecialEventsByYear);
|
|
226
|
+
router.post(`${base}/special-events/purge`, jsonBody, ...adminMws, admin.purgeSpecialEventsByYear);
|
|
220
227
|
});
|
|
221
228
|
|
|
222
229
|
// HelloAsso callback endpoint (hardened)
|
package/package.json
CHANGED
package/plugin.json
CHANGED
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
},
|
|
29
29
|
"templates": "./templates",
|
|
30
30
|
"modules": {
|
|
31
|
-
"../admin/plugins/calendar-onekite.js": "./public/admin.js",
|
|
32
31
|
"admin/plugins/calendar-onekite": "./public/admin.js"
|
|
33
32
|
},
|
|
34
33
|
"scripts": [
|
|
@@ -37,5 +36,5 @@
|
|
|
37
36
|
"acpScripts": [
|
|
38
37
|
"public/admin.js"
|
|
39
38
|
],
|
|
40
|
-
"version": "1.0.
|
|
41
|
-
}
|
|
39
|
+
"version": "1.0.54"
|
|
40
|
+
}
|