Files
dtx_store/uni_modules/uni-id-cf/uniCloud/cloudfunctions/uni-id-cf/index.js
唐明明 1c6091371e init
2022-06-07 16:37:03 +08:00

504 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
let uniID = require('uni-id')
const uniCaptcha = require('uni-captcha')
const createConfig = require('uni-config-center')
const uniIdConfig = createConfig({
pluginId: 'uni-id'
}).config()
const db = uniCloud.database()
const dbCmd = db.command
const usersDB = db.collection('uni-id-users')
exports.main = async (event, context) => {
//UNI_WYQ:这里的uniID换成新的保证多人访问不会冲突
uniID = uniID.createInstance({
context
})
console.log('event : ' + JSON.stringify(event))
/*
1.event为客户端 uniCloud.callFunction填写的data的值这里介绍一下其中的属性
action表示要执行的任务名称、比如登陆login、退出登陆 logout等
params业务数据内容
uniIdToken系统自动传递的token数据来源客户端的 uni.getStorageSync('uni_id_token')
*/
const {
action,
uniIdToken,
inviteCode
} = event;
const deviceInfo = event.deviceInfo || {};
let params = event.params || {};
/*
2.在某些操作之前我们要对用户对身份进行校验也就是要检查用户的token再将得到的uid写入params.uid
校验用到的方法是uniID.checkToken 详情https://uniapp.dcloud.io/uniCloud/uni-id?id=checktoken
讨论,我们假设一个这样的场景,代码如下。
如:
uniCloud.callFunction({
name:"xxx",
data:{
"params":{
uid:"通过某种方式获取来的别人的uid"
}
}
})
用户就这样轻易地伪造了他人的uid传递给服务端有一句话叫前端从来的数据是不可信任的
所以这里我们需要将uniID.checkToken返回的uid写入到params.uid
*/
let noCheckAction = ['register', 'checkToken', 'login', 'logout', 'sendSmsCode', 'createCaptcha',
'verifyCaptcha', 'refreshCaptcha', 'inviteLogin', 'loginByWeixin', 'loginByUniverify',
'loginByApple', 'loginBySms', 'resetPwdBySmsCode', 'registerAdmin'
]
if (!noCheckAction.includes(action)) {
if (!uniIdToken) {
return {
code: 403,
msg: '缺少token'
}
}
let payload = await uniID.checkToken(uniIdToken)
if (payload.code && payload.code > 0) {
return payload
}
params.uid = payload.uid
}
//禁止前台用户传递角色
if (action.slice(0, 7) == "loginBy") {
if (params.role) {
return {
code: 403,
msg: '禁止前台用户传递角色'
}
}
}
//3.注册成功后创建新用户的积分表方法
async function registerSuccess(uid) {
//用户接受邀请
if (inviteCode) {
await uniID.acceptInvite({
inviteCode,
uid
});
}
//添加当前用户设备信息
await db.collection('uni-id-device').add({
...deviceInfo,
user_id: uid
})
await db.collection('uni-id-scores').add({
user_id: uid,
score: 1,
type: 1,
balance: 1,
comment: "",
create_date: Date.now()
})
}
//4.记录成功登录的日志方法
const loginLog = async (res = {}) => {
const now = Date.now()
const uniIdLogCollection = db.collection('uni-id-log')
let logData = {
deviceId: params.deviceId || context.DEVICEID,
ip: params.ip || context.CLIENTIP,
type: res.type,
ua: context.CLIENTUA,
create_date: now
};
Object.assign(logData,
res.code === 0 ? {
user_id: res.uid,
state: 1
} : {
state: 0
})
if (res.type == 'register') {
await registerSuccess(res.uid)
} else {
if (Object.keys(deviceInfo).length) {
console.log(979797, {
deviceInfo,
user_id: res
});
//更新当前用户设备信息
await db.collection('uni-id-device').where({
user_id: res.uid
}).update(deviceInfo)
}
}
return await uniIdLogCollection.add(logData)
}
let res = {}
switch (action) { //根据action的值执行对应的操作
case 'bindMobileByUniverify':
let {
appid, apiKey, apiSecret
} = uniIdConfig.service.univerify
let univerifyRes = await uniCloud.getPhoneNumber({
provider: 'univerify',
appid,
apiKey,
apiSecret,
access_token: params.access_token,
openid: params.openid
})
if (univerifyRes.code === 0) {
res = await uniID.bindMobile({
uid: params.uid,
mobile: univerifyRes.phoneNumber
})
res.mobile = univerifyRes.phoneNumber
}
break;
case 'bindMobileBySms':
// console.log({
// uid: params.uid,
// mobile: params.mobile,
// code: params.code
// });
res = await uniID.bindMobile({
uid: params.uid,
mobile: params.mobile,
code: params.code
})
// console.log(res);
break;
case 'register':
var {
username, password, nickname
} = params
if (/^1\d{10}$/.test(username)) {
return {
code: 401,
msg: '用户名不能是手机号'
}
};
if (/^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/.test(username)) {
return {
code: 401,
msg: '用户名不能是邮箱'
}
}
res = await uniID.register({
username,
password,
nickname,
inviteCode
});
if (res.code === 0) {
await registerSuccess(res.uid)
}
break;
case 'login':
//防止黑客恶意破解登录,连续登录失败一定次数后,需要用户提供验证码
const getNeedCaptcha = async () => {
//当用户最近“2小时内(recordDate)”登录失败达到2次(recordSize)时。要求用户提交验证码
const now = Date.now(),
recordDate = 120 * 60 * 1000,
recordSize = 2;
const uniIdLogCollection = db.collection('uni-id-log')
let recentRecord = await uniIdLogCollection.where({
deviceId: params.deviceId || context.DEVICEID,
create_date: dbCmd.gt(now - recordDate),
type: 'login'
})
.orderBy('create_date', 'desc')
.limit(recordSize)
.get();
return recentRecord.data.filter(item => item.state === 0).length === recordSize;
}
let passed = false;
let needCaptcha = await getNeedCaptcha();
console.log('needCaptcha', needCaptcha);
if (needCaptcha) {
res = await uniCaptcha.verify({
...params,
scene: 'login'
})
if (res.code === 0) passed = true;
}
if (!needCaptcha || passed) {
res = await uniID.login({
...params,
queryField: ['username', 'email', 'mobile']
});
res.type = 'login'
await loginLog(res);
needCaptcha = await getNeedCaptcha();
}
res.needCaptcha = needCaptcha;
break;
case 'loginByWeixin':
res = await uniID.loginByWeixin(params);
await uniID.updateUser({
uid: res.uid,
username: "微信用户"
});
res.userInfo.username = "微信用户"
await loginLog(res)
break;
case 'loginByUniverify':
res = await uniID.loginByUniverify(params)
await loginLog(res)
break;
case 'loginByApple':
res = await uniID.loginByApple(params)
await loginLog(res)
break;
case 'checkToken':
res = await uniID.checkToken(uniIdToken);
break;
case 'logout':
res = await uniID.logout(uniIdToken)
break;
case 'sendSmsCode':
/* -开始- 测试期间,为节约资源。统一虚拟短信验证码为: 123456开启以下代码块即可 */
// return uniID.setVerifyCode({
// mobile: params.mobile,
// code: '123456',
// type: params.type
// })
/* -结束- */
// 简单限制一下客户端调用频率
const ipLimit = await db.collection('opendb-verify-codes').where({
ip: context.CLIENTIP,
created_at: dbCmd.gt(Date.now() - 60000)
}).get()
if (ipLimit.data.length > 0) {
return {
code: 429,
msg: '请求过于频繁'
}
}
const templateId = '11753' // 替换为自己申请的模板id
if (!templateId) {
return {
code: 500,
msg: 'sendSmsCode需要传入自己的templateId参考https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=sendsmscode'
}
}
const randomStr = '00000' + Math.floor(Math.random() * 1000000)
const code = randomStr.substring(randomStr.length - 6)
res = await uniID.sendSmsCode({
mobile: params.mobile,
code,
type: params.type,
templateId
})
break;
case 'loginBySms':
if (!params.code) {
return {
code: 500,
msg: '请填写验证码'
}
}
if (!/^1\d{10}$/.test(params.mobile)) {
return {
code: 500,
msg: '手机号码填写错误'
}
}
res = await uniID.loginBySms(params)
await loginLog(res)
break;
case 'resetPwdBySmsCode':
if (!params.code) {
return {
code: 500,
msg: '请填写验证码'
}
}
if (!/^1\d{10}$/.test(params.mobile)) {
return {
code: 500,
msg: '手机号码填写错误'
}
}
params.type = 'login'
let loginBySmsRes = await uniID.loginBySms(params)
// console.log(loginBySmsRes);
if (loginBySmsRes.code === 0) {
res = await uniID.resetPwd({
password: params.password,
"uid": loginBySmsRes.uid
})
} else {
return loginBySmsRes
}
break;
case 'getInviteCode':
res = await uniID.getUserInfo({
uid: params.uid,
field: ['my_invite_code']
})
if (res.code === 0) {
res.myInviteCode = res.userInfo.my_invite_code
delete res.userInfo
}
break;
case 'getInvitedUser':
res = await uniID.getInvitedUser(params)
break;
case 'updatePwd':
res = await uniID.updatePwd(params)
break;
case 'createCaptcha':
res = await uniCaptcha.create(params)
break;
case 'refreshCaptcha':
res = await uniCaptcha.refresh(params)
break;
case 'getUserInviteCode':
res = await uniID.getUserInfo({
uid: params.uid,
field: ['my_invite_code']
})
if (!res.userInfo.my_invite_code) {
res = await uniID.setUserInviteCode({
uid: params.uid
})
}
break;
// =========================== admin api start =========================
case 'registerAdmin': {
var {
username,
password
} = params
let {
total
} = await db.collection('uni-id-users').where({
role: 'admin'
}).count()
if (total) {
return {
code: 10001,
message: '超级管理员已存在,请登录...'
}
}
const appid = params.appid
const appName = params.appName
delete params.appid
delete params.appName
res = await uniID.register({
username,
password,
role: ["admin"]
})
if (res.code === 0) {
const app = await db.collection('opendb-app-list').where({
appid
}).count()
if (!app.total) {
await db.collection('opendb-app-list').add({
appid,
name: appName,
description: "admin 管理后台",
create_date: Date.now()
})
}
}
}
break;
case 'registerUser':
const {
userInfo
} = await uniID.getUserInfo({
uid: params.uid
})
if (userInfo.role.indexOf('admin') === -1) {
res = {
code: 403,
message: '非法访问, 无权限注册超级管理员',
}
} else {
// 过滤 dcloud_appid注册用户成功后再提交
const dcloudAppidList = params.dcloud_appid
delete params.dcloud_appid
res = await uniID.register({
autoSetDcloudAppid: false,
...params
})
if (res.code === 0) {
delete res.token
delete res.tokenExpired
await uniID.setAuthorizedAppLogin({
uid: res.uid,
dcloudAppidList
})
}
}
break;
case 'updateUser': {
const {
userInfo
} = await uniID.getUserInfo({
uid: params.uid
})
if (userInfo.role.indexOf('admin') === -1) {
res = {
code: 403,
message: '非法访问, 无权限注册超级管理员',
}
} else {
// 过滤 dcloud_appid注册用户成功后再提交
const dcloudAppidList = params.dcloud_appid
delete params.dcloud_appid
// 过滤 password注册用户成功后再提交
const password = params.password
delete params.password
// 过滤 uid、id
const id = params.id
delete params.id
delete params.uid
res = await uniID.updateUser({
uid: id,
...params
})
if (res.code === 0) {
if (password) {
await uniID.resetPwd({
uid: id,
password
})
}
await uniID.setAuthorizedAppLogin({
uid: id,
dcloudAppidList
})
}
}
break;
}
case 'getCurrentUserInfo':
res = await uniID.getUserInfo({
uid: params.uid,
...params
})
break;
// =========================== admin api end =========================
default:
res = {
code: 403,
msg: '非法访问'
}
break;
}
//返回数据给客户端
return res
}