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

1.新增获取邀请码接口getUserInviteCode 2.在邀请用户下载应用页面,自动设置被邀请用户的剪切板为邀请者的code(仅支持安卓端)...

1.新增获取邀请码接口getUserInviteCode 2.在邀请用户下载应用页面,自动设置被邀请用户的剪切板为邀请者的code(仅支持安卓端) 3.在注册或登陆并注册请求时自动添加剪切板中的请求参数 4.统一接口名称为驼峰法
上级 fd526ab7
......@@ -42,8 +42,10 @@ uni-starter + uniCloud admin,提供了用户端和管理端的基础模板,
### 功能模块介绍
#### 1. 拦截器与路由守卫
第三方路由拦截库,一般带有window对象等问题并不适合在uni-app中使用;另外传统路由拦截方式都是给原生方法做嵌套,首先这种写法并不优雅,另外不同项目的作者可能会不同的第三方路由库,这非常不利于生态的建设。你可能从插件市场拉下来一个项目有太多的学习成本,与你自有项目结合有大量差异需要去磨平。为此`uni-starter`基于`uni.addInterceptor`拦截器。
拦截器顾名思义,是在框架方法执行的各个环节(包含:拦截前触发、成功回调拦截、失败回调拦截、完成回调拦截)插入逻辑,篡改参数或终止运行。
第三方路由拦截库,一般带有window对象等问题,并不适合在uni-app中使用;另外传统路由拦截方式都是给原生方法做嵌套,首先这种写法并不优雅,也不支持ide的代码提示。
另外不同项目的作者可能会不同的第三方路由库,这非常不利于生态的建设。你可能从插件市场拉下来一个项目有太多的学习成本,与你自有项目结合有大量差异需要去磨平。
为此`uni-starter`基于`uni.addInterceptor`(拦截器)实现路由守卫。
拦截器顾名思义,是在框架方法执行的各个环节(包含:拦截前触发、成功回调拦截、失败回调拦截、完成回调拦截)插入逻辑,篡改数据或终止运行。
```
const {"router": {needLogin,login} } = uniStarterConfig //需要登录的页面
let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"];
......@@ -85,7 +87,6 @@ uni-starter + uniCloud admin,提供了用户端和管理端的基础模板,
```
#### 2.登录模块
- uni-start集成的登录方式有:验证码登录(smsCode)、读取手机SIM卡一键登录(univerify)、账号密码登录(username)、微信登录(weixin)、苹果登录(apple)
- 使用方式:在 `uni-starter.config.js`->`router`->`login`下完全列举你需要的登录方式。这里支持用[条件编译](https://uniapp.dcloud.io/platform?id=%e6%9d%a1%e4%bb%b6%e7%bc%96%e8%af%91)因此你可以配置在不同平台下拥有的登录方式。
- 优先级策略:
如果:配置内容为:["username","smsCode"],用户执行如下代码:
......@@ -94,10 +95,10 @@ uni-starter + uniCloud admin,提供了用户端和管理端的基础模板,
url: "/pages/ucenter/login-page/index/index"
})
```
访问登录页面,但会被拦截器自动切换到“配置的第0项的登录方式对应的页面”,即账户登录方式页面,路径:`/pages/ucenter/login-page/pwd-login/pwd-login`
- 生效策略:未列举到的或设备环境不支持的登录方式将被隐藏。
- 配置:
访问登录页面,会被拦截器自动切换到"配置的第0项(这里是`username`)的登录方式对应的页面”,即`账户登录`方式页面,路径:`/pages/ucenter/login-page/pwd-login/pwd-login`
- uni-start集成的登录方式有:验证码登录(smsCode)、读取手机SIM卡一键登录(univerify)、账号密码登录(username)、微信登录(weixin)、苹果登录(apple)
- 生效策略:登陆方式有如上5种,你希望有几种登陆方式就在配置中列举几种。有的登陆方式可能因为设备环境问题而不被支持;比如你正确地配置了微信登陆,但是用户的手机并没有安装微信,这样微信登陆功能就无法使用,并且如果出现这种情况你的app会被iOS的App Store拒绝上架。所以在这里,我们的生效策略在检测:你是否有列举到某个配置项为前提的情况下,增加了检测当前环境是否支持,如果不支持会自动隐藏。
- 其他配置:
+ 服务端:uni-starter服务端使用[uni-config-center](https://ext.dcloud.net.cn/plugin?id=4425)统一管理这些配置,文件路径`/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json`详情下文[目录结构](#id=catalogue)[uni-id配置说明](https://uniapp.dcloud.io/uniCloud/uni-id?id=configjson%e7%9a%84%e8%af%b4%e6%98%8e)
+ 应用模块:`manifest.json` App模块配置 --> OAuth(登录鉴权)--> 勾选并配置你所需要的模块
- 短信登陆:
......@@ -186,7 +187,7 @@ uni-starter + uniCloud admin,提供了用户端和管理端的基础模板,
2. 配置后提交云端打包后生效。理论上绝大部分和`manifest.json`生效相关的配置均需要提交云打包后生效
#### 10.拦截器改造后的uniCloud
1. Debug,调试期间开启Debug。接口一旦file就会弹出真实错误信息。否则将弹出,系统错误请稍后再试!
1. Debug,调试期间开启Debug。接口一旦fail就会弹出真实错误信息。否则将弹出,系统错误请稍后再试!
```
if(Debug){
console.log(e);
......@@ -409,3 +410,4 @@ uni-starter
### 第三方插件(感谢插件作者,排名不分前后):
1. 图片裁剪 [limeClipper](https://ext.dcloud.net.cn/plugin?id=3594) @作者: 陌上华年
2. 二维码生成 [Sansnn-uQRCode](https://ext.dcloud.net.cn/plugin?id=1287) @作者: 3snn
3. clipboard.js [clipboard](https://clipboardjs.com/)
\ No newline at end of file
## 1.0.19(2021-06-17)
1.新增获取邀请码接口getUserInviteCode 2.在邀请用户下载应用页面,自动设置被邀请用户的剪切板为邀请者的code(仅支持安卓端) 3.在注册或登陆并注册请求时自动添加剪切板中的请求参数 4.统一接口名称为驼峰法
## 1.0.18(2021-06-15)
修复,APP端有安装微信客户端但未显示微信登陆快捷键的问题
## 1.0.17(2021-06-09)
修复,非APP端deviceInfo为空引起的登陆失败问题
## 1.0.16(2021-06-08)
......
......@@ -9,11 +9,15 @@ import interceptorChooseImage from '@/uni_modules/json-interceptor-chooseImage/j
const db = uniCloud.database()
export default function() {
// #ifndef H5
setTimeout(()=>{
// #endif
// uniStarterConfig挂载到getApp().
const app = getApp({allowDefault: true})
app.globalData.config = uniStarterConfig;
// #ifndef H5
},30)
// #endif
// 初始化appVersion(仅app生效)
initAppVersion();
......@@ -108,6 +112,31 @@ export default function() {
}
console.log("重新登陆/注册,获取设备id",deviceInfo);
option.data.deviceInfo = deviceInfo
// #ifndef H5
//注册可能不仅仅走register接口,还有登陆并注册的接口
option.data.inviteCode = await new Promise((callBack)=>{
uni.getClipboardData({
success: function (res) {
if(res.data.slice(0,18) =='uniInvitationCode:'){
let uniInvitationCode = res.data.slice(18,38)
console.log('当前用户是其他用户推荐下载的,推荐者的code是:'+uniInvitationCode);
// uni.showModal({
// content: '当前用户是其他用户推荐下载的,推荐者的code是:'+uniInvitationCode,
// showCancel: false
// });
callBack(uniInvitationCode)
//当前用户是其他用户推荐下载的。这里登记他的推荐者id 为当前用户的myInviteCode。判断如果是注册
}else{
callBack(false)
}
},
fail() {
callBack(false)
}
});
})
// #endif
}
// #endif
console.log(JSON.stringify(option));
......@@ -174,10 +203,14 @@ export default function() {
console.log(e.result.code);
switch (e.result.code){
case 403:
uni.showModal({
content: '未登陆,跳登陆',
showCancel: false
});
uni.navigateTo({
url: "/pages/ucenter/login-page/index/index"
})
break;
case 30203:
uni.navigateTo({
url: "/pages/ucenter/login-page/index/index"
})
break;
case 50101:
uni.showToast({
......@@ -234,6 +267,13 @@ export default function() {
},
fail(err) { // 失败回调拦截
console.log(err);
if(Debug){
console.log(err);
uni.showModal({
content: JSON.stringify(err),
showCancel: false
});
}
},
})
})
......
<template>
<view v-if="pass">
<slot></slot>
</view>
</template>
<script>
export default {
name:"uni-id-show",
props: {
isLogin:{
type: Boolean,
default(){
return false
}
},
role: {
type: [Array,String],
default(){
return "ALL"
}
},
permission: {
type: [Array,String],
default(){
return "ALL"
}
}
},
data() {
return {
pass: true
}
},
created() {
this.check()
},
methods:{
check(){
let {permission,role,tokenExpired,uid} = uniCloud.getCurrentUserInfo()
console.log(permission,role,tokenExpired,uid);
let pass = true
//1.是否需要登陆
if(this.isLogin){
pass = uid != null
}
//2.角色要求
if(this.role != "ALL"){
pass = role.some(item => this.role.includes(item));
}
//3.权限要求
if(this.permission != "ALL"){
pass = permission.some(item => this.permission.includes(item));
}
this.pass = pass
}
}
}
</script>
\ No newline at end of file
......@@ -121,11 +121,11 @@
}) => {
if (this.config[id].isChecked && this.loginConfig.includes(id)) {
if (id == 'weixin') {
if (~plus.runtime.isApplicationExist({
if (!plus.runtime.isApplicationExist({
pname: 'com.tencent.mm',
action: 'weixin://'
})) {
// console.log("微信应用未安装");
console.log("微信应用未安装");
return
}
}
......@@ -297,12 +297,12 @@
console.log({
params,
type
});
});
let action = 'loginBy'+ type.trim().toLowerCase().replace(type[0], type[0].toUpperCase())
uniCloud.callFunction({
name: 'uni-id-cf',
data: {
action: 'login_by_' + type,
params
action,params
},
success: ({
result
......@@ -321,7 +321,7 @@
complete: () => {
uni.hideLoading()
}
})
})
},
async getUserInfo(e) {
return new Promise((resolve, reject) => {
......
......@@ -32,8 +32,6 @@
},
"Share": {
},
"Push": {
},
"OAuth": {
},
"FaceID": {
......@@ -70,8 +68,6 @@
},
"sdkConfigs": {
"oauth": {
"univerify": {
},
"apple": {
},
"weixin": {
......
{
"id": "uni-starter",
"displayName": "uni-starter",
"version": "1.0.17",
"description": "云端一体应用快速开发模版",
"version": "1.0.19",
"description": "云端一体应用快速开发基本项目模版",
"keywords": [
"uni-starter",
"login",
......@@ -12,7 +12,7 @@
],
"repository": "https://codechina.csdn.net/dcloud/uni-starter.git",
"engines": {
"HBuilderX": "^3.1.17"
"HBuilderX": "^3.1.18"
},
"dcloudext": {
"category": [
......@@ -77,4 +77,4 @@
}
}
}
}
\ No newline at end of file
}
{
"pages": [
{
"pages": [{
"path": "pages/list/list",
"style": {
"navigationStyle":"custom",
"navigationStyle": "custom",
"enablePullDownRefresh": true
}
},
......@@ -70,7 +69,8 @@
"style": {
"navigationBarTitleText": "关于"
// #ifdef APP-PLUS
,"app-plus": {
,
"app-plus": {
"titleNView": {
"buttons": [{
"type": "share"
......@@ -136,7 +136,7 @@
"navigationBarTitleText": ""
}
},{
}, {
"path": "pages/common/webview/webview",
"style": {
"navigationBarTitleText": "",
......@@ -156,6 +156,13 @@
"navigationBarTitleText": "阅读记录",
"enablePullDownRefresh": true
}
}, {
"path": "pages/ucenter/invite/invite",
"style": {
"navigationStyle":"custom",
"enablePullDownRefresh": false
}
}
],
"globalStyle": {
......@@ -169,9 +176,9 @@
"list": [{
"path": "pages/list/list"
},
{
"path": "pages/ucenter/login-page/index/index"
},{
{
"path": "pages/ucenter/login-page/index/index"
}, {
"path": "pages/ucenter/userinfo/userinfo"
},
{
......@@ -202,4 +209,4 @@
"text": "我的"
}]
}
}
}
......@@ -3,7 +3,7 @@
<!-- #ifndef H5 -->
<statusBar></statusBar>
<!-- #endif -->
<!-- 搜索功能 -->
<!-- 搜索功能 -->
<uni-search-bar @click="searchClick" class="uni-search-box" v-model="keyword" ref="searchBar" radius="100"
cancelButton="none" disabled />
<unicloud-db ref='udb' v-slot:default="{data,pagination,hasMore, loading, error, options}" @error="onqueryerror"
......@@ -199,4 +199,4 @@
.f1 {
flex: 1;
}
</style>
</style>
\ No newline at end of file
<template>
<view>
<web-view :src="url"></web-view>
</view>
</template>
<script>
export default {
created() {
document.getElementById("openApp").style.display = 'none'
document.getElementsByTagName("body")[0].style = ""
},
onLoad({
code
}) {
this.code = code
},
onReady() {
var IframeOnClick = {
resolution: 200,
iframes: [],
interval: null,
Iframe: function() {
this.element = arguments[0];
this.cb = arguments[1];
this.hasTracked = false;
},
track: function(element, cb) {
this.iframes.push(new this.Iframe(element, cb));
if (!this.interval) {
var _this = this;
this.interval = setInterval(function() { _this.checkClick(); }, this.resolution);
}
},
checkClick: function() {
if (document.activeElement) {
var activeElement = document.activeElement;
for (var i in this.iframes) {
if (activeElement === this.iframes[i].element) { // user is in this Iframe
if (this.iframes[i].hasTracked == false) {
this.iframes[i].cb.apply(window, []);
this.iframes[i].hasTracked = true;
}
} else {
this.iframes[i].hasTracked = false;
}
}
}
}
};
IframeOnClick.track(document.getElementsByTagName("iframe")[0], ()=>{
this.copy()
});
},
computed: {
url() {
return getApp().globalData.config.about.download
}
},
data() {
return {
code: ""
}
},
methods: {
copy() {
console.log('copy');
if(!this.code){
return false
}
uni.setClipboardData({
data: 'uniInvitationCode:' + this.code,
success: () => {
uni.showModal({
content: '成功在用户剪切板中存储,邀请人code:'+this.code,
showCancel: false
});
},
fail: () => {
uni.showModal({
content: '失败,未能。在用户剪切板中存储,邀请人code',
showCancel: false
});
}
})
uni.hideToast()
/* 以下临时解决h5端样式和键盘弹出端错误解决方案,后续会直接内置*/
document.getElementById("#clipboard").style.top = '-999px';
uni.hideKeyboard()
}
}
}
</script>
<style>
</style>
......@@ -42,17 +42,6 @@
},
methods: {
submit(){ //完成并提交
// this.-request('uni-id-cf/loginBySms',
// {
// "mobile":this.phone,
// "code":this.code
// },
// e=>{
// console.log(e);
// this.loginSuccess(e)
// },
// {showLoading:true})
uniCloud.callFunction({
name:'uni-id-cf',
data:{
......
......@@ -95,44 +95,8 @@
}
}
})
// this.-request('uni-id-cf/login', {
// "username": this.username,
// "password": this.password,
// "captcha":this.captcha
// }, result => {
// console.log(result);
// if (result.code === 0) {
// this.loginSuccess(result)
// } else {
// if (result.needCaptcha) {
// uni.showToast({
// title: result.msg,
// icon: 'none'
// });
// this.createCaptcha()
// }else{
// uni.showModal({
// title: '错误',
// content: result.msg,
// showCancel: false,
// confirmText: '知道了'
// });
// }
// }
// })
},
createCaptcha(){
// this.-request(
// 'uni-id-cf/createCaptcha', {
// scene: "login"
// },
// result => {
// if (result.code === 0) {
// this.captchaBase64 = result.captchaBase64
// }
// })
uniCloud.callFunction({
name:'uni-id-cf',
data:{
......
......@@ -137,20 +137,6 @@
submit() {
this.$refs.form.submit()
.then(res => {
// this.-request('uni-id-cf/resetPwdBySmsCode', {
// "mobile": this.formData.phone,
// "code": this.formData.code,
// "password": this.formData.pwd
// }, result => {
// console.log(result);
// uni.showToast({
// title: result.msg,
// icon: 'none'
// });
// if (result.code === 0) {
// uni.navigateBack()
// }
// })
uniCloud.callFunction({
name:'uni-id-cf',
data:{
......
......@@ -63,12 +63,6 @@ import mixin from '../common/login-page.mixin.js';
})
},
submitForm(params) {
// this.-request('uni-id-cf/register',params,result=>{
// console.log(result);
// if(result.code === 0){
// this.loginSuccess(result)
// }
// })
uniCloud.callFunction({
name:'uni-id-cf',
data:{
......
......@@ -14,11 +14,8 @@
</uni-grid>
<uni-list class="center-list" v-for="(sublist , index) in ucenterList" :key="index">
<uni-list-item v-for="(item,i) in sublist" :title="item.title" link :rightText="item.rightText" :key="i"
:clickable="true" :to="item.to"
@click="ucenterListClick(item)"
:show-extra-icon="true"
:extraIcon="{type:item.icon,color:'#999'}"
>
:clickable="true" :to="item.to" @click="ucenterListClick(item)" :show-extra-icon="true"
:extraIcon="{type:item.icon,color:'#999'}">
<view v-if="item.showBadge" class="item-footer" slot="footer">
<text class="item-footer-text">{{item.rightText}}</text>
<view class="item-footer-badge"></view>
......@@ -35,6 +32,7 @@
} from 'vuex';
import checkUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
import callCheckVersion from '@/uni_modules/uni-upgrade-center-app/utils/call-check-version';
import uniShare from 'uni_modules/uni-share/js_sdk/uni-share.js';
const db = uniCloud.database();
const dbCollectionName = 'uni-id-scores';
......@@ -65,34 +63,41 @@
{
"title": '去评分',
"event": 'gotoMarket',
"icon":"hand-thumbsup"
"icon": "hand-thumbsup"
},
//#endif
{
"title": '阅读过的文章',
"to": '/pages/ucenter/read-news-log/read-news-log',
"icon":"flag"
"icon": "flag"
},
{
"title": '我的积分',
"to": '',
"event": 'getScore',
"icon":"paperplane"
}
"icon": "paperplane"
}
// #ifndef H5
,{
"title": '分销推荐',
"event": 'share',
"icon": "redo"
}
// #endif
],
[{
"title": '问题与反馈',
"to": '/uni_modules/uni-feedback/pages/uni-feedback/uni-feedback',
"icon":"help"
"icon": "help"
}, {
"title": '设置',
"to": '/pages/ucenter/settings/settings',
"icon":"gear"
"icon": "gear"
}],
[{
"title": '关于',
"to": '/pages/ucenter/about/about',
"icon":"info"
"icon": "info"
}]
]
}
......@@ -103,7 +108,7 @@
title: '检查更新',
rightText: this.appVersion.version + '-' + this.appVersion.versionCode,
event: 'checkVersion',
icon:'loop',
icon: 'loop',
showBadge: this.appVersion.hasNew
})
//#endif
......@@ -206,6 +211,79 @@
}).finally(() => {
uni.hideLoading()
})
},
async share() {
let {result} = await uniCloud.callFunction({
name: 'uni-id-cf',
data: {
action: 'getUserInviteCode'
}
})
console.log(result);
let myInviteCode = result.myInviteCode || result.userInfo.my_invite_code
console.log(myInviteCode);
let {
appName,
logo,
company,
slogan
} = this.appConfig.about
// #ifdef APP-PLUS
uniShare({
content: { //公共的分享类型(type)、链接(herf)、标题(title)、summary(描述)、imageUrl(缩略图)
type: 0,
href: this.appConfig.h5.url +
`/#/pages/ucenter/invite/invite?code=${myInviteCode}`,
title: appName,
summary: slogan,
imageUrl: logo + '?x-oss-process=image/resize,m_fill,h_100,w_100' //压缩图片解决,在ios端分享图过大导致的图片失效问题
},
menus: [{
"img": "/static/app-plus/sharemenu/wechatfriend.png",
"text": "微信好友",
"share": {
"provider": "weixin",
"scene": "WXSceneSession"
}
},
{
"img": "/static/app-plus/sharemenu/wechatmoments.png",
"text": "微信朋友圈",
"share": {
"provider": "weixin",
"scene": "WXSenceTimeline"
}
},
{
"img": "/static/app-plus/sharemenu/weibo.png",
"text": "微博",
"share": {
"provider": "sinaweibo"
}
},
{
"img": "/static/app-plus/sharemenu/qq.png",
"text": "QQ",
"share": {
"provider": "qq"
}
},
{
"img": "/static/app-plus/sharemenu/copyurl.png",
"text": "复制",
"share": "copyurl"
},
{
"img": "/static/app-plus/sharemenu/more.png",
"text": "更多",
"share": "shareSystem"
}
],
cancelText: "取消分享",
}, e => { //callback
console.log(e);
})
// #endif
}
}
}
......@@ -285,17 +363,17 @@
/*修改边线粗细示例*/
/* #ifndef APP-NVUE */
.center-list /deep/ .uni-list--border:after{
.center-list /deep/ .uni-list--border:after {
-webkit-transform: scaleY(0.2);
transform: scaleY(0.2);
transform: scaleY(0.2);
margin-left: 80rpx;
}
.center-list /deep/ .uni-list--border-top,
.center-list /deep/ .uni-list--border-bottom{
display: none;
}
}
.center-list /deep/ .uni-list--border-top,
.center-list /deep/ .uni-list--border-bottom {
display: none;
}
/* #endif */
.item-footer {
flex-direction: row;
......@@ -319,4 +397,4 @@
/* #endif */
background-color: #DD524D;
}
</style>
</style>
......@@ -48,20 +48,6 @@
*/
submit() {
console.log(this.formData);
// this.-request('uni-id-cf/bind_mobile_by_sms', {
// "mobile": this.formData.phone,
// "code": this.formData.code
// }, result=> {
// console.log(result);
// this.setUserInfo({"mobile":result.mobile})
// uni.showToast({
// title: result.msg,
// icon: 'none'
// });
// if (result.code === 0) {
// uni.navigateBack()
// }
// })
uniCloud.callFunction({
name:'uni-id-cf',
data:{
......
......@@ -70,25 +70,6 @@
"univerifyStyle": this.univerifyStyle,
success: async e => {
console.log(e.authResult);
// this.-request('uni-id-cf/bind_mobile_by_univerify',
// e.authResult,
// result=>
// {
// console.log(result);
// if(result.code===0){
// this.setUserInfo({"mobile":result.mobile})
// uni.closeAuthView()
// }else{
// uni.showModal({
// content: JSON.stringify(result.msg),
// showCancel: false,
// complete() {
// uni.closeAuthView()
// }
// });
// }
// }
// )
uniCloud.callFunction({
name:'uni-id-cf',
data:{
......@@ -114,7 +95,7 @@
},
fail: (err) => {
console.log(err);
if(err.code=='30002'){
if(err.code=='30002'||err.code=='30001'){
this.bindMobileBySmsCode()
}
}
......
......@@ -42,7 +42,7 @@ module.exports = {
//公司名称
"company": "数字天堂(北京)网络技术有限公司",
//口号
"slogan": "为开发而生",
"slogan": "云端一体应用快速开发模版",
//政策协议
"agreements": [{
"title": "用户服务协议", //协议名称
......
......@@ -7,37 +7,45 @@ const uniIdConfig = createConfig({
})._config
const db = uniCloud.database()
const dbCmd = db.command
exports.main = async (event, context) => {
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} = 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','login_by_weixin','login_by_univerify','login_by_apple','loginBySms','resetPwdBySmsCode']
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
} = 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 {
......@@ -52,14 +60,23 @@ exports.main = async (event, context) => {
params.uid = payload.uid
}
//禁止前台用户传递角色
if (action.slice(0,7) == "loginBy") {
if (params.role) {
return {
code: 403,
msg: '禁止前台用户传递角色'
}
}
}
//3.注册成功后创建新用户的积分表方法
async function registerSuccess(uid) {
//添加当前用户设备信息
await db.collection('uni-id-device').add({
...deviceInfo,
user_id:uid
})
async function registerSuccess(uid) {
//添加当前用户设备信息
await db.collection('uni-id-device').add({
...deviceInfo,
user_id: uid
})
await db.collection('uni-id-scores').add({
user_id: uid,
score: 1,
......@@ -67,16 +84,16 @@ exports.main = async (event, context) => {
balance: 1,
comment: "",
create_date: Date.now()
})
})
}
//4.记录成功登录的日志方法
const loginLog = async (res = {}, type = 'login') => {
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,
type: res.type,
ua: context.CLIENTUA,
create_date: now
};
......@@ -88,19 +105,21 @@ exports.main = async (event, context) => {
} : {
state: 0
})
if (res.type == 'register') {
if (res.type == 'register') {
await registerSuccess(res.uid)
}else{
if(Object.keys(deviceInfo).length){
//更新当前用户设备信息
await db.collection('uni-id-device').where({user_id:res.uid}).update(deviceInfo)
}
} else {
if (Object.keys(deviceInfo).length) {
//更新当前用户设备信息
await db.collection('uni-id-device').where({
user_id: res.uid
}).update(deviceInfo)
}
}
return await uniIdLogCollection.add(logData)
}
let res = {}
switch (action) { //根据action的值执行对应的操作
let res = {}
switch (action) { //根据action的值执行对应的操作
case 'bind_mobile_by_univerify':
let {
appid, apiKey, apiSecret
......@@ -122,22 +141,20 @@ exports.main = async (event, context) => {
}
break;
case 'bind_mobile_by_sms':
console.log({
uid: params.uid,
mobile: params.mobile,
code: params.code
});
// 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);
// console.log(res);
break;
case 'register':
var {
username, password, nickname
} = params
case 'register':
var {username, password, nickname,inviteCode} = params
if (/^1\d{10}$/.test(username)) {
return {
code: 401,
......@@ -150,34 +167,30 @@ exports.main = async (event, context) => {
msg: '用户名不能是邮箱'
}
}
res = await uniID.register({
username,
password,
nickname
});
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;
}
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);
......@@ -193,17 +206,22 @@ exports.main = async (event, context) => {
res = await uniID.login({
...params,
queryField: ['username', 'email', 'mobile']
});
if(res.code === 0){
await loginLog(res);
});
if (res.code === 0) {
await loginLog(res);
}
needCaptcha = await getNeedCaptcha();
}
res.needCaptcha = needCaptcha;
break;
case 'login_by_weixin':
res = await uniID.loginByWeixin({...params});
case 'loginByWeixin':
var {
username, password, nickname
} = params
res = await uniID.loginByWeixin({
...params
});
await uniID.updateUser({
uid: res.uid,
username: "微信用户"
......@@ -211,11 +229,11 @@ exports.main = async (event, context) => {
res.userInfo.username = "微信用户"
await loginLog(res)
break;
case 'login_by_univerify':
case 'loginByUniverify':
res = await uniID.loginByUniverify(params)
await loginLog(res)
break;
case 'login_by_apple':
case 'loginByApple':
res = await uniID.loginByApple(params)
await loginLog(res)
break;
......@@ -258,7 +276,6 @@ exports.main = async (event, context) => {
type: params.type,
templateId
})
await loginLog(res)
break;
case 'loginBySms':
if (!params.code) {
......@@ -302,7 +319,7 @@ exports.main = async (event, context) => {
}
}
let loginBySmsRes = await uniID.loginBySms(params)
console.log(loginBySmsRes);
// console.log(loginBySmsRes);
if (loginBySmsRes.code === 0) {
res = await uniID.resetPwd({
password: params.password,
......@@ -337,6 +354,19 @@ exports.main = async (event, context) => {
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 -----------
case 'registerAdmin':
var {
username, password
......@@ -352,12 +382,39 @@ exports.main = async (event, context) => {
message: '超级管理员已存在,请登录...'
}
}
return this.ctx.uniID.register({
return uniID.register({
username,
password,
role: ["admin"]
})
break;
case 'registerUser':
const {
userInfo
} = await uniID.getUserInfo({
uid: params.uid,
})
if (userInfo.role.indexOf('admin') === -1 && params.role.indexOf('admin') > -1) {
res = {
code: 403,
message: '非法访问, 无权限注册超级管理员',
}
} else {
res = await uniID.register({
...params
})
if (res.code === 0) {
delete res.token
delete res.tokenExpired
}
}
break;
case 'getCurrentUserInfo':
res = uniID.getUserInfo({
uid: params.uid,
...params
})
break;
default:
res = {
code: 403,
......
// 本文件中的json内容将在云函数【运行】时作为参数传给云函数。
// 配置教程参考:https://uniapp.dcloud.net.cn/uniCloud/quickstart?id=runparam
{
"action": "login_by_weixin",
"action": "getUserInviteCode",
"params": {
"code": "093tK5Ga1X1D6B0MSAHa13uRH04tK5Gs"
}
},
"uniInvitationCode":"CY2A8B",
"uniIdToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiI2MGMwMzMwOTI0OTU3OTAwMDFiMDAwZGIiLCJyb2xlIjpbXSwicGVybWlzc2lvbiI6W10sImNsaWVudElkIjoiMTk1Zjc3YzE4MGMyM2UzZjVhOGE4ZjM4ZTQyOTAxODYiLCJpYXQiOjE2MjMyMjgxMTYsImV4cCI6MTYyMzIzNTMxNn0.vtNSqdhCaI6fdvk5aHo5Dmdsb5MkBS8omk0b0YzAgIs"
}
......@@ -4,7 +4,7 @@
"tokenExpiresIn": 7200,
"tokenExpiresThreshold": 600,
"passwordErrorLimit": 6,
"bindTokenToDevice": true,
"bindTokenToDevice": false,
"passwordErrorRetryTime": 3600,
"autoSetInviteCode": false,
"forceInviteCode": false,
......
......@@ -30,7 +30,6 @@
"modules" : {
"Fingerprint" : {},
"Share" : {},
"Push" : {},
"OAuth" : {},
"FaceID" : {}
},
......@@ -60,7 +59,6 @@
"ios" : {},
"sdkConfigs" : {
"oauth" : {
"univerify" : {},
"apple" : {},
"weixin" : {
"appid" : "wxffdd8fa6ec4ef2a0",
......
......@@ -4,7 +4,7 @@
"tokenExpiresIn": 7200,
"tokenExpiresThreshold": 600,
"passwordErrorLimit": 6,
"bindTokenToDevice": true,
"bindTokenToDevice": false,
"passwordErrorRetryTime": 3600,
"autoSetInviteCode": false,
"forceInviteCode": false,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册