nodebb-plugin-calendar-onekite 11.2.0 → 11.2.2

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 CHANGED
@@ -19,12 +19,33 @@ function formatFR(tsOrIso) {
19
19
  }
20
20
 
21
21
  async function sendEmail(template, toEmail, subject, data) {
22
- if (!toEmail) return;
22
+ // Prefer sending by uid (NodeBB core expects uid in various places)
23
+ const uid = data && Number.isInteger(data.uid) ? data.uid : null;
24
+ if (!toEmail && !uid) return;
23
25
 
24
26
  const settings = await meta.settings.get('calendar-onekite').catch(() => ({}));
25
27
  const lang = (settings && settings.defaultLang) || (meta && meta.config && meta.config.defaultLang) || 'fr';
26
28
  const params = Object.assign({}, data || {}, subject ? { subject } : {});
27
29
 
30
+ // If we have a uid, use the native uid-based sender first.
31
+ try {
32
+ if (uid && typeof emailer.send === 'function') {
33
+ // NodeBB: send(template, uid, params)
34
+ if (emailer.send.length >= 3) {
35
+ await emailer.send(template, uid, params);
36
+ } else {
37
+ await emailer.send(template, uid, params);
38
+ }
39
+ return;
40
+ }
41
+ } catch (err) {
42
+ console.warn('[calendar-onekite] Failed to send email', {
43
+ template,
44
+ toEmail,
45
+ err: err && err.message ? err.message : String(err),
46
+ });
47
+ }
48
+
28
49
  try {
29
50
  if (typeof emailer.sendToEmail === 'function') {
30
51
  // NodeBB: sendToEmail(template, email, language, params)
@@ -36,10 +57,6 @@ async function sendEmail(template, toEmail, subject, data) {
36
57
  }
37
58
  return;
38
59
  }
39
- if (typeof emailer.send === 'function') {
40
- // Fallback: send(template, uid, params) - not usable without uid
41
- return;
42
- }
43
60
  } catch (err) {
44
61
  console.warn('[calendar-onekite] Failed to send email', {
45
62
  template,
@@ -184,6 +201,7 @@ admin.approveReservation = async function (req, res) {
184
201
  ? `https://www.openstreetmap.org/?mlat=${encodeURIComponent(String(latNum))}&mlon=${encodeURIComponent(String(lonNum))}#map=18/${encodeURIComponent(String(latNum))}/${encodeURIComponent(String(lonNum))}`
185
202
  : '';
186
203
  await sendEmail('calendar-onekite_approved', requester.email, 'Location matériel - Réservation validée', {
204
+ uid: parseInt(r.uid, 10),
187
205
  username: requester.username,
188
206
  itemName: (Array.isArray(r.itemNames) ? r.itemNames.join(', ') : (r.itemName || '')),
189
207
  itemNames: (Array.isArray(r.itemNames) ? r.itemNames : (r.itemName ? [r.itemName] : [])),
@@ -216,6 +234,7 @@ admin.refuseReservation = async function (req, res) {
216
234
  const requester = await user.getUserFields(r.uid, ['username', 'email']);
217
235
  if (requester && requester.email) {
218
236
  await sendEmail('calendar-onekite_refused', requester.email, 'Location matériel - Réservation refusée', {
237
+ uid: parseInt(r.uid, 10),
219
238
  username: requester.username,
220
239
  itemName: r.itemName,
221
240
  start: formatFR(r.start),
@@ -24,7 +24,8 @@ const SETTINGS_KEY = 'calendar-onekite';
24
24
  const PROCESSED_KEY = 'calendar-onekite:helloasso:processedPayments';
25
25
 
26
26
  async function sendEmail(template, toEmail, subject, data) {
27
- if (!toEmail) return;
27
+ const uidFromData = data && Number.isInteger(data.uid) ? data.uid : null;
28
+ if (!toEmail && !uidFromData) return;
28
29
  try {
29
30
  const emailer = require.main.require('./src/emailer');
30
31
  // NodeBB core signature is typically:
@@ -33,6 +34,23 @@ async function sendEmail(template, toEmail, subject, data) {
33
34
  const language = (meta && meta.config && (meta.config.defaultLang || meta.config.defaultLanguage)) || 'fr';
34
35
  const params = Object.assign({}, data || {}, subject ? { subject } : {});
35
36
 
37
+ // In NodeBB 4.x, various email flows expect a uid to be present.
38
+ // If we have it, always prefer the uid-based sender.
39
+ let uid = uidFromData;
40
+ if (!uid && toEmail && typeof user.getUidByEmail === 'function') {
41
+ try {
42
+ uid = await user.getUidByEmail(toEmail);
43
+ if (uid && typeof uid === 'string') uid = parseInt(uid, 10);
44
+ } catch (e) {
45
+ uid = null;
46
+ }
47
+ }
48
+ if (uid && typeof emailer.send === 'function') {
49
+ // NodeBB: send(template, uid, params)
50
+ await emailer.send(template, uid, params);
51
+ return;
52
+ }
53
+
36
54
  if (typeof emailer.sendToEmail === 'function') {
37
55
  // Prefer the canonical signature.
38
56
  // If a fork uses a shorter signature, we'll still try passing params as 3rd arg.
@@ -44,17 +62,8 @@ async function sendEmail(template, toEmail, subject, data) {
44
62
  return;
45
63
  }
46
64
 
47
- if (typeof emailer.send === 'function') {
48
- if (emailer.send.length >= 4) {
49
- await emailer.send(template, toEmail, language, params);
50
- return;
51
- }
52
- if (emailer.send.length === 3) {
53
- await emailer.send(template, toEmail, params);
54
- return;
55
- }
56
- await emailer.send(template, toEmail, language, params);
57
- }
65
+ // Do not call emailer.send with an email address (it expects uid). If we reach here,
66
+ // fall back to sendToEmail only.
58
67
  } catch (err) {
59
68
  // eslint-disable-next-line no-console
60
69
  console.warn('[calendar-onekite] Failed to send email (webhook)', { template, toEmail, err: String(err && err.message || err) });
@@ -345,6 +354,7 @@ async function handler(req, res, next) {
345
354
  const requester = await user.getUserFields(r.uid, ['username', 'email']);
346
355
  if (requester && requester.email) {
347
356
  await sendEmail('calendar-onekite_paid', requester.email, 'Location matériel - Paiement reçu', {
357
+ uid: parseInt(r.uid, 10),
348
358
  username: requester.username,
349
359
  itemName: (Array.isArray(r.itemNames) ? r.itemNames.join(', ') : (r.itemName || '')),
350
360
  itemNames: (Array.isArray(r.itemNames) ? r.itemNames : (r.itemName ? [r.itemName] : [])),
package/library.js CHANGED
@@ -24,15 +24,18 @@ Plugin.init = async function (params) {
24
24
 
25
25
  // Build middleware arrays safely and always spread them into Express route methods.
26
26
  // Express will throw if any callback is undefined, so we filter strictly.
27
- const publicExpose = mw(middleware && middleware.exposeUid);
28
- const publicAuth = mw(middleware && middleware.exposeUid, middleware && middleware.ensureLoggedIn);
27
+ // Auth middlewares differ slightly depending on NodeBB configuration.
28
+ // In v4, some installs rely on middleware.authenticate rather than exposeUid.
29
+ const baseExpose = mw(middleware && (middleware.authenticate || middleware.exposeUid));
30
+ const publicExpose = baseExpose;
31
+ const publicAuth = mw(middleware && (middleware.authenticate || middleware.exposeUid), middleware && middleware.ensureLoggedIn);
29
32
 
30
33
  // Robust admin guard: avoid middleware.admin.checkPrivileges() signature differences
31
34
  // across NodeBB versions. We treat membership in the 'administrators' group as admin.
32
35
  const Groups = require.main.require('./src/groups');
33
36
  async function adminOnly(req, res, next) {
34
37
  try {
35
- const uid = req.uid;
38
+ const uid = req.uid || (req.user && req.user.uid) || (req.session && req.session.uid);
36
39
  if (!uid) {
37
40
  return res.status(401).json({ status: { code: 'not-authorized', message: 'Not logged in' } });
38
41
  }
@@ -45,7 +48,11 @@ Plugin.init = async function (params) {
45
48
  return next(err);
46
49
  }
47
50
  }
48
- const adminMws = mw(middleware && middleware.exposeUid, middleware && middleware.ensureLoggedIn, adminOnly);
51
+ const adminMws = mw(
52
+ middleware && (middleware.authenticate || middleware.exposeUid),
53
+ middleware && middleware.ensureLoggedIn,
54
+ adminOnly
55
+ );
49
56
 
50
57
  // Page routes (HTML)
51
58
  // IMPORTANT: pass an ARRAY for middlewares (even if empty), otherwise
@@ -63,7 +70,6 @@ Plugin.init = async function (params) {
63
70
  router.put('/api/v3/plugins/calendar-onekite/reservations/:rid/refuse', ...publicExpose, api.refuseReservation);
64
71
  router.put('/api/v3/plugins/calendar-onekite/reservations/:rid/cancel', ...publicExpose, api.cancelReservation);
65
72
 
66
- router.get('/api/v3/plugins/calendar-onekite/special-events', ...publicExpose, api.getSpecialEvents);
67
73
  router.post('/api/v3/plugins/calendar-onekite/special-events', ...publicExpose, api.createSpecialEvent);
68
74
  router.delete('/api/v3/plugins/calendar-onekite/special-events/:eid', ...publicExpose, api.deleteSpecialEvent);
69
75
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-calendar-onekite",
3
- "version": "11.2.0",
3
+ "version": "11.2.2",
4
4
  "description": "FullCalendar-based equipment reservation workflow with admin approval & HelloAsso payment for NodeBB",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
package/public/client.js CHANGED
@@ -849,7 +849,7 @@ function toDatetimeLocalValue(date) {
849
849
  showAlert('error', 'Impossible : au moins un matériel est déjà réservé ou en attente sur cette période.');
850
850
  } else {
851
851
  const msg = payload && (payload.message || payload.error || payload.msg) ? String(payload.message || payload.error || payload.msg) : '';
852
- showAlert('error', msg || ((e && (e.status === 401 || e.status === 403)) ? 'Erreur vous devez être adhérent Onekite' : 'Erreur lors de la création de la demande.'));
852
+ showAlert('error', msg || ((e && (e.status === 401 || e.status === 403)) ? 'Vous devez être adhérent Onekite' : 'Erreur lors de la création de la demande.'));
853
853
  }
854
854
  calendar.unselect();
855
855
  isDialogOpen = false;