This commit is contained in:
payacom
2026-08-31 20:45:41 +03:30
parent fa9f23c61d
commit 3f416a7a60
367 changed files with 621895 additions and 6443 deletions

103
utils/ensureUserIndexes.js Normal file
View File

@@ -0,0 +1,103 @@
const UserModel = require('../models/UserModel')
const SPARSE_UNIQUE_FIELDS = ['mobile', 'email', 'google_id']
/**
* ایندکس unique غیر-sparse روی mobile باعث می‌شود فقط یک کاربر بدون موبایل
* در دیتابیس مجاز باشد (dup key: { mobile: null }).
* این تابع nullها را unset می‌کند و ایندکس‌ها را sparse می‌سازد.
*/
async function ensureUserSparseUniqueIndexes () {
const collection = UserModel.collection
for (const field of SPARSE_UNIQUE_FIELDS) {
try {
const unsetResult = await collection.updateMany(
{ [field]: null },
{ $unset: { [field]: '' } }
)
if (unsetResult.modifiedCount > 0) {
console.log(
`[ensureUserIndexes] unset null ${field}: ${unsetResult.modifiedCount}`
)
}
} catch (err) {
console.error(`[ensureUserIndexes] unset ${field} failed:`, err.message)
}
}
try {
const indexes = await collection.indexes()
for (const field of SPARSE_UNIQUE_FIELDS) {
const existing = indexes.filter(
(idx) =>
idx.key &&
Object.keys(idx.key).length === 1 &&
idx.key[field] === 1 &&
idx.unique
)
for (const idx of existing) {
const isSparse = Boolean(idx.sparse)
if (!isSparse) {
try {
await collection.dropIndex(idx.name)
console.log(`[ensureUserIndexes] dropped non-sparse index ${idx.name}`)
} catch (err) {
console.error(
`[ensureUserIndexes] drop ${idx.name} failed:`,
err.message
)
}
}
}
}
for (const field of SPARSE_UNIQUE_FIELDS) {
const name = `${field}_1`
try {
await collection.createIndex(
{ [field]: 1 },
{ unique: true, sparse: true, name, background: true }
)
console.log(`[ensureUserIndexes] ensured sparse unique index ${name}`)
} catch (err) {
// already exists with same options
if (err?.code !== 85 && err?.code !== 86) {
console.error(
`[ensureUserIndexes] create ${name} failed:`,
err.message
)
}
}
}
} catch (err) {
console.error('[ensureUserIndexes] index sync failed:', err.message)
}
// کاربران pending بدون کارت ملی نباید تیک خاکستری داشته باشند
try {
const cleaned = await collection.updateMany(
{
is_verified: 'pending',
$or: [
{ national_card_image: null },
{ national_card_image: { $exists: false } },
{ national_card_image: '' },
],
},
{ $set: { is_verified: 'none' } }
)
if (cleaned.modifiedCount > 0) {
console.log(
`[ensureUserIndexes] cleared pending without card: ${cleaned.modifiedCount}`
)
}
} catch (err) {
console.error('[ensureUserIndexes] pending cleanup failed:', err.message)
}
}
module.exports = {
ensureUserSparseUniqueIndexes,
}