reels
This commit is contained in:
@@ -12,6 +12,11 @@ function isSocialUser (user) {
|
||||
}
|
||||
|
||||
function isBasicRegistrationComplete (user) {
|
||||
// کاربرِ زیرمجموعه همون لحظهی ساخت توسطِ صاحبِ اکانت کامل ساخته میشه (نام،
|
||||
// نامکاربری، رمز) — user_type براش معنا نداره، پس نباید وارد ویزاردِ ثبتنام بشه
|
||||
if (user?.is_sub_user) {
|
||||
return Boolean(user?.user_name && user?.password && user?.first_name)
|
||||
}
|
||||
const hasPassword = isSocialUser(user) || Boolean(user?.password)
|
||||
return Boolean(
|
||||
user?.user_name &&
|
||||
@@ -22,6 +27,7 @@ function isBasicRegistrationComplete (user) {
|
||||
}
|
||||
|
||||
function getRegistrationStep (user) {
|
||||
if (user?.is_sub_user) return 'complete'
|
||||
if (!user?.user_name) return 'user_name'
|
||||
if (!isSocialUser(user) && !user.password) return 'password'
|
||||
if (!user.first_name) return 'first_name'
|
||||
@@ -33,6 +39,14 @@ function isRegistrationIncomplete (user) {
|
||||
return !isBasicRegistrationComplete(user)
|
||||
}
|
||||
|
||||
/**
|
||||
* کاربر گوگلی/اینستاگرامی که هنوز نامکاربری یا رمز عبور ندارد — قبل از اولین
|
||||
* پیام یا ثبت درخواست همکاری باید تکمیلش کند (مودال ستکردن نامکاربری+رمز).
|
||||
*/
|
||||
function needsUsernameAndPassword (user) {
|
||||
return isSocialUser(user) && (!user?.user_name || !user?.password)
|
||||
}
|
||||
|
||||
function buildAuthResponse (user, token) {
|
||||
const step = getRegistrationStep(user)
|
||||
const incomplete = isRegistrationIncomplete(user)
|
||||
@@ -49,6 +63,8 @@ function buildAuthResponse (user, token) {
|
||||
page: incomplete ? 'auth-page' : 'home',
|
||||
user_type: incomplete ? null : user.user_type,
|
||||
registrationComplete: !incomplete,
|
||||
is_sub_user: Boolean(user.is_sub_user),
|
||||
sub_user_permissions: user.is_sub_user ? (user.sub_user_permissions || []) : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,5 +75,6 @@ module.exports = {
|
||||
isBasicRegistrationComplete,
|
||||
getRegistrationStep,
|
||||
isRegistrationIncomplete,
|
||||
needsUsernameAndPassword,
|
||||
buildAuthResponse
|
||||
}
|
||||
|
||||
34
utils/strongPasswordValidation.js
Normal file
34
utils/strongPasswordValidation.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* این پسورد پایهی رمزنگاری E2EE هم هست (کلید با آن wrap میشود)، برای همین
|
||||
* قانون قویتری از پسورد معمولیِ ثبتنام/تغییر رمز (که فقط حرف+عدد میخواهد) دارد.
|
||||
*/
|
||||
const STRONG_PASSWORD_MIN_LENGTH = 8
|
||||
const STRONG_PASSWORD_MAX_LENGTH = 64
|
||||
const STRONG_PASSWORD_REGEX = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,64}$/
|
||||
|
||||
const validateStrongPassword = (password) => {
|
||||
if (!password || typeof password !== 'string') {
|
||||
return 'رمز عبور الزامی است'
|
||||
}
|
||||
|
||||
if (password.length < STRONG_PASSWORD_MIN_LENGTH) {
|
||||
return `رمز عبور باید حداقل ${STRONG_PASSWORD_MIN_LENGTH} کاراکتر باشد`
|
||||
}
|
||||
|
||||
if (password.length > STRONG_PASSWORD_MAX_LENGTH) {
|
||||
return `رمز عبور نمیتواند بیشتر از ${STRONG_PASSWORD_MAX_LENGTH} کاراکتر باشد`
|
||||
}
|
||||
|
||||
if (!STRONG_PASSWORD_REGEX.test(password)) {
|
||||
return 'رمز عبور باید شامل حروف بزرگ، حروف کوچک، عدد و یک کاراکتر خاص باشد'
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
STRONG_PASSWORD_REGEX,
|
||||
STRONG_PASSWORD_MIN_LENGTH,
|
||||
STRONG_PASSWORD_MAX_LENGTH,
|
||||
validateStrongPassword
|
||||
}
|
||||
40
utils/subUserAuth.js
Normal file
40
utils/subUserAuth.js
Normal file
@@ -0,0 +1,40 @@
|
||||
const UserModel = require('../models/UserModel')
|
||||
|
||||
// وقتی توکن مالِ یه کاربرِ زیرمجموعهست (is_sub_user)، req.user باید اکانتِ اصلی
|
||||
// (parent_account_id) باشه — نه خودِ سندِ زیرمجموعه — تا همهی کنترلرهای فعلی
|
||||
// (پست/کامنت/فروشگاه/...) بدونِ هیچ تغییری محتوا رو به اکانتِ اصلی نسبت بدن.
|
||||
// req.actingSubUser فقط برای چکِ پرمیژن (requireSubUserPermission) استفاده میشه.
|
||||
// چون این لوکاپ هر بار از دیتابیس تازه انجام میشه (نه از خودِ JWT)، غیرفعالکردنِ
|
||||
// یه زیرمجموعه بلافاصله از درخواستِ بعدیش جلوگیری میکنه.
|
||||
async function resolveActingUser (userId) {
|
||||
const loaded = await UserModel.findById(userId)
|
||||
if (!loaded) {
|
||||
return { error: 'NOT_FOUND' }
|
||||
}
|
||||
|
||||
if (!loaded.is_sub_user) {
|
||||
return { user: loaded, actingSubUser: null, rawUser: loaded }
|
||||
}
|
||||
|
||||
if (loaded.sub_user_active === false) {
|
||||
return { error: 'SUB_USER_DISABLED' }
|
||||
}
|
||||
|
||||
const parent = loaded.parent_account_id
|
||||
? await UserModel.findById(loaded.parent_account_id)
|
||||
: null
|
||||
if (!parent) {
|
||||
return { error: 'NOT_FOUND' }
|
||||
}
|
||||
|
||||
return {
|
||||
user: parent,
|
||||
rawUser: loaded,
|
||||
actingSubUser: {
|
||||
_id: loaded._id,
|
||||
permissions: loaded.sub_user_permissions || []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { resolveActingUser }
|
||||
27
utils/subUserPermissions.js
Normal file
27
utils/subUserPermissions.js
Normal file
@@ -0,0 +1,27 @@
|
||||
// کاتالوگِ پرمیژنهایی که صاحبِ اکانت میتونه به کاربرِ زیرمجموعه بده — مطابقِ
|
||||
// utils/panelPermissions.js (همون الگو برای پنلِ ادمین)
|
||||
const SUB_USER_PERMISSIONS = [
|
||||
{ key: 'posts_stories', label: 'ثبت پست و استوری' },
|
||||
{ key: 'reply_dm', label: 'جواب دادن به دایرکت' },
|
||||
{ key: 'reply_comments', label: 'جواب دادن به کامنت' },
|
||||
{ key: 'create_shop', label: 'ساخت فروشگاه' },
|
||||
{ key: 'shop_products', label: 'ثبت و ویرایش کالا' },
|
||||
{ key: 'order_status', label: 'تغییر وضعیت سفارشات' },
|
||||
{ key: 'billboards', label: 'ساخت و ویرایش بیلبورد' },
|
||||
{ key: 'projects', label: 'ساخت و مدیریت پروژه' },
|
||||
{ key: 'academy_packages', label: 'ساخت و مدیریت پکیج آموزشی' },
|
||||
{ key: 'bookings', label: 'ساخت رزرو آنلاین' }
|
||||
]
|
||||
|
||||
const SUB_USER_PERMISSION_KEYS = new Set(SUB_USER_PERMISSIONS.map((p) => p.key))
|
||||
|
||||
function sanitizeSubUserPermissions (input) {
|
||||
if (!Array.isArray(input)) return []
|
||||
return [...new Set(input.filter((key) => SUB_USER_PERMISSION_KEYS.has(key)))]
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
SUB_USER_PERMISSIONS,
|
||||
SUB_USER_PERMISSION_KEYS,
|
||||
sanitizeSubUserPermissions
|
||||
}
|
||||
@@ -7,7 +7,10 @@ function isVerifiedBadge (badge) {
|
||||
}
|
||||
|
||||
function computeVerifyBadge ({ is_verified, license_verified, gold_badge }) {
|
||||
if (gold_badge) return 'gold'
|
||||
// تیک طلایی فقط زمانی نمایش داده میشه که کاربر از قبل مدارک هویتش (تیک آبی)
|
||||
// هم تایید شده باشه — وگرنه فعال بودنِ gold_badge (مثلاً بهاشتباه یا قبل از
|
||||
// تایید مدارک) نباید تیک آبیِ تازهتاییدشده رو بپوشونه
|
||||
if (gold_badge && is_verified === 'verified') return 'gold'
|
||||
if (license_verified) return 'green'
|
||||
if (is_verified === 'verified') return 'blue'
|
||||
if (is_verified === 'pending') return 'gray'
|
||||
|
||||
Reference in New Issue
Block a user