提交 63d5a802 编写于 作者: DCloud_JSON's avatar DCloud_JSON

update uni-id-co

上级 9c928886
...@@ -198,52 +198,6 @@ function getRuleCategory(rule) { ...@@ -198,52 +198,6 @@ function getRuleCategory(rule) {
} }
} }
function isMatchUnionType(val, rule) {
if (!rule.children || rule.children.length === 0) {
return true
}
const children = rule.children
for (let i = 0; i < children.length; i++) {
const child = children[i]
const category = getRuleCategory(child)
let pass = false
switch (category) {
case 'base':
pass = isMatchBaseType(val, child)
break
case 'array':
pass = isMatchArrayType(val, child)
break
default:
break
}
if (pass) {
return true
}
}
return false
}
function isMatchBaseType(val, rule) {
if (typeof baseValidator[rule.type] !== 'function') {
throw new Error(`invalid schema type: ${rule.type}`)
}
const validateRes = baseValidator[rule.type](val)
if (validateRes && validateRes.errCode) {
return false
}
return true
}
function isMatchArrayType(arr, rule) {
if (getType(arr) !== 'array') {
return false
}
if (rule.children && rule.children.length && arr.some(item => !isMatchUnionType(item, rule))) {
return false
}
return true
}
// 特殊符号 https://www.ibm.com/support/pages/password-strength-rules ~!@#$%^&*_-+=`|\(){}[]:;"'<>,.?/ // 特殊符号 https://www.ibm.com/support/pages/password-strength-rules ~!@#$%^&*_-+=`|\(){}[]:;"'<>,.?/
// const specialChar = '~!@#$%^&*_-+=`|\(){}[]:;"\'<>,.?/' // const specialChar = '~!@#$%^&*_-+=`|\(){}[]:;"\'<>,.?/'
...@@ -320,7 +274,57 @@ class Validator { ...@@ -320,7 +274,57 @@ class Validator {
return this.customValidator[type] || this.baseValidator[type] return this.customValidator[type] || this.baseValidator[type]
} }
_isMatchUnionType(val, rule) {
if (!rule.children || rule.children.length === 0) {
return true
}
const children = rule.children
for (let i = 0; i < children.length; i++) {
const child = children[i]
const category = getRuleCategory(child)
let pass = false
switch (category) {
case 'base':
pass = this._isMatchBaseType(val, child)
break
case 'array':
pass = this._isMatchArrayType(val, child)
break
default:
break
}
if (pass) {
return true
}
}
return false
}
_isMatchBaseType(val, rule) {
const method = this.getRealBaseValidator(rule.type)
if (typeof method !== 'function') {
throw new Error(`invalid schema type: ${rule.type}`)
}
const validateRes = method(val)
if (validateRes && validateRes.errCode) {
return false
}
return true
}
_isMatchArrayType(arr, rule) {
if (getType(arr) !== 'array') {
return false
}
if (rule.children && rule.children.length && arr.some(item => !this._isMatchUnionType(item, rule))) {
return false
}
return true
}
get validator() { get validator() {
const _this = this
return new Proxy({}, { return new Proxy({}, {
get: (_, prop) => { get: (_, prop) => {
if (typeof prop !== 'string') { if (typeof prop !== 'string') {
...@@ -332,7 +336,7 @@ class Validator { ...@@ -332,7 +336,7 @@ class Validator {
} }
const rule = parseValidatorName(prop) const rule = parseValidatorName(prop)
return function (val) { return function (val) {
if (!isMatchUnionType(val, rule)) { if (!_this._isMatchUnionType(val, rule)) {
return { return {
errCode: ERROR.INVALID_PARAM errCode: ERROR.INVALID_PARAM
} }
......
const word = { const word = {
login: 'login', login: 'login',
'verify-mobile': 'verify mobile number' 'verify-mobile': 'verify phone number'
} }
const sentence = { const sentence = {
'uni-id-account-exists': 'Account exists', 'uni-id-account-exists': 'Account exists',
'uni-id-account-not-exists': 'Account does not exists', 'uni-id-account-not-exists': 'Account does not exists',
'uni-id-account-not-exists-in-current-app': 'Account does not exists in current app', 'uni-id-account-not-exists-in-current-app': 'Account does not exists in current app',
'uni-id-account-conflict': 'User account conflict', 'uni-id-account-conflict': 'User account conflict',
'uni-id-account-banned': 'Account has been banned', 'uni-id-account-banned': 'Account has been banned',
'uni-id-account-auditing': 'Account audit in progress', 'uni-id-account-auditing': 'Account audit in progress',
'uni-id-account-audit-failed': 'Account audit failed', 'uni-id-account-audit-failed': 'Account audit failed',
'uni-id-account-closed': 'Account has been closed', 'uni-id-account-closed': 'Account has been closed',
'uni-id-captcha-required': 'Captcha required', 'uni-id-captcha-required': 'Captcha required',
'uni-id-password-error': 'Password error', 'uni-id-password-error': 'Password error',
'uni-id-password-error-exceed-limit': 'The number of password errors is excessive', 'uni-id-password-error-exceed-limit': 'The number of password errors is excessive',
'uni-id-invalid-username': 'Invalid username', 'uni-id-invalid-username': 'Invalid username',
'uni-id-invalid-password': 'invalid password', 'uni-id-invalid-password': 'invalid password',
'uni-id-invalid-password-super': 'Passwords must have 8-16 characters and contain uppercase letters, lowercase letters, numbers, and symbols.', 'uni-id-invalid-password-super': 'Passwords must have 8-16 characters and contain uppercase letters, lowercase letters, numbers, and symbols.',
'uni-id-invalid-password-strong': 'Passwords must have 8-16 characters and contain letters, numbers and symbols.', 'uni-id-invalid-password-strong': 'Passwords must have 8-16 characters and contain letters, numbers and symbols.',
'uni-id-invalid-password-medium': 'Passwords must have 8-16 characters and contain at least two of the following: letters, numbers, and symbols.', 'uni-id-invalid-password-medium': 'Passwords must have 8-16 characters and contain at least two of the following: letters, numbers, and symbols.',
'uni-id-invalid-password-weak': 'Passwords must have 6-16 characters and contain letters and numbers.', 'uni-id-invalid-password-weak': 'Passwords must have 6-16 characters and contain letters and numbers.',
'uni-id-invalid-mobile': 'Invalid mobile mobile number', 'uni-id-invalid-mobile': 'Invalid mobile phone number',
'uni-id-invalid-email': 'Invalid email address', 'uni-id-invalid-email': 'Invalid email address',
'uni-id-invalid-nickname': 'Invalid nickname', 'uni-id-invalid-nickname': 'Invalid nickname',
'uni-id-invalid-param': 'Invalid parameter', 'uni-id-invalid-param': 'Invalid parameter',
'uni-id-param-required': 'Parameter required: {param}', 'uni-id-param-required': 'Parameter required: {param}',
'uni-id-get-third-party-account-failed': 'Get third party account failed', 'uni-id-get-third-party-account-failed': 'Get third party account failed',
'uni-id-get-third-party-user-info-failed': 'Get third party user info failed', 'uni-id-get-third-party-user-info-failed': 'Get third party user info failed',
'uni-id-mobile-verify-code-error': 'Verify code error or expired', 'uni-id-mobile-verify-code-error': 'Verify code error or expired',
'uni-id-email-verify-code-error': 'Verify code error or expired', 'uni-id-email-verify-code-error': 'Verify code error or expired',
'uni-id-admin-exists': 'Administrator exists', 'uni-id-admin-exists': 'Administrator exists',
'uni-id-permission-error': 'Permission denied', 'uni-id-permission-error': 'Permission denied',
'uni-id-system-error': 'System error', 'uni-id-system-error': 'System error',
'uni-id-set-invite-code-failed': 'Set invite code failed', 'uni-id-set-invite-code-failed': 'Set invite code failed',
'uni-id-invalid-invite-code': 'Invalid invite code', 'uni-id-invalid-invite-code': 'Invalid invite code',
'uni-id-change-inviter-forbidden': 'Change inviter is not allowed', 'uni-id-change-inviter-forbidden': 'Change inviter is not allowed',
'uni-id-bind-conflict': 'This account has been bound', 'uni-id-bind-conflict': 'This account has been bound',
'uni-id-admin-exist-in-other-apps': 'Administrator is registered in other consoles', 'uni-id-admin-exist-in-other-apps': 'Administrator is registered in other consoles',
'uni-id-unbind-failed': 'Please bind first and then unbind', 'uni-id-unbind-failed': 'Please bind first and then unbind',
'uni-id-unbind-not-supported': 'Unbinding is not supported', 'uni-id-unbind-not-supported': 'Unbinding is not supported',
'uni-id-unbind-mobile-not-exists': 'This is the only way to login at the moment, please bind your mobile number and then try to unbind', 'uni-id-unbind-mobile-not-exists': 'This is the only way to login at the moment, please bind your phone number and then try to unbind',
'uni-id-unbind-password-not-exists': 'Please set a password first', 'uni-id-unbind-password-not-exists': 'Please set a password first',
'uni-id-unsupported-request': 'Unsupported request', 'uni-id-unsupported-request': 'Unsupported request',
'uni-id-illegal-request': 'Illegal request', 'uni-id-illegal-request': 'Illegal request',
'uni-id-config-field-required': 'Config field required: {field}', 'uni-id-config-field-required': 'Config field required: {field}',
'uni-id-config-field-invalid': 'Config field: {field} is invalid', 'uni-id-config-field-invalid': 'Config field: {field} is invalid',
'uni-id-frv-fail': 'Real name certify failed', 'uni-id-frv-fail': 'Real name certify failed',
'uni-id-frv-processing': 'Waiting for face recognition', 'uni-id-frv-processing': 'Waiting for face recognition',
'uni-id-realname-verified': 'This account has been verified', 'uni-id-realname-verified': 'This account has been verified',
'uni-id-idcard-exists': 'The ID number has been bound to the account', 'uni-id-idcard-exists': 'The ID number has been bound to the account',
'uni-id-invalid-idcard': 'ID number is invalid', 'uni-id-invalid-idcard': 'ID number is invalid',
'uni-id-invalid-realname': 'The name can only be Chinese characters', 'uni-id-invalid-realname': 'The name can only be Chinese characters',
'uni-id-unknown-error': 'unknown error', 'uni-id-unknown-error': 'unknown error',
'uni-id-realname-verify-upper-limit': 'The number of real-name certify on the day has reached the upper limit' 'uni-id-realname-verify-upper-limit': 'The number of real-name certify on the day has reached the upper limit'
} }
module.exports = { module.exports = {
...word, ...word,
...sentence ...sentence
} }
const { const {
callWxOpenApi, callWxOpenApi,
buildUrl buildUrl
} = require('../normalize') } = require('../normalize')
module.exports = class Auth { module.exports = class Auth {
constructor (options) { constructor (options) {
this.options = Object.assign({ this.options = Object.assign({
baseUrl: 'https://api.weixin.qq.com', baseUrl: 'https://api.weixin.qq.com',
timeout: 5000 timeout: 5000
}, options) }, options)
} }
async _requestWxOpenapi ({ name, url, data, options }) { async _requestWxOpenapi ({ name, url, data, options }) {
const defaultOptions = { const defaultOptions = {
method: 'GET', method: 'GET',
dataType: 'json', dataType: 'json',
dataAsQueryString: true, dataAsQueryString: true,
timeout: this.options.timeout timeout: this.options.timeout
} }
const result = await callWxOpenApi({ const result = await callWxOpenApi({
name: `auth.${name}`, name: `auth.${name}`,
url: `${this.options.baseUrl}${buildUrl(url, data)}`, url: `${this.options.baseUrl}${buildUrl(url, data)}`,
data, data,
options, options,
defaultOptions defaultOptions
}) })
return result return result
} }
async code2Session (code) { async code2Session (code) {
const url = '/sns/jscode2session' const url = '/sns/jscode2session'
const result = await this._requestWxOpenapi({ const result = await this._requestWxOpenapi({
name: 'code2Session', name: 'code2Session',
url, url,
data: { data: {
grant_type: 'authorization_code', grant_type: 'authorization_code',
appid: this.options.appId, appid: this.options.appId,
secret: this.options.secret, secret: this.options.secret,
js_code: code js_code: code
} }
}) })
return result return result
} }
async getOauthAccessToken (code) { async getOauthAccessToken (code) {
const url = '/sns/oauth2/access_token' const url = '/sns/oauth2/access_token'
const result = await this._requestWxOpenapi({ const result = await this._requestWxOpenapi({
name: 'getOauthAccessToken', name: 'getOauthAccessToken',
url, url,
data: { data: {
grant_type: 'authorization_code', grant_type: 'authorization_code',
appid: this.options.appId, appid: this.options.appId,
secret: this.options.secret, secret: this.options.secret,
code code
} }
}) })
if (result.expiresIn) { if (result.expiresIn) {
result.expired = Date.now() + result.expiresIn * 1000 result.expired = Date.now() + result.expiresIn * 1000
// delete result.expiresIn // delete result.expiresIn
} }
return result return result
} }
async getUserInfo ({ async getUserInfo ({
accessToken, accessToken,
openid openid
} = {}) { } = {}) {
const url = '/sns/userinfo' const url = '/sns/userinfo'
const { const {
nickname, nickname,
headimgurl: avatar headimgurl: avatar
} = await this._requestWxOpenapi({ } = await this._requestWxOpenapi({
name: 'getUserInfo', name: 'getUserInfo',
url, url,
data: { data: {
accessToken, accessToken,
openid, openid,
appid: this.options.appId, appid: this.options.appId,
secret: this.options.secret, secret: this.options.secret,
scope: 'snsapi_userinfo' scope: 'snsapi_userinfo'
} }
}) })
return { return {
nickname, nickname,
avatar avatar
} }
} }
async getmobileNumber (accessToken, code) { async getPhoneNumber (accessToken, code) {
const url = `/wxa/business/getusermobilenumber?access_token=${accessToken}` const url = `/wxa/business/getuserphonenumber?access_token=${accessToken}`
const { mobileInfo } = await this._requestWxOpenapi({ const { phoneInfo } = await this._requestWxOpenapi({
name: 'getmobileNumber', name: 'getPhoneNumber',
url, url,
data: { data: {
code code
}, },
options: { options: {
method: 'POST', method: 'POST',
dataAsQueryString: false, dataAsQueryString: false,
headers: { headers: {
'content-type': 'application/json' 'content-type': 'application/json'
} }
} }
}) })
return { return {
puremobileNumber: mobileInfo.puremobileNumber purePhoneNumber: phoneInfo.purePhoneNumber
} }
} }
} }
...@@ -22,8 +22,6 @@ async function sendSmsCode ({ ...@@ -22,8 +22,6 @@ async function sendSmsCode ({
} = {}) { } = {}) {
const requiredParams = [ const requiredParams = [
'name', 'name',
'smsKey',
'smsSecret',
'codeExpiresIn' 'codeExpiresIn'
] ]
const smsConfig = (this.config.service && this.config.service.sms) || {} const smsConfig = (this.config.service && this.config.service.sms) || {}
...@@ -62,7 +60,7 @@ async function sendSmsCode ({ ...@@ -62,7 +60,7 @@ async function sendSmsCode ({
await uniCloud.sendSms({ await uniCloud.sendSms({
smsKey: smsConfig.smsKey, smsKey: smsConfig.smsKey,
smsSecret: smsConfig.smsSecret, smsSecret: smsConfig.smsSecret,
mobile: mobile, phone: mobile,
templateId, templateId,
data: { data: {
name: smsConfig.name, name: smsConfig.name,
......
async function getmobileNumber ({ async function getPhoneNumber ({
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
access_token, access_token,
openid openid
} = {}) { } = {}) {
const requiredParams = ['apiKey', 'apiSecret'] const requiredParams = []
const univerifyConfig = (this.config.service && this.config.service.univerify) || {} const univerifyConfig = (this.config.service && this.config.service.univerify) || {}
for (let i = 0; i < requiredParams.length; i++) { for (let i = 0; i < requiredParams.length; i++) {
const key = requiredParams[i] const key = requiredParams[i]
...@@ -11,7 +11,7 @@ async function getmobileNumber ({ ...@@ -11,7 +11,7 @@ async function getmobileNumber ({
throw new Error(`Missing config param: service.univerify.${key}`) throw new Error(`Missing config param: service.univerify.${key}`)
} }
} }
return uniCloud.getmobileNumber({ return uniCloud.getPhoneNumber({
provider: 'univerify', provider: 'univerify',
appid: this.getUniversalClientInfo().appId, appid: this.getUniversalClientInfo().appId,
apiKey: univerifyConfig.apiKey, apiKey: univerifyConfig.apiKey,
...@@ -23,5 +23,5 @@ async function getmobileNumber ({ ...@@ -23,5 +23,5 @@ async function getmobileNumber ({
} }
module.exports = { module.exports = {
getmobileNumber getPhoneNumber
} }
...@@ -67,6 +67,8 @@ module.exports = function () { ...@@ -67,6 +67,8 @@ module.exports = function () {
.join('&') .join('&')
if (isNaN(Number(timestamp)) || (Number(timestamp) + timeout) < Date.now()) { if (isNaN(Number(timestamp)) || (Number(timestamp) + timeout) < Date.now()) {
console.error('[timestamp error], timestamp:', timestamp, 'timeout:', timeout)
throw { throw {
errCode: ERROR.ILLEGAL_REQUEST errCode: ERROR.ILLEGAL_REQUEST
} }
...@@ -75,6 +77,7 @@ module.exports = function () { ...@@ -75,6 +77,7 @@ module.exports = function () {
const reSignature = crypto.createHmac('sha256', `${this.config.requestAuthSecret + nonce}`).update(`${timestamp}${bodyStr}`).digest('hex') const reSignature = crypto.createHmac('sha256', `${this.config.requestAuthSecret + nonce}`).update(`${timestamp}${bodyStr}`).digest('hex')
if (signature !== reSignature.toUpperCase()) { if (signature !== reSignature.toUpperCase()) {
console.error('[signature error], signature:', signature, 'reSignature:', reSignature.toUpperCase(), 'requestAuthSecret:', this.config.requestAuthSecret)
throw { throw {
errCode: ERROR.ILLEGAL_REQUEST errCode: ERROR.ILLEGAL_REQUEST
} }
......
const { const {
setUserStatus setUserStatus
} = require('../../lib/utils/update-user-info') } = require('../../lib/utils/update-user-info')
const { const {
USER_STATUS USER_STATUS
} = require('../../common/constants') } = require('../../common/constants')
/** /**
* 注销账户 * 注销账户
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#close-account * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#close-account
* @returns * @returns
*/ */
module.exports = async function () { module.exports = async function () {
const { uid } = this.authInfo const { uid } = this.authInfo
return setUserStatus(uid, USER_STATUS.CLOSED) return setUserStatus(uid, USER_STATUS.CLOSED)
} }
const { const {
userCollection userCollection
} = require('../../common/constants') } = require('../../common/constants')
const { const {
ERROR ERROR
} = require('../../common/error') } = require('../../common/error')
function isUsernameSet (userRecord) { function isUsernameSet (userRecord) {
return !!userRecord.username return !!userRecord.username
} }
function isNicknameSet (userRecord) { function isNicknameSet (userRecord) {
return !!userRecord.nickname return !!userRecord.nickname
} }
function isPasswordSet (userRecord) { function isPasswordSet (userRecord) {
return !!userRecord.password return !!userRecord.password
} }
function isMobileBound (userRecord) { function isMobileBound (userRecord) {
return !!(userRecord.mobile && userRecord.mobile_confirmed) return !!(userRecord.mobile && userRecord.mobile_confirmed)
} }
function isEmailBound (userRecord) { function isEmailBound (userRecord) {
return !!(userRecord.email && userRecord.email_confirmed) return !!(userRecord.email && userRecord.email_confirmed)
} }
function isWeixinBound (userRecord) { function isWeixinBound (userRecord) {
return !!( return !!(
userRecord.wx_unionid || userRecord.wx_unionid ||
Object.keys(userRecord.wx_openid || {}).length Object.keys(userRecord.wx_openid || {}).length
) )
} }
function isQQBound (userRecord) { function isQQBound (userRecord) {
return !!( return !!(
userRecord.qq_unionid || userRecord.qq_unionid ||
Object.keys(userRecord.qq_openid || {}).length Object.keys(userRecord.qq_openid || {}).length
) )
} }
function isAlipayBound (userRecord) { function isAlipayBound (userRecord) {
return !!userRecord.ali_openid return !!userRecord.ali_openid
} }
function isAppleBound (userRecord) { function isAppleBound (userRecord) {
return !!userRecord.apple_openid return !!userRecord.apple_openid
} }
/** /**
* 获取账户账户简略信息 * 获取账户账户简略信息
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#get-account-info * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#get-account-info
*/ */
module.exports = async function () { module.exports = async function () {
const { const {
uid uid
} = this.authInfo } = this.authInfo
const getUserRes = await userCollection.doc(uid).get() const getUserRes = await userCollection.doc(uid).get()
const userRecord = getUserRes && getUserRes.data && getUserRes.data[0] const userRecord = getUserRes && getUserRes.data && getUserRes.data[0]
if (!userRecord) { if (!userRecord) {
throw { throw {
errCode: ERROR.ACCOUNT_NOT_EXISTS errCode: ERROR.ACCOUNT_NOT_EXISTS
} }
} }
return { return {
errCode: 0, errCode: 0,
isUsernameSet: isUsernameSet(userRecord), isUsernameSet: isUsernameSet(userRecord),
isNicknameSet: isNicknameSet(userRecord), isNicknameSet: isNicknameSet(userRecord),
isPasswordSet: isPasswordSet(userRecord), isPasswordSet: isPasswordSet(userRecord),
isMobileBound: isMobileBound(userRecord), isMobileBound: isMobileBound(userRecord),
isEmailBound: isEmailBound(userRecord), isEmailBound: isEmailBound(userRecord),
isWeixinBound: isWeixinBound(userRecord), isWeixinBound: isWeixinBound(userRecord),
isQQBound: isQQBound(userRecord), isQQBound: isQQBound(userRecord),
isAlipayBound: isAlipayBound(userRecord), isAlipayBound: isAlipayBound(userRecord),
isAppleBound: isAppleBound(userRecord) isAppleBound: isAppleBound(userRecord)
} }
} }
const { userCollection } = require('../../common/constants') const { userCollection } = require('../../common/constants')
const { ERROR } = require('../../common/error') const { ERROR } = require('../../common/error')
const { decryptData } = require('../../common/sensitive-aes-cipher') const { decryptData } = require('../../common/sensitive-aes-cipher')
const { dataDesensitization } = require('../../common/utils') const { dataDesensitization } = require('../../common/utils')
/** /**
* 获取实名信息 * 获取实名信息
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#get-realname-info * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#get-realname-info
* @param {Object} params * @param {Object} params
* @param {Boolean} params.decryptData 是否解密数据 * @param {Boolean} params.decryptData 是否解密数据
* @returns * @returns
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
decryptData: { decryptData: {
required: false, required: false,
type: 'boolean' type: 'boolean'
} }
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { decryptData: isDecryptData = true } = params const { decryptData: isDecryptData = true } = params
const { const {
uid uid
} = this.authInfo } = this.authInfo
const getUserRes = await userCollection.doc(uid).get() const getUserRes = await userCollection.doc(uid).get()
const userRecord = getUserRes && getUserRes.data && getUserRes.data[0] const userRecord = getUserRes && getUserRes.data && getUserRes.data[0]
if (!userRecord) { if (!userRecord) {
throw { throw {
errCode: ERROR.ACCOUNT_NOT_EXISTS errCode: ERROR.ACCOUNT_NOT_EXISTS
} }
} }
const { realname_auth: realNameAuth = {} } = userRecord const { realname_auth: realNameAuth = {} } = userRecord
return { return {
errCode: 0, errCode: 0,
type: realNameAuth.type, type: realNameAuth.type,
authStatus: realNameAuth.auth_status, authStatus: realNameAuth.auth_status,
realName: isDecryptData ? dataDesensitization(decryptData.call(this, realNameAuth.real_name), { onlyLast: true }) : realNameAuth.real_name, realName: isDecryptData ? dataDesensitization(decryptData.call(this, realNameAuth.real_name), { onlyLast: true }) : realNameAuth.real_name,
identity: isDecryptData ? dataDesensitization(decryptData.call(this, realNameAuth.identity)) : realNameAuth.identity identity: isDecryptData ? dataDesensitization(decryptData.call(this, realNameAuth.identity)) : realNameAuth.identity
} }
} }
const { const {
ERROR ERROR
} = require('../../common/error') } = require('../../common/error')
const { const {
getNeedCaptcha, getNeedCaptcha,
verifyCaptcha verifyCaptcha
} = require('../../lib/utils/captcha') } = require('../../lib/utils/captcha')
const { const {
verifyEmailCode verifyEmailCode
} = require('../../lib/utils/verify-code') } = require('../../lib/utils/verify-code')
const { const {
userCollection, userCollection,
EMAIL_SCENE, EMAIL_SCENE,
CAPTCHA_SCENE, CAPTCHA_SCENE,
LOG_TYPE LOG_TYPE
} = require('../../common/constants') } = require('../../common/constants')
const { const {
findUser findUser
} = require('../../lib/utils/account') } = require('../../lib/utils/account')
const PasswordUtils = require('../../lib/utils/password') const PasswordUtils = require('../../lib/utils/password')
/** /**
* 通过邮箱验证码重置密码 * 通过邮箱验证码重置密码
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#reset-pwd-by-email * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#reset-pwd-by-email
* @param {object} params * @param {object} params
* @param {string} params.email 邮箱 * @param {string} params.email 邮箱
* @param {string} params.code 邮箱验证码 * @param {string} params.code 邮箱验证码
* @param {string} params.password 密码 * @param {string} params.password 密码
* @param {string} params.captcha 图形验证码 * @param {string} params.captcha 图形验证码
* @returns {object} * @returns {object}
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
email: 'email', email: 'email',
code: 'string', code: 'string',
password: 'password', password: 'password',
captcha: { captcha: {
required: false, required: false,
type: 'string' type: 'string'
} }
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { const {
email, email,
code, code,
password, password,
captcha captcha
} = params } = params
const needCaptcha = await getNeedCaptcha.call(this, { const needCaptcha = await getNeedCaptcha.call(this, {
email, email,
type: LOG_TYPE.RESET_PWD_BY_EMAIL type: LOG_TYPE.RESET_PWD_BY_EMAIL
}) })
if (needCaptcha) { if (needCaptcha) {
await verifyCaptcha.call(this, { await verifyCaptcha.call(this, {
captcha, captcha,
scene: CAPTCHA_SCENE.RESET_PWD_BY_EMAIL scene: CAPTCHA_SCENE.RESET_PWD_BY_EMAIL
}) })
} }
try { try {
// 验证手机号验证码,验证不通过时写入失败日志 // 验证手机号验证码,验证不通过时写入失败日志
await verifyEmailCode({ await verifyEmailCode({
email, email,
code, code,
scene: EMAIL_SCENE.RESET_PWD_BY_EMAIL scene: EMAIL_SCENE.RESET_PWD_BY_EMAIL
}) })
} catch (error) { } catch (error) {
await this.middleware.uniIdLog({ await this.middleware.uniIdLog({
data: { data: {
email email
}, },
type: LOG_TYPE.RESET_PWD_BY_EMAIL, type: LOG_TYPE.RESET_PWD_BY_EMAIL,
success: false success: false
}) })
throw error throw error
} }
// 根据手机号查找匹配的用户 // 根据手机号查找匹配的用户
const { const {
total, total,
userMatched userMatched
} = await findUser.call(this, { } = await findUser.call(this, {
userQuery: { userQuery: {
email email
}, },
authorizedApp: [this.getUniversalClientInfo().appId] authorizedApp: [this.getUniversalClientInfo().appId]
}) })
if (userMatched.length === 0) { if (userMatched.length === 0) {
if (total > 0) { if (total > 0) {
throw { throw {
errCode: ERROR.ACCOUNT_NOT_EXISTS_IN_CURRENT_APP errCode: ERROR.ACCOUNT_NOT_EXISTS_IN_CURRENT_APP
} }
} }
throw { throw {
errCode: ERROR.ACCOUNT_NOT_EXISTS errCode: ERROR.ACCOUNT_NOT_EXISTS
} }
} else if (userMatched.length > 1) { } else if (userMatched.length > 1) {
throw { throw {
errCode: ERROR.ACCOUNT_CONFLICT errCode: ERROR.ACCOUNT_CONFLICT
} }
} }
const { _id: uid } = userMatched[0] const { _id: uid } = userMatched[0]
const { const {
passwordHash, passwordHash,
version version
} = new PasswordUtils({ } = new PasswordUtils({
clientInfo: this.getUniversalClientInfo(), clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret passwordSecret: this.config.passwordSecret
}).generatePasswordHash({ }).generatePasswordHash({
password password
}) })
// 更新用户密码 // 更新用户密码
await userCollection.doc(uid).update({ await userCollection.doc(uid).update({
password: passwordHash, password: passwordHash,
password_secret_version: version, password_secret_version: version,
valid_token_date: Date.now() valid_token_date: Date.now()
}) })
// 写入成功日志 // 写入成功日志
await this.middleware.uniIdLog({ await this.middleware.uniIdLog({
data: { data: {
email email
}, },
type: LOG_TYPE.RESET_PWD_BY_SMS type: LOG_TYPE.RESET_PWD_BY_SMS
}) })
return { return {
errCode: 0 errCode: 0
} }
} }
const { const {
ERROR ERROR
} = require('../../common/error') } = require('../../common/error')
const { const {
getNeedCaptcha, getNeedCaptcha,
verifyCaptcha verifyCaptcha
} = require('../../lib/utils/captcha') } = require('../../lib/utils/captcha')
const { const {
verifyMobileCode verifyMobileCode
} = require('../../lib/utils/verify-code') } = require('../../lib/utils/verify-code')
const { const {
userCollection, userCollection,
SMS_SCENE, SMS_SCENE,
CAPTCHA_SCENE, CAPTCHA_SCENE,
LOG_TYPE LOG_TYPE
} = require('../../common/constants') } = require('../../common/constants')
const { const {
findUser findUser
} = require('../../lib/utils/account') } = require('../../lib/utils/account')
const PasswordUtils = require('../../lib/utils/password') const PasswordUtils = require('../../lib/utils/password')
/** /**
* 通过短信验证码重置密码 * 通过短信验证码重置密码
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#reset-pwd-by-sms * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#reset-pwd-by-sms
* @param {object} params * @param {object} params
* @param {string} params.mobile 手机号 * @param {string} params.mobile 手机号
* @param {string} params.mobile 短信验证码 * @param {string} params.mobile 短信验证码
* @param {string} params.password 密码 * @param {string} params.password 密码
* @param {string} params.captcha 图形验证码 * @param {string} params.captcha 图形验证码
* @returns {object} * @returns {object}
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
mobile: 'mobile', mobile: 'mobile',
code: 'string', code: 'string',
password: 'password', password: 'password',
captcha: { captcha: {
required: false, required: false,
type: 'string' type: 'string'
} }
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { const {
mobile, mobile,
code, code,
password, password,
captcha captcha
} = params } = params
const needCaptcha = await getNeedCaptcha.call(this, { const needCaptcha = await getNeedCaptcha.call(this, {
mobile, mobile,
type: LOG_TYPE.RESET_PWD_BY_SMS type: LOG_TYPE.RESET_PWD_BY_SMS
}) })
if (needCaptcha) { if (needCaptcha) {
await verifyCaptcha.call(this, { await verifyCaptcha.call(this, {
captcha, captcha,
scene: CAPTCHA_SCENE.RESET_PWD_BY_SMS scene: CAPTCHA_SCENE.RESET_PWD_BY_SMS
}) })
} }
try { try {
// 验证手机号验证码,验证不通过时写入失败日志 // 验证手机号验证码,验证不通过时写入失败日志
await verifyMobileCode({ await verifyMobileCode({
mobile, mobile,
code, code,
scene: SMS_SCENE.RESET_PWD_BY_SMS scene: SMS_SCENE.RESET_PWD_BY_SMS
}) })
} catch (error) { } catch (error) {
await this.middleware.uniIdLog({ await this.middleware.uniIdLog({
data: { data: {
mobile mobile
}, },
type: LOG_TYPE.RESET_PWD_BY_SMS, type: LOG_TYPE.RESET_PWD_BY_SMS,
success: false success: false
}) })
throw error throw error
} }
// 根据手机号查找匹配的用户 // 根据手机号查找匹配的用户
const { const {
total, total,
userMatched userMatched
} = await findUser.call(this, { } = await findUser.call(this, {
userQuery: { userQuery: {
mobile mobile
}, },
authorizedApp: [this.getUniversalClientInfo().appId] authorizedApp: [this.getUniversalClientInfo().appId]
}) })
if (userMatched.length === 0) { if (userMatched.length === 0) {
if (total > 0) { if (total > 0) {
throw { throw {
errCode: ERROR.ACCOUNT_NOT_EXISTS_IN_CURRENT_APP errCode: ERROR.ACCOUNT_NOT_EXISTS_IN_CURRENT_APP
} }
} }
throw { throw {
errCode: ERROR.ACCOUNT_NOT_EXISTS errCode: ERROR.ACCOUNT_NOT_EXISTS
} }
} else if (userMatched.length > 1) { } else if (userMatched.length > 1) {
throw { throw {
errCode: ERROR.ACCOUNT_CONFLICT errCode: ERROR.ACCOUNT_CONFLICT
} }
} }
const { _id: uid } = userMatched[0] const { _id: uid } = userMatched[0]
const { const {
passwordHash, passwordHash,
version version
} = new PasswordUtils({ } = new PasswordUtils({
clientInfo: this.getUniversalClientInfo(), clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret passwordSecret: this.config.passwordSecret
}).generatePasswordHash({ }).generatePasswordHash({
password password
}) })
// 更新用户密码 // 更新用户密码
await userCollection.doc(uid).update({ await userCollection.doc(uid).update({
password: passwordHash, password: passwordHash,
password_secret_version: version, password_secret_version: version,
valid_token_date: Date.now() valid_token_date: Date.now()
}) })
// 写入成功日志 // 写入成功日志
await this.middleware.uniIdLog({ await this.middleware.uniIdLog({
data: { data: {
mobile mobile
}, },
type: LOG_TYPE.RESET_PWD_BY_SMS type: LOG_TYPE.RESET_PWD_BY_SMS
}) })
return { return {
errCode: 0 errCode: 0
} }
} }
const { const {
userCollection userCollection
} = require('../../common/constants') } = require('../../common/constants')
const { const {
ERROR ERROR
} = require('../../common/error') } = require('../../common/error')
const PasswordUtils = require('../../lib/utils/password') const PasswordUtils = require('../../lib/utils/password')
/** /**
* 更新密码 * 更新密码
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#update-pwd * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#update-pwd
* @param {object} params * @param {object} params
* @param {string} params.oldPassword 旧密码 * @param {string} params.oldPassword 旧密码
* @param {string} params.newPassword 新密码 * @param {string} params.newPassword 新密码
* @returns {object} * @returns {object}
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
oldPassword: 'string', // 防止密码规则调整导致旧密码无法更新 oldPassword: 'string', // 防止密码规则调整导致旧密码无法更新
newPassword: 'password' newPassword: 'password'
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const uid = this.authInfo.uid const uid = this.authInfo.uid
const getUserRes = await userCollection.doc(uid).get() const getUserRes = await userCollection.doc(uid).get()
const userRecord = getUserRes.data[0] const userRecord = getUserRes.data[0]
if (!userRecord) { if (!userRecord) {
throw { throw {
errCode: ERROR.ACCOUNT_NOT_EXISTS errCode: ERROR.ACCOUNT_NOT_EXISTS
} }
} }
const { const {
oldPassword, oldPassword,
newPassword newPassword
} = params } = params
const passwordUtils = new PasswordUtils({ const passwordUtils = new PasswordUtils({
userRecord, userRecord,
clientInfo: this.getUniversalClientInfo(), clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret passwordSecret: this.config.passwordSecret
}) })
const { const {
success: checkPasswordSuccess success: checkPasswordSuccess
} = passwordUtils.checkUserPassword({ } = passwordUtils.checkUserPassword({
password: oldPassword, password: oldPassword,
autoRefresh: false autoRefresh: false
}) })
if (!checkPasswordSuccess) { if (!checkPasswordSuccess) {
throw { throw {
errCode: ERROR.PASSWORD_ERROR errCode: ERROR.PASSWORD_ERROR
} }
} }
const { const {
passwordHash, passwordHash,
version version
} = passwordUtils.generatePasswordHash({ } = passwordUtils.generatePasswordHash({
password: newPassword password: newPassword
}) })
await userCollection.doc(uid).update({ await userCollection.doc(uid).update({
password: passwordHash, password: passwordHash,
password_secret_version: version, password_secret_version: version,
valid_token_date: Date.now() // refreshToken时会校验,如果创建token时间在此时间点之前,则拒绝下发新token,返回token失效错误码 valid_token_date: Date.now() // refreshToken时会校验,如果创建token时间在此时间点之前,则拒绝下发新token,返回token失效错误码
}) })
// 执行更新密码操作后客户端应将用户退出重新登录 // 执行更新密码操作后客户端应将用户退出重新登录
return { return {
errCode: 0 errCode: 0
} }
} }
const { const {
findUser findUser
} = require('../../lib/utils/account') } = require('../../lib/utils/account')
const { const {
ERROR ERROR
} = require('../../common/error') } = require('../../common/error')
const { const {
userCollection userCollection
} = require('../../common/constants') } = require('../../common/constants')
const PasswordUtils = require('../../lib/utils/password') const PasswordUtils = require('../../lib/utils/password')
/** /**
* 新增用户 * 新增用户
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#add-user * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#add-user
* @param {Object} params * @param {Object} params
* @param {String} params.username 用户名 * @param {String} params.username 用户名
* @param {String} params.password 密码 * @param {String} params.password 密码
* @param {String} params.nickname 昵称 * @param {String} params.nickname 昵称
* @param {Array} params.authorizedApp 允许登录的AppID列表 * @param {Array} params.authorizedApp 允许登录的AppID列表
* @param {Array} params.role 用户角色列表 * @param {Array} params.role 用户角色列表
* @param {String} params.mobile 手机号 * @param {String} params.mobile 手机号
* @param {String} params.email 邮箱 * @param {String} params.email 邮箱
* @param {Array} params.tags 用户标签 * @param {Array} params.tags 用户标签
* @param {Number} params.status 用户状态 * @param {Number} params.status 用户状态
* @returns * @returns
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
username: 'username', username: 'username',
password: 'password', password: 'password',
authorizedApp: { authorizedApp: {
required: false, required: false,
type: 'array<string>' type: 'array<string>'
}, // 指定允许登录的app,传空数组或不传时表示可以不可以在任何端登录 }, // 指定允许登录的app,传空数组或不传时表示可以不可以在任何端登录
nickname: { nickname: {
required: false, required: false,
type: 'nickname' type: 'nickname'
}, },
role: { role: {
require: false, require: false,
type: 'array<string>' type: 'array<string>'
}, },
mobile: { mobile: {
required: false, required: false,
type: 'mobile' type: 'mobile'
}, },
email: { email: {
required: false, required: false,
type: 'email' type: 'email'
}, },
tags: { tags: {
required: false, required: false,
type: 'array<string>' type: 'array<string>'
}, },
status: { status: {
required: false, required: false,
type: 'number' type: 'number'
} }
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { const {
username, username,
password, password,
authorizedApp, authorizedApp,
nickname, nickname,
role, role,
mobile, mobile,
email, email,
tags, tags,
status status
} = params } = params
const { const {
userMatched userMatched
} = await findUser({ } = await findUser({
userQuery: { userQuery: {
username, username,
mobile, mobile,
email email
}, },
authorizedApp authorizedApp
}) })
if (userMatched.length) { if (userMatched.length) {
throw { throw {
errCode: ERROR.ACCOUNT_EXISTS errCode: ERROR.ACCOUNT_EXISTS
} }
} }
const passwordUtils = new PasswordUtils({ const passwordUtils = new PasswordUtils({
clientInfo: this.getUniversalClientInfo(), clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret passwordSecret: this.config.passwordSecret
}) })
const { const {
passwordHash, passwordHash,
version version
} = passwordUtils.generatePasswordHash({ } = passwordUtils.generatePasswordHash({
password password
}) })
const data = { const data = {
username, username,
password: passwordHash, password: passwordHash,
password_secret_version: version, password_secret_version: version,
dcloud_appid: authorizedApp || [], dcloud_appid: authorizedApp || [],
nickname, nickname,
role: role || [], role: role || [],
mobile, mobile,
email, email,
tags: tags || [], tags: tags || [],
status status
} }
if (email) { if (email) {
data.email_confirmed = 1 data.email_confirmed = 1
} }
if (mobile) { if (mobile) {
data.mobile_confirmed = 1 data.mobile_confirmed = 1
} }
// 触发 beforeRegister 钩子 // 触发 beforeRegister 钩子
const beforeRegister = this.hooks.beforeRegister const beforeRegister = this.hooks.beforeRegister
let userRecord = data let userRecord = data
if (beforeRegister) { if (beforeRegister) {
userRecord = await beforeRegister({ userRecord = await beforeRegister({
userRecord, userRecord,
clientInfo: this.getUniversalClientInfo() clientInfo: this.getUniversalClientInfo()
}) })
} }
await userCollection.add(userRecord) await userCollection.add(userRecord)
return { return {
errCode: 0, errCode: 0,
errMsg: '' errMsg: ''
} }
} }
const { const {
findUser findUser
} = require('../../lib/utils/account') } = require('../../lib/utils/account')
const { const {
ERROR ERROR
} = require('../../common/error') } = require('../../common/error')
const { const {
userCollection userCollection
} = require('../../common/constants') } = require('../../common/constants')
const PasswordUtils = require('../../lib/utils/password') const PasswordUtils = require('../../lib/utils/password')
/** /**
* 修改用户 * 修改用户
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#update-user * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#update-user
* @param {Object} params * @param {Object} params
* @param {String} params.uid 要更新的用户id * @param {String} params.uid 要更新的用户id
* @param {String} params.username 用户名 * @param {String} params.username 用户名
* @param {String} params.password 密码 * @param {String} params.password 密码
* @param {String} params.nickname 昵称 * @param {String} params.nickname 昵称
* @param {Array} params.authorizedApp 允许登录的AppID列表 * @param {Array} params.authorizedApp 允许登录的AppID列表
* @param {Array} params.role 用户角色列表 * @param {Array} params.role 用户角色列表
* @param {String} params.mobile 手机号 * @param {String} params.mobile 手机号
* @param {String} params.email 邮箱 * @param {String} params.email 邮箱
* @param {Array} params.tags 用户标签 * @param {Array} params.tags 用户标签
* @param {Number} params.status 用户状态 * @param {Number} params.status 用户状态
* @returns * @returns
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
uid: 'string', uid: 'string',
username: 'username', username: 'username',
password: { password: {
required: false, required: false,
type: 'password' type: 'password'
}, },
authorizedApp: { authorizedApp: {
required: false, required: false,
type: 'array<string>' type: 'array<string>'
}, // 指定允许登录的app,传空数组或不传时表示可以不可以在任何端登录 }, // 指定允许登录的app,传空数组或不传时表示可以不可以在任何端登录
nickname: { nickname: {
required: false, required: false,
type: 'nickname' type: 'nickname'
}, },
role: { role: {
require: false, require: false,
type: 'array<string>' type: 'array<string>'
}, },
mobile: { mobile: {
required: false, required: false,
type: 'mobile' type: 'mobile'
}, },
email: { email: {
required: false, required: false,
type: 'email' type: 'email'
}, },
tags: { tags: {
required: false, required: false,
type: 'array<string>' type: 'array<string>'
}, },
status: { status: {
required: false, required: false,
type: 'number' type: 'number'
} }
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { const {
uid, uid,
username, username,
password, password,
authorizedApp, authorizedApp,
nickname, nickname,
role, role,
mobile, mobile,
email, email,
tags, tags,
status status
} = params } = params
// 更新的用户数据字段 // 更新的用户数据字段
const data = { const data = {
username, username,
dcloud_appid: authorizedApp, dcloud_appid: authorizedApp,
nickname, nickname,
role, role,
mobile, mobile,
email, email,
tags, tags,
status status
} }
const realData = Object.keys(data).reduce((res, key) => { const realData = Object.keys(data).reduce((res, key) => {
const item = data[key] const item = data[key]
if (item !== undefined) { if (item !== undefined) {
res[key] = item res[key] = item
} }
return res return res
}, {}) }, {})
// 更新用户名时验证用户名是否重新 // 更新用户名时验证用户名是否重新
if (username) { if (username) {
const { const {
userMatched userMatched
} = await findUser({ } = await findUser({
userQuery: { userQuery: {
username username
}, },
authorizedApp authorizedApp
}) })
if (userMatched.filter(user => user._id !== uid).length) { if (userMatched.filter(user => user._id !== uid).length) {
throw { throw {
errCode: ERROR.ACCOUNT_EXISTS errCode: ERROR.ACCOUNT_EXISTS
} }
} }
} }
if (password) { if (password) {
const passwordUtils = new PasswordUtils({ const passwordUtils = new PasswordUtils({
clientInfo: this.getUniversalClientInfo(), clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret passwordSecret: this.config.passwordSecret
}) })
const { const {
passwordHash, passwordHash,
version version
} = passwordUtils.generatePasswordHash({ } = passwordUtils.generatePasswordHash({
password password
}) })
realData.password = passwordHash realData.password = passwordHash
realData.password_secret_version = version realData.password_secret_version = version
} }
await userCollection.doc(uid).update(realData) await userCollection.doc(uid).update(realData)
return { return {
errCode: 0 errCode: 0
} }
} }
...@@ -4,8 +4,7 @@ function isMobileCodeSupported () { ...@@ -4,8 +4,7 @@ function isMobileCodeSupported () {
} }
function isUniverifySupport () { function isUniverifySupport () {
const config = this.config return true
return !!(config.service && config.service.univerify && config.service.univerify.apiKey)
} }
function isWeixinSupported () { function isWeixinSupported () {
...@@ -47,7 +46,7 @@ const loginTypeTester = { ...@@ -47,7 +46,7 @@ const loginTypeTester = {
/** /**
* 获取支持的登录方式 * 获取支持的登录方式
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#get-supported-login-type * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#get-supported-login-type
* @returns * @returns
*/ */
module.exports = async function () { module.exports = async function () {
......
const { preLogin, postLogin } = require('../../lib/utils/login') const { preLogin, postLogin } = require('../../lib/utils/login')
const { EXTERNAL_DIRECT_CONNECT_PROVIDER } = require('../../common/constants') const { EXTERNAL_DIRECT_CONNECT_PROVIDER } = require('../../common/constants')
const { ERROR } = require('../../common/error') const { ERROR } = require('../../common/error')
/** /**
* 外部用户登录 * 外部用户登录
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#external-login * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#external-login
* @param {object} params * @param {object} params
* @param {string} params.uid uni-id体系用户id * @param {string} params.uid uni-id体系用户id
* @param {string} params.externalUid 业务系统的用户id * @param {string} params.externalUid 业务系统的用户id
* @returns {object} * @returns {object}
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
uid: { uid: {
required: false, required: false,
type: 'string' type: 'string'
}, },
externalUid: { externalUid: {
required: false, required: false,
type: 'string' type: 'string'
} }
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { const {
uid, uid,
externalUid externalUid
} = params } = params
if (!uid && !externalUid) { if (!uid && !externalUid) {
throw { throw {
errCode: ERROR.PARAM_REQUIRED, errCode: ERROR.PARAM_REQUIRED,
errMsgValue: { errMsgValue: {
param: 'uid or externalUid' param: 'uid or externalUid'
} }
} }
} }
let query let query
if (uid) { if (uid) {
query = { query = {
_id: uid _id: uid
} }
} else { } else {
query = { query = {
identities: { identities: {
provider: EXTERNAL_DIRECT_CONNECT_PROVIDER, provider: EXTERNAL_DIRECT_CONNECT_PROVIDER,
uid: externalUid uid: externalUid
} }
} }
} }
const user = await preLogin.call(this, { const user = await preLogin.call(this, {
user: query user: query
}) })
const result = await postLogin.call(this, { const result = await postLogin.call(this, {
user user
}) })
return { return {
errCode: result.errCode, errCode: result.errCode,
newToken: result.newToken, newToken: result.newToken,
uid: result.uid uid: result.uid
} }
} }
const url = require('url') const url = require('url')
const { preRegister, postRegister } = require('../../lib/utils/register') const { preRegister, postRegister } = require('../../lib/utils/register')
const { EXTERNAL_DIRECT_CONNECT_PROVIDER } = require('../../common/constants') const { EXTERNAL_DIRECT_CONNECT_PROVIDER } = require('../../common/constants')
/** /**
* 外部注册用户 * 外部注册用户
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#external-register * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#external-register
* @param {object} params * @param {object} params
* @param {string} params.externalUid 业务系统的用户id * @param {string} params.externalUid 业务系统的用户id
* @param {string} params.nickname 昵称 * @param {string} params.nickname 昵称
* @param {number} params.gender 性别 * @param {number} params.gender 性别
* @param {string} params.avatar 头像 * @param {string} params.avatar 头像
* @returns {object} * @returns {object}
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
externalUid: 'string', externalUid: 'string',
nickname: { nickname: {
required: false, required: false,
type: 'nickname' type: 'nickname'
}, },
gender: { gender: {
required: false, required: false,
type: 'number' type: 'number'
}, },
avatar: { avatar: {
required: false, required: false,
type: 'string' type: 'string'
} }
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { const {
externalUid, externalUid,
avatar, avatar,
gender, gender,
nickname nickname
} = params } = params
await preRegister.call(this, { await preRegister.call(this, {
user: { user: {
identities: { identities: {
provider: EXTERNAL_DIRECT_CONNECT_PROVIDER, provider: EXTERNAL_DIRECT_CONNECT_PROVIDER,
uid: externalUid uid: externalUid
} }
} }
}) })
const extraData = {} const extraData = {}
if (avatar) { if (avatar) {
// eslint-disable-next-line n/no-deprecated-api // eslint-disable-next-line n/no-deprecated-api
const avatarPath = url.parse(avatar).pathname const avatarPath = url.parse(avatar).pathname
const extName = avatarPath.indexOf('.') > -1 ? avatarPath.split('.').pop() : '' const extName = avatarPath.indexOf('.') > -1 ? avatarPath.split('.').pop() : ''
extraData.avatar_file = { extraData.avatar_file = {
name: avatarPath, name: avatarPath,
extname: extName, extname: extName,
url: avatar url: avatar
} }
} }
const result = await postRegister.call(this, { const result = await postRegister.call(this, {
user: { user: {
avatar, avatar,
gender, gender,
nickname, nickname,
identities: [ identities: [
{ {
provider: EXTERNAL_DIRECT_CONNECT_PROVIDER, provider: EXTERNAL_DIRECT_CONNECT_PROVIDER,
userInfo: { userInfo: {
avatar, avatar,
gender, gender,
nickname nickname
}, },
uid: externalUid uid: externalUid
} }
] ]
}, },
extraData extraData
}) })
return { return {
errCode: result.errCode, errCode: result.errCode,
newToken: result.newToken, newToken: result.newToken,
externalUid, externalUid,
avatar, avatar,
gender, gender,
nickname, nickname,
uid: result.uid uid: result.uid
} }
} }
const url = require('url') const url = require('url')
const { userCollection, EXTERNAL_DIRECT_CONNECT_PROVIDER } = require('../../common/constants') const { userCollection, EXTERNAL_DIRECT_CONNECT_PROVIDER } = require('../../common/constants')
const { ERROR } = require('../../common/error') const { ERROR } = require('../../common/error')
const { findUser } = require('../../lib/utils/account') const { findUser } = require('../../lib/utils/account')
const PasswordUtils = require('../../lib/utils/password') const PasswordUtils = require('../../lib/utils/password')
/** /**
* 使用 uid 或 externalUid 获取用户信息 * 使用 uid 或 externalUid 获取用户信息
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#external-update-userinfo * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#external-update-userinfo
* @param {object} params * @param {object} params
* @param {string} params.uid uni-id体系的用户id * @param {string} params.uid uni-id体系的用户id
* @param {string} params.externalUid 业务系统的用户id * @param {string} params.externalUid 业务系统的用户id
* @param {string} params.nickname 昵称 * @param {string} params.nickname 昵称
* @param {string} params.gender 性别 * @param {string} params.gender 性别
* @param {string} params.avatar 头像 * @param {string} params.avatar 头像
* @returns {object} * @returns {object}
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
uid: { uid: {
required: false, required: false,
type: 'string' type: 'string'
}, },
externalUid: { externalUid: {
required: false, required: false,
type: 'string' type: 'string'
}, },
username: { username: {
required: false, required: false,
type: 'string' type: 'string'
}, },
password: { password: {
required: false, required: false,
type: 'password' type: 'password'
}, },
authorizedApp: { authorizedApp: {
required: false, required: false,
type: 'array<string>' type: 'array<string>'
}, // 指定允许登录的app,传空数组或不传时表示可以不可以在任何端登录 }, // 指定允许登录的app,传空数组或不传时表示可以不可以在任何端登录
nickname: { nickname: {
required: false, required: false,
type: 'nickname' type: 'nickname'
}, },
role: { role: {
require: false, require: false,
type: 'array<string>' type: 'array<string>'
}, },
mobile: { mobile: {
required: false, required: false,
type: 'mobile' type: 'mobile'
}, },
email: { email: {
required: false, required: false,
type: 'email' type: 'email'
}, },
tags: { tags: {
required: false, required: false,
type: 'array<string>' type: 'array<string>'
}, },
status: { status: {
required: false, required: false,
type: 'number' type: 'number'
}, },
gender: { gender: {
required: false, required: false,
type: 'number' type: 'number'
}, },
avatar: { avatar: {
required: false, required: false,
type: 'string' type: 'string'
} }
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { const {
uid, uid,
externalUid, externalUid,
username, username,
password, password,
authorizedApp, authorizedApp,
nickname, nickname,
role, role,
mobile, mobile,
email, email,
tags, tags,
status, status,
avatar, avatar,
gender gender
} = params } = params
if (!uid && !externalUid) { if (!uid && !externalUid) {
throw { throw {
errCode: ERROR.PARAM_REQUIRED, errCode: ERROR.PARAM_REQUIRED,
errMsgValue: { errMsgValue: {
param: 'uid or externalUid' param: 'uid or externalUid'
} }
} }
} }
let query let query
if (uid) { if (uid) {
query = { query = {
_id: uid _id: uid
} }
} else { } else {
query = { query = {
identities: { identities: {
provider: EXTERNAL_DIRECT_CONNECT_PROVIDER, provider: EXTERNAL_DIRECT_CONNECT_PROVIDER,
uid: externalUid uid: externalUid
} }
} }
} }
const users = await userCollection.where(query).get() const users = await userCollection.where(query).get()
const user = users.data && users.data[0] const user = users.data && users.data[0]
if (!user) { if (!user) {
throw { throw {
errCode: ERROR.ACCOUNT_NOT_EXISTS errCode: ERROR.ACCOUNT_NOT_EXISTS
} }
} }
// 更新的用户数据字段 // 更新的用户数据字段
const data = { const data = {
username, username,
dcloud_appid: authorizedApp, dcloud_appid: authorizedApp,
nickname, nickname,
role, role,
mobile, mobile,
email, email,
tags, tags,
status, status,
avatar, avatar,
gender gender
} }
const realData = Object.keys(data).reduce((res, key) => { const realData = Object.keys(data).reduce((res, key) => {
const item = data[key] const item = data[key]
if (item !== undefined) { if (item !== undefined) {
res[key] = item res[key] = item
} }
return res return res
}, {}) }, {})
// 更新用户名时验证用户名是否重新 // 更新用户名时验证用户名是否重新
if (username) { if (username) {
const { const {
userMatched userMatched
} = await findUser({ } = await findUser({
userQuery: { userQuery: {
username username
}, },
authorizedApp authorizedApp
}) })
if (userMatched.filter(user => user._id !== uid).length) { if (userMatched.filter(user => user._id !== uid).length) {
throw { throw {
errCode: ERROR.ACCOUNT_EXISTS errCode: ERROR.ACCOUNT_EXISTS
} }
} }
} }
if (password) { if (password) {
const passwordUtils = new PasswordUtils({ const passwordUtils = new PasswordUtils({
clientInfo: this.getUniversalClientInfo(), clientInfo: this.getUniversalClientInfo(),
passwordSecret: this.config.passwordSecret passwordSecret: this.config.passwordSecret
}) })
const { const {
passwordHash, passwordHash,
version version
} = passwordUtils.generatePasswordHash({ } = passwordUtils.generatePasswordHash({
password password
}) })
realData.password = passwordHash realData.password = passwordHash
realData.password_secret_version = version realData.password_secret_version = version
} }
if (avatar) { if (avatar) {
// eslint-disable-next-line n/no-deprecated-api // eslint-disable-next-line n/no-deprecated-api
const avatarPath = url.parse(avatar).pathname const avatarPath = url.parse(avatar).pathname
const extName = avatarPath.indexOf('.') > -1 ? avatarPath.split('.').pop() : '' const extName = avatarPath.indexOf('.') > -1 ? avatarPath.split('.').pop() : ''
realData.avatar_file = { realData.avatar_file = {
name: avatarPath, name: avatarPath,
extname: extName, extname: extName,
url: avatar url: avatar
} }
} }
if (user.identities.length) { if (user.identities.length) {
const identity = user.identities.find(item => item.provider === EXTERNAL_DIRECT_CONNECT_PROVIDER) const identity = user.identities.find(item => item.provider === EXTERNAL_DIRECT_CONNECT_PROVIDER)
if (identity) { if (identity) {
identity.userInfo = { identity.userInfo = {
avatar, avatar,
gender, gender,
nickname nickname
} }
} }
realData.identities = user.identities realData.identities = user.identities
} }
await userCollection.where(query).update(realData) await userCollection.where(query).update(realData)
return { return {
errCode: 0 errCode: 0
} }
} }
const { userCollection, REAL_NAME_STATUS, frvLogsCollection } = require('../../common/constants') const { userCollection, REAL_NAME_STATUS, frvLogsCollection } = require('../../common/constants')
const { dataDesensitization, catchAwait } = require('../../common/utils') const { dataDesensitization, catchAwait } = require('../../common/utils')
const { encryptData, decryptData } = require('../../common/sensitive-aes-cipher') const { encryptData, decryptData } = require('../../common/sensitive-aes-cipher')
const { ERROR } = require('../../common/error') const { ERROR } = require('../../common/error')
/** /**
* 查询认证结果 * 查询认证结果
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#get-frv-auth-result * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#get-frv-auth-result
* @param {Object} params * @param {Object} params
* @param {String} params.certifyId 认证ID * @param {String} params.certifyId 认证ID
* @returns * @returns
*/ */
module.exports = async function (params) { module.exports = async function (params) {
const schema = { const schema = {
certifyId: 'string' certifyId: 'string'
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { uid } = this.authInfo // 从authInfo中取出uid属性 const { uid } = this.authInfo // 从authInfo中取出uid属性
const { certifyId } = params // 从params中取出certifyId属性 const { certifyId } = params // 从params中取出certifyId属性
const user = await userCollection.doc(uid).get() // 根据uid查询用户信息 const user = await userCollection.doc(uid).get() // 根据uid查询用户信息
const userInfo = user.data && user.data[0] // 从查询结果中获取userInfo对象 const userInfo = user.data && user.data[0] // 从查询结果中获取userInfo对象
// 如果用户不存在,抛出账户不存在的错误 // 如果用户不存在,抛出账户不存在的错误
if (!userInfo) { if (!userInfo) {
throw { throw {
errCode: ERROR.ACCOUNT_NOT_EXISTS errCode: ERROR.ACCOUNT_NOT_EXISTS
} }
} }
const { realname_auth: realNameAuth = {} } = userInfo const { realname_auth: realNameAuth = {} } = userInfo
// 如果用户已经实名认证,抛出已实名认证的错误 // 如果用户已经实名认证,抛出已实名认证的错误
if (realNameAuth.auth_status === REAL_NAME_STATUS.CERTIFIED) { if (realNameAuth.auth_status === REAL_NAME_STATUS.CERTIFIED) {
throw { throw {
errCode: ERROR.REAL_NAME_VERIFIED errCode: ERROR.REAL_NAME_VERIFIED
} }
} }
// 初始化实人认证服务 // 初始化实人认证服务
const frvManager = uniCloud.getFacialRecognitionVerifyManager({ const frvManager = uniCloud.getFacialRecognitionVerifyManager({
requestId: this.getUniCloudRequestId() requestId: this.getUniCloudRequestId()
}) })
// 调用frvManager的getAuthResult方法,获取认证结果 // 调用frvManager的getAuthResult方法,获取认证结果
const [error, res] = await catchAwait(frvManager.getAuthResult({ const [error, res] = await catchAwait(frvManager.getAuthResult({
certifyId certifyId
})) }))
// 如果出现错误,抛出未知错误并打印日志 // 如果出现错误,抛出未知错误并打印日志
if (error) { if (error) {
console.log(ERROR.UNKNOWN_ERROR, 'error: ', error) console.log(ERROR.UNKNOWN_ERROR, 'error: ', error)
throw error throw error
} }
// 如果认证状态为“PROCESSING”,抛出认证正在处理中的错误 // 如果认证状态为“PROCESSING”,抛出认证正在处理中的错误
if (res.authState === 'PROCESSING') { if (res.authState === 'PROCESSING') {
throw { throw {
errCode: ERROR.FRV_PROCESSING errCode: ERROR.FRV_PROCESSING
} }
} }
// 如果认证状态为“FAIL”,更新认证日志的状态并抛出认证失败的错误 // 如果认证状态为“FAIL”,更新认证日志的状态并抛出认证失败的错误
if (res.authState === 'FAIL') { if (res.authState === 'FAIL') {
await frvLogsCollection.where({ await frvLogsCollection.where({
certify_id: certifyId certify_id: certifyId
}).update({ }).update({
status: REAL_NAME_STATUS.CERTIFY_FAILED status: REAL_NAME_STATUS.CERTIFY_FAILED
}) })
console.log(ERROR.FRV_FAIL, 'error: ', res) console.log(ERROR.FRV_FAIL, 'error: ', res)
throw { throw {
errCode: ERROR.FRV_FAIL errCode: ERROR.FRV_FAIL
} }
} }
// 如果认证状态不为“SUCCESS”,抛出未知错误并打印日志 // 如果认证状态不为“SUCCESS”,抛出未知错误并打印日志
if (res.authState !== 'SUCCESS') { if (res.authState !== 'SUCCESS') {
console.log(ERROR.UNKNOWN_ERROR, 'source res: ', res) console.log(ERROR.UNKNOWN_ERROR, 'source res: ', res)
throw { throw {
errCode: ERROR.UNKNOWN_ERROR errCode: ERROR.UNKNOWN_ERROR
} }
} }
// 根据certifyId查询认证记录 // 根据certifyId查询认证记录
const frvLogs = await frvLogsCollection.where({ const frvLogs = await frvLogsCollection.where({
certify_id: certifyId certify_id: certifyId
}).get() }).get()
const log = frvLogs.data && frvLogs.data[0] const log = frvLogs.data && frvLogs.data[0]
const updateData = { const updateData = {
realname_auth: { realname_auth: {
auth_status: REAL_NAME_STATUS.CERTIFIED, auth_status: REAL_NAME_STATUS.CERTIFIED,
real_name: log.real_name, real_name: log.real_name,
identity: log.identity, identity: log.identity,
auth_date: Date.now(), auth_date: Date.now(),
type: 0 type: 0
} }
} }
// 如果获取到了认证照片的地址,则会对其进行下载,并使用uniCloud.uploadFile方法将其上传到云存储,并将上传后的fileID保存起来。 // 如果获取到了认证照片的地址,则会对其进行下载,并使用uniCloud.uploadFile方法将其上传到云存储,并将上传后的fileID保存起来。
if (res.pictureUrl) { if (res.pictureUrl) {
const pictureRes = await uniCloud.httpclient.request(res.pictureUrl) const pictureRes = await uniCloud.httpclient.request(res.pictureUrl)
if (pictureRes.status < 400) { if (pictureRes.status < 400) {
const { const {
fileID fileID
} = await uniCloud.uploadFile({ } = await uniCloud.uploadFile({
cloudPath: `user/id-card/${uid}.b64`, cloudPath: `user/id-card/${uid}.b64`,
fileContent: Buffer.from(encryptData.call(this, pictureRes.data.toString('base64'))) fileContent: Buffer.from(encryptData.call(this, pictureRes.data.toString('base64')))
}) })
updateData.realname_auth.in_hand = fileID updateData.realname_auth.in_hand = fileID
} }
} }
await Promise.all([ await Promise.all([
// 更新用户认证状态 // 更新用户认证状态
userCollection.doc(uid).update(updateData), userCollection.doc(uid).update(updateData),
// 更新实人认证记录状态 // 更新实人认证记录状态
frvLogsCollection.where({ frvLogsCollection.where({
certify_id: certifyId certify_id: certifyId
}).update({ }).update({
status: REAL_NAME_STATUS.CERTIFIED status: REAL_NAME_STATUS.CERTIFIED
}) })
]) ])
return { return {
errCode: 0, errCode: 0,
authStatus: REAL_NAME_STATUS.CERTIFIED, authStatus: REAL_NAME_STATUS.CERTIFIED,
realName: dataDesensitization(decryptData.call(this, log.real_name), { onlyLast: true }), // 对姓名进行脱敏处理 realName: dataDesensitization(decryptData.call(this, log.real_name), { onlyLast: true }), // 对姓名进行脱敏处理
identity: dataDesensitization(decryptData.call(this, log.identity)) // 对身份证号进行脱敏处理 identity: dataDesensitization(decryptData.call(this, log.identity)) // 对身份证号进行脱敏处理
} }
} }
const { userCollection, REAL_NAME_STATUS, frvLogsCollection, dbCmd } = require('../../common/constants') const { userCollection, REAL_NAME_STATUS, frvLogsCollection, dbCmd } = require('../../common/constants')
const { ERROR } = require('../../common/error') const { ERROR } = require('../../common/error')
const { encryptData } = require('../../common/sensitive-aes-cipher') const { encryptData } = require('../../common/sensitive-aes-cipher')
const { getCurrentDateTimestamp } = require('../../common/utils') const { getCurrentDateTimestamp } = require('../../common/utils')
// const CertifyIdExpired = 25 * 60 * 1000 // certifyId 过期时间为30分钟,在25分时置为过期 // const CertifyIdExpired = 25 * 60 * 1000 // certifyId 过期时间为30分钟,在25分时置为过期
/** /**
* 获取认证ID * 获取认证ID
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#get-frv-certify-id * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#get-frv-certify-id
* @param {Object} params * @param {Object} params
* @param {String} params.realName 真实姓名 * @param {String} params.realName 真实姓名
* @param {String} params.idCard 身份证号码 * @param {String} params.idCard 身份证号码
* @param {String} params.metaInfo 客户端初始化时返回的metaInfo * @param {String} params.metaInfo 客户端初始化时返回的metaInfo
* @returns * @returns
*/ */
module.exports = async function (params) { module.exports = async function (params) {
const schema = { const schema = {
realName: 'realName', realName: 'realName',
idCard: 'idCard', idCard: 'idCard',
metaInfo: 'string' metaInfo: 'string'
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { realName: originalRealName, idCard: originalIdCard, metaInfo } = params // 解构出传入参数的真实姓名、身份证号码、其他元数据 const { realName: originalRealName, idCard: originalIdCard, metaInfo } = params // 解构出传入参数的真实姓名、身份证号码、其他元数据
const realName = encryptData.call(this, originalRealName) // 对真实姓名进行加密处理 const realName = encryptData.call(this, originalRealName) // 对真实姓名进行加密处理
const idCard = encryptData.call(this, originalIdCard) // 对身份证号码进行加密处理 const idCard = encryptData.call(this, originalIdCard) // 对身份证号码进行加密处理
const { uid } = this.authInfo // 获取当前用户的 ID const { uid } = this.authInfo // 获取当前用户的 ID
const idCardCertifyLimit = this.config.idCardCertifyLimit || 1 // 获取身份证认证限制次数,默认为1次 const idCardCertifyLimit = this.config.idCardCertifyLimit || 1 // 获取身份证认证限制次数,默认为1次
const realNameCertifyLimit = this.config.realNameCertifyLimit || 5 // 获取实名认证限制次数,默认为5次 const realNameCertifyLimit = this.config.realNameCertifyLimit || 5 // 获取实名认证限制次数,默认为5次
const frvNeedAlivePhoto = this.config.frvNeedAlivePhoto || false // 是否需要拍摄活体照片,默认为 false const frvNeedAlivePhoto = this.config.frvNeedAlivePhoto || false // 是否需要拍摄活体照片,默认为 false
const user = await userCollection.doc(uid).get() // 获取用户信息 const user = await userCollection.doc(uid).get() // 获取用户信息
const userInfo = user.data && user.data[0] // 获取用户信息对象中的实名认证信息 const userInfo = user.data && user.data[0] // 获取用户信息对象中的实名认证信息
const { realname_auth: realNameAuth = {} } = userInfo // 解构出实名认证信息中的认证状态对象,默认为空对象 const { realname_auth: realNameAuth = {} } = userInfo // 解构出实名认证信息中的认证状态对象,默认为空对象
// 如果用户已经实名认证过,不能再次认证 // 如果用户已经实名认证过,不能再次认证
if (realNameAuth.auth_status === REAL_NAME_STATUS.CERTIFIED) { if (realNameAuth.auth_status === REAL_NAME_STATUS.CERTIFIED) {
throw { throw {
errCode: ERROR.REAL_NAME_VERIFIED errCode: ERROR.REAL_NAME_VERIFIED
} }
} }
// 查询已经使用同一个身份证认证的账号数量,如果超过限制则不能认证 // 查询已经使用同一个身份证认证的账号数量,如果超过限制则不能认证
const idCardAccount = await userCollection.where({ const idCardAccount = await userCollection.where({
'realname_auth.type': 0, realname_auth: {
'realname_auth.auth_status': REAL_NAME_STATUS.CERTIFIED, type: 0, // 用户认证状态是个人
'realname_auth.identity': idCard auth_status: REAL_NAME_STATUS.CERTIFIED, // 认证状态为已认证
}).get() identity: idCard // 身份证号码和传入参数的身份证号码相同
if (idCardAccount.data.length >= idCardCertifyLimit) { }
throw { }).get()
errCode: ERROR.ID_CARD_EXISTS if (idCardAccount.data.length >= idCardCertifyLimit) {
} throw {
} errCode: ERROR.ID_CARD_EXISTS
}
// 查询用户今天已经进行的实名认证次数,如果超过限制则不能认证 }
const userFrvLogs = await frvLogsCollection.where({
user_id: uid, // 查询用户今天已经进行的实名认证次数,如果超过限制则不能认证
created_date: dbCmd.gt(getCurrentDateTimestamp()) // 查询今天的认证记录 const userFrvLogs = await frvLogsCollection.where({
}).get() user_id: uid,
created_date: dbCmd.gt(getCurrentDateTimestamp()) // 查询今天的认证记录
// 限制用户每日认证次数 }).get()
if (userFrvLogs.data && userFrvLogs.data.length >= realNameCertifyLimit) {
throw { // 限制用户每日认证次数
errCode: ERROR.REAL_NAME_VERIFY_UPPER_LIMIT if (userFrvLogs.data && userFrvLogs.data.length >= realNameCertifyLimit) {
} throw {
} errCode: ERROR.REAL_NAME_VERIFY_UPPER_LIMIT
}
// 初始化实人认证服务 }
const frvManager = uniCloud.getFacialRecognitionVerifyManager({
requestId: this.getUniCloudRequestId() // 获取当前 // 初始化实人认证服务
}) const frvManager = uniCloud.getFacialRecognitionVerifyManager({
// 调用实人认证服务,获取认证 ID requestId: this.getUniCloudRequestId() // 获取当前
const res = await frvManager.getCertifyId({ })
realName: originalRealName, // 调用实人认证服务,获取认证 ID
idCard: originalIdCard, const res = await frvManager.getCertifyId({
needPicture: frvNeedAlivePhoto, realName: originalRealName,
metaInfo idCard: originalIdCard,
}) needPicture: frvNeedAlivePhoto,
metaInfo
// 将认证记录插入到实名认证日志中 })
await frvLogsCollection.add({
user_id: uid, // 将认证记录插入到实名认证日志中
certify_id: res.certifyId, await frvLogsCollection.add({
real_name: realName, user_id: uid,
identity: idCard, certify_id: res.certifyId,
status: REAL_NAME_STATUS.WAITING_CERTIFIED, real_name: realName,
created_date: Date.now() identity: idCard,
}) status: REAL_NAME_STATUS.WAITING_CERTIFIED,
created_date: Date.now()
// 返回认证ID })
return {
certifyId: res.certifyId // 返回认证ID
} return {
} certifyId: res.certifyId
}
}
const { const {
acceptInvite acceptInvite
} = require('../../lib/utils/fission') } = require('../../lib/utils/fission')
/** /**
* 接受邀请 * 接受邀请
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#accept-invite * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#accept-invite
* @param {Object} params * @param {Object} params
* @param {String} params.inviteCode 邀请码 * @param {String} params.inviteCode 邀请码
* @returns * @returns
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
inviteCode: 'string' inviteCode: 'string'
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { const {
inviteCode inviteCode
} = params } = params
const uid = this.authInfo.uid const uid = this.authInfo.uid
return acceptInvite({ return acceptInvite({
uid, uid,
inviteCode inviteCode
}) })
} }
const { const {
userCollection userCollection
} = require('../../common/constants') } = require('../../common/constants')
const { const {
coverMobile coverMobile
} = require('../../common/utils') } = require('../../common/utils')
/** /**
* 获取受邀用户 * 获取受邀用户
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#get-invited-user * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#get-invited-user
* @param {Object} params * @param {Object} params
* @param {Number} params.level 获取受邀用户的级数,1表示直接邀请的用户 * @param {Number} params.level 获取受邀用户的级数,1表示直接邀请的用户
* @param {Number} params.limit 返回数据大小 * @param {Number} params.limit 返回数据大小
* @param {Number} params.offset 返回数据偏移 * @param {Number} params.offset 返回数据偏移
* @param {Boolean} params.needTotal 是否需要返回总数 * @param {Boolean} params.needTotal 是否需要返回总数
* @returns * @returns
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
level: 'number', level: 'number',
limit: { limit: {
required: false, required: false,
type: 'number' type: 'number'
}, },
offset: { offset: {
required: false, required: false,
type: 'number' type: 'number'
}, },
needTotal: { needTotal: {
required: false, required: false,
type: 'boolean' type: 'boolean'
} }
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { const {
level, level,
limit = 20, limit = 20,
offset = 0, offset = 0,
needTotal = false needTotal = false
} = params } = params
const uid = this.authInfo.uid const uid = this.authInfo.uid
const query = { const query = {
[`inviter_uid.${level - 1}`]: uid [`inviter_uid.${level - 1}`]: uid
} }
const getUserRes = await userCollection.where(query) const getUserRes = await userCollection.where(query)
.field({ .field({
_id: true, _id: true,
avatar: true, avatar: true,
avatar_file: true, avatar_file: true,
username: true, username: true,
nickname: true, nickname: true,
mobile: true, mobile: true,
invite_time: true invite_time: true
}) })
.orderBy('invite_time', 'desc') .orderBy('invite_time', 'desc')
.skip(offset) .skip(offset)
.limit(limit) .limit(limit)
.get() .get()
const invitedUser = getUserRes.data.map(item => { const invitedUser = getUserRes.data.map(item => {
return { return {
uid: item._id, uid: item._id,
username: item.username, username: item.username,
nickname: item.nickname, nickname: item.nickname,
mobile: coverMobile(item.mobile), mobile: coverMobile(item.mobile),
inviteTime: item.invite_time, inviteTime: item.invite_time,
avatar: item.avatar, avatar: item.avatar,
avatarFile: item.avatar_file avatarFile: item.avatar_file
} }
}) })
const result = { const result = {
errCode: 0, errCode: 0,
invitedUser invitedUser
} }
if (needTotal) { if (needTotal) {
const getTotalRes = await userCollection.where(query).count() const getTotalRes = await userCollection.where(query).count()
result.total = getTotalRes.total result.total = getTotalRes.total
} }
return result return result
} }
const { const {
initAlipay initAlipay
} = require('../../lib/third-party/index') } = require('../../lib/third-party/index')
const { const {
ERROR ERROR
} = require('../../common/error') } = require('../../common/error')
const { const {
preUnifiedLogin, preUnifiedLogin,
postUnifiedLogin postUnifiedLogin
} = require('../../lib/utils/unified-login') } = require('../../lib/utils/unified-login')
const { const {
LOG_TYPE LOG_TYPE
} = require('../../common/constants') } = require('../../common/constants')
/** /**
* 支付宝登录 * 支付宝登录
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#login-by-alipay * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login-by-alipay
* @param {Object} params * @param {Object} params
* @param {String} params.code 支付宝小程序客户端登录返回的code * @param {String} params.code 支付宝小程序客户端登录返回的code
* @param {String} params.inviteCode 邀请码 * @param {String} params.inviteCode 邀请码
* @returns * @returns
*/ */
module.exports = async function (params = {}) { module.exports = async function (params = {}) {
const schema = { const schema = {
code: 'string', code: 'string',
inviteCode: { inviteCode: {
type: 'string', type: 'string',
required: false required: false
} }
} }
this.middleware.validate(params, schema) this.middleware.validate(params, schema)
const { const {
code, code,
inviteCode inviteCode
} = params } = params
const alipayApi = initAlipay.call(this) const alipayApi = initAlipay.call(this)
let getAlipayAccountResult let getAlipayAccountResult
try { try {
getAlipayAccountResult = await alipayApi.code2Session(code) getAlipayAccountResult = await alipayApi.code2Session(code)
} catch (error) { } catch (error) {
console.error(error) console.error(error)
await this.middleware.uniIdLog({ await this.middleware.uniIdLog({
success: false, success: false,
type: LOG_TYPE.LOGIN type: LOG_TYPE.LOGIN
}) })
throw { throw {
errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED
} }
} }
const { const {
openid openid
} = getAlipayAccountResult } = getAlipayAccountResult
const { const {
type, type,
user user
} = await preUnifiedLogin.call(this, { } = await preUnifiedLogin.call(this, {
user: { user: {
ali_openid: openid ali_openid: openid
} }
}) })
return postUnifiedLogin.call(this, { return postUnifiedLogin.call(this, {
user, user,
extraData: {}, extraData: {},
isThirdParty: true, isThirdParty: true,
type, type,
inviteCode inviteCode
}) })
} }
const { const {
logout logout
} = require('../../lib/utils/logout') } = require('../../lib/utils/logout')
/** /**
* 用户退出登录 * 用户退出登录
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages-x.html#logout * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#logout
* @returns * @returns
*/ */
module.exports = async function () { module.exports = async function () {
await logout.call(this) await logout.call(this)
return { return {
errCode: 0 errCode: 0
} }
} }
{ {
"name": "uni-id-co", "name": "uni-id-co",
"version": "1.1.14", "version": "1.1.15",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"keywords": [], "keywords": [],
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
"uni-captcha": "file:../../../../uni-captcha/uniCloud/cloudfunctions/common/uni-captcha", "uni-captcha": "file:../../../../uni-captcha/uniCloud/cloudfunctions/common/uni-captcha",
"uni-config-center": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center", "uni-config-center": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center",
"uni-id-common": "file:../../../../uni-id-common/uniCloud/cloudfunctions/common/uni-id-common", "uni-id-common": "file:../../../../uni-id-common/uniCloud/cloudfunctions/common/uni-id-common",
"uni-open-bridge-common": "file:../../../../uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common",
"uni-cloud-s2s": "file:../../../../uni-cloud-s2s/uniCloud/cloudfunctions/common/uni-cloud-s2s" "uni-cloud-s2s": "file:../../../../uni-cloud-s2s/uniCloud/cloudfunctions/common/uni-cloud-s2s"
}, },
"extensions": { "extensions": {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册