From 3d6987f761b168113c009845d8ff028f9ca86688 Mon Sep 17 00:00:00 2001 From: Fringg Date: Wed, 25 Feb 2026 04:42:40 +0300 Subject: [PATCH] feat: add granular user permissions (balance, subscription, promo_group, referral, send_offer) Split users:edit into fine-grained permissions. Guard UI sections with hasPermission checks so moderators only see what they can do. --- src/locales/en.json | 7 +- src/locales/fa.json | 7 +- src/locales/ru.json | 7 +- src/locales/zh.json | 7 +- src/pages/AdminUserDetail.tsx | 286 ++++++++++++++++++---------------- 5 files changed, 176 insertions(+), 138 deletions(-) diff --git a/src/locales/en.json b/src/locales/en.json index 1fe6329..58a243c 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -2618,7 +2618,12 @@ "manage": "Manage", "ban": "Ban", "unban": "Unban", - "assign": "Assign" + "assign": "Assign", + "promo_group": "Promo group", + "balance": "Balance", + "subscription": "Subscription", + "send_offer": "Send offer", + "referral": "Referral %" }, "toggleSection": "Toggle all {{section}} permissions", "selectedPermissions_one": "{{count}} permission selected", diff --git a/src/locales/fa.json b/src/locales/fa.json index 652584d..614efa1 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -2407,7 +2407,12 @@ "manage": "مدیریت", "ban": "مسدود کردن", "unban": "رفع مسدودیت", - "assign": "اختصاص" + "assign": "اختصاص", + "promo_group": "گروه تبلیغاتی", + "balance": "موجودی", + "subscription": "اشتراک", + "send_offer": "ارسال پیشنهاد", + "referral": "درصد ارجاع" }, "toggleSection": "تغییر وضعیت تمام مجوزهای {{section}}", "selectedPermissions_other": "{{count}} مجوز انتخاب شده", diff --git a/src/locales/ru.json b/src/locales/ru.json index 4c02a6a..9376a0d 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -3166,7 +3166,12 @@ "manage": "Управление", "ban": "Бан", "unban": "Разбан", - "assign": "Назначение" + "assign": "Назначение", + "promo_group": "Промо-группа", + "balance": "Баланс", + "subscription": "Подписка", + "send_offer": "Промо-предложение", + "referral": "Реф. процент" }, "toggleSection": "Переключить все права {{section}}", "selectedPermissions_one": "{{count}} разрешение выбрано", diff --git a/src/locales/zh.json b/src/locales/zh.json index b6b8d8a..d81072d 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -2406,7 +2406,12 @@ "manage": "管理", "ban": "封禁", "unban": "解封", - "assign": "分配" + "assign": "分配", + "promo_group": "促销组", + "balance": "余额", + "subscription": "订阅", + "send_offer": "发送优惠", + "referral": "推荐佣金" }, "toggleSection": "切换所有 {{section}} 权限", "selectedPermissions_other": "已选择 {{count}} 个权限", diff --git a/src/pages/AdminUserDetail.tsx b/src/pages/AdminUserDetail.tsx index 73b9db3..2399957 100644 --- a/src/pages/AdminUserDetail.tsx +++ b/src/pages/AdminUserDetail.tsx @@ -386,7 +386,7 @@ export default function AdminUserDetail() { useEffect(() => { if (activeTab === 'info') { loadReferrals(); - if (hasPermission('promo_groups:read')) loadPromoGroups(); + if (hasPermission('users:promo_group')) loadPromoGroups(); } if (activeTab === 'sync' && hasPermission('users:sync')) loadSyncStatus(); if (activeTab === 'subscription') { @@ -935,7 +935,7 @@ export default function AdminUserDetail() {
{t('admin.users.detail.promoGroup')} - {hasPermission('promo_groups:read') && ( + {hasPermission('users:promo_group') && ( + {hasPermission('users:referral') && ( + + )}
@@ -1358,72 +1360,78 @@ export default function AdminUserDetail() { )} {/* Actions */} -
-
- {t('admin.users.detail.subscription.actions')} -
-
- - - {subAction === 'extend' && ( - - )} - - {subAction === 'change_tariff' && ( + {hasPermission('users:subscription') && ( +
+
+ {t('admin.users.detail.subscription.actions')} +
+
- )} - + {subAction === 'extend' && ( + + )} + + {subAction === 'change_tariff' && ( + + )} + + +
-
+ )} - ) : ( + ) : hasPermission('users:subscription') ? (
{t('admin.users.detail.subscription.noActive')} @@ -1463,6 +1471,12 @@ export default function AdminUserDetail() {
+ ) : ( +
+
+ {t('admin.users.detail.subscription.noActive')} +
+
)} {/* Panel Info */} @@ -1788,39 +1802,41 @@ export default function AdminUserDetail() {
{/* Add/subtract form */} -
- - setBalanceDescription(e.target.value)} - placeholder={t('admin.users.detail.balance.descriptionPlaceholder')} - className="input" - maxLength={500} - /> -
- - + {hasPermission('users:balance') && ( +
+ + setBalanceDescription(e.target.value)} + placeholder={t('admin.users.detail.balance.descriptionPlaceholder')} + className="input" + maxLength={500} + /> +
+ + +
-
+ )} {/* Active promo offer */} {user.promo_offer_discount_percent > 0 && ( @@ -1869,38 +1885,40 @@ export default function AdminUserDetail() { )} {/* Send promo offer */} -
-
- {t('admin.users.detail.sendOffer')} + {hasPermission('users:send_offer') && ( +
+
+ {t('admin.users.detail.sendOffer')} +
+
+ + + +
-
- - - -
-
+ )} {/* Recent transactions */} {user.recent_transactions.length > 0 && (