diff --git a/controllers/application/academy/middlewares/isHalfRegister.js b/controllers/application/academy/middlewares/isHalfRegister.js index 823f8c6..72c3ec3 100644 --- a/controllers/application/academy/middlewares/isHalfRegister.js +++ b/controllers/application/academy/middlewares/isHalfRegister.js @@ -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({ diff --git a/controllers/application/academy/middlewares/isRegister.js b/controllers/application/academy/middlewares/isRegister.js index 516c584..262872b 100644 --- a/controllers/application/academy/middlewares/isRegister.js +++ b/controllers/application/academy/middlewares/isRegister.js @@ -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', diff --git a/controllers/application/login/loginWithUserName.js b/controllers/application/login/loginWithUserName.js index 387388d..ded6b6f 100644 --- a/controllers/application/login/loginWithUserName.js +++ b/controllers/application/login/loginWithUserName.js @@ -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, diff --git a/controllers/application/login/verifyController.js b/controllers/application/login/verifyController.js index 5d39c22..1ef37aa 100644 --- a/controllers/application/login/verifyController.js +++ b/controllers/application/login/verifyController.js @@ -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, diff --git a/controllers/application/profile/profileController.js b/controllers/application/profile/profileController.js index 47e8e13..bda10aa 100644 --- a/controllers/application/profile/profileController.js +++ b/controllers/application/profile/profileController.js @@ -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 || diff --git a/controllers/application/register/userFullNameController.js b/controllers/application/register/userFullNameController.js index f19cb2c..412a0b8 100644 --- a/controllers/application/register/userFullNameController.js +++ b/controllers/application/register/userFullNameController.js @@ -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({ diff --git a/controllers/application/register/usernameController.js b/controllers/application/register/usernameController.js index 28752c4..0fa941e 100644 --- a/controllers/application/register/usernameController.js +++ b/controllers/application/register/usernameController.js @@ -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() diff --git a/middlewares/isHalfRegister.js b/middlewares/isHalfRegister.js index 823f8c6..72c3ec3 100644 --- a/middlewares/isHalfRegister.js +++ b/middlewares/isHalfRegister.js @@ -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({ diff --git a/middlewares/isRegister.js b/middlewares/isRegister.js index 516c584..262872b 100644 --- a/middlewares/isRegister.js +++ b/middlewares/isRegister.js @@ -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', diff --git a/utils/usernameSuggestions.js b/utils/usernameSuggestions.js index 92c9833..51e26a7 100644 --- a/utils/usernameSuggestions.js +++ b/utils/usernameSuggestions.js @@ -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 }