strapi-plugin-magic-mark 3.0.0 → 3.0.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/README.md +1 -1
- package/dist/_chunks/{App-C5UU0yUr.js → App-B6x0aSMN.js} +97 -55
- package/dist/_chunks/{App-Dt-v39BQ.mjs → App-BCliVBSB.mjs} +98 -56
- package/dist/_chunks/UpgradePage-Bm0SkuCi.js +353 -0
- package/dist/_chunks/UpgradePage-GoocQ4av.mjs +351 -0
- package/dist/_chunks/de-Cs9dd3Mr.js +138 -0
- package/dist/_chunks/de-DOVki5VS.mjs +138 -0
- package/dist/_chunks/en-CE3r46Y2.js +138 -0
- package/dist/_chunks/en-Cf5-O03L.mjs +138 -0
- package/dist/_chunks/es-Ba6JcPIm.mjs +138 -0
- package/dist/_chunks/es-D4AOyJYJ.js +138 -0
- package/dist/_chunks/fr-CWSfoA8i.js +138 -0
- package/dist/_chunks/fr-CrMBXR3c.mjs +138 -0
- package/dist/_chunks/{index-B-Cc7QNW.mjs → index-B_EiWnCU.mjs} +13 -4
- package/dist/_chunks/index-D5-84IjV.js +3365 -0
- package/dist/_chunks/{index-B11QBtag.js → index-DA7Jswi4.js} +12 -3
- package/dist/_chunks/index-DdTUt6EH.mjs +3361 -0
- package/dist/_chunks/pt-BXxZ1Zym.mjs +138 -0
- package/dist/_chunks/pt-DW_6r_mP.js +138 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/QueryBuilder.d.ts +12 -1
- package/dist/admin/src/components/RelationFieldSelector.d.ts +24 -0
- package/dist/admin/src/components/SimpleAdvancedFilterModal.d.ts +2 -0
- package/dist/admin/src/components/UpgradePrompt.d.ts +22 -0
- package/dist/admin/src/hooks/useFeatureGate.d.ts +88 -0
- package/dist/admin/src/hooks/useRelationSchema.d.ts +27 -0
- package/dist/admin/src/pages/UpgradePage.d.ts +6 -0
- package/dist/admin/src/utils/queryGenerator.d.ts +4 -0
- package/dist/admin/src/utils/queryToStructure.d.ts +8 -1
- package/dist/admin/src/utils/theme.d.ts +95 -0
- package/dist/server/index.js +212 -9
- package/dist/server/index.mjs +212 -9
- package/dist/server/src/controllers/index.d.ts +1 -0
- package/dist/server/src/controllers/license.d.ts +4 -0
- package/dist/server/src/index.d.ts +24 -1
- package/dist/server/src/services/index.d.ts +23 -1
- package/dist/server/src/services/license-guard.d.ts +48 -2
- package/package.json +1 -1
- package/dist/_chunks/de-Bag-366k.mjs +0 -49
- package/dist/_chunks/de-Dic_hhjg.js +0 -49
- package/dist/_chunks/en-C5BvHqNo.js +0 -54
- package/dist/_chunks/en-zokEerzt.mjs +0 -54
- package/dist/_chunks/es-BlSQpU1z.js +0 -54
- package/dist/_chunks/es-Br1ucP3h.mjs +0 -54
- package/dist/_chunks/fr-BHciYPYG.js +0 -54
- package/dist/_chunks/fr-Dzo3kt_q.mjs +0 -54
- package/dist/_chunks/index-BAmZV8aX.mjs +0 -2020
- package/dist/_chunks/index-RuDV4dTy.js +0 -2024
- package/dist/_chunks/pt-DQoGyzyD.mjs +0 -54
- package/dist/_chunks/pt-Dawo5aUA.js +0 -54
package/dist/server/index.js
CHANGED
|
@@ -228,6 +228,17 @@ const bookmarkController = ({ strapi }) => ({
|
|
|
228
228
|
return ctx.throw(400, "Path is required");
|
|
229
229
|
}
|
|
230
230
|
const userId = user.documentId || String(user.id);
|
|
231
|
+
const licenseGuard = strapi.plugin("magic-mark").service("license-guard");
|
|
232
|
+
const limitCheck = await licenseGuard.canCreateBookmark(userId);
|
|
233
|
+
if (!limitCheck.canCreate) {
|
|
234
|
+
return ctx.throw(403, {
|
|
235
|
+
error: "BOOKMARK_LIMIT_REACHED",
|
|
236
|
+
message: limitCheck.message || `Bookmark limit reached (${limitCheck.current}/${limitCheck.max}). Upgrade to Premium or Advanced to create more bookmarks.`,
|
|
237
|
+
current: limitCheck.current,
|
|
238
|
+
max: limitCheck.max,
|
|
239
|
+
upgradeUrl: "/admin/settings/magic-mark/upgrade"
|
|
240
|
+
});
|
|
241
|
+
}
|
|
231
242
|
const service = strapi.plugin("magic-mark").service("bookmarks");
|
|
232
243
|
const bookmark = await service.create(name, path2, query, emoji, description, userId, sharedWithRoles, sharedWithUsers, isPublic);
|
|
233
244
|
ctx.body = {
|
|
@@ -620,6 +631,27 @@ const license = ({ strapi }) => ({
|
|
|
620
631
|
strapi.log.error("Error storing license key:", error);
|
|
621
632
|
return ctx.badRequest("Error validating license key");
|
|
622
633
|
}
|
|
634
|
+
},
|
|
635
|
+
/**
|
|
636
|
+
* Get license limits and feature flags for current user
|
|
637
|
+
*/
|
|
638
|
+
async getLimits(ctx) {
|
|
639
|
+
try {
|
|
640
|
+
const user = ctx.state.user;
|
|
641
|
+
if (!user) {
|
|
642
|
+
return ctx.unauthorized("User not authenticated");
|
|
643
|
+
}
|
|
644
|
+
const userId = user.documentId || String(user.id);
|
|
645
|
+
const licenseGuard = strapi.plugin("magic-mark").service("license-guard");
|
|
646
|
+
const limits = await licenseGuard.getLicenseLimits(userId);
|
|
647
|
+
return ctx.send({
|
|
648
|
+
success: true,
|
|
649
|
+
data: limits
|
|
650
|
+
});
|
|
651
|
+
} catch (error) {
|
|
652
|
+
strapi.log.error("Error getting license limits:", error);
|
|
653
|
+
return ctx.badRequest("Error getting license limits");
|
|
654
|
+
}
|
|
623
655
|
}
|
|
624
656
|
});
|
|
625
657
|
const controllers = {
|
|
@@ -741,6 +773,14 @@ const admin = {
|
|
|
741
773
|
config: {
|
|
742
774
|
policies: []
|
|
743
775
|
}
|
|
776
|
+
},
|
|
777
|
+
{
|
|
778
|
+
method: "GET",
|
|
779
|
+
path: "/license/limits",
|
|
780
|
+
handler: "license.getLimits",
|
|
781
|
+
config: {
|
|
782
|
+
policies: []
|
|
783
|
+
}
|
|
744
784
|
}
|
|
745
785
|
]
|
|
746
786
|
};
|
|
@@ -1239,19 +1279,23 @@ const licenseGuardService = ({ strapi }) => ({
|
|
|
1239
1279
|
}
|
|
1240
1280
|
},
|
|
1241
1281
|
/**
|
|
1242
|
-
* Get
|
|
1282
|
+
* Get current license data from store (fetches fresh from server)
|
|
1283
|
+
* This is the correct way to get license data with all feature flags
|
|
1243
1284
|
*/
|
|
1244
|
-
async
|
|
1285
|
+
async getCurrentLicense() {
|
|
1245
1286
|
try {
|
|
1246
|
-
const
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1287
|
+
const pluginStore = strapi.store({
|
|
1288
|
+
type: "plugin",
|
|
1289
|
+
name: "magic-mark"
|
|
1290
|
+
});
|
|
1291
|
+
const licenseKey = await pluginStore.get({ key: "licenseKey" });
|
|
1292
|
+
if (!licenseKey) {
|
|
1293
|
+
return null;
|
|
1251
1294
|
}
|
|
1252
|
-
|
|
1295
|
+
const license2 = await this.getLicenseByKey(licenseKey);
|
|
1296
|
+
return license2;
|
|
1253
1297
|
} catch (error) {
|
|
1254
|
-
strapi.log.error("[
|
|
1298
|
+
strapi.log.error("[LICENSE] Error loading current license:", error);
|
|
1255
1299
|
return null;
|
|
1256
1300
|
}
|
|
1257
1301
|
},
|
|
@@ -1360,6 +1404,165 @@ const licenseGuardService = ({ strapi }) => ({
|
|
|
1360
1404
|
return false;
|
|
1361
1405
|
}
|
|
1362
1406
|
},
|
|
1407
|
+
/**
|
|
1408
|
+
* Get bookmark limit based on license tier
|
|
1409
|
+
* @returns Bookmark limit: 10 (free), 50 (premium), -1 (advanced/unlimited)
|
|
1410
|
+
*/
|
|
1411
|
+
async getBookmarkLimit() {
|
|
1412
|
+
try {
|
|
1413
|
+
const licenseGuard = strapi.licenseGuard;
|
|
1414
|
+
const licenseData = licenseGuard?.data;
|
|
1415
|
+
if (licenseData?.featureAdvanced) {
|
|
1416
|
+
return -1;
|
|
1417
|
+
}
|
|
1418
|
+
if (licenseData?.featurePremium) {
|
|
1419
|
+
return 50;
|
|
1420
|
+
}
|
|
1421
|
+
return 10;
|
|
1422
|
+
} catch (error) {
|
|
1423
|
+
strapi.log.debug("[LICENSE] Error getting bookmark limit, using free tier");
|
|
1424
|
+
return 10;
|
|
1425
|
+
}
|
|
1426
|
+
},
|
|
1427
|
+
/**
|
|
1428
|
+
* Check if user can create more bookmarks
|
|
1429
|
+
* @param userId - User's documentId
|
|
1430
|
+
* @returns Object with canCreate boolean and current/max counts
|
|
1431
|
+
*/
|
|
1432
|
+
async canCreateBookmark(userId) {
|
|
1433
|
+
try {
|
|
1434
|
+
const limit = await this.getBookmarkLimit();
|
|
1435
|
+
if (limit === -1) {
|
|
1436
|
+
return { canCreate: true, current: 0, max: -1 };
|
|
1437
|
+
}
|
|
1438
|
+
const BOOKMARK_UID2 = "plugin::magic-mark.bookmark";
|
|
1439
|
+
const bookmarks = await strapi.documents(BOOKMARK_UID2).findMany({
|
|
1440
|
+
filters: { creatorId: userId }
|
|
1441
|
+
});
|
|
1442
|
+
const currentCount = bookmarks?.length || 0;
|
|
1443
|
+
if (currentCount >= limit) {
|
|
1444
|
+
return {
|
|
1445
|
+
canCreate: false,
|
|
1446
|
+
current: currentCount,
|
|
1447
|
+
max: limit,
|
|
1448
|
+
message: `Bookmark limit reached (${currentCount}/${limit}). Upgrade to create more bookmarks.`
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
return { canCreate: true, current: currentCount, max: limit };
|
|
1452
|
+
} catch (error) {
|
|
1453
|
+
strapi.log.error("[LICENSE] Error checking bookmark limit:", error);
|
|
1454
|
+
return { canCreate: true, current: 0, max: 10 };
|
|
1455
|
+
}
|
|
1456
|
+
},
|
|
1457
|
+
/**
|
|
1458
|
+
* Get current license limits and feature flags
|
|
1459
|
+
* @param userId - User's documentId for bookmark count
|
|
1460
|
+
* @returns License limits object
|
|
1461
|
+
*/
|
|
1462
|
+
async getLicenseLimits(userId) {
|
|
1463
|
+
try {
|
|
1464
|
+
const license2 = await this.getCurrentLicense();
|
|
1465
|
+
strapi.log.info("[LICENSE] getLicenseLimits - license exists:", !!license2);
|
|
1466
|
+
if (license2) {
|
|
1467
|
+
strapi.log.info("[LICENSE] getLicenseLimits - featurePremium:", license2.featurePremium);
|
|
1468
|
+
strapi.log.info("[LICENSE] getLicenseLimits - featureAdvanced:", license2.featureAdvanced);
|
|
1469
|
+
}
|
|
1470
|
+
let tier = "free";
|
|
1471
|
+
if (license2?.featureEnterprise === true) tier = "enterprise";
|
|
1472
|
+
else if (license2?.featureAdvanced === true) tier = "advanced";
|
|
1473
|
+
else if (license2?.featurePremium === true) tier = "premium";
|
|
1474
|
+
const isPremium = tier === "premium" || tier === "advanced" || tier === "enterprise";
|
|
1475
|
+
const isAdvanced = tier === "advanced" || tier === "enterprise";
|
|
1476
|
+
strapi.log.info("[LICENSE] getLicenseLimits - detected tier:", tier);
|
|
1477
|
+
const bookmarkCheck = await this.canCreateBookmark(userId);
|
|
1478
|
+
return {
|
|
1479
|
+
maxBookmarks: bookmarkCheck.max,
|
|
1480
|
+
currentBookmarks: bookmarkCheck.current,
|
|
1481
|
+
canCreate: bookmarkCheck.canCreate,
|
|
1482
|
+
tier,
|
|
1483
|
+
features: {
|
|
1484
|
+
queryHistory: isPremium || isAdvanced,
|
|
1485
|
+
export: isPremium || isAdvanced,
|
|
1486
|
+
analytics: isAdvanced,
|
|
1487
|
+
bulkOperations: isAdvanced,
|
|
1488
|
+
customIntegrations: isAdvanced
|
|
1489
|
+
}
|
|
1490
|
+
};
|
|
1491
|
+
} catch (error) {
|
|
1492
|
+
strapi.log.error("[LICENSE] Error getting license limits:", error);
|
|
1493
|
+
return {
|
|
1494
|
+
maxBookmarks: 10,
|
|
1495
|
+
currentBookmarks: 0,
|
|
1496
|
+
canCreate: true,
|
|
1497
|
+
tier: "free",
|
|
1498
|
+
features: {
|
|
1499
|
+
queryHistory: false,
|
|
1500
|
+
export: false,
|
|
1501
|
+
analytics: false,
|
|
1502
|
+
bulkOperations: false,
|
|
1503
|
+
customIntegrations: false
|
|
1504
|
+
}
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1507
|
+
},
|
|
1508
|
+
/**
|
|
1509
|
+
* Check if a specific feature is available based on license
|
|
1510
|
+
* @param feature - Feature key to check
|
|
1511
|
+
* @returns Boolean indicating if feature is available
|
|
1512
|
+
*/
|
|
1513
|
+
hasFeature(feature) {
|
|
1514
|
+
try {
|
|
1515
|
+
const licenseGuard = strapi.licenseGuard;
|
|
1516
|
+
const licenseData = licenseGuard?.data;
|
|
1517
|
+
const isPremium = licenseData?.featurePremium || false;
|
|
1518
|
+
const isAdvanced = licenseData?.featureAdvanced || false;
|
|
1519
|
+
const featureRequirements = {
|
|
1520
|
+
// Free tier
|
|
1521
|
+
basicBookmarks: "free",
|
|
1522
|
+
basicFilters: "free",
|
|
1523
|
+
// Premium tier
|
|
1524
|
+
extendedBookmarks: "premium",
|
|
1525
|
+
queryHistory: "premium",
|
|
1526
|
+
exportBookmarks: "premium",
|
|
1527
|
+
sharedBookmarks: "premium",
|
|
1528
|
+
// Advanced tier
|
|
1529
|
+
unlimitedBookmarks: "advanced",
|
|
1530
|
+
advancedFilters: "advanced",
|
|
1531
|
+
subGroups: "advanced",
|
|
1532
|
+
bulkOperations: "advanced",
|
|
1533
|
+
analytics: "advanced",
|
|
1534
|
+
customIntegrations: "advanced"
|
|
1535
|
+
};
|
|
1536
|
+
const requiredTier = featureRequirements[feature] || "free";
|
|
1537
|
+
let currentTierLevel = 0;
|
|
1538
|
+
if (isAdvanced) currentTierLevel = 2;
|
|
1539
|
+
else if (isPremium) currentTierLevel = 1;
|
|
1540
|
+
const tierLevels = {
|
|
1541
|
+
free: 0,
|
|
1542
|
+
premium: 1,
|
|
1543
|
+
advanced: 2
|
|
1544
|
+
};
|
|
1545
|
+
return currentTierLevel >= tierLevels[requiredTier];
|
|
1546
|
+
} catch (error) {
|
|
1547
|
+
strapi.log.debug("[LICENSE] Error checking feature:", feature);
|
|
1548
|
+
return false;
|
|
1549
|
+
}
|
|
1550
|
+
},
|
|
1551
|
+
/**
|
|
1552
|
+
* Get current tier name
|
|
1553
|
+
* @returns 'free' | 'premium' | 'advanced'
|
|
1554
|
+
*/
|
|
1555
|
+
getCurrentTier() {
|
|
1556
|
+
try {
|
|
1557
|
+
const licenseGuard = strapi.licenseGuard;
|
|
1558
|
+
const licenseData = licenseGuard?.data;
|
|
1559
|
+
if (licenseData?.featureAdvanced) return "advanced";
|
|
1560
|
+
if (licenseData?.featurePremium) return "premium";
|
|
1561
|
+
return "free";
|
|
1562
|
+
} catch (error) {
|
|
1563
|
+
return "free";
|
|
1564
|
+
}
|
|
1565
|
+
},
|
|
1363
1566
|
/**
|
|
1364
1567
|
* Cleanup on plugin destroy
|
|
1365
1568
|
*/
|
package/dist/server/index.mjs
CHANGED
|
@@ -224,6 +224,17 @@ const bookmarkController = ({ strapi }) => ({
|
|
|
224
224
|
return ctx.throw(400, "Path is required");
|
|
225
225
|
}
|
|
226
226
|
const userId = user.documentId || String(user.id);
|
|
227
|
+
const licenseGuard = strapi.plugin("magic-mark").service("license-guard");
|
|
228
|
+
const limitCheck = await licenseGuard.canCreateBookmark(userId);
|
|
229
|
+
if (!limitCheck.canCreate) {
|
|
230
|
+
return ctx.throw(403, {
|
|
231
|
+
error: "BOOKMARK_LIMIT_REACHED",
|
|
232
|
+
message: limitCheck.message || `Bookmark limit reached (${limitCheck.current}/${limitCheck.max}). Upgrade to Premium or Advanced to create more bookmarks.`,
|
|
233
|
+
current: limitCheck.current,
|
|
234
|
+
max: limitCheck.max,
|
|
235
|
+
upgradeUrl: "/admin/settings/magic-mark/upgrade"
|
|
236
|
+
});
|
|
237
|
+
}
|
|
227
238
|
const service = strapi.plugin("magic-mark").service("bookmarks");
|
|
228
239
|
const bookmark = await service.create(name, path, query, emoji, description, userId, sharedWithRoles, sharedWithUsers, isPublic);
|
|
229
240
|
ctx.body = {
|
|
@@ -616,6 +627,27 @@ const license = ({ strapi }) => ({
|
|
|
616
627
|
strapi.log.error("Error storing license key:", error);
|
|
617
628
|
return ctx.badRequest("Error validating license key");
|
|
618
629
|
}
|
|
630
|
+
},
|
|
631
|
+
/**
|
|
632
|
+
* Get license limits and feature flags for current user
|
|
633
|
+
*/
|
|
634
|
+
async getLimits(ctx) {
|
|
635
|
+
try {
|
|
636
|
+
const user = ctx.state.user;
|
|
637
|
+
if (!user) {
|
|
638
|
+
return ctx.unauthorized("User not authenticated");
|
|
639
|
+
}
|
|
640
|
+
const userId = user.documentId || String(user.id);
|
|
641
|
+
const licenseGuard = strapi.plugin("magic-mark").service("license-guard");
|
|
642
|
+
const limits = await licenseGuard.getLicenseLimits(userId);
|
|
643
|
+
return ctx.send({
|
|
644
|
+
success: true,
|
|
645
|
+
data: limits
|
|
646
|
+
});
|
|
647
|
+
} catch (error) {
|
|
648
|
+
strapi.log.error("Error getting license limits:", error);
|
|
649
|
+
return ctx.badRequest("Error getting license limits");
|
|
650
|
+
}
|
|
619
651
|
}
|
|
620
652
|
});
|
|
621
653
|
const controllers = {
|
|
@@ -737,6 +769,14 @@ const admin = {
|
|
|
737
769
|
config: {
|
|
738
770
|
policies: []
|
|
739
771
|
}
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
method: "GET",
|
|
775
|
+
path: "/license/limits",
|
|
776
|
+
handler: "license.getLimits",
|
|
777
|
+
config: {
|
|
778
|
+
policies: []
|
|
779
|
+
}
|
|
740
780
|
}
|
|
741
781
|
]
|
|
742
782
|
};
|
|
@@ -1235,19 +1275,23 @@ const licenseGuardService = ({ strapi }) => ({
|
|
|
1235
1275
|
}
|
|
1236
1276
|
},
|
|
1237
1277
|
/**
|
|
1238
|
-
* Get
|
|
1278
|
+
* Get current license data from store (fetches fresh from server)
|
|
1279
|
+
* This is the correct way to get license data with all feature flags
|
|
1239
1280
|
*/
|
|
1240
|
-
async
|
|
1281
|
+
async getCurrentLicense() {
|
|
1241
1282
|
try {
|
|
1242
|
-
const
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1283
|
+
const pluginStore = strapi.store({
|
|
1284
|
+
type: "plugin",
|
|
1285
|
+
name: "magic-mark"
|
|
1286
|
+
});
|
|
1287
|
+
const licenseKey = await pluginStore.get({ key: "licenseKey" });
|
|
1288
|
+
if (!licenseKey) {
|
|
1289
|
+
return null;
|
|
1247
1290
|
}
|
|
1248
|
-
|
|
1291
|
+
const license2 = await this.getLicenseByKey(licenseKey);
|
|
1292
|
+
return license2;
|
|
1249
1293
|
} catch (error) {
|
|
1250
|
-
strapi.log.error("[
|
|
1294
|
+
strapi.log.error("[LICENSE] Error loading current license:", error);
|
|
1251
1295
|
return null;
|
|
1252
1296
|
}
|
|
1253
1297
|
},
|
|
@@ -1356,6 +1400,165 @@ const licenseGuardService = ({ strapi }) => ({
|
|
|
1356
1400
|
return false;
|
|
1357
1401
|
}
|
|
1358
1402
|
},
|
|
1403
|
+
/**
|
|
1404
|
+
* Get bookmark limit based on license tier
|
|
1405
|
+
* @returns Bookmark limit: 10 (free), 50 (premium), -1 (advanced/unlimited)
|
|
1406
|
+
*/
|
|
1407
|
+
async getBookmarkLimit() {
|
|
1408
|
+
try {
|
|
1409
|
+
const licenseGuard = strapi.licenseGuard;
|
|
1410
|
+
const licenseData = licenseGuard?.data;
|
|
1411
|
+
if (licenseData?.featureAdvanced) {
|
|
1412
|
+
return -1;
|
|
1413
|
+
}
|
|
1414
|
+
if (licenseData?.featurePremium) {
|
|
1415
|
+
return 50;
|
|
1416
|
+
}
|
|
1417
|
+
return 10;
|
|
1418
|
+
} catch (error) {
|
|
1419
|
+
strapi.log.debug("[LICENSE] Error getting bookmark limit, using free tier");
|
|
1420
|
+
return 10;
|
|
1421
|
+
}
|
|
1422
|
+
},
|
|
1423
|
+
/**
|
|
1424
|
+
* Check if user can create more bookmarks
|
|
1425
|
+
* @param userId - User's documentId
|
|
1426
|
+
* @returns Object with canCreate boolean and current/max counts
|
|
1427
|
+
*/
|
|
1428
|
+
async canCreateBookmark(userId) {
|
|
1429
|
+
try {
|
|
1430
|
+
const limit = await this.getBookmarkLimit();
|
|
1431
|
+
if (limit === -1) {
|
|
1432
|
+
return { canCreate: true, current: 0, max: -1 };
|
|
1433
|
+
}
|
|
1434
|
+
const BOOKMARK_UID2 = "plugin::magic-mark.bookmark";
|
|
1435
|
+
const bookmarks = await strapi.documents(BOOKMARK_UID2).findMany({
|
|
1436
|
+
filters: { creatorId: userId }
|
|
1437
|
+
});
|
|
1438
|
+
const currentCount = bookmarks?.length || 0;
|
|
1439
|
+
if (currentCount >= limit) {
|
|
1440
|
+
return {
|
|
1441
|
+
canCreate: false,
|
|
1442
|
+
current: currentCount,
|
|
1443
|
+
max: limit,
|
|
1444
|
+
message: `Bookmark limit reached (${currentCount}/${limit}). Upgrade to create more bookmarks.`
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
return { canCreate: true, current: currentCount, max: limit };
|
|
1448
|
+
} catch (error) {
|
|
1449
|
+
strapi.log.error("[LICENSE] Error checking bookmark limit:", error);
|
|
1450
|
+
return { canCreate: true, current: 0, max: 10 };
|
|
1451
|
+
}
|
|
1452
|
+
},
|
|
1453
|
+
/**
|
|
1454
|
+
* Get current license limits and feature flags
|
|
1455
|
+
* @param userId - User's documentId for bookmark count
|
|
1456
|
+
* @returns License limits object
|
|
1457
|
+
*/
|
|
1458
|
+
async getLicenseLimits(userId) {
|
|
1459
|
+
try {
|
|
1460
|
+
const license2 = await this.getCurrentLicense();
|
|
1461
|
+
strapi.log.info("[LICENSE] getLicenseLimits - license exists:", !!license2);
|
|
1462
|
+
if (license2) {
|
|
1463
|
+
strapi.log.info("[LICENSE] getLicenseLimits - featurePremium:", license2.featurePremium);
|
|
1464
|
+
strapi.log.info("[LICENSE] getLicenseLimits - featureAdvanced:", license2.featureAdvanced);
|
|
1465
|
+
}
|
|
1466
|
+
let tier = "free";
|
|
1467
|
+
if (license2?.featureEnterprise === true) tier = "enterprise";
|
|
1468
|
+
else if (license2?.featureAdvanced === true) tier = "advanced";
|
|
1469
|
+
else if (license2?.featurePremium === true) tier = "premium";
|
|
1470
|
+
const isPremium = tier === "premium" || tier === "advanced" || tier === "enterprise";
|
|
1471
|
+
const isAdvanced = tier === "advanced" || tier === "enterprise";
|
|
1472
|
+
strapi.log.info("[LICENSE] getLicenseLimits - detected tier:", tier);
|
|
1473
|
+
const bookmarkCheck = await this.canCreateBookmark(userId);
|
|
1474
|
+
return {
|
|
1475
|
+
maxBookmarks: bookmarkCheck.max,
|
|
1476
|
+
currentBookmarks: bookmarkCheck.current,
|
|
1477
|
+
canCreate: bookmarkCheck.canCreate,
|
|
1478
|
+
tier,
|
|
1479
|
+
features: {
|
|
1480
|
+
queryHistory: isPremium || isAdvanced,
|
|
1481
|
+
export: isPremium || isAdvanced,
|
|
1482
|
+
analytics: isAdvanced,
|
|
1483
|
+
bulkOperations: isAdvanced,
|
|
1484
|
+
customIntegrations: isAdvanced
|
|
1485
|
+
}
|
|
1486
|
+
};
|
|
1487
|
+
} catch (error) {
|
|
1488
|
+
strapi.log.error("[LICENSE] Error getting license limits:", error);
|
|
1489
|
+
return {
|
|
1490
|
+
maxBookmarks: 10,
|
|
1491
|
+
currentBookmarks: 0,
|
|
1492
|
+
canCreate: true,
|
|
1493
|
+
tier: "free",
|
|
1494
|
+
features: {
|
|
1495
|
+
queryHistory: false,
|
|
1496
|
+
export: false,
|
|
1497
|
+
analytics: false,
|
|
1498
|
+
bulkOperations: false,
|
|
1499
|
+
customIntegrations: false
|
|
1500
|
+
}
|
|
1501
|
+
};
|
|
1502
|
+
}
|
|
1503
|
+
},
|
|
1504
|
+
/**
|
|
1505
|
+
* Check if a specific feature is available based on license
|
|
1506
|
+
* @param feature - Feature key to check
|
|
1507
|
+
* @returns Boolean indicating if feature is available
|
|
1508
|
+
*/
|
|
1509
|
+
hasFeature(feature) {
|
|
1510
|
+
try {
|
|
1511
|
+
const licenseGuard = strapi.licenseGuard;
|
|
1512
|
+
const licenseData = licenseGuard?.data;
|
|
1513
|
+
const isPremium = licenseData?.featurePremium || false;
|
|
1514
|
+
const isAdvanced = licenseData?.featureAdvanced || false;
|
|
1515
|
+
const featureRequirements = {
|
|
1516
|
+
// Free tier
|
|
1517
|
+
basicBookmarks: "free",
|
|
1518
|
+
basicFilters: "free",
|
|
1519
|
+
// Premium tier
|
|
1520
|
+
extendedBookmarks: "premium",
|
|
1521
|
+
queryHistory: "premium",
|
|
1522
|
+
exportBookmarks: "premium",
|
|
1523
|
+
sharedBookmarks: "premium",
|
|
1524
|
+
// Advanced tier
|
|
1525
|
+
unlimitedBookmarks: "advanced",
|
|
1526
|
+
advancedFilters: "advanced",
|
|
1527
|
+
subGroups: "advanced",
|
|
1528
|
+
bulkOperations: "advanced",
|
|
1529
|
+
analytics: "advanced",
|
|
1530
|
+
customIntegrations: "advanced"
|
|
1531
|
+
};
|
|
1532
|
+
const requiredTier = featureRequirements[feature] || "free";
|
|
1533
|
+
let currentTierLevel = 0;
|
|
1534
|
+
if (isAdvanced) currentTierLevel = 2;
|
|
1535
|
+
else if (isPremium) currentTierLevel = 1;
|
|
1536
|
+
const tierLevels = {
|
|
1537
|
+
free: 0,
|
|
1538
|
+
premium: 1,
|
|
1539
|
+
advanced: 2
|
|
1540
|
+
};
|
|
1541
|
+
return currentTierLevel >= tierLevels[requiredTier];
|
|
1542
|
+
} catch (error) {
|
|
1543
|
+
strapi.log.debug("[LICENSE] Error checking feature:", feature);
|
|
1544
|
+
return false;
|
|
1545
|
+
}
|
|
1546
|
+
},
|
|
1547
|
+
/**
|
|
1548
|
+
* Get current tier name
|
|
1549
|
+
* @returns 'free' | 'premium' | 'advanced'
|
|
1550
|
+
*/
|
|
1551
|
+
getCurrentTier() {
|
|
1552
|
+
try {
|
|
1553
|
+
const licenseGuard = strapi.licenseGuard;
|
|
1554
|
+
const licenseData = licenseGuard?.data;
|
|
1555
|
+
if (licenseData?.featureAdvanced) return "advanced";
|
|
1556
|
+
if (licenseData?.featurePremium) return "premium";
|
|
1557
|
+
return "free";
|
|
1558
|
+
} catch (error) {
|
|
1559
|
+
return "free";
|
|
1560
|
+
}
|
|
1561
|
+
},
|
|
1359
1562
|
/**
|
|
1360
1563
|
* Cleanup on plugin destroy
|
|
1361
1564
|
*/
|
|
@@ -23,5 +23,9 @@ declare const _default: ({ strapi }: any) => {
|
|
|
23
23
|
* Store and validate an existing license key
|
|
24
24
|
*/
|
|
25
25
|
storeKey(ctx: any): Promise<any>;
|
|
26
|
+
/**
|
|
27
|
+
* Get license limits and feature flags for current user
|
|
28
|
+
*/
|
|
29
|
+
getLimits(ctx: any): Promise<any>;
|
|
26
30
|
};
|
|
27
31
|
export default _default;
|
|
@@ -30,6 +30,7 @@ declare const _default: {
|
|
|
30
30
|
createAndActivate(ctx: any): Promise<any>;
|
|
31
31
|
ping(ctx: any): Promise<any>;
|
|
32
32
|
storeKey(ctx: any): Promise<any>;
|
|
33
|
+
getLimits(ctx: any): Promise<any>;
|
|
33
34
|
};
|
|
34
35
|
};
|
|
35
36
|
routes: {
|
|
@@ -85,10 +86,32 @@ declare const _default: {
|
|
|
85
86
|
verifyLicense(licenseKey: string, allowGracePeriod?: boolean): Promise<import("./services/license-guard").VerificationResult>;
|
|
86
87
|
pingLicense(licenseKey: string): Promise<any>;
|
|
87
88
|
getLicenseByKey(licenseKey: string): Promise<import("./services/license-guard").LicenseData>;
|
|
88
|
-
|
|
89
|
+
getCurrentLicense(): Promise<import("./services/license-guard").LicenseData>;
|
|
89
90
|
startPinging(licenseKey: string, intervalMinutes?: number): NodeJS.Timeout;
|
|
90
91
|
initialize(): Promise<import("./services/license-guard").LicenseStatus>;
|
|
91
92
|
storeLicenseKey(licenseKey: string): Promise<boolean>;
|
|
93
|
+
getBookmarkLimit(): Promise<number>;
|
|
94
|
+
canCreateBookmark(userId: string): Promise<{
|
|
95
|
+
canCreate: boolean;
|
|
96
|
+
current: number;
|
|
97
|
+
max: number;
|
|
98
|
+
message?: string;
|
|
99
|
+
}>;
|
|
100
|
+
getLicenseLimits(userId: string): Promise<{
|
|
101
|
+
maxBookmarks: number;
|
|
102
|
+
currentBookmarks: number;
|
|
103
|
+
canCreate: boolean;
|
|
104
|
+
tier: string;
|
|
105
|
+
features: {
|
|
106
|
+
queryHistory: boolean;
|
|
107
|
+
export: boolean;
|
|
108
|
+
analytics: boolean;
|
|
109
|
+
bulkOperations: boolean;
|
|
110
|
+
customIntegrations: boolean;
|
|
111
|
+
};
|
|
112
|
+
}>;
|
|
113
|
+
hasFeature(feature: string): boolean;
|
|
114
|
+
getCurrentTier(): "free" | "premium" | "advanced";
|
|
92
115
|
cleanup(): void;
|
|
93
116
|
};
|
|
94
117
|
};
|
|
@@ -35,10 +35,32 @@ declare const _default: {
|
|
|
35
35
|
verifyLicense(licenseKey: string, allowGracePeriod?: boolean): Promise<import("./license-guard").VerificationResult>;
|
|
36
36
|
pingLicense(licenseKey: string): Promise<any>;
|
|
37
37
|
getLicenseByKey(licenseKey: string): Promise<import("./license-guard").LicenseData>;
|
|
38
|
-
|
|
38
|
+
getCurrentLicense(): Promise<import("./license-guard").LicenseData>;
|
|
39
39
|
startPinging(licenseKey: string, intervalMinutes?: number): NodeJS.Timeout;
|
|
40
40
|
initialize(): Promise<import("./license-guard").LicenseStatus>;
|
|
41
41
|
storeLicenseKey(licenseKey: string): Promise<boolean>;
|
|
42
|
+
getBookmarkLimit(): Promise<number>;
|
|
43
|
+
canCreateBookmark(userId: string): Promise<{
|
|
44
|
+
canCreate: boolean;
|
|
45
|
+
current: number;
|
|
46
|
+
max: number;
|
|
47
|
+
message?: string;
|
|
48
|
+
}>;
|
|
49
|
+
getLicenseLimits(userId: string): Promise<{
|
|
50
|
+
maxBookmarks: number;
|
|
51
|
+
currentBookmarks: number;
|
|
52
|
+
canCreate: boolean;
|
|
53
|
+
tier: string;
|
|
54
|
+
features: {
|
|
55
|
+
queryHistory: boolean;
|
|
56
|
+
export: boolean;
|
|
57
|
+
analytics: boolean;
|
|
58
|
+
bulkOperations: boolean;
|
|
59
|
+
customIntegrations: boolean;
|
|
60
|
+
};
|
|
61
|
+
}>;
|
|
62
|
+
hasFeature(feature: string): boolean;
|
|
63
|
+
getCurrentTier(): "free" | "premium" | "advanced";
|
|
42
64
|
cleanup(): void;
|
|
43
65
|
};
|
|
44
66
|
};
|
|
@@ -79,9 +79,10 @@ declare const licenseGuardService: ({ strapi }: {
|
|
|
79
79
|
*/
|
|
80
80
|
getLicenseByKey(licenseKey: string): Promise<LicenseData | null>;
|
|
81
81
|
/**
|
|
82
|
-
* Get
|
|
82
|
+
* Get current license data from store (fetches fresh from server)
|
|
83
|
+
* This is the correct way to get license data with all feature flags
|
|
83
84
|
*/
|
|
84
|
-
|
|
85
|
+
getCurrentLicense(): Promise<LicenseData | null>;
|
|
85
86
|
/**
|
|
86
87
|
* Start periodic pinging for a license
|
|
87
88
|
*/
|
|
@@ -95,6 +96,51 @@ declare const licenseGuardService: ({ strapi }: {
|
|
|
95
96
|
* Store license key after creation
|
|
96
97
|
*/
|
|
97
98
|
storeLicenseKey(licenseKey: string): Promise<boolean>;
|
|
99
|
+
/**
|
|
100
|
+
* Get bookmark limit based on license tier
|
|
101
|
+
* @returns Bookmark limit: 10 (free), 50 (premium), -1 (advanced/unlimited)
|
|
102
|
+
*/
|
|
103
|
+
getBookmarkLimit(): Promise<number>;
|
|
104
|
+
/**
|
|
105
|
+
* Check if user can create more bookmarks
|
|
106
|
+
* @param userId - User's documentId
|
|
107
|
+
* @returns Object with canCreate boolean and current/max counts
|
|
108
|
+
*/
|
|
109
|
+
canCreateBookmark(userId: string): Promise<{
|
|
110
|
+
canCreate: boolean;
|
|
111
|
+
current: number;
|
|
112
|
+
max: number;
|
|
113
|
+
message?: string;
|
|
114
|
+
}>;
|
|
115
|
+
/**
|
|
116
|
+
* Get current license limits and feature flags
|
|
117
|
+
* @param userId - User's documentId for bookmark count
|
|
118
|
+
* @returns License limits object
|
|
119
|
+
*/
|
|
120
|
+
getLicenseLimits(userId: string): Promise<{
|
|
121
|
+
maxBookmarks: number;
|
|
122
|
+
currentBookmarks: number;
|
|
123
|
+
canCreate: boolean;
|
|
124
|
+
tier: string;
|
|
125
|
+
features: {
|
|
126
|
+
queryHistory: boolean;
|
|
127
|
+
export: boolean;
|
|
128
|
+
analytics: boolean;
|
|
129
|
+
bulkOperations: boolean;
|
|
130
|
+
customIntegrations: boolean;
|
|
131
|
+
};
|
|
132
|
+
}>;
|
|
133
|
+
/**
|
|
134
|
+
* Check if a specific feature is available based on license
|
|
135
|
+
* @param feature - Feature key to check
|
|
136
|
+
* @returns Boolean indicating if feature is available
|
|
137
|
+
*/
|
|
138
|
+
hasFeature(feature: string): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Get current tier name
|
|
141
|
+
* @returns 'free' | 'premium' | 'advanced'
|
|
142
|
+
*/
|
|
143
|
+
getCurrentTier(): 'free' | 'premium' | 'advanced';
|
|
98
144
|
/**
|
|
99
145
|
* Cleanup on plugin destroy
|
|
100
146
|
*/
|
package/package.json
CHANGED