This commit is contained in:
payacom
2026-07-07 14:56:19 +03:30
parent abb6884dd0
commit 525565d685
10 changed files with 36 additions and 71 deletions

View File

@@ -28,6 +28,7 @@ module.exports = async (req, res, next) => {
const user = await UserModel.findById(decodedToken.id)
if (!user.user_name ||
!user.first_name ||
!user.last_name ||
!user.user_type ||
!user.password) {
return res.status(403).send({

View File

@@ -26,6 +26,7 @@ module.exports = async (req, res, next) => {
const user = await UserModel.findById(decodedToken.id)
if (!user.user_name ||
!user.first_name ||
!user.last_name ||
!user.password) {
return res.status(403).send({
status: 'error',

View File

@@ -64,7 +64,7 @@ const loginWithUserName = async (req, res, next) => {
(!user.password) { step = 'password' } else if
(!user.first_name) { step = 'first_name' } else if
(!user.user_type) { step = 'user_type' }
if (!user.user_type || user.user_name === null || !user.first_name) {
if (!user.user_type || user.user_name === null || !user.first_name || !user.last_name) {
return res.json({
message: 'کد تایید صحیح بود',
token,

View File

@@ -64,7 +64,7 @@ const verifyUser = async (req, res, next) => {
(!user.password) { step = 'password' } else if
(!user.first_name) { step = 'first_name' } else if
(!user.user_type) { step = 'user_type' } else { step = 'profile_image' }
if (!user.user_type || user.user_name === null || !user.first_name) {
if (!user.user_type || user.user_name === null || !user.first_name || !user.last_name) {
return res.json({
message: 'کد تایید صحیح بود',
token,

View File

@@ -81,6 +81,7 @@ const getProfile = async (req, res, next) => {
let isRegister = true
if (!user.user_name ||
!user.first_name ||
!user.last_name ||
!user.user_type ||
!user.national_card_image ||
!user.password ||

View File

@@ -7,6 +7,8 @@ const setUserFullNameValidationRules = () => {
return [
check('first_name')
.notEmpty().withMessage('نام نمی‌تواند خالی باشد'),
check('last_name')
.notEmpty().withMessage('نام خانوادگی نمی‌تواند خالی باشد')
]
}
@@ -33,7 +35,7 @@ const setUserFullName = async (req, res, next) => {
// آپدیت نام کاربری به صورت lowercase
user.first_name = first_name.trim().toLowerCase()
user.last_name = last_name?.trim() ? last_name.trim().toLowerCase() : null
user.last_name = last_name.trim().toLowerCase()
await user.save()
return res.json({

View File

@@ -14,7 +14,6 @@ const setUserName = async (req, res, next) => {
})
}
// جستجوی کاربر با شماره موبایل ارسالی
const user = await UserModel.findOne({ mobile })
if (!user) {
return res.status(404).json({
@@ -22,6 +21,7 @@ const setUserName = async (req, res, next) => {
message: 'کاربری با این شماره موبایل یافت نشد'
})
}
const validationError = validateUsername(user_name)
if (validationError) {
return res.status(422).json({
@@ -32,7 +32,6 @@ const setUserName = async (req, res, next) => {
const normalizedUserName = user_name.trim().toLowerCase()
// بررسی تکراری بودن user_name
const existingUser = await UserModel.findOne({ user_name: { $regex: new RegExp('^' + normalizedUserName + '$', 'i') } })
if (existingUser && existingUser._id.toString() !== user._id.toString()) {
const suggestions = await generateUsernameSuggestions(
@@ -47,7 +46,6 @@ const setUserName = async (req, res, next) => {
})
}
// آپدیت نام کاربری به صورت lowercase
user.user_name = normalizedUserName
await user.save()

View File

@@ -28,6 +28,7 @@ module.exports = async (req, res, next) => {
const user = await UserModel.findById(decodedToken.id)
if (!user.user_name ||
!user.first_name ||
!user.last_name ||
!user.user_type ||
!user.password) {
return res.status(403).send({

View File

@@ -26,6 +26,7 @@ module.exports = async (req, res, next) => {
const user = await UserModel.findById(decodedToken.id)
if (!user.user_name ||
!user.first_name ||
!user.last_name ||
!user.password) {
return res.status(403).send({
status: 'error',

View File

@@ -12,79 +12,40 @@ const isUsernameTaken = async (UserModel, userName, excludeUserId) => {
return true
}
const splitBaseAndSuffix = (value) => {
const match = value.match(/^(.*?)(\d+)$/)
if (!match || !match[1]) {
return { core: value, suffix: null }
}
return { core: match[1], suffix: Number.parseInt(match[2], 10) }
const buildCandidates = (base, attempt) => {
const random2 = () => String(Math.floor(Math.random() * 90 + 10))
const random3 = () => String(Math.floor(Math.random() * 900 + 100))
const random4 = () => String(Math.floor(Math.random() * 9000 + 1000))
const builders = [
() => `${base}_${random2()}`,
() => `${base}.${random2()}`,
() => `${base}${random3()}`,
() => `${base}-${random2()}`,
() => `${base}_${random3()}`,
() => `${base}${random4()}`,
]
return builders[attempt % builders.length]()
}
const trimToMax = (value) =>
value.length > USERNAME_MAX_LENGTH ? value.slice(0, USERNAME_MAX_LENGTH) : value
/** پیشنهادهای مشابه: amiri2 → amiri3, amiri5, amiiri3, amiri334 */
const buildCandidates = (base) => {
const { core, suffix } = splitBaseAndSuffix(base)
const candidates = []
if (suffix !== null && !Number.isNaN(suffix)) {
candidates.push(`${core}${suffix + 1}`)
candidates.push(`${core}${suffix + 3}`)
candidates.push(`${core}${suffix}${Math.floor(Math.random() * 9 + 1)}`)
}
const numericSuffixes = [3, 5, 7, 12, 21, 34, 99, 334, 567]
numericSuffixes.forEach((num) => {
candidates.push(`${core}${num}`)
})
for (let i = 1; i < Math.min(core.length, 5); i += 1) {
const ch = core[i]
if (!ch) continue
const doubled = `${core.slice(0, i)}${ch}${core.slice(i)}`
candidates.push(`${doubled}${suffix !== null ? suffix + 1 : 3}`)
candidates.push(`${doubled}${Math.floor(Math.random() * 90 + 10)}`)
}
candidates.push(`${core}_${suffix !== null ? suffix + 1 : 1}`)
candidates.push(`${core}.${Math.floor(Math.random() * 900 + 100)}`)
candidates.push(`${core}-${Math.floor(Math.random() * 90 + 10)}`)
return [...new Set(candidates.map(trimToMax))]
}
const generateUsernameSuggestions = async (
UserModel,
baseUsername,
excludeUserId,
count = 3
) => {
const base = baseUsername.trim().toLowerCase()
const generateUsernameSuggestions = async (UserModel, baseUserName, excludeUserId) => {
const base = trimToMax(baseUserName.trim().toLowerCase())
const suggestions = []
const tried = new Set([base])
let attempt = 0
for (let attempt = 0; attempt < 80 && suggestions.length < count; attempt += 1) {
const candidates = buildCandidates(base)
while (suggestions.length < 3 && attempt < 30) {
const candidate = trimToMax(buildCandidates(base, attempt))
attempt += 1
for (const candidate of candidates) {
if (suggestions.length >= count) break
if (tried.has(candidate)) continue
tried.add(candidate)
if (validateUsername(candidate)) continue
if (validateUsername(candidate)) continue
if (suggestions.includes(candidate)) continue
if (await isUsernameTaken(UserModel, candidate, excludeUserId)) continue
const taken = await isUsernameTaken(UserModel, candidate, excludeUserId)
if (!taken) suggestions.push(candidate)
}
if (suggestions.length < count) {
const fallback = trimToMax(`${base}${Math.floor(Math.random() * 9000 + 1000)}`)
if (!tried.has(fallback) && !validateUsername(fallback)) {
tried.add(fallback)
const taken = await isUsernameTaken(UserModel, fallback, excludeUserId)
if (!taken) suggestions.push(fallback)
}
}
suggestions.push(candidate)
}
return suggestions
@@ -92,5 +53,4 @@ const generateUsernameSuggestions = async (
module.exports = {
generateUsernameSuggestions,
isUsernameTaken
}