首次完整推送,
V:1.20240808.006
This commit is contained in:
@ -0,0 +1,246 @@
|
||||
const {
|
||||
findUser
|
||||
} = require('./account')
|
||||
const {
|
||||
userCollection,
|
||||
LOG_TYPE
|
||||
} = require('../../common/constants')
|
||||
const {
|
||||
ERROR
|
||||
} = require('../../common/error')
|
||||
const {
|
||||
logout
|
||||
} = require('./logout')
|
||||
const PasswordUtils = require('./password')
|
||||
|
||||
async function realPreLogin (params = {}) {
|
||||
const {
|
||||
user
|
||||
} = params
|
||||
const appId = this.getUniversalClientInfo().appId
|
||||
const {
|
||||
total,
|
||||
userMatched
|
||||
} = await findUser({
|
||||
userQuery: user,
|
||||
authorizedApp: appId
|
||||
})
|
||||
if (userMatched.length === 0) {
|
||||
if (total > 0) {
|
||||
throw {
|
||||
errCode: ERROR.ACCOUNT_NOT_EXISTS_IN_CURRENT_APP
|
||||
}
|
||||
}
|
||||
throw {
|
||||
errCode: ERROR.ACCOUNT_NOT_EXISTS
|
||||
}
|
||||
} else if (userMatched.length > 1) {
|
||||
throw {
|
||||
errCode: ERROR.ACCOUNT_CONFLICT
|
||||
}
|
||||
}
|
||||
const userRecord = userMatched[0]
|
||||
checkLoginUserRecord(userRecord)
|
||||
return userRecord
|
||||
}
|
||||
|
||||
async function preLogin (params = {}) {
|
||||
const {
|
||||
user
|
||||
} = params
|
||||
try {
|
||||
const user = await realPreLogin.call(this, params)
|
||||
return user
|
||||
} catch (error) {
|
||||
await this.middleware.uniIdLog({
|
||||
success: false,
|
||||
data: user,
|
||||
type: LOG_TYPE.LOGIN
|
||||
})
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function preLoginWithPassword (params = {}) {
|
||||
const {
|
||||
user,
|
||||
password
|
||||
} = params
|
||||
try {
|
||||
const userRecord = await realPreLogin.call(this, params)
|
||||
const {
|
||||
passwordErrorLimit,
|
||||
passwordErrorRetryTime
|
||||
} = this.config
|
||||
const {
|
||||
clientIP
|
||||
} = this.getUniversalClientInfo()
|
||||
// 根据ip地址,密码错误次数过多,锁定登录
|
||||
let loginIPLimit = userRecord.login_ip_limit || []
|
||||
// 清理无用记录
|
||||
loginIPLimit = loginIPLimit.filter(item => item.last_error_time > Date.now() - passwordErrorRetryTime * 1000)
|
||||
let currentIPLimit = loginIPLimit.find(item => item.ip === clientIP)
|
||||
if (currentIPLimit && currentIPLimit.error_times >= passwordErrorLimit) {
|
||||
throw {
|
||||
errCode: ERROR.PASSWORD_ERROR_EXCEED_LIMIT
|
||||
}
|
||||
}
|
||||
const passwordUtils = new PasswordUtils({
|
||||
userRecord,
|
||||
clientInfo: this.getUniversalClientInfo(),
|
||||
passwordSecret: this.config.passwordSecret
|
||||
})
|
||||
|
||||
const {
|
||||
success: checkPasswordSuccess,
|
||||
refreshPasswordInfo
|
||||
} = passwordUtils.checkUserPassword({
|
||||
password
|
||||
})
|
||||
if (!checkPasswordSuccess) {
|
||||
// 更新用户ip对应的密码错误记录
|
||||
if (!currentIPLimit) {
|
||||
currentIPLimit = {
|
||||
ip: clientIP,
|
||||
error_times: 1,
|
||||
last_error_time: Date.now()
|
||||
}
|
||||
loginIPLimit.push(currentIPLimit)
|
||||
} else {
|
||||
currentIPLimit.error_times++
|
||||
currentIPLimit.last_error_time = Date.now()
|
||||
}
|
||||
await userCollection.doc(userRecord._id).update({
|
||||
login_ip_limit: loginIPLimit
|
||||
})
|
||||
throw {
|
||||
errCode: ERROR.PASSWORD_ERROR
|
||||
}
|
||||
}
|
||||
const extraData = {}
|
||||
if (refreshPasswordInfo) {
|
||||
extraData.password = refreshPasswordInfo.passwordHash
|
||||
extraData.password_secret_version = refreshPasswordInfo.version
|
||||
}
|
||||
|
||||
const currentIPLimitIndex = loginIPLimit.indexOf(currentIPLimit)
|
||||
if (currentIPLimitIndex > -1) {
|
||||
loginIPLimit.splice(currentIPLimitIndex, 1)
|
||||
}
|
||||
extraData.login_ip_limit = loginIPLimit
|
||||
return {
|
||||
user: userRecord,
|
||||
extraData
|
||||
}
|
||||
} catch (error) {
|
||||
await this.middleware.uniIdLog({
|
||||
success: false,
|
||||
data: user,
|
||||
type: LOG_TYPE.LOGIN
|
||||
})
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
function checkLoginUserRecord (user) {
|
||||
switch (user.status) {
|
||||
case undefined:
|
||||
case 0:
|
||||
break
|
||||
case 1:
|
||||
throw {
|
||||
errCode: ERROR.ACCOUNT_BANNED
|
||||
}
|
||||
case 2:
|
||||
throw {
|
||||
errCode: ERROR.ACCOUNT_AUDITING
|
||||
}
|
||||
case 3:
|
||||
throw {
|
||||
errCode: ERROR.ACCOUNT_AUDIT_FAILED
|
||||
}
|
||||
case 4:
|
||||
throw {
|
||||
errCode: ERROR.ACCOUNT_CLOSED
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
async function thirdPartyLogin (params = {}) {
|
||||
const {
|
||||
user
|
||||
} = params
|
||||
return {
|
||||
mobileConfirmed: !!user.mobile_confirmed,
|
||||
emailConfirmed: !!user.email_confirmed
|
||||
}
|
||||
}
|
||||
|
||||
async function postLogin (params = {}) {
|
||||
const {
|
||||
user,
|
||||
extraData,
|
||||
isThirdParty = false
|
||||
} = params
|
||||
const {
|
||||
clientIP
|
||||
} = this.getUniversalClientInfo()
|
||||
const uniIdToken = this.getUniversalUniIdToken()
|
||||
const uid = user._id
|
||||
const updateData = {
|
||||
last_login_date: Date.now(),
|
||||
last_login_ip: clientIP,
|
||||
...extraData
|
||||
}
|
||||
const createTokenRes = await this.uniIdCommon.createToken({
|
||||
uid
|
||||
})
|
||||
|
||||
const {
|
||||
errCode,
|
||||
token,
|
||||
tokenExpired
|
||||
} = createTokenRes
|
||||
if (errCode) {
|
||||
throw createTokenRes
|
||||
}
|
||||
|
||||
if (uniIdToken) {
|
||||
try {
|
||||
await logout.call(this)
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
await userCollection.doc(uid).update(updateData)
|
||||
await this.middleware.uniIdLog({
|
||||
data: {
|
||||
user_id: uid
|
||||
},
|
||||
type: LOG_TYPE.LOGIN
|
||||
})
|
||||
return {
|
||||
errCode: 0,
|
||||
newToken: {
|
||||
token,
|
||||
tokenExpired
|
||||
},
|
||||
uid,
|
||||
...(
|
||||
isThirdParty
|
||||
? thirdPartyLogin({
|
||||
user
|
||||
})
|
||||
: {}
|
||||
),
|
||||
passwordConfirmed: !!user.password
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
preLogin,
|
||||
postLogin,
|
||||
checkLoginUserRecord,
|
||||
preLoginWithPassword
|
||||
}
|
Reference in New Issue
Block a user