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

update uni-id-co

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