strapi-plugin-magic-mail 1.0.1

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.
Files changed (91) hide show
  1. package/COPYRIGHT_NOTICE.txt +13 -0
  2. package/LICENSE +22 -0
  3. package/README.md +1420 -0
  4. package/admin/jsconfig.json +10 -0
  5. package/admin/src/components/AddAccountModal.jsx +1943 -0
  6. package/admin/src/components/Initializer.jsx +14 -0
  7. package/admin/src/components/LicenseGuard.jsx +475 -0
  8. package/admin/src/components/PluginIcon.jsx +5 -0
  9. package/admin/src/hooks/useAuthRefresh.js +44 -0
  10. package/admin/src/hooks/useLicense.js +158 -0
  11. package/admin/src/index.js +86 -0
  12. package/admin/src/pages/Analytics.jsx +762 -0
  13. package/admin/src/pages/App.jsx +111 -0
  14. package/admin/src/pages/EmailDesigner/EditorPage.jsx +1405 -0
  15. package/admin/src/pages/EmailDesigner/TemplateList.jsx +1807 -0
  16. package/admin/src/pages/HomePage.jsx +1233 -0
  17. package/admin/src/pages/LicensePage.jsx +424 -0
  18. package/admin/src/pages/RoutingRules.jsx +1141 -0
  19. package/admin/src/pages/Settings.jsx +603 -0
  20. package/admin/src/pluginId.js +3 -0
  21. package/admin/src/translations/de.json +71 -0
  22. package/admin/src/translations/en.json +70 -0
  23. package/admin/src/translations/es.json +71 -0
  24. package/admin/src/translations/fr.json +71 -0
  25. package/admin/src/translations/pt.json +71 -0
  26. package/admin/src/utils/fetchWithRetry.js +123 -0
  27. package/admin/src/utils/getTranslation.js +5 -0
  28. package/dist/_chunks/App-B-Gp4Vbr.js +7568 -0
  29. package/dist/_chunks/App-BymMjoGM.mjs +7543 -0
  30. package/dist/_chunks/LicensePage-Bl02myMx.mjs +342 -0
  31. package/dist/_chunks/LicensePage-CJXwPnEe.js +344 -0
  32. package/dist/_chunks/Settings-C_TmKwcz.mjs +400 -0
  33. package/dist/_chunks/Settings-zuFQ3pnn.js +402 -0
  34. package/dist/_chunks/de-CN-G9j1S.js +64 -0
  35. package/dist/_chunks/de-DS04rP54.mjs +64 -0
  36. package/dist/_chunks/en-BDc7Jk8u.js +64 -0
  37. package/dist/_chunks/en-BEFQJXvR.mjs +64 -0
  38. package/dist/_chunks/es-BpV1MIdm.js +64 -0
  39. package/dist/_chunks/es-DQHwzPpP.mjs +64 -0
  40. package/dist/_chunks/fr-BG1WfEVm.mjs +64 -0
  41. package/dist/_chunks/fr-vpziIpRp.js +64 -0
  42. package/dist/_chunks/pt-CMoGrOib.mjs +64 -0
  43. package/dist/_chunks/pt-ODpAhDNa.js +64 -0
  44. package/dist/admin/index.js +89 -0
  45. package/dist/admin/index.mjs +90 -0
  46. package/dist/server/index.js +6214 -0
  47. package/dist/server/index.mjs +6208 -0
  48. package/package.json +113 -0
  49. package/server/jsconfig.json +10 -0
  50. package/server/src/bootstrap.js +153 -0
  51. package/server/src/config/features.js +260 -0
  52. package/server/src/config/index.js +6 -0
  53. package/server/src/content-types/email-account/schema.json +93 -0
  54. package/server/src/content-types/email-event/index.js +8 -0
  55. package/server/src/content-types/email-event/schema.json +57 -0
  56. package/server/src/content-types/email-link/index.js +8 -0
  57. package/server/src/content-types/email-link/schema.json +49 -0
  58. package/server/src/content-types/email-log/index.js +8 -0
  59. package/server/src/content-types/email-log/schema.json +106 -0
  60. package/server/src/content-types/email-template/schema.json +74 -0
  61. package/server/src/content-types/email-template-version/schema.json +60 -0
  62. package/server/src/content-types/index.js +33 -0
  63. package/server/src/content-types/routing-rule/schema.json +59 -0
  64. package/server/src/controllers/accounts.js +220 -0
  65. package/server/src/controllers/analytics.js +347 -0
  66. package/server/src/controllers/controller.js +26 -0
  67. package/server/src/controllers/email-designer.js +474 -0
  68. package/server/src/controllers/index.js +21 -0
  69. package/server/src/controllers/license.js +267 -0
  70. package/server/src/controllers/oauth.js +474 -0
  71. package/server/src/controllers/routing-rules.js +122 -0
  72. package/server/src/controllers/test.js +383 -0
  73. package/server/src/destroy.js +23 -0
  74. package/server/src/index.js +25 -0
  75. package/server/src/middlewares/index.js +3 -0
  76. package/server/src/policies/index.js +3 -0
  77. package/server/src/register.js +5 -0
  78. package/server/src/routes/admin.js +469 -0
  79. package/server/src/routes/content-api.js +37 -0
  80. package/server/src/routes/index.js +9 -0
  81. package/server/src/services/account-manager.js +277 -0
  82. package/server/src/services/analytics.js +496 -0
  83. package/server/src/services/email-designer.js +870 -0
  84. package/server/src/services/email-router.js +1420 -0
  85. package/server/src/services/index.js +17 -0
  86. package/server/src/services/license-guard.js +418 -0
  87. package/server/src/services/oauth.js +515 -0
  88. package/server/src/services/service.js +7 -0
  89. package/server/src/utils/encryption.js +81 -0
  90. package/strapi-admin.js +4 -0
  91. package/strapi-server.js +4 -0
@@ -0,0 +1,267 @@
1
+ /**
2
+ * License Controller for MagicMail Plugin
3
+ * Manages licenses directly from the Admin Panel
4
+ */
5
+
6
+ module.exports = ({ strapi }) => ({
7
+ /**
8
+ * Auto-create license with logged-in admin user data
9
+ */
10
+ async autoCreate(ctx) {
11
+ try {
12
+ // Get the logged-in admin user
13
+ const adminUser = ctx.state.user;
14
+
15
+ if (!adminUser) {
16
+ return ctx.unauthorized('No admin user logged in');
17
+ }
18
+
19
+ const licenseGuard = strapi.plugin('magic-mail').service('license-guard');
20
+
21
+ // Use admin user data for license creation
22
+ const license = await licenseGuard.createLicense({
23
+ email: adminUser.email,
24
+ firstName: adminUser.firstname || 'Admin',
25
+ lastName: adminUser.lastname || 'User',
26
+ });
27
+
28
+ if (!license) {
29
+ return ctx.badRequest('Failed to create license');
30
+ }
31
+
32
+ // Store the license key
33
+ await licenseGuard.storeLicenseKey(license.licenseKey);
34
+
35
+ // Start pinging
36
+ const pingInterval = licenseGuard.startPinging(license.licenseKey, 15);
37
+
38
+ // Update global license guard
39
+ strapi.licenseGuardMagicMail = {
40
+ licenseKey: license.licenseKey,
41
+ pingInterval,
42
+ data: license,
43
+ };
44
+
45
+ return ctx.send({
46
+ success: true,
47
+ message: 'License automatically created and activated',
48
+ data: license,
49
+ });
50
+ } catch (error) {
51
+ strapi.log.error('[magic-mail] Error auto-creating license:', error);
52
+ return ctx.badRequest('Error creating license');
53
+ }
54
+ },
55
+
56
+ /**
57
+ * Get current license status
58
+ */
59
+ async getStatus(ctx) {
60
+ try {
61
+ const licenseGuard = strapi.plugin('magic-mail').service('license-guard');
62
+ const pluginStore = strapi.store({
63
+ type: 'plugin',
64
+ name: 'magic-mail'
65
+ });
66
+ const licenseKey = await pluginStore.get({ key: 'licenseKey' });
67
+
68
+ if (!licenseKey) {
69
+ return ctx.send({
70
+ success: false,
71
+ demo: true,
72
+ valid: false,
73
+ message: 'No license found. Running in demo mode.',
74
+ });
75
+ }
76
+
77
+ const verification = await licenseGuard.verifyLicense(licenseKey);
78
+ const license = await licenseGuard.getLicenseByKey(licenseKey);
79
+
80
+ return ctx.send({
81
+ success: true,
82
+ valid: verification.valid,
83
+ demo: false,
84
+ data: {
85
+ licenseKey,
86
+ email: license?.email || null,
87
+ firstName: license?.firstName || null,
88
+ lastName: license?.lastName || null,
89
+ isActive: license?.isActive || false,
90
+ isExpired: license?.isExpired || false,
91
+ isOnline: license?.isOnline || false,
92
+ expiresAt: license?.expiresAt,
93
+ lastPingAt: license?.lastPingAt,
94
+ deviceName: license?.deviceName,
95
+ deviceId: license?.deviceId,
96
+ ipAddress: license?.ipAddress,
97
+ features: {
98
+ premium: license?.featurePremium || false,
99
+ advanced: license?.featureAdvanced || false,
100
+ enterprise: license?.featureEnterprise || false,
101
+ },
102
+ maxDevices: license?.maxDevices || 1,
103
+ currentDevices: license?.currentDevices || 0,
104
+ },
105
+ });
106
+ } catch (error) {
107
+ strapi.log.error('[magic-mail] Error getting license status:', error);
108
+ return ctx.badRequest('Error getting license status');
109
+ }
110
+ },
111
+
112
+ /**
113
+ * Store and validate an existing license key
114
+ */
115
+ async storeKey(ctx) {
116
+ try {
117
+ const { licenseKey, email } = ctx.request.body;
118
+
119
+ if (!licenseKey || !licenseKey.trim()) {
120
+ return ctx.badRequest('License key is required');
121
+ }
122
+
123
+ if (!email || !email.trim()) {
124
+ return ctx.badRequest('Email address is required');
125
+ }
126
+
127
+ const trimmedKey = licenseKey.trim();
128
+ const trimmedEmail = email.trim().toLowerCase();
129
+ const licenseGuard = strapi.plugin('magic-mail').service('license-guard');
130
+
131
+ // Verify the license key first
132
+ const verification = await licenseGuard.verifyLicense(trimmedKey);
133
+
134
+ if (!verification.valid) {
135
+ strapi.log.warn(`[magic-mail] ⚠️ Invalid license key attempted: ${trimmedKey.substring(0, 8)}...`);
136
+ return ctx.badRequest('Invalid or expired license key');
137
+ }
138
+
139
+ // Get license details to verify email
140
+ const license = await licenseGuard.getLicenseByKey(trimmedKey);
141
+
142
+ if (!license) {
143
+ return ctx.badRequest('License not found');
144
+ }
145
+
146
+ // Verify email matches
147
+ if (license.email.toLowerCase() !== trimmedEmail) {
148
+ strapi.log.warn(`[magic-mail] ⚠️ Email mismatch for license key`);
149
+ return ctx.badRequest('Email address does not match this license key');
150
+ }
151
+
152
+ // Store the license key
153
+ await licenseGuard.storeLicenseKey(trimmedKey);
154
+
155
+ // Start pinging
156
+ const pingInterval = licenseGuard.startPinging(trimmedKey, 15);
157
+
158
+ // Update global license guard
159
+ strapi.licenseGuardMagicMail = {
160
+ licenseKey: trimmedKey,
161
+ pingInterval,
162
+ data: verification.data,
163
+ };
164
+
165
+ strapi.log.info(`[magic-mail] ✅ License validated and stored`);
166
+
167
+ return ctx.send({
168
+ success: true,
169
+ message: 'License activated successfully',
170
+ data: verification.data,
171
+ });
172
+ } catch (error) {
173
+ strapi.log.error('[magic-mail] Error storing license key:', error);
174
+ return ctx.badRequest('Error storing license key');
175
+ }
176
+ },
177
+
178
+ /**
179
+ * Debug endpoint to check license data
180
+ */
181
+ async debugLicense(ctx) {
182
+ try {
183
+ const licenseGuard = strapi.plugin('magic-mail').service('license-guard');
184
+ const license = await licenseGuard.getCurrentLicense();
185
+
186
+ ctx.body = {
187
+ success: true,
188
+ rawLicense: license,
189
+ detectedFlags: {
190
+ featurePremium: license?.featurePremium,
191
+ featureAdvanced: license?.featureAdvanced,
192
+ featureEnterprise: license?.featureEnterprise,
193
+ },
194
+ detectedTier: license?.featureEnterprise ? 'enterprise' :
195
+ license?.featureAdvanced ? 'advanced' :
196
+ license?.featurePremium ? 'premium' : 'free',
197
+ };
198
+ } catch (error) {
199
+ strapi.log.error('[magic-mail] Error in debugLicense:', error);
200
+ ctx.throw(500, 'Error debugging license');
201
+ }
202
+ },
203
+
204
+ /**
205
+ * Get license limits and available features
206
+ */
207
+ async getLimits(ctx) {
208
+ try {
209
+ const licenseGuard = strapi.plugin('magic-mail').service('license-guard');
210
+ const features = require('../config/features');
211
+
212
+ const license = await licenseGuard.getCurrentLicense();
213
+ const maxAccounts = await licenseGuard.getMaxAccounts();
214
+ const maxRules = await licenseGuard.getMaxRoutingRules();
215
+ const maxTemplates = await licenseGuard.getMaxEmailTemplates();
216
+
217
+ // Get current counts
218
+ const currentAccounts = await strapi.entityService.count('plugin::magic-mail.email-account');
219
+ const currentRules = await strapi.entityService.count('plugin::magic-mail.routing-rule');
220
+ const currentTemplates = await strapi.entityService.count('plugin::magic-mail.email-template');
221
+
222
+ // Get tier info - check both formats
223
+ let tier = 'free';
224
+ if (license?.featureEnterprise === true || license?.features?.enterprise === true) tier = 'enterprise';
225
+ else if (license?.featureAdvanced === true || license?.features?.advanced === true) tier = 'advanced';
226
+ else if (license?.featurePremium === true || license?.features?.premium === true) tier = 'premium';
227
+
228
+ const tierConfig = features[tier] || features.free;
229
+
230
+ // Only log in development mode
231
+ if (process.env.NODE_ENV === 'development') {
232
+ strapi.log.debug('[magic-mail] License tier:', tier);
233
+ }
234
+
235
+ ctx.body = {
236
+ success: true,
237
+ tier,
238
+ limits: {
239
+ accounts: {
240
+ current: currentAccounts,
241
+ max: maxAccounts,
242
+ unlimited: maxAccounts === -1,
243
+ canCreate: maxAccounts === -1 || currentAccounts < maxAccounts,
244
+ },
245
+ routingRules: {
246
+ current: currentRules,
247
+ max: maxRules,
248
+ unlimited: maxRules === -1,
249
+ canCreate: maxRules === -1 || currentRules < maxRules,
250
+ },
251
+ emailTemplates: {
252
+ current: currentTemplates,
253
+ max: maxTemplates,
254
+ unlimited: maxTemplates === -1,
255
+ canCreate: maxTemplates === -1 || currentTemplates < maxTemplates,
256
+ },
257
+ },
258
+ allowedProviders: tierConfig.providers,
259
+ features: tierConfig.features,
260
+ };
261
+ } catch (error) {
262
+ strapi.log.error('[magic-mail] Error getting license limits:', error);
263
+ ctx.throw(500, 'Error getting license limits');
264
+ }
265
+ },
266
+ });
267
+