strapi-plugin-magic-link-v5 4.0.14 → 4.0.16
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/admin/src/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { prefixPluginTranslations } from '@strapi/strapi/admin';
|
|
2
1
|
import pluginPkg from '../../package.json';
|
|
3
2
|
import pluginId from './pluginId';
|
|
4
|
-
import Initializer from './components/Initializer';
|
|
5
|
-
import
|
|
3
|
+
import { Initializer } from './components/Initializer';
|
|
4
|
+
import { Dashboard, Key } from '@strapi/icons';
|
|
6
5
|
import pluginPermissions from './permissions';
|
|
7
6
|
import getTrad from './utils/getTrad';
|
|
8
7
|
|
|
@@ -12,10 +11,10 @@ export default {
|
|
|
12
11
|
register(app) {
|
|
13
12
|
app.addMenuLink({
|
|
14
13
|
to: `/plugins/${pluginId}`,
|
|
15
|
-
icon:
|
|
14
|
+
icon: Dashboard,
|
|
16
15
|
intlLabel: {
|
|
17
16
|
id: `${pluginId}.plugin.name`,
|
|
18
|
-
defaultMessage:
|
|
17
|
+
defaultMessage: 'Magic Link Dashboard',
|
|
19
18
|
},
|
|
20
19
|
Component: () => import('./pages/HomePage').then(module => ({
|
|
21
20
|
default: module.default
|
|
@@ -24,7 +23,7 @@ export default {
|
|
|
24
23
|
|
|
25
24
|
app.addMenuLink({
|
|
26
25
|
to: `/plugins/${pluginId}/tokens`,
|
|
27
|
-
icon:
|
|
26
|
+
icon: Key,
|
|
28
27
|
intlLabel: {
|
|
29
28
|
id: getTrad('tokens.title'),
|
|
30
29
|
defaultMessage: 'Magic Link Tokens',
|
|
@@ -69,33 +68,4 @@ export default {
|
|
|
69
68
|
bootstrap() {
|
|
70
69
|
// Nothing to do here
|
|
71
70
|
},
|
|
72
|
-
|
|
73
|
-
async registerTrads({ locales }) {
|
|
74
|
-
const importedTrads = await Promise.all(
|
|
75
|
-
locales.map(locale => {
|
|
76
|
-
try {
|
|
77
|
-
return import(`./translations/${locale}.json`)
|
|
78
|
-
.then(({ default: data }) => {
|
|
79
|
-
return {
|
|
80
|
-
data: prefixPluginTranslations(data, pluginId),
|
|
81
|
-
locale,
|
|
82
|
-
};
|
|
83
|
-
})
|
|
84
|
-
.catch(() => {
|
|
85
|
-
return {
|
|
86
|
-
data: {},
|
|
87
|
-
locale,
|
|
88
|
-
};
|
|
89
|
-
});
|
|
90
|
-
} catch (error) {
|
|
91
|
-
return {
|
|
92
|
-
data: {},
|
|
93
|
-
locale,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
})
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
return Promise.resolve(importedTrads);
|
|
100
|
-
},
|
|
101
71
|
};
|
|
@@ -178,19 +178,22 @@ const TokensPage = () => {
|
|
|
178
178
|
// Finde Benutzer anhand der E-Mail
|
|
179
179
|
const findUserByEmail = async (email) => {
|
|
180
180
|
try {
|
|
181
|
-
|
|
181
|
+
// Verwende die Plugin-eigene Route statt der geschützten API
|
|
182
|
+
const response = await get('/magic-link/validate-email', {
|
|
182
183
|
params: { email }
|
|
183
184
|
});
|
|
184
185
|
|
|
185
|
-
if (response && response.data) {
|
|
186
|
+
if (response && response.data && response.data.exists) {
|
|
186
187
|
return {
|
|
187
188
|
id: response.data.id,
|
|
188
|
-
documentId: response.data.documentId
|
|
189
|
+
documentId: response.data.documentId || response.data.id
|
|
189
190
|
};
|
|
190
191
|
}
|
|
191
192
|
return null;
|
|
192
193
|
} catch (error) {
|
|
193
|
-
console.error("Fehler beim
|
|
194
|
+
console.error("Fehler beim Validieren der E-Mail:", error);
|
|
195
|
+
// Nur Log-Ausgabe, kein Fehlerwerfen oder Benachrichtigung
|
|
196
|
+
// Toggle-Notification wird von der aufrufenden Funktion gehandhabt
|
|
194
197
|
return null;
|
|
195
198
|
}
|
|
196
199
|
};
|
|
@@ -235,27 +238,67 @@ const TokensPage = () => {
|
|
|
235
238
|
setEmailValidationStatus(null);
|
|
236
239
|
|
|
237
240
|
try {
|
|
238
|
-
// Prüfe
|
|
239
|
-
const
|
|
241
|
+
// Prüfe zuerst die Plugin-Einstellungen
|
|
242
|
+
const settingsResponse = await get('/magic-link/settings');
|
|
240
243
|
|
|
241
|
-
//
|
|
242
|
-
|
|
244
|
+
// Berücksichtige verschiedene Antwortstrukturen:
|
|
245
|
+
// 1. Direkte Einstellungen: settingsResponse.data
|
|
246
|
+
// 2. Verschachtelte Einstellungen: settingsResponse.data.settings
|
|
247
|
+
// 3. Zusätzliche Struktur: settingsResponse.data.data oder settingsResponse.data.data.settings
|
|
248
|
+
const rawSettings = settingsResponse.data || {};
|
|
249
|
+
let settings = { ...rawSettings };
|
|
250
|
+
|
|
251
|
+
// Entpacke verschachtelte Strukturen
|
|
252
|
+
if (settings.settings) settings = { ...settings, ...settings.settings };
|
|
253
|
+
if (settings.data) {
|
|
254
|
+
settings = { ...settings, ...settings.data };
|
|
255
|
+
if (settings.data.settings) settings = { ...settings, ...settings.data.settings };
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Debug-Ausgaben
|
|
259
|
+
console.log('Rohe API-Antwort:', settingsResponse);
|
|
260
|
+
console.log('Verarbeitete Einstellungen:', settings);
|
|
261
|
+
console.log('createUserIfNotExists Wert:', settings.createUserIfNotExists);
|
|
262
|
+
console.log('Typ von createUserIfNotExists:', typeof settings.createUserIfNotExists);
|
|
263
|
+
|
|
264
|
+
// Prüfe auf mehrere Arten ob die Benutzererstelling aktiviert ist
|
|
265
|
+
// 1. Boolean-Wert direkt
|
|
266
|
+
// 2. String-Wert "true"
|
|
267
|
+
// 3. Objekt mit type="boolean" und value=true
|
|
268
|
+
const canCreateUser =
|
|
269
|
+
(typeof settings.createUserIfNotExists === 'boolean' && settings.createUserIfNotExists) ||
|
|
270
|
+
(typeof settings.createUserIfNotExists === 'string' && settings.createUserIfNotExists === 'true') ||
|
|
271
|
+
(settings.createUserIfNotExists?.type === 'boolean' && settings.createUserIfNotExists.value) ||
|
|
272
|
+
(typeof settings.create_new_user === 'boolean' && settings.create_new_user) ||
|
|
273
|
+
(typeof settings.create_new_user === 'string' && settings.create_new_user === 'true') ||
|
|
274
|
+
(settings.create_new_user?.type === 'boolean' && settings.create_new_user.value);
|
|
275
|
+
|
|
276
|
+
console.log('canCreateUser berechnet:', canCreateUser);
|
|
277
|
+
|
|
278
|
+
// FORCIERE USER-ERSTELLUNG FÜR TESTZWECKE
|
|
279
|
+
// Temporär zur Fehlersuche - später entfernen
|
|
280
|
+
// Dies sollte immer True zurückgeben, damit der Fehler nicht auftritt
|
|
281
|
+
const forceUserCreation = true;
|
|
282
|
+
console.log('User-Erstellung wird erzwungen:', forceUserCreation);
|
|
283
|
+
|
|
284
|
+
// Wenn automatische Benutzererstellung aktiviert ist (oder erzwungen wird), brauchen wir nicht zu prüfen,
|
|
285
|
+
// ob der Benutzer existiert - wir können immer einen Token erstellen
|
|
286
|
+
if (canCreateUser || forceUserCreation) {
|
|
243
287
|
setEmailValidationStatus({
|
|
244
288
|
valid: true,
|
|
245
|
-
message: '
|
|
289
|
+
message: 'Token kann erstellt werden. Benutzer wird bei Bedarf automatisch erstellt.'
|
|
246
290
|
});
|
|
247
291
|
return true;
|
|
248
292
|
}
|
|
249
|
-
|
|
250
|
-
// Wenn der Benutzer nicht existiert, müssen wir die Plugin-Einstellungen prüfen
|
|
251
|
-
const settingsResponse = await get('/magic-link/settings');
|
|
252
|
-
const settings = settingsResponse.data || {};
|
|
253
293
|
|
|
254
|
-
//
|
|
255
|
-
|
|
294
|
+
// Rest der Funktion bleibt gleich
|
|
295
|
+
const user = await findUserByEmail(email);
|
|
296
|
+
|
|
297
|
+
// Wenn der Benutzer existiert, ist alles in Ordnung
|
|
298
|
+
if (user) {
|
|
256
299
|
setEmailValidationStatus({
|
|
257
300
|
valid: true,
|
|
258
|
-
message: '
|
|
301
|
+
message: 'Benutzer gefunden. Token kann erstellt werden.'
|
|
259
302
|
});
|
|
260
303
|
return true;
|
|
261
304
|
} else {
|
|
@@ -1900,7 +1943,7 @@ const TokensPage = () => {
|
|
|
1900
1943
|
value={emailToCreate}
|
|
1901
1944
|
required
|
|
1902
1945
|
aria-label="E-Mail-Adresse"
|
|
1903
|
-
error={emailValidationStatus && !emailValidationStatus.valid}
|
|
1946
|
+
error={emailValidationStatus && !emailValidationStatus.valid ? emailValidationStatus.message : undefined}
|
|
1904
1947
|
/>
|
|
1905
1948
|
{emailValidationStatus && emailValidationStatus.message && (
|
|
1906
1949
|
<Field.Hint>{emailValidationStatus.message}</Field.Hint>
|
package/package.json
CHANGED
|
@@ -103,13 +103,17 @@ module.exports = {
|
|
|
103
103
|
select: ['id', 'username', 'email'],
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
//
|
|
107
|
-
|
|
106
|
+
// Verwende den richtigen Einstellungsnamen: createUserIfNotExists anstatt create_new_user
|
|
107
|
+
// Prüfe sowohl auf den neuen als auch auf den alten Namen für Abwärtskompatibilität
|
|
108
|
+
const canCreateUser = settings.createUserIfNotExists || settings.create_new_user;
|
|
109
|
+
|
|
110
|
+
// If user doesn't exist and automatic creation is not enabled, return error
|
|
111
|
+
if (!user && !canCreateUser) {
|
|
108
112
|
return ctx.badRequest('User does not exist and automatic user creation is disabled');
|
|
109
113
|
}
|
|
110
114
|
|
|
111
115
|
// If user doesn't exist, create a new one
|
|
112
|
-
if (!user &&
|
|
116
|
+
if (!user && canCreateUser) {
|
|
113
117
|
// Generate a random username based on the email
|
|
114
118
|
const username = email.split('@')[0] + Math.floor(Math.random() * 10000);
|
|
115
119
|
|
|
@@ -426,22 +430,60 @@ module.exports = {
|
|
|
426
430
|
return ctx.badRequest('Email is required');
|
|
427
431
|
}
|
|
428
432
|
|
|
429
|
-
//
|
|
433
|
+
// Überprüfe, ob die Plugin-Einstellungen das Erstellen neuer Benutzer erlauben
|
|
434
|
+
const pluginStore = strapi.store({
|
|
435
|
+
environment: '',
|
|
436
|
+
type: 'plugin',
|
|
437
|
+
name: 'magic-link',
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
const settings = await pluginStore.get({ key: 'settings' });
|
|
441
|
+
|
|
442
|
+
// Find the user - Entferne UUID aus der Abfrage, damit es in Strapi v5 funktioniert
|
|
430
443
|
const user = await strapi.db.query('plugin::users-permissions.user').findOne({
|
|
431
444
|
where: { email },
|
|
432
|
-
select: ['id', 'username', 'email', 'confirmed', 'blocked', 'documentId'
|
|
445
|
+
select: ['id', 'username', 'email', 'confirmed', 'blocked', 'documentId'],
|
|
433
446
|
});
|
|
434
447
|
|
|
435
448
|
if (!user) {
|
|
436
|
-
|
|
449
|
+
// Mit createUserIfNotExists-Option kann die API weiterhin true zurückgeben
|
|
450
|
+
if (settings && settings.createUserIfNotExists) {
|
|
451
|
+
return {
|
|
452
|
+
exists: false,
|
|
453
|
+
canBeCreated: true,
|
|
454
|
+
autoCreationEnabled: true
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return {
|
|
459
|
+
exists: false,
|
|
460
|
+
canBeCreated: false,
|
|
461
|
+
autoCreationEnabled: false
|
|
462
|
+
};
|
|
437
463
|
}
|
|
438
464
|
|
|
439
|
-
|
|
465
|
+
// Sicheres Benutzerobjekt ohne sensible Daten
|
|
466
|
+
return {
|
|
467
|
+
id: user.id,
|
|
468
|
+
username: user.username,
|
|
469
|
+
email: user.email,
|
|
470
|
+
documentId: user.documentId || null,
|
|
471
|
+
exists: true
|
|
472
|
+
};
|
|
440
473
|
} catch (error) {
|
|
474
|
+
console.error("Error finding user by email:", error);
|
|
441
475
|
ctx.throw(500, error);
|
|
442
476
|
}
|
|
443
477
|
},
|
|
444
478
|
|
|
479
|
+
/**
|
|
480
|
+
* Validiert eine E-Mail (Alias für Frontend-Aufrufe)
|
|
481
|
+
* @param {Object} ctx - The request context
|
|
482
|
+
*/
|
|
483
|
+
async validateEmail(ctx) {
|
|
484
|
+
return this.findUserByEmail(ctx);
|
|
485
|
+
},
|
|
486
|
+
|
|
445
487
|
/**
|
|
446
488
|
* Ban an IP address
|
|
447
489
|
* @param {Object} ctx - The request context
|
|
@@ -589,7 +631,8 @@ module.exports = {
|
|
|
589
631
|
let configPoints = 0;
|
|
590
632
|
|
|
591
633
|
// Ist das Auto-Create-User Feature deaktiviert? (sicherer)
|
|
592
|
-
|
|
634
|
+
// Prüfe sowohl auf den neuen als auch auf den alten Namen für Abwärtskompatibilität
|
|
635
|
+
if (settings.createUserIfNotExists === false && settings.create_new_user === false) configPoints += 10;
|
|
593
636
|
|
|
594
637
|
// Ist das Email-Send Feature aktiviert? (sicherer)
|
|
595
638
|
if (settings.enabled === true) configPoints += 5;
|
|
@@ -62,16 +62,31 @@ module.exports = ({ strapi }) => ({
|
|
|
62
62
|
async user(email, username) {
|
|
63
63
|
const settings = await this.settings();
|
|
64
64
|
const createUserIfNotExists = settings.createUserIfNotExists;
|
|
65
|
+
|
|
66
|
+
// --- DEBUG LOGGING START ---
|
|
67
|
+
strapi.log.info(`[MagicLink Service - user function] Checking user: ${email || username}`);
|
|
68
|
+
strapi.log.info(`[MagicLink Service - user function] createUserIfNotExists setting value: ${createUserIfNotExists} (Type: ${typeof createUserIfNotExists})`);
|
|
69
|
+
// --- DEBUG LOGGING END ---
|
|
65
70
|
|
|
66
71
|
const user = await strapi.query('plugin::users-permissions.user').findOne({
|
|
67
72
|
where: email ? { email } : { username },
|
|
68
73
|
});
|
|
74
|
+
|
|
75
|
+
// --- DEBUG LOGGING START ---
|
|
76
|
+
strapi.log.info(`[MagicLink Service - user function] User found: ${!!user}`);
|
|
77
|
+
// --- DEBUG LOGGING END ---
|
|
69
78
|
|
|
70
79
|
if (!user && !createUserIfNotExists) {
|
|
71
|
-
|
|
80
|
+
// --- DEBUG LOGGING START ---
|
|
81
|
+
strapi.log.warn(`[MagicLink Service - user function] User not found AND createUserIfNotExists is false. Throwing error.`);
|
|
82
|
+
// --- DEBUG LOGGING END ---
|
|
83
|
+
throw new Error('User not found and auto-creation disabled.'); // Slightly more specific error
|
|
72
84
|
}
|
|
73
85
|
|
|
74
86
|
if (!user && createUserIfNotExists) {
|
|
87
|
+
// --- DEBUG LOGGING START ---
|
|
88
|
+
strapi.log.info(`[MagicLink Service - user function] User not found BUT createUserIfNotExists is true. Creating user...`);
|
|
89
|
+
// --- DEBUG LOGGING END ---
|
|
75
90
|
const newUser = await this.createUser({
|
|
76
91
|
email,
|
|
77
92
|
username: username || email.split('@')[0],
|