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.
- package/COPYRIGHT_NOTICE.txt +13 -0
- package/LICENSE +22 -0
- package/README.md +1420 -0
- package/admin/jsconfig.json +10 -0
- package/admin/src/components/AddAccountModal.jsx +1943 -0
- package/admin/src/components/Initializer.jsx +14 -0
- package/admin/src/components/LicenseGuard.jsx +475 -0
- package/admin/src/components/PluginIcon.jsx +5 -0
- package/admin/src/hooks/useAuthRefresh.js +44 -0
- package/admin/src/hooks/useLicense.js +158 -0
- package/admin/src/index.js +86 -0
- package/admin/src/pages/Analytics.jsx +762 -0
- package/admin/src/pages/App.jsx +111 -0
- package/admin/src/pages/EmailDesigner/EditorPage.jsx +1405 -0
- package/admin/src/pages/EmailDesigner/TemplateList.jsx +1807 -0
- package/admin/src/pages/HomePage.jsx +1233 -0
- package/admin/src/pages/LicensePage.jsx +424 -0
- package/admin/src/pages/RoutingRules.jsx +1141 -0
- package/admin/src/pages/Settings.jsx +603 -0
- package/admin/src/pluginId.js +3 -0
- package/admin/src/translations/de.json +71 -0
- package/admin/src/translations/en.json +70 -0
- package/admin/src/translations/es.json +71 -0
- package/admin/src/translations/fr.json +71 -0
- package/admin/src/translations/pt.json +71 -0
- package/admin/src/utils/fetchWithRetry.js +123 -0
- package/admin/src/utils/getTranslation.js +5 -0
- package/dist/_chunks/App-B-Gp4Vbr.js +7568 -0
- package/dist/_chunks/App-BymMjoGM.mjs +7543 -0
- package/dist/_chunks/LicensePage-Bl02myMx.mjs +342 -0
- package/dist/_chunks/LicensePage-CJXwPnEe.js +344 -0
- package/dist/_chunks/Settings-C_TmKwcz.mjs +400 -0
- package/dist/_chunks/Settings-zuFQ3pnn.js +402 -0
- package/dist/_chunks/de-CN-G9j1S.js +64 -0
- package/dist/_chunks/de-DS04rP54.mjs +64 -0
- package/dist/_chunks/en-BDc7Jk8u.js +64 -0
- package/dist/_chunks/en-BEFQJXvR.mjs +64 -0
- package/dist/_chunks/es-BpV1MIdm.js +64 -0
- package/dist/_chunks/es-DQHwzPpP.mjs +64 -0
- package/dist/_chunks/fr-BG1WfEVm.mjs +64 -0
- package/dist/_chunks/fr-vpziIpRp.js +64 -0
- package/dist/_chunks/pt-CMoGrOib.mjs +64 -0
- package/dist/_chunks/pt-ODpAhDNa.js +64 -0
- package/dist/admin/index.js +89 -0
- package/dist/admin/index.mjs +90 -0
- package/dist/server/index.js +6214 -0
- package/dist/server/index.mjs +6208 -0
- package/package.json +113 -0
- package/server/jsconfig.json +10 -0
- package/server/src/bootstrap.js +153 -0
- package/server/src/config/features.js +260 -0
- package/server/src/config/index.js +6 -0
- package/server/src/content-types/email-account/schema.json +93 -0
- package/server/src/content-types/email-event/index.js +8 -0
- package/server/src/content-types/email-event/schema.json +57 -0
- package/server/src/content-types/email-link/index.js +8 -0
- package/server/src/content-types/email-link/schema.json +49 -0
- package/server/src/content-types/email-log/index.js +8 -0
- package/server/src/content-types/email-log/schema.json +106 -0
- package/server/src/content-types/email-template/schema.json +74 -0
- package/server/src/content-types/email-template-version/schema.json +60 -0
- package/server/src/content-types/index.js +33 -0
- package/server/src/content-types/routing-rule/schema.json +59 -0
- package/server/src/controllers/accounts.js +220 -0
- package/server/src/controllers/analytics.js +347 -0
- package/server/src/controllers/controller.js +26 -0
- package/server/src/controllers/email-designer.js +474 -0
- package/server/src/controllers/index.js +21 -0
- package/server/src/controllers/license.js +267 -0
- package/server/src/controllers/oauth.js +474 -0
- package/server/src/controllers/routing-rules.js +122 -0
- package/server/src/controllers/test.js +383 -0
- package/server/src/destroy.js +23 -0
- package/server/src/index.js +25 -0
- package/server/src/middlewares/index.js +3 -0
- package/server/src/policies/index.js +3 -0
- package/server/src/register.js +5 -0
- package/server/src/routes/admin.js +469 -0
- package/server/src/routes/content-api.js +37 -0
- package/server/src/routes/index.js +9 -0
- package/server/src/services/account-manager.js +277 -0
- package/server/src/services/analytics.js +496 -0
- package/server/src/services/email-designer.js +870 -0
- package/server/src/services/email-router.js +1420 -0
- package/server/src/services/index.js +17 -0
- package/server/src/services/license-guard.js +418 -0
- package/server/src/services/oauth.js +515 -0
- package/server/src/services/service.js +7 -0
- package/server/src/utils/encryption.js +81 -0
- package/strapi-admin.js +4 -0
- package/strapi-server.js +4 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const emailRouter = require('./email-router');
|
|
4
|
+
const accountManager = require('./account-manager');
|
|
5
|
+
const oauth = require('./oauth');
|
|
6
|
+
const licenseGuard = require('./license-guard');
|
|
7
|
+
const emailDesigner = require('./email-designer');
|
|
8
|
+
const analytics = require('./analytics');
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
'email-router': emailRouter,
|
|
12
|
+
'account-manager': accountManager,
|
|
13
|
+
oauth,
|
|
14
|
+
'license-guard': licenseGuard,
|
|
15
|
+
'email-designer': emailDesigner,
|
|
16
|
+
analytics,
|
|
17
|
+
};
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* License Guard Service for MagicMail
|
|
3
|
+
* Handles license creation, verification, and ping tracking
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const crypto = require('crypto');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const pluginPkg = require('../../../package.json');
|
|
9
|
+
|
|
10
|
+
// FIXED LICENSE SERVER URL
|
|
11
|
+
const LICENSE_SERVER_URL = 'https://magicapi.fitlex.me';
|
|
12
|
+
|
|
13
|
+
module.exports = ({ strapi }) => ({
|
|
14
|
+
/**
|
|
15
|
+
* Get license server URL
|
|
16
|
+
*/
|
|
17
|
+
getLicenseServerUrl() {
|
|
18
|
+
return LICENSE_SERVER_URL;
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Generate device ID
|
|
23
|
+
*/
|
|
24
|
+
generateDeviceId() {
|
|
25
|
+
try {
|
|
26
|
+
const networkInterfaces = os.networkInterfaces();
|
|
27
|
+
const macAddresses = [];
|
|
28
|
+
|
|
29
|
+
Object.values(networkInterfaces).forEach(interfaces => {
|
|
30
|
+
interfaces?.forEach(iface => {
|
|
31
|
+
if (iface.mac && iface.mac !== '00:00:00:00:00:00') {
|
|
32
|
+
macAddresses.push(iface.mac);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const identifier = `${macAddresses.join('-')}-${os.hostname()}`;
|
|
38
|
+
return crypto.createHash('sha256').update(identifier).digest('hex').substring(0, 32);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
return crypto.randomBytes(16).toString('hex');
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
getDeviceName() {
|
|
45
|
+
try {
|
|
46
|
+
return os.hostname() || 'Unknown Device';
|
|
47
|
+
} catch (error) {
|
|
48
|
+
return 'Unknown Device';
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
getIpAddress() {
|
|
53
|
+
try {
|
|
54
|
+
const networkInterfaces = os.networkInterfaces();
|
|
55
|
+
for (const name of Object.keys(networkInterfaces)) {
|
|
56
|
+
const interfaces = networkInterfaces[name];
|
|
57
|
+
if (interfaces) {
|
|
58
|
+
for (const iface of interfaces) {
|
|
59
|
+
if (iface.family === 'IPv4' && !iface.internal) {
|
|
60
|
+
return iface.address;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return '127.0.0.1';
|
|
66
|
+
} catch (error) {
|
|
67
|
+
return '127.0.0.1';
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
getUserAgent() {
|
|
72
|
+
const pluginVersion = pluginPkg.version || '1.0.0';
|
|
73
|
+
const strapiVersion = strapi.config.get('info.strapi') || '5.0.0';
|
|
74
|
+
return `MagicMail/${pluginVersion} Strapi/${strapiVersion} Node/${process.version} ${os.platform()}/${os.release()}`;
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
async createLicense({ email, firstName, lastName }) {
|
|
78
|
+
try {
|
|
79
|
+
const deviceId = this.generateDeviceId();
|
|
80
|
+
const deviceName = this.getDeviceName();
|
|
81
|
+
const ipAddress = this.getIpAddress();
|
|
82
|
+
const userAgent = this.getUserAgent();
|
|
83
|
+
|
|
84
|
+
const licenseServerUrl = this.getLicenseServerUrl();
|
|
85
|
+
const response = await fetch(`${licenseServerUrl}/api/licenses/create`, {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
headers: { 'Content-Type': 'application/json' },
|
|
88
|
+
body: JSON.stringify({
|
|
89
|
+
email,
|
|
90
|
+
firstName,
|
|
91
|
+
lastName,
|
|
92
|
+
deviceName,
|
|
93
|
+
deviceId,
|
|
94
|
+
ipAddress,
|
|
95
|
+
userAgent,
|
|
96
|
+
pluginName: 'magic-mail',
|
|
97
|
+
productName: 'MagicMail - Email Business Suite',
|
|
98
|
+
}),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const data = await response.json();
|
|
102
|
+
|
|
103
|
+
if (data.success) {
|
|
104
|
+
strapi.log.info('[magic-mail] ✅ License created:', data.data.licenseKey);
|
|
105
|
+
return data.data;
|
|
106
|
+
} else {
|
|
107
|
+
strapi.log.error('[magic-mail] ❌ License creation failed:', data);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
} catch (error) {
|
|
111
|
+
strapi.log.error('[magic-mail] ❌ Error creating license:', error);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
async verifyLicense(licenseKey, allowGracePeriod = false) {
|
|
117
|
+
try {
|
|
118
|
+
const controller = new AbortController();
|
|
119
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
120
|
+
|
|
121
|
+
const licenseServerUrl = this.getLicenseServerUrl();
|
|
122
|
+
const response = await fetch(`${licenseServerUrl}/api/licenses/verify`, {
|
|
123
|
+
method: 'POST',
|
|
124
|
+
headers: { 'Content-Type': 'application/json' },
|
|
125
|
+
body: JSON.stringify({
|
|
126
|
+
licenseKey,
|
|
127
|
+
pluginName: 'magic-mail',
|
|
128
|
+
productName: 'MagicMail - Email Business Suite',
|
|
129
|
+
}),
|
|
130
|
+
signal: controller.signal,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
clearTimeout(timeoutId);
|
|
134
|
+
const data = await response.json();
|
|
135
|
+
|
|
136
|
+
if (data.success && data.data) {
|
|
137
|
+
return { valid: true, data: data.data, gracePeriod: false };
|
|
138
|
+
} else {
|
|
139
|
+
return { valid: false, data: null };
|
|
140
|
+
}
|
|
141
|
+
} catch (error) {
|
|
142
|
+
if (allowGracePeriod) {
|
|
143
|
+
strapi.log.warn('[magic-mail] ⚠️ License verification timeout - grace period active');
|
|
144
|
+
return { valid: true, data: null, gracePeriod: true };
|
|
145
|
+
}
|
|
146
|
+
strapi.log.error('[magic-mail] ❌ License verification error:', error.message);
|
|
147
|
+
return { valid: false, data: null };
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
async getLicenseByKey(licenseKey) {
|
|
152
|
+
try {
|
|
153
|
+
const licenseServerUrl = this.getLicenseServerUrl();
|
|
154
|
+
const url = `${licenseServerUrl}/api/licenses/key/${licenseKey}`;
|
|
155
|
+
|
|
156
|
+
const response = await fetch(url, {
|
|
157
|
+
method: 'GET',
|
|
158
|
+
headers: { 'Content-Type': 'application/json' },
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const data = await response.json();
|
|
162
|
+
|
|
163
|
+
if (data.success && data.data) {
|
|
164
|
+
return data.data;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return null;
|
|
168
|
+
} catch (error) {
|
|
169
|
+
strapi.log.error('[magic-mail] Error fetching license by key:', error);
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
async pingLicense(licenseKey) {
|
|
175
|
+
try {
|
|
176
|
+
const deviceId = this.generateDeviceId();
|
|
177
|
+
const deviceName = this.getDeviceName();
|
|
178
|
+
const ipAddress = this.getIpAddress();
|
|
179
|
+
const userAgent = this.getUserAgent();
|
|
180
|
+
|
|
181
|
+
const licenseServerUrl = this.getLicenseServerUrl();
|
|
182
|
+
const response = await fetch(`${licenseServerUrl}/api/licenses/ping`, {
|
|
183
|
+
method: 'POST',
|
|
184
|
+
headers: { 'Content-Type': 'application/json' },
|
|
185
|
+
body: JSON.stringify({
|
|
186
|
+
licenseKey,
|
|
187
|
+
deviceId,
|
|
188
|
+
deviceName,
|
|
189
|
+
ipAddress,
|
|
190
|
+
userAgent,
|
|
191
|
+
pluginName: 'magic-mail',
|
|
192
|
+
}),
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const data = await response.json();
|
|
196
|
+
return data.success ? data.data : null;
|
|
197
|
+
} catch (error) {
|
|
198
|
+
// Silent fail for pings
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
async storeLicenseKey(licenseKey) {
|
|
204
|
+
const pluginStore = strapi.store({
|
|
205
|
+
type: 'plugin',
|
|
206
|
+
name: 'magic-mail'
|
|
207
|
+
});
|
|
208
|
+
await pluginStore.set({ key: 'licenseKey', value: licenseKey });
|
|
209
|
+
strapi.log.info(`[magic-mail] ✅ License key stored: ${licenseKey.substring(0, 8)}...`);
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
startPinging(licenseKey, intervalMinutes = 15) {
|
|
213
|
+
// Immediate ping
|
|
214
|
+
this.pingLicense(licenseKey);
|
|
215
|
+
|
|
216
|
+
const interval = setInterval(async () => {
|
|
217
|
+
try {
|
|
218
|
+
await this.pingLicense(licenseKey);
|
|
219
|
+
} catch (error) {
|
|
220
|
+
console.error('[magic-mail] Ping error:', error);
|
|
221
|
+
}
|
|
222
|
+
}, intervalMinutes * 60 * 1000);
|
|
223
|
+
|
|
224
|
+
return interval;
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Get current license data from store
|
|
229
|
+
*/
|
|
230
|
+
async getCurrentLicense() {
|
|
231
|
+
try {
|
|
232
|
+
const pluginStore = strapi.store({
|
|
233
|
+
type: 'plugin',
|
|
234
|
+
name: 'magic-mail'
|
|
235
|
+
});
|
|
236
|
+
const licenseKey = await pluginStore.get({ key: 'licenseKey' });
|
|
237
|
+
|
|
238
|
+
if (!licenseKey) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const license = await this.getLicenseByKey(licenseKey);
|
|
243
|
+
return license;
|
|
244
|
+
} catch (error) {
|
|
245
|
+
strapi.log.error(`[magic-mail] ❌ Error loading license:`, error);
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Check if license has specific feature
|
|
252
|
+
*/
|
|
253
|
+
async hasFeature(featureName) {
|
|
254
|
+
const license = await this.getCurrentLicense();
|
|
255
|
+
const features = require('../config/features');
|
|
256
|
+
return features.hasFeature(license, featureName);
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Check if provider is allowed
|
|
261
|
+
*/
|
|
262
|
+
async isProviderAllowed(provider) {
|
|
263
|
+
const license = await this.getCurrentLicense();
|
|
264
|
+
const features = require('../config/features');
|
|
265
|
+
return features.isProviderAllowed(license, provider);
|
|
266
|
+
},
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Get max allowed accounts
|
|
270
|
+
*/
|
|
271
|
+
async getMaxAccounts() {
|
|
272
|
+
const license = await this.getCurrentLicense();
|
|
273
|
+
const features = require('../config/features');
|
|
274
|
+
return features.getMaxAccounts(license);
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Get max allowed routing rules
|
|
279
|
+
*/
|
|
280
|
+
async getMaxRoutingRules() {
|
|
281
|
+
const license = await this.getCurrentLicense();
|
|
282
|
+
const features = require('../config/features');
|
|
283
|
+
return features.getMaxRoutingRules(license);
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Get max allowed email templates
|
|
288
|
+
*/
|
|
289
|
+
async getMaxEmailTemplates() {
|
|
290
|
+
const license = await this.getCurrentLicense();
|
|
291
|
+
const features = require('../config/features');
|
|
292
|
+
return features.getMaxEmailTemplates(license);
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Initialize license guard
|
|
297
|
+
* Checks for existing license and starts pinging
|
|
298
|
+
*/
|
|
299
|
+
async initialize() {
|
|
300
|
+
try {
|
|
301
|
+
strapi.log.info('🔐 Initializing License Guard...');
|
|
302
|
+
|
|
303
|
+
// Check if license key exists in plugin store
|
|
304
|
+
const pluginStore = strapi.store({
|
|
305
|
+
type: 'plugin',
|
|
306
|
+
name: 'magic-mail'
|
|
307
|
+
});
|
|
308
|
+
const licenseKey = await pluginStore.get({ key: 'licenseKey' });
|
|
309
|
+
|
|
310
|
+
// Check last validation timestamp
|
|
311
|
+
const lastValidated = await pluginStore.get({ key: 'lastValidated' });
|
|
312
|
+
const now = new Date();
|
|
313
|
+
const gracePeriodHours = 24;
|
|
314
|
+
let withinGracePeriod = false;
|
|
315
|
+
|
|
316
|
+
if (lastValidated) {
|
|
317
|
+
const lastValidatedDate = new Date(lastValidated);
|
|
318
|
+
const hoursSinceValidation = (now.getTime() - lastValidatedDate.getTime()) / (1000 * 60 * 60);
|
|
319
|
+
withinGracePeriod = hoursSinceValidation < gracePeriodHours;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
strapi.log.info('──────────────────────────────────────────────────────────');
|
|
323
|
+
strapi.log.info(`📦 Plugin Store Check:`);
|
|
324
|
+
if (licenseKey) {
|
|
325
|
+
strapi.log.info(` ✅ License Key found: ${licenseKey}`);
|
|
326
|
+
strapi.log.info(` 🔑 Key (short): ${licenseKey.substring(0, 10)}...`);
|
|
327
|
+
if (lastValidated) {
|
|
328
|
+
const lastValidatedDate = new Date(lastValidated);
|
|
329
|
+
const hoursAgo = Math.floor((now.getTime() - lastValidatedDate.getTime()) / (1000 * 60 * 60));
|
|
330
|
+
strapi.log.info(` 🕐 Last validated: ${hoursAgo}h ago (Grace: ${withinGracePeriod ? 'ACTIVE' : 'EXPIRED'})`);
|
|
331
|
+
} else {
|
|
332
|
+
strapi.log.info(` 🕐 Last validated: Never (Grace: ACTIVE for first ${gracePeriodHours}h)`);
|
|
333
|
+
}
|
|
334
|
+
} else {
|
|
335
|
+
strapi.log.info(` ❌ No license key stored`);
|
|
336
|
+
}
|
|
337
|
+
strapi.log.info('──────────────────────────────────────────────────────────');
|
|
338
|
+
|
|
339
|
+
if (!licenseKey) {
|
|
340
|
+
strapi.log.info('📄 No license found - Running in demo mode');
|
|
341
|
+
strapi.log.info('💡 Create a license in the admin panel to activate full features');
|
|
342
|
+
return {
|
|
343
|
+
valid: false,
|
|
344
|
+
demo: true,
|
|
345
|
+
data: null,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
strapi.log.info('📄 Verifying stored license key...');
|
|
350
|
+
|
|
351
|
+
// Verify license (allow grace period if we have a last validation)
|
|
352
|
+
const verification = await this.verifyLicense(licenseKey, withinGracePeriod);
|
|
353
|
+
|
|
354
|
+
if (verification.valid) {
|
|
355
|
+
// Get license details for display
|
|
356
|
+
const license = await this.getLicenseByKey(licenseKey);
|
|
357
|
+
|
|
358
|
+
strapi.log.info(`✅ License verified online: ACTIVE (Key: ${licenseKey.substring(0, 10)}...)`);
|
|
359
|
+
|
|
360
|
+
// Update last validated timestamp
|
|
361
|
+
await pluginStore.set({
|
|
362
|
+
key: 'lastValidated',
|
|
363
|
+
value: now.toISOString()
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
strapi.log.info('✅ License is valid and active');
|
|
367
|
+
|
|
368
|
+
// Start automatic pinging
|
|
369
|
+
const pingInterval = this.startPinging(licenseKey, 15);
|
|
370
|
+
strapi.log.info('📡 Started pinging license every 15 minutes');
|
|
371
|
+
|
|
372
|
+
// Store interval globally so we can clean it up
|
|
373
|
+
strapi.licenseGuardMagicMail = {
|
|
374
|
+
licenseKey,
|
|
375
|
+
pingInterval,
|
|
376
|
+
data: verification.data,
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// Display license info box
|
|
380
|
+
strapi.log.info('╔════════════════════════════════════════════════════════════════╗');
|
|
381
|
+
strapi.log.info('║ ✅ MAGIC MAIL PLUGIN LICENSE ACTIVE ║');
|
|
382
|
+
strapi.log.info('║ ║');
|
|
383
|
+
strapi.log.info(`║ License: ${licenseKey.padEnd(38, ' ')}║`);
|
|
384
|
+
strapi.log.info(`║ User: ${(license?.firstName + ' ' + license?.lastName).padEnd(41, ' ')}║`);
|
|
385
|
+
strapi.log.info(`║ Email: ${(license?.email || 'N/A').padEnd(40, ' ')}║`);
|
|
386
|
+
strapi.log.info('║ ║');
|
|
387
|
+
strapi.log.info('║ 🔄 Auto-pinging every 15 minutes ║');
|
|
388
|
+
strapi.log.info('╚════════════════════════════════════════════════════════════════╝');
|
|
389
|
+
|
|
390
|
+
return {
|
|
391
|
+
valid: true,
|
|
392
|
+
demo: false,
|
|
393
|
+
data: verification.data,
|
|
394
|
+
gracePeriod: verification.gracePeriod || false,
|
|
395
|
+
};
|
|
396
|
+
} else {
|
|
397
|
+
strapi.log.error(`❌ License validation failed (Key: ${licenseKey.substring(0, 10)}...)`);
|
|
398
|
+
strapi.log.info('──────────────────────────────────────────────────────────');
|
|
399
|
+
strapi.log.info('⚠️ Running in demo mode with limited features');
|
|
400
|
+
return {
|
|
401
|
+
valid: false,
|
|
402
|
+
demo: true,
|
|
403
|
+
error: 'Invalid or expired license',
|
|
404
|
+
data: null,
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
} catch (error) {
|
|
408
|
+
strapi.log.error('❌ Error initializing License Guard:', error);
|
|
409
|
+
return {
|
|
410
|
+
valid: false,
|
|
411
|
+
demo: true,
|
|
412
|
+
error: error.message,
|
|
413
|
+
data: null,
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
});
|
|
418
|
+
|