提交 589ef43f 编写于 作者: C chenruilong

Merge branch 'dev'

......@@ -4,5 +4,6 @@ unpackage/
node_modules/
.vite/
uni_modules_tools/copy
/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json
/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json
.idea
......@@ -128,7 +128,7 @@
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "3",
"vueVersion" : "2",
"h5" : {
"unipush" : {
"enable" : false
......
......@@ -26,9 +26,12 @@
"value": "smsCode",
"text": "手机验证码"
}, {
"value": "apple",
"text": "苹果登录"
}]
"value": "apple",
"text": "苹果登录"
}, {
"value": "weixinMobile",
"text": "微信手机号登录"
}]
}
},
onLoad() {},
......@@ -80,4 +83,4 @@
font-size: 18px;
color: #8f8f94;
}
</style>
</style>
// 在本文件中可配置云数据库初始化,数据格式见:https://uniapp.dcloud.io/uniCloud/hellodb?id=db-init
// 编写完毕后对本文件点右键,可按配置规则创建表和添加数据
{
"opendb-device":{},
"opendb-open-data":{},
"opendb-verify-codes":{},
"uni-id-device":{},
"uni-id-log":{},
"uni-id-permissions":{},
"uni-id-roles":{},
"uni-id-users":{}
}
## 1.0.25(2022-10-14)
- uni-id-co 增加 微信授权手机号登录方式 [文档](https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login-by-weixin-mobile)
- uni-id-co 增加 解绑第三方平台账号 [文档](https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#unbind-third-account)
- uni-id-co 微信绑定手机号支持通过`getPhoneNumber`事件回调的`code`绑定 [文档](https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#bind-mobile-by-mp-weixin)
- 修复 sendSmsCode 接口未在参数内传递 templateId 时 未能从配置文件读取 templateId 的Bug
## 1.0.24(2022-10-08)
- 修复 报uni-id-users表schema内错误的bug
## 1.0.23(2022-10-08)
- 修复 vue3下vite编译发行打包失败
- 修复 某些情况下注册账号,报TypeErroe:Cannot read properties of undefined (reading ’showToast‘)的错误
## 1.0.22(2022-09-23)
- 修复 某些情况下,修改密码报“两次输入密码不一致”的bug
## 1.0.21(2022-09-21)
......
import pagesJson from '@/pages.json'
const uniIdCo = uniCloud.importObject("uni-id-co")
const db = uniCloud.database();
const db = uniCloud.database();
const usersTable = db.collection('uni-id-users')
let hostUserInfo = uni.getStorageSync('uni-id-pages-userInfo')||{}
console.log( hostUserInfo);
const data = {
userInfo: hostUserInfo,
hasLogin: Object.keys(hostUserInfo).length != 0
}
console.log('data', data);
// 定义 mutations, 修改属性
export const mutations = {
// data不为空,表示传递要更新的值(注意不是覆盖是合并),什么也不传时,直接查库获取更新
async updateUserInfo(data = false) {
let hostUserInfo = uni.getStorageSync('uni-id-pages-userInfo')||{}
console.log( hostUserInfo);
const data = {
userInfo: hostUserInfo,
hasLogin: Object.keys(hostUserInfo).length != 0
}
console.log('data', data);
// 定义 mutations, 修改属性
export const mutations = {
// data不为空,表示传递要更新的值(注意不是覆盖是合并),什么也不传时,直接查库获取更新
async updateUserInfo(data = false) {
if (data) {
usersTable.where('_id==$env.uid').update(data).then(e => {
console.log(e);
......@@ -32,32 +32,32 @@ export const mutations = {
icon: 'none'
});
}
})
} else {
})
} else {
try {
let res = await usersTable.where("'_id' == $cloudEnv_uid")
.field('mobile,nickname,username,email,avatar_file')
.get()
console.log('fromDbData',res.result.data);
this.setUserInfo(res.result.data[0])
} catch (e) {
this.setUserInfo({},{cover:true})
console.error(e.message, e.errCode);
}
}
},
async setUserInfo(data, {cover}={cover:false}) {
.get()
console.log('fromDbData',res.result.data);
this.setUserInfo(res.result.data[0])
} catch (e) {
this.setUserInfo({},{cover:true})
console.error(e.message, e.errCode);
}
}
},
async setUserInfo(data, {cover}={cover:false}) {
console.log('set-userInfo', data);
let userInfo = cover?data:Object.assign(store.userInfo,data)
store.userInfo = Object.assign({},userInfo)
store.hasLogin = Object.keys(store.userInfo).length != 0
console.log('store.userInfo', store.userInfo);
uni.setStorage({
key: "uni-id-pages-userInfo",
data:store.userInfo
})
return data
store.userInfo = Object.assign({},userInfo)
store.hasLogin = Object.keys(store.userInfo).length != 0
console.log('store.userInfo', store.userInfo);
uni.setStorage({
key: "uni-id-pages-userInfo",
data:store.userInfo
})
return data
},
async logout() {
await uniIdCo.logout()
......@@ -69,7 +69,7 @@ export const mutations = {
uni.$emit('uni-id-pages-logout')
this.setUserInfo({},{cover:true})
},
loginSuccess(e){
loginSuccess(e = {}){
const {
showToast = true, toastText = '登录成功', autoBack = true, uniIdRedirectUrl = ''
} = e
......@@ -94,7 +94,7 @@ export const mutations = {
delta++
}
})
console.log('判断需要返回几层:', pages, delta);
// console.log('判断需要返回几层:', delta);
if (uniIdRedirectUrl) {
return uni.reLaunch({
url: uniIdRedirectUrl
......@@ -106,32 +106,32 @@ export const mutations = {
return window.history.go(-3)
}
// #endif
if (delta) {
const page = pagesJson.pages[0]
return uni.reLaunch({
url: `/${page.path}`
})
}
uni.navigateBack({
delta
})
}
}
}
// #ifdef VUE2
import Vue from 'vue'
// 通过Vue.observable创建一个可响应的对象
export const store = Vue.observable(data)
// #endif
// #ifdef VUE3
import {
reactive
} from 'vue'
// 通过Vue.observable创建一个可响应的对象
export const store = reactive(data)
}
// #ifdef VUE2
import Vue from 'vue'
// 通过Vue.observable创建一个可响应的对象
export const store = Vue.observable(data)
// #endif
// #ifdef VUE3
import {
reactive
} from 'vue'
// 通过Vue.observable创建一个可响应的对象
export const store = reactive(data)
// #endif
......@@ -14,16 +14,16 @@
</template>
<script>
import config from '@/uni_modules/uni-id-pages/config.js'
//前一个窗口的页面地址。控制点击切换快捷登录方式是创建还是返回
import {
store,
mutations
} from '@/uni_modules/uni-id-pages/common/store.js'
//前一个窗口的页面地址。控制点击切换快捷登录方式是创建还是返回
import {
store,
mutations
} from '@/uni_modules/uni-id-pages/common/store.js'
const db = uniCloud.database();
const usersTable = db.collection('uni-id-users')
let allServicesList = []
let allServicesList = []
export default {
computed: {
agreements() {
......@@ -45,17 +45,17 @@
]
},
agree: {
get() {
get() {
return this.getParentComponent().agree
},
set(agree) {
console.log('setAgree', agree);
set(agree) {
console.log('setAgree', agree);
return this.getParentComponent().agree = agree
}
}
},
data() {
return {
data() {
return {
servicesList: [{
"id": "username",
"text": "账号登录",
......@@ -127,11 +127,11 @@
"list": []
},
"privacyTerms": {
"defaultCheckBoxState": false, // 条款勾选框初始状态 默认值: true
"textColor": "#BBBBBB", // 文字颜色 默认值:#BBBBBB
"termsColor": "#5496E3", // 协议文字颜色 默认值: #5496E3
"prefix": "我已阅读并同意", // 条款前的文案 默认值:“我已阅读并同意”
"suffix": "并使用本机号码登录", // 条款后的文案 默认值:“并使用本机号码登录”
"defaultCheckBoxState": false, // 条款勾选框初始状态 默认值: true
"textColor": "#BBBBBB", // 文字颜色 默认值:#BBBBBB
"termsColor": "#5496E3", // 协议文字颜色 默认值: #5496E3
"prefix": "我已阅读并同意", // 条款前的文案 默认值:“我已阅读并同意”
"suffix": "并使用本机号码登录", // 条款后的文案 默认值:“并使用本机号码登录”
"privacyItems": []
}
}
......@@ -147,14 +147,14 @@
let loginTypes = config.loginTypes
servicesList = servicesList.filter(item => {
// #ifndef APP
//非app端去掉apple登录
if (item.id == 'apple') {
return false
}
// #endif
// #ifdef APP
//去掉非ios系统上的apple登录
if (item.id == 'apple' && uni.getSystemInfoSync().osName != 'ios') {
......@@ -196,7 +196,7 @@
// #ifndef H5
return this.$parent;
// #endif
// #ifdef H5
return this.$parent.$parent;
// #endif
......@@ -234,8 +234,8 @@
console.log('出乎意料的情况,path:' + path);
}
},
async login_before(type, navigateBack = true) {
console.log(type);
async login_before(type, navigateBack = true, options = {}) {
console.log(type);
//提示空实现
if (["qq",
"xiaomi",
......@@ -251,7 +251,7 @@
icon: 'none'
});
}
//检查当前环境是否支持这种登录方式
// #ifdef APP
let isAppExist = true
......@@ -272,66 +272,65 @@
})
})
// #endif
if (
// #ifdef APP
!isAppExist
// #endif
//非app端使用了,app特有登录方式
// #ifndef APP
["univerify","apple"].includes(type)
// #endif
) {
return uni.showToast({
title: '当前设备不支持此登录,请选择其他登录方式',
icon: 'none'
});
}
//判断是否需要弹出隐私协议授权框
console.log(type, this.agree);
let needAgreements = (config?.agreements?.scope || []).includes('register')
console.log(type, this.agree);
let needAgreements = (config?.agreements?.scope || []).includes('register')
console.log({
needAgreements
});
if (type != 'univerify' && needAgreements && !this.agree) {
if (type != 'univerify' && needAgreements && !this.agree) {
let agreementsRef = this.getParentComponent().$refs.agreements
return agreementsRef.popup(() => {
return agreementsRef.popup(() => {
console.log(type, navigateBack);
this.login_before(type, navigateBack)
this.login_before(type, navigateBack, options)
})
}
// #ifdef H5
if(type == 'weixin'){
// console.log('开始微信网页登录');
let redirectUrl = location.protocol +'//'+
document.domain +
(window.location.href.includes('#')?'/#':'') +
'/uni_modules/uni-id-pages/pages/login/login-withoutpwd?is_weixin_redirect=true&type=weixin'
console.log('redirectUrl----',redirectUrl);
let ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == 'micromessenger'){
// console.log('在微信公众号内');
return window.open(`https://open.weixin.qq.com/connect/oauth2/authorize?
appid=${config.appid.weixin.h5}
&redirect_uri=${encodeURIComponent(redirectUrl)}
&response_type=code
&scope=snsapi_userinfo
&state=STATE&connect_redirect=1#wechat_redirect`);
}else{
// console.log('非微信公众号内');
return location.href = `https://open.weixin.qq.com/connect/qrconnect?appid=${config.appid.weixin.web}
&redirect_uri=${encodeURIComponent(redirectUrl)}
&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect`
}
}
// #endif
}
// #ifdef H5
if(type == 'weixin'){
// console.log('开始微信网页登录');
let redirectUrl = location.protocol +'//'+
document.domain +
(window.location.href.includes('#')?'/#':'') +
'/uni_modules/uni-id-pages/pages/login/login-withoutpwd?is_weixin_redirect=true&type=weixin'
console.log('redirectUrl----',redirectUrl);
let ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == 'micromessenger'){
// console.log('在微信公众号内');
return window.open(`https://open.weixin.qq.com/connect/oauth2/authorize?
appid=${config.appid.weixin.h5}
&redirect_uri=${encodeURIComponent(redirectUrl)}
&response_type=code
&scope=snsapi_userinfo
&state=STATE&connect_redirect=1#wechat_redirect`);
}else{
// console.log('非微信公众号内');
return location.href = `https://open.weixin.qq.com/connect/qrconnect?appid=${config.appid.weixin.web}
&redirect_uri=${encodeURIComponent(redirectUrl)}
&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect`
}
}
// #endif
uni.showLoading({
mask: true
})
......@@ -397,6 +396,13 @@
}
})
}
if (type === 'weixinMobile') {
return this.login({
phoneCode: options.phoneNumberCode
}, type)
}
uni.login({
"provider": type,
"onlyAuthorize": true,
......@@ -422,14 +428,14 @@
}
})
},
login(params, type) { //联网验证登录
login(params, type) { //联网验证登录
console.log('执行登录开始----');
console.log({
params,
type
});
//toLowerCase
let action = 'loginBy' + type.trim().toLowerCase().replace(type[0], type[0].toUpperCase())
let action = 'loginBy' + type.trim().replace(type[0], type[0].toUpperCase())
const uniIdCo = uniCloud.importObject("uni-id-co",{
customUI:true
})
......@@ -441,17 +447,17 @@
});
// #ifdef MP-WEIXIN
//如果是微信小程序端的微信登录,且为首次登录,就弹出获取微信昵称+头像用于绑定资料
if (type == 'weixin' && result.type == "register") {
mutations.loginSuccess({
if (['weixin', 'weixinMobile'].includes(type) && result.type == "register") {
mutations.loginSuccess({
...result,
showToast: false,
autoBack: false
})
return this.$refs.userProfile.open(result.uid)
}
// #endif
// #ifdef H5
result.loginType = type
// #endif
// #ifdef H5
result.loginType = type
// #endif
mutations.loginSuccess(result)
})
......@@ -514,10 +520,10 @@
flex-wrap: wrap;
width: 750rpx;
justify-content: space-around;
position: fixed;
position: fixed;
left: 0;
}
.item {
flex-direction: column;
justify-content: center;
......@@ -536,7 +542,7 @@
height: 160rpx;
}
}
@media screen and (max-width: 690px) {
.fab-login-box {
bottom: 10rpx;
......@@ -545,7 +551,7 @@
/* #endif */
.logo {
width: 60rpx;
......
{
"id": "uni-id-pages",
"displayName": "uni-id-pages",
"version": "1.0.22",
"version": "1.0.25",
"description": "云端一体简单、统一、可扩展的用户中心页面模版",
"keywords": [
"用户管理",
......
......@@ -7,11 +7,12 @@
<!-- 顶部文字 -->
<text class="title">请选择登录方式</text>
<!-- 快捷登录框 当url带参数时有效 -->
<template v-if="['apple','weixin'].includes(type)">
<template v-if="['apple','weixin', 'weixinMobile'].includes(type)">
<text class="tip">将根据第三方账号服务平台的授权范围获取你的信息</text>
<view class="quickLogin">
<image @click="quickLogin" :src="imgSrc" mode="widthFix" class="quickLoginBtn"></image>
<uni-id-pages-agreements scope="register" ref="agreements"></uni-id-pages-agreements>
<image v-if="type !== 'weixinMobile'" @click="quickLogin" :src="imgSrc" mode="widthFix" class="quickLoginBtn"></image>
<button v-else type="primary" open-type="getPhoneNumber" @getphonenumber="quickLogin">微信授权手机号登录</button>
<uni-id-pages-agreements scope="register" ref="agreements"></uni-id-pages-agreements>
</view>
</template>
<template v-else>
......@@ -98,8 +99,16 @@
//#endif
},
methods: {
quickLogin() {
this.$refs.uniFabLogin.login_before(this.type)
quickLogin(e) {
let options = {}
if (e.detail?.code) {
options.phoneNumberCode = e.detail.code
}
if (this.type === 'weixinMobile' && !e.detail?.code) return
this.$refs.uniFabLogin.login_before(this.type, true, options)
},
toSmsPage() {
console.log('toSmsPage',this.agree);
......@@ -203,7 +212,7 @@
margin-top: -15px;
margin-bottom: 20px;
}
@media screen and (min-width: 690px) {
.quickLogin{
height: auto;
......
......@@ -53,9 +53,6 @@
mutations
} from '@/uni_modules/uni-id-pages/common/store.js'
const {
loginSuccess
} = mutations
const uniIdCo = uniCloud.importObject("uni-id-co")
export default {
mixins: [mixin],
......@@ -118,7 +115,7 @@
submitForm(params) {
uniIdCo.registerUser(this.formData).then(e => {
console.log(e);
loginSuccess()
this.loginSuccess(e)
})
.catch(e => {
console.log(e);
......
......@@ -30,11 +30,11 @@
</view>
<view v-if="isShowPhotoBtn" @tap="uploadImage">
<slot name="photo" v-if="$slots.photo" />
<image v-else src="uni_modules/uni-id-pages/static/limeClipper/photo.svg" />
<image v-else src="./images/photo.svg" />
</view>
<view v-if="isShowRotateBtn" @tap="rotate">
<slot name="rotate" v-if="$slots.rotate" />
<image v-else src="uni_modules/uni-id-pages/static/limeClipper/rotate.svg" data-type="inverse" />
<image v-else src="./images/rotate.svg" data-type="inverse" />
</view>
<view v-if="isShowConfirmBtn" @tap="confirm">
<slot name="confirm" v-if="$slots.confirm" />
......
......@@ -33,16 +33,16 @@
const db = uniCloud.database();
const usersTable = db.collection('uni-id-users')
const uniIdCo = uniCloud.importObject("uni-id-co")
import {
store,
mutations
} from '@/uni_modules/uni-id-pages/common/store.js'
import {
store,
mutations
} from '@/uni_modules/uni-id-pages/common/store.js'
export default {
computed: {
userInfo() {
return store.userInfo
}
},
computed: {
userInfo() {
return store.userInfo
}
},
data() {
return {
univerifyStyle: {
......@@ -82,12 +82,12 @@
}
})
},
logout(){
mutations.logout()
},
bindMobileSuccess(){
mutations.updateUserInfo()
},
logout(){
mutations.logout()
},
bindMobileSuccess(){
mutations.updateUserInfo()
},
changePassword(){
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/userinfo/change_pwd/change_pwd',
......@@ -126,7 +126,7 @@
console.log(e.authResult);
uniIdCo.bindMobileByUniverify(e.authResult).then(res => {
console.log(res);
mutations.updateUserInfo()
mutations.updateUserInfo()
}).catch(e => {
console.log(e);
}).finally(e=>{
......@@ -143,29 +143,64 @@
})
},
bindMobileBySmsCode() {
uni.navigateTo({
url: './bind-mobile/bind-mobile'
})
uni.navigateTo({
url: './bind-mobile/bind-mobile'
})
},
setNickname(nickname) {
console.log(nickname);
if (nickname) {
mutations.updateUserInfo({nickname})
this.$refs.dialog.close()
} else {
this.$refs.dialog.open()
}
if (nickname) {
mutations.updateUserInfo({nickname})
this.$refs.dialog.close()
} else {
this.$refs.dialog.open()
}
},
deactivate(){
uni.navigateTo({
url:"/uni_modules/uni-id-pages/pages/userinfo/deactivate/deactivate"
})
}
},
async bindThirdAccount(provider) {
const uniIdCo = uniCloud.importObject("uni-id-co")
const bindField = {
weixin: 'wx_openid',
alipay: 'ali_openid',
apple: 'apple_openid',
qq: 'qq_openid'
}[provider.toLowerCase()]
if (this.userInfo[bindField]) {
await uniIdCo['unbind' + provider]()
await mutations.updateUserInfo()
} else {
uni.login({
provider: provider.toLowerCase(),
onlyAuthorize: true,
success: async e => {
const res = await uniIdCo['bind' + provider]({
code: e.code
})
if (res.errCode) {
uni.showToast({
title: res.errMsg || '绑定失败'
})
}
await mutations.updateUserInfo()
},
fail: async (err) => {
console.log(err);
uni.hideLoading()
}
})
}
}
}
}
</script>
<style lang="scss" scoped>
@import "@/uni_modules/uni-id-pages/common/login-page.scss";
.uni-content {
......@@ -211,7 +246,7 @@
background-color: #FFFFFF;
width: 80%;
}
.mt10{
margin-top: 10px;
}
......
......@@ -52,7 +52,11 @@ const LOG_TYPE = {
BIND_WEIXIN: 'bind-weixin',
BIND_QQ: 'bind-qq',
BIND_APPLE: 'bind-apple',
BIND_ALIPAY: 'bind-alipay'
BIND_ALIPAY: 'bind-alipay',
UNBIND_WEIXIN: 'unbind-weixin',
UNBIND_QQ: 'unbind-qq',
UNBIND_ALIPAY: 'unbind-alipay',
UNBIND_APPLE: 'unbind-apple'
}
const SMS_SCENE = {
......
......@@ -30,7 +30,12 @@ const ERROR = {
SET_INVITE_CODE_FAILED: 'uni-id-set-invite-code-failed',
INVALID_INVITE_CODE: 'uni-id-invalid-invite-code',
CHANGE_INVITER_FORBIDDEN: 'uni-id-change-inviter-forbidden',
BIND_CONFLICT: 'uni-id-bind-conflict'
BIND_CONFLICT: 'uni-id-bind-conflict',
UNBIND_FAIL: 'uni-id-unbind-failed',
UNBIND_NOT_SUPPORTED: 'uni-id-unbind-not-supported',
UNBIND_UNIQUE_LOGIN: 'uni-id-unbind-unique-login',
UNBIND_PASSWORD_NOT_EXISTS: 'uni-id-unbind-password-not-exists',
UNBIND_MOBILE_NOT_EXISTS: 'uni-id-unbind-mobile-not-exists'
}
function isUniIdError (errCode) {
......
......@@ -171,6 +171,13 @@ function getNonceStr (length = 16) {
return str.substring(0, length)
}
try {
require('lodash.merge')
} catch (error) {
console.error('uni-id-co缺少依赖,请在uniCloud/cloudfunctions/common/uni-id-co目录执行 npm install 安装依赖')
throw error
}
module.exports = {
getType,
isValidString,
......
......@@ -62,5 +62,17 @@ module.exports = {
},
getAccountInfo: {
auth: true
},
unbindWeixin: {
auth: true
},
unbindAlipay: {
auth: true
},
unbindQQ: {
auth: true
},
unbindApple: {
auth: true
}
}
......@@ -29,7 +29,8 @@ const {
loginByWeixin,
loginByAlipay,
loginByQQ,
loginByApple
loginByApple,
loginByWeixinMobile
} = require('./module/login/index')
const {
logout
......@@ -41,7 +42,11 @@ const {
bindAlipay,
bindApple,
bindQQ,
bindWeixin
bindWeixin,
unbindWeixin,
unbindAlipay,
unbindQQ,
unbindApple
} = require('./module/relate/index')
const {
updatePwd,
......@@ -74,7 +79,7 @@ const {
} = require('./module/dev/index')
module.exports = {
async _before() {
async _before () {
const clientInfo = this.getClientInfo()
/**
* 检查clientInfo,无appId和uniPlatform时本云对象无法正常运行
......@@ -157,7 +162,7 @@ module.exports = {
// 挂载uni-captcha到this上,方便后续调用
this.uniCaptcha = uniCaptcha
Object.defineProperty(this, 'uniOpenBridge', {
get() {
get () {
return require('uni-open-bridge-common')
}
})
......@@ -181,7 +186,7 @@ module.exports = {
// 通用权限校验模块
await this.middleware.accessControl()
},
_after(error, result) {
_after (error, result) {
if (error) {
// 处理中间件内抛出的标准响应对象
if (error.errCode && getType(error) === 'object') {
......@@ -217,6 +222,10 @@ module.exports = {
* @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
*/
addUser,
......@@ -359,6 +368,7 @@ module.exports = {
* @returns
*/
loginByApple,
loginByWeixinMobile,
/**
* 用户退出登录
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#logout
......@@ -541,5 +551,30 @@ module.exports = {
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#get-supported-login-type
* @returns
*/
getSupportedLoginType
getSupportedLoginType,
/**
* 解绑微信
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#unbind-weixin
* @returns
*/
unbindWeixin,
/**
* 解绑支付宝
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#unbind-alipay
* @returns
*/
unbindAlipay,
/**
* 解绑QQ
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#unbind-qq
* @returns
*/
unbindQQ,
/**
* 解绑Apple
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#unbind-apple
* @returns
*/
unbindApple
}
......@@ -35,7 +35,12 @@ const sentence = {
'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-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'
}
module.exports = {
......
......@@ -35,7 +35,12 @@ const sentence = {
'uni-id-set-invite-code-failed': '设置邀请码失败',
'uni-id-invalid-invite-code': '邀请码不可用',
'uni-id-change-inviter-forbidden': '禁止修改邀请人',
'uni-id-bind-conflict': '此账号已被绑定'
'uni-id-bind-conflict': '此账号已被绑定',
'uni-id-admin-exist-in-other-apps': '超级管理员已在其他控制台注册',
'uni-id-unbind-failed': '请先绑定后再解绑',
'uni-id-unbind-not-supported': '不支持解绑',
'uni-id-unbind-mobile-not-exists': '这是当前唯一登录方式,请绑定手机号后再尝试解绑',
'uni-id-unbind-password-not-exists': '请先设置密码在尝试解绑'
}
module.exports = {
......
......@@ -86,4 +86,26 @@ module.exports = class Auth {
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
}
}
}
......@@ -219,7 +219,8 @@ async function postLogin (params = {}) {
user
})
: {}
)
),
passwordConfirmed: !!user.password
}
}
......
......@@ -5,8 +5,15 @@ const {
ERROR
} = require('../../common/error')
const {
userCollection
userCollection, dbCmd, USER_IDENTIFIER
} = require('../../common/constants')
const {
getUserIdentifier
} = require('../../lib/utils/account')
const {
batchFindObjctValue
} = require('../../common/utils')
const merge = require('lodash.merge')
/**
......@@ -56,7 +63,100 @@ async function postBind ({
}
}
async function preUnBind ({
uid,
unBindAccount,
logType
}) {
const notUnBind = ['username', 'mobile', 'email']
const userIdentifier = getUserIdentifier(unBindAccount)
const condition = Object.keys(userIdentifier).reduce((res, key) => {
if (userIdentifier[key]) {
if (notUnBind.includes(key)) {
throw {
errCode: ERROR.UNBIND_NOT_SUPPORTED
}
}
res.push({
[key]: userIdentifier[key]
})
}
return res
}, [])
const currentUnBindAccount = Object.keys(userIdentifier).reduce((res, key) => {
if (userIdentifier[key]) {
res.push(key)
}
return res
}, [])
const { data: users } = await userCollection.where(dbCmd.and(
{ _id: uid },
dbCmd.or(condition)
)).get()
if (users.length <= 0) {
await this.middleware.uniIdLog({
data: {
user_id: uid
},
type: logType,
success: false
})
throw {
errCode: ERROR.UNBIND_FAIL
}
}
const [user] = users
const otherAccounts = batchFindObjctValue(user, Object.keys(USER_IDENTIFIER).filter(key => !notUnBind.includes(key) && !currentUnBindAccount.includes(key)))
let hasOtherAccountBind = false
for (const key in otherAccounts) {
if (otherAccounts[key]) {
hasOtherAccountBind = true
break
}
}
// 如果没有其他第三方登录方式
if (!hasOtherAccountBind) {
// 存在用户名或者邮箱但是没有设置过没密码就提示设置密码
if ((user.username || user.email) && !user.password) {
throw {
errCode: ERROR.UNBIND_PASSWORD_NOT_EXISTS
}
}
// 账号任何登录方式都没有就优先绑定手机号
if (!user.mobile) {
throw {
errCode: ERROR.UNBIND_MOBILE_NOT_EXISTS
}
}
}
}
async function postUnBind ({
uid,
unBindAccount,
logType
}) {
await userCollection.doc(uid).update(unBindAccount)
await this.middleware.uniIdLog({
data: {
user_id: uid
},
type: logType
})
return {
errCode: 0
}
}
module.exports = {
preBind,
postBind
postBind,
preUnBind,
postUnBind
}
......@@ -45,7 +45,7 @@ async function sendSmsCode ({
action = this.t('verify-mobile')
break
}
const sceneConfig = smsConfig.scene || {}
const sceneConfig = (smsConfig.scene || {})[scene] || {}
if (!templateId) {
templateId = sceneConfig.templateId
}
......
......@@ -177,10 +177,22 @@ async function getWeixinCache ({
})
}
async function getWeixinAccessToken () {
const weixinPlatform = getWeixinPlatform.call(this)
const appId = this.getClientInfo().appId
const cache = await this.uniOpenBridge.getAccessToken({
dcloudAppid: appId,
platform: 'weixin-' + weixinPlatform
})
return cache.access_token
}
module.exports = {
decryptWeixinData,
getWeixinPlatform,
generateWeixinCache,
getWeixinCache,
saveWeixinUserKey
saveWeixinUserKey,
getWeixinAccessToken
}
......@@ -15,5 +15,6 @@ module.exports = {
loginByEmailLink: require('./login-by-email-link'),
loginByEmailCode: require('./login-by-email-code'),
loginByFacebook: require('./login-by-facebook'),
loginByGoogle: require('./login-by-google')
loginByGoogle: require('./login-by-google'),
loginByWeixinMobile: require('./login-by-weixin-mobile')
}
const {
initWeixin
} = require('../../lib/third-party/index')
const {
getWeixinPlatform,
getWeixinAccessToken,
generateWeixinCache,
saveWeixinUserKey
} = require('../../lib/utils/weixin')
const {
ERROR
} = require('../../common/error')
const {
preUnifiedLogin,
postUnifiedLogin
} = require('../../lib/utils/unified-login')
const {
LOG_TYPE
} = require('../../common/constants')
const {
preBind,
postBind
} = require('../../lib/utils/relate')
/**
* 微信授权手机号登录
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login-by-weixin-mobile
* @param {Object} params
* @param {String} params.phoneCode 微信手机号返回的code
* @param {String} params.inviteCode 邀请码
* @returns
*/
module.exports = async function (params = {}) {
const schema = {
phoneCode: 'string',
inviteCode: {
type: 'string',
required: false
}
}
this.middleware.validate(params, schema)
const { phoneCode, inviteCode } = params
const weixinApi = initWeixin.call(this)
let mobile
try {
const accessToken = await getWeixinAccessToken.call(this)
const mobileRes = await weixinApi.getPhoneNumber(accessToken, phoneCode)
mobile = mobileRes.purePhoneNumber
} catch (error) {
console.error(error)
await this.middleware.uniIdLog({
success: false,
type: LOG_TYPE.LOGIN
})
throw {
errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED
}
}
const { type, user } = await preUnifiedLogin.call(this, {
user: {
mobile
}
})
let extraData = {
mobile_confirmed: 1
}
if (type === 'login') {
// 绑定手机号
if (!user.mobile_confirmed) {
const bindAccount = {
mobile
}
await preBind.call(this, {
uid: user._id,
bindAccount,
logType: LOG_TYPE.BIND_MOBILE
})
await postBind.call(this, {
uid: user._id,
bindAccount,
extraData: {
mobile_confirmed: 1
},
logType: LOG_TYPE.BIND_MOBILE
})
extraData = {
...extraData,
...bindAccount
}
}
}
return postUnifiedLogin.call(this, {
user,
extraData: {
...extraData
},
isThirdParty: false,
type,
inviteCode
})
}
......@@ -37,9 +37,19 @@ module.exports = async function (params = {}) {
role: 'admin'
}).limit(1).get()
if (getAdminRes.data.length > 0) {
return {
errCode: ERROR.ADMIN_EXISTS,
errMsg: this.t('uni-id-admin-exists')
const [admin] = getAdminRes.data
const appId = this.getClientInfo().appId
if (!admin.dcloud_appid || (admin.dcloud_appid && admin.dcloud_appid.includes(appId))) {
return {
errCode: ERROR.ADMIN_EXISTS,
errMsg: this.t('uni-id-admin-exists')
}
} else {
return {
errCode: ERROR.ADMIN_EXISTS,
errMsg: this.t('uni-id-admin-exist-in-other-apps')
}
}
}
const {
......
......@@ -47,7 +47,7 @@ module.exports = async function (params = {}) {
} = getAlipayAccountResult
const bindAccount = {
apple_openid: openid
ali_openid: openid
}
await preBind.call(this, {
uid,
......
......@@ -7,8 +7,10 @@ const {
} = require('../../common/constants')
const {
decryptWeixinData,
getWeixinCache
getWeixinCache, getWeixinAccessToken
} = require('../../lib/utils/weixin')
const { initWeixin } = require('../../lib/third-party')
const { ERROR } = require('../../common/error')
/**
* 通过微信绑定手机号
......@@ -16,6 +18,7 @@ const {
* @param {Object} params
* @param {String} params.encryptedData 微信获取手机号返回的加密信息
* @param {String} params.iv 微信获取手机号返回的初始向量
* @param {String} params.code 微信获取手机号返回的code
* @returns
*/
module.exports = async function (params = {}) {
......@@ -26,30 +29,58 @@ module.exports = async function (params = {}) {
* 因此此接口不应直接使用客户端login获取的code,只能使用缓存的sessionKey
*/
const schema = {
encryptedData: 'string',
iv: 'string'
encryptedData: {
required: false,
type: 'string'
},
iv: {
required: false,
type: 'string'
},
code: {
required: false,
type: 'string'
}
}
const {
encryptedData,
iv
iv,
code
} = params
this.middleware.validate(params, schema)
if ((!encryptedData && !iv) && !code) {
return {
errCode: ERROR.INVALID_PARAM
}
}
const uid = this.authInfo.uid
const sessionKey = await getWeixinCache.call(this, {
uid,
key: 'session_key'
})
if (!sessionKey) {
throw new Error('Session key not found')
let mobile
if (code) {
// 区分客户端类型 小程序还是App
const accessToken = await getWeixinAccessToken.call(this)
const weixinApi = initWeixin.call(this)
const res = await weixinApi.getPhoneNumber(accessToken, code)
mobile = res.purePhoneNumber
} else {
const sessionKey = await getWeixinCache.call(this, {
uid,
key: 'session_key'
})
if (!sessionKey) {
throw new Error('Session key not found')
}
const res = decryptWeixinData.call(this, {
encryptedData,
sessionKey,
iv
})
mobile = res.purePhoneNumber
}
const {
purePhoneNumber: mobile
} = decryptWeixinData.call(this, {
encryptedData,
sessionKey,
iv
})
const bindAccount = {
mobile
......
......@@ -5,5 +5,9 @@ module.exports = {
bindAlipay: require('./bind-alipay'),
bindApple: require('./bind-apple'),
bindQQ: require('./bind-qq'),
bindWeixin: require('./bind-weixin')
bindWeixin: require('./bind-weixin'),
unbindWeixin: require('./unbind-weixin'),
unbindAlipay: require('./unbind-alipay'),
unbindQQ: require('./unbind-qq'),
unbindApple: require('./unbind-apple')
}
const {
preUnBind,
postUnBind
} = require('../../lib/utils/relate')
const {
LOG_TYPE, dbCmd
} = require('../../common/constants')
/**
* 解绑支付宝
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#unbind-alipay
* @returns
*/
module.exports = async function () {
const { uid } = this.authInfo
await preUnBind.call(this, {
uid,
unBindAccount: {
ali_openid: dbCmd.exists(true)
},
logType: LOG_TYPE.UNBIND_ALIPAY
})
return await postUnBind.call(this, {
uid,
unBindAccount: {
ali_openid: dbCmd.remove()
},
logType: LOG_TYPE.UNBIND_ALIPAY
})
}
const {
preUnBind,
postUnBind
} = require('../../lib/utils/relate')
const {
LOG_TYPE, dbCmd
} = require('../../common/constants')
/**
* 解绑apple
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#unbind-apple
* @returns
*/
module.exports = async function () {
const { uid } = this.authInfo
await preUnBind.call(this, {
uid,
unBindAccount: {
apple_openid: dbCmd.exists(true)
},
logType: LOG_TYPE.UNBIND_APPLE
})
return await postUnBind.call(this, {
uid,
unBindAccount: {
apple_openid: dbCmd.remove()
},
logType: LOG_TYPE.UNBIND_APPLE
})
}
const {
preUnBind,
postUnBind
} = require('../../lib/utils/relate')
const {
LOG_TYPE, dbCmd
} = require('../../common/constants')
const {
getQQPlatform
} = require('../../lib/utils/qq')
/**
* 解绑QQ
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#unbind-qq
* @returns
*/
module.exports = async function () {
const { uid } = this.authInfo
const { appId } = this.getClientInfo()
const qqPlatform = getQQPlatform.call(this)
await preUnBind.call(this, {
uid,
unBindAccount: {
qq_openid: dbCmd.or([
{
[qqPlatform]: dbCmd.exists(true)
},
{
[`${qqPlatform}_${appId}`]: dbCmd.exists(true)
}
]),
qq_unionid: dbCmd.exists(true)
},
logType: LOG_TYPE.UNBIND_QQ
})
return await postUnBind.call(this, {
uid,
unBindAccount: {
qq_openid: dbCmd.remove(),
qq_unionid: dbCmd.remove()
},
logType: LOG_TYPE.UNBIND_QQ
})
}
const {
preUnBind,
postUnBind
} = require('../../lib/utils/relate')
const {
LOG_TYPE, dbCmd
} = require('../../common/constants')
const {
getWeixinPlatform
} = require('../../lib/utils/weixin')
/**
* 解绑微信
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#unbind-weixin
* @returns
*/
module.exports = async function () {
const { uid } = this.authInfo
const weixinPlatform = getWeixinPlatform.call(this)
await preUnBind.call(this, {
uid,
unBindAccount: {
wx_openid: {
[weixinPlatform]: dbCmd.exists(true)
},
wx_unionid: dbCmd.exists(true)
},
logType: LOG_TYPE.UNBIND_WEIXIN
})
return await postUnBind.call(this, {
uid,
unBindAccount: {
wx_openid: dbCmd.remove(),
wx_unionid: dbCmd.remove()
},
logType: LOG_TYPE.UNBIND_WEIXIN
})
}
{
"name": "uni-id-co",
"version": "1.0.22",
"version": "1.0.25",
"description": "",
"main": "index.js",
"keywords": [],
......@@ -13,5 +13,7 @@
"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"
},
"extensions": {}
"extensions": {
"uni-cloud-sms": {}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册