104 lines
3.0 KiB
JavaScript
104 lines
3.0 KiB
JavaScript
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,
|
||
}
|