diff --git a/App.vue b/App.vue index bc02d1584ea7f533fd41301807aecc369f3f75d2..e3f3a825a44eb33737300c2ff2dd056ca9f43324 100644 --- a/App.vue +++ b/App.vue @@ -5,6 +5,7 @@ openApp() //创建在h5端全局悬浮引导用户下载app的功能 // #endif import checkIsAgree from '@/pages/uni-agree/utils/uni-agree.js'; + import uniIdPageInit from '@/uni_modules/uni-id-pages/init.js'; export default { globalData: { searchText: '', @@ -17,9 +18,11 @@ console.log('App Launch') this.globalData.$i18n = this.$i18n this.globalData.$t = str => this.$t(str) - - initApp(); + console.log('uni.getPushClientId',uni.getPushClientId); + + initApp(); + uniIdPageInit() // #ifdef APP-PLUS //checkIsAgree(); APP端暂时先用原生默认生成的。目前,自定义方式启动vue界面时,原生层已经请求了部分权限这并不符合国家的法规 diff --git a/changelog.md b/changelog.md index 91584bfef6fe42b248f416345074794fe9d1be8c..3916007064eebfe0a7a5330c5f1c8e16d5761123 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,5 @@ +## 2.0.5(2022-10-19) +- 更新依赖的`uni-id-pages`的版本为1.0.26 ## 2.0.4(2022-09-21) - 新增 使用uni-id-pages的账号信息的状态管理功能 ## 2.0.3(2022-09-20) diff --git a/common/appInit.js b/common/appInit.js index 90dae4945cf9042d438d8da0133c98dea383f1de..24e567237058c85baa4d3a5e2e512c43a8729588 100644 --- a/common/appInit.js +++ b/common/appInit.js @@ -47,11 +47,11 @@ export default async function() { methodName, // 云对象的方法名称 params // 参数列表 }) { - console.log('interceptObject',{ - objectName, // 云对象名称 - methodName, // 云对象的方法名称 - params // 参数列表 - }); + // console.log('interceptObject',{ + // objectName, // 云对象名称 + // methodName, // 云对象的方法名称 + // params // 参数列表 + // }); if(objectName == "uni-id-co" && (methodName.includes('loginBy') || ['login','registerUser'].includes(methodName) )){ console.log('执行登录相关云对象'); params[0].inviteCode = await new Promise((callBack) => { @@ -84,7 +84,7 @@ export default async function() { }) // console.log(params); } - console.log(params); + // console.log(params); }, success(e) { console.log(e); @@ -94,17 +94,17 @@ export default async function() { }, fail(e){ console.error(e); - if (debug) { - uni.showModal({ - content: JSON.stringify(e), - showCancel: false - }); - }else{ - uni.showToast({ - title: '系统错误请稍后再试', - icon:'error' - }); - } + // if (debug) { + // uni.showModal({ + // content: JSON.stringify(e), + // showCancel: false + // }); + // }else{ + // uni.showToast({ + // title: '系统错误请稍后再试', + // icon:'error' + // }); + // } } }) diff --git a/manifest.json b/manifest.json index 9e0642400723a1e8abc3562effe233cdda1b0612..da54b1881cea6b8e11516a7e816ad48b0d7c1397 100644 --- a/manifest.json +++ b/manifest.json @@ -40,6 +40,9 @@ "ios": { }, "sdkConfigs": { + "push": { + "unipush": null + } } } }, diff --git a/uni-starter.config.js b/uni-starter.config.js index ec8ca38ee7853d5fab8bae1f746c499b50778b81..4ff232d70a99dd38ffea5ea685cf723c1cc6fcf2 100644 --- a/uni-starter.config.js +++ b/uni-starter.config.js @@ -1,7 +1,5 @@ //这是应用的配置页面,App.vue挂载到getApp().globalData.config export default { - //是否打开调试模式 - "debug":false, "h5": { "url": "https://uni-starter.dcloud.net.cn", // 前端网页托管的域名 // 在h5端全局悬浮引导用户下载app的功能 更多自定义要求在/common/openApp.js中修改 @@ -17,7 +15,7 @@ export default { "mp": { "weixin": { //微信小程序原始id,微信小程序分享时 - "id": "gh_33446d7f7a26" + "id": "" } }, //关于应用 diff --git a/uni_modules/uni-easyinput/changelog.md b/uni_modules/uni-easyinput/changelog.md index 74b726905f322327c6177022afd5c893e7192f48..33130c6692c48693395d0b8be88938450fe70f88 100644 --- a/uni_modules/uni-easyinput/changelog.md +++ b/uni_modules/uni-easyinput/changelog.md @@ -1,3 +1,7 @@ +## 1.1.3(2022-09-22) +- 修复,引入 uni.scss 引入默认主题色报错的问题 +## 1.1.2(2022-09-22) +- 增加主题色 primaryColor 配置选项 ## 1.1.1(2022-09-19) - 修复,输入后回车,change 事件触发两次,[详情](https://ask.dcloud.net.cn/question/152149) ## 1.1.0(2022-06-30) diff --git a/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue b/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue index a1250dd6f523b80f1528817a8c6221a40b67697a..fdc023a413b04ea59a55d20a27fa9a35ce047fcf 100644 --- a/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue +++ b/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue @@ -18,7 +18,7 @@ + :color="focusShow ? primaryColor :'#c0c4cc'" @click="onEyes"> - - + + + + + diff --git a/uni_modules/uni-id-pages/init.js b/uni_modules/uni-id-pages/init.js index b1b3d1f03c9155697d0fe4f7d7336373658d525b..e89b0dc2f4689a54492499734fab043126ffc298 100644 --- a/uni_modules/uni-id-pages/init.js +++ b/uni_modules/uni-id-pages/init.js @@ -34,7 +34,7 @@ export default async function() { google: 'google', alipay: 'alipay', apple: "apple" - } + } //遍历客户端配置的登录方式,与服务端比对。并在错误时抛出错误提示 let list = loginTypes.filter(type => !supportedLoginType.includes(data[type])) if (list.length) { @@ -55,7 +55,8 @@ export default async function() { }) } // #endif - + +/* 注释此代码块原因:与uni-starter中的appinit逻辑一致 //3. 绑定clientDB错误事件 // clientDB对象 const db = uniCloud.database() @@ -72,9 +73,9 @@ export default async function() { } // 解绑clientDB错误事件 //db.off('error', onDBError) +*/ - - //4. 同步客户端push_clientid至device表 + //4. 同步客户端push_clientid至uni-id-device表 if (uniCloud.onRefreshToken) { uniCloud.onRefreshToken(() => { console.log('onRefreshToken'); @@ -90,10 +91,14 @@ export default async function() { console.log('getPushClientId', res); }, fail(e) { - console.log(e) + console.error(e, + "uni-id-pages 默认在刷新token(登录、注销、切换用户)后获取push客户端标识同步至uni-id-device表;", + "\n", + "如果你不使用push模块,请注释或删除,路径:/uni-starter/uni_modules/uni-id-pages/init.js 第79-103行代码" + ) } }) } }) - } + } } diff --git a/uni_modules/uni-id-pages/package.json b/uni_modules/uni-id-pages/package.json index 03c9393cc012990d8ff75dbc2a7d02d63eb8d15d..4f0138305e51b0aa78477554d54f547e45c7751e 100644 --- a/uni_modules/uni-id-pages/package.json +++ b/uni_modules/uni-id-pages/package.json @@ -1,7 +1,7 @@ { "id": "uni-id-pages", "displayName": "uni-id-pages", - "version": "1.0.21", + "version": "1.0.26", "description": "云端一体简单、统一、可扩展的用户中心页面模版", "keywords": [ "用户管理", diff --git a/uni_modules/uni-id-pages/pages/common/webview/webview.vue b/uni_modules/uni-id-pages/pages/common/webview/webview.vue index 83d07ec7c66b41c98b924e1fe54d036f89333a76..ce78dd2e7f524d7b51fb9928d28f0c760f3e9a4a 100644 --- a/uni_modules/uni-id-pages/pages/common/webview/webview.vue +++ b/uni_modules/uni-id-pages/pages/common/webview/webview.vue @@ -1,40 +1,40 @@ - - - - - - + + + + + + diff --git a/uni_modules/uni-id-pages/pages/login/login-smscode.vue b/uni_modules/uni-id-pages/pages/login/login-smscode.vue index df67bc4877542c47c0ca6314b77d163187a403df..ec00e5d51571385bb99d5db0a38062927aa5c530 100644 --- a/uni_modules/uni-id-pages/pages/login/login-smscode.vue +++ b/uni_modules/uni-id-pages/pages/login/login-smscode.vue @@ -1,122 +1,122 @@ - - - - + + + + diff --git a/uni_modules/uni-id-pages/pages/login/login-withoutpwd.vue b/uni_modules/uni-id-pages/pages/login/login-withoutpwd.vue index a4e1804d55be4668935ae7f0ef4447f12b02cc26..785a45c572b2aebfc2114d29fa5b26e5842c5eb7 100644 --- a/uni_modules/uni-id-pages/pages/login/login-withoutpwd.vue +++ b/uni_modules/uni-id-pages/pages/login/login-withoutpwd.vue @@ -1,212 +1,221 @@ - - - - - - + + + + + + diff --git a/uni_modules/uni-id-pages/pages/register/register-admin.vue b/uni_modules/uni-id-pages/pages/register/register-admin.vue index 71690d95ce7940278769a666522b152f58d5141c..df96425c331e047b4006d0172192ea197dcb491b 100644 --- a/uni_modules/uni-id-pages/pages/register/register-admin.vue +++ b/uni_modules/uni-id-pages/pages/register/register-admin.vue @@ -1,179 +1,179 @@ - - - - - - + + + + + + diff --git a/uni_modules/uni-id-pages/pages/register/register-by-email.vue b/uni_modules/uni-id-pages/pages/register/register-by-email.vue index f45dc57ad8004b95ee01b3a74c851ad8e0218e30..a6cf62c5546afb343e11aeada5661b820bb1b2be 100644 --- a/uni_modules/uni-id-pages/pages/register/register-by-email.vue +++ b/uni_modules/uni-id-pages/pages/register/register-by-email.vue @@ -1,216 +1,216 @@ - - - - - - + + + + + + diff --git a/uni_modules/uni-id-pages/pages/register/register.vue b/uni_modules/uni-id-pages/pages/register/register.vue index 28c5d12aad8d102064c2f87fef9ee28bea5786ac..e769f3462297fe5a3d5bd6dde418871d37c0bf6f 100644 --- a/uni_modules/uni-id-pages/pages/register/register.vue +++ b/uni_modules/uni-id-pages/pages/register/register.vue @@ -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); diff --git a/uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email.vue b/uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email.vue index 71ca8fe70fa20f5cfc0ecf181ca5e405c0afd756..d23339833f232c8dc80adc4348500db12160b4a5 100644 --- a/uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email.vue +++ b/uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email.vue @@ -1,223 +1,223 @@ - - - - - - + + + + + + diff --git a/uni_modules/uni-id-pages/pages/retrieve/retrieve.vue b/uni_modules/uni-id-pages/pages/retrieve/retrieve.vue index 74ed220cf68fb2192702f7e0aee07f895a173912..f1a17c32a295e2ec5b210cf779e45b5c773f17da 100644 --- a/uni_modules/uni-id-pages/pages/retrieve/retrieve.vue +++ b/uni_modules/uni-id-pages/pages/retrieve/retrieve.vue @@ -1,246 +1,246 @@ - - - - - - + + + + + + diff --git a/uni_modules/uni-id-pages/pages/userinfo/bind-mobile/bind-mobile.vue b/uni_modules/uni-id-pages/pages/userinfo/bind-mobile/bind-mobile.vue index 15d68ebfff5b87fa8c02d0684190f400490ade4c..67442efd45750f5d76290c59325cd391824af925 100644 --- a/uni_modules/uni-id-pages/pages/userinfo/bind-mobile/bind-mobile.vue +++ b/uni_modules/uni-id-pages/pages/userinfo/bind-mobile/bind-mobile.vue @@ -1,130 +1,130 @@ - - - - - + + + + + diff --git a/uni_modules/uni-id-pages/pages/userinfo/cropImage/cropImage.vue b/uni_modules/uni-id-pages/pages/userinfo/cropImage/cropImage.vue index 0a9e701768d2739362c88b7364b3a74f3b5c872d..3c2d98963e351f3fa1a082df6f9d3553c4952a2d 100644 --- a/uni_modules/uni-id-pages/pages/userinfo/cropImage/cropImage.vue +++ b/uni_modules/uni-id-pages/pages/userinfo/cropImage/cropImage.vue @@ -1,39 +1,39 @@ - - - - - \ No newline at end of file diff --git a/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/README.md b/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/README.md index 9219f815af48cf5b2c5b999f22af1e608e9970d8..160c207dcda67881e8a02ef9ff5ce2f8e67422d7 100644 --- a/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/README.md +++ b/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/README.md @@ -1,227 +1,227 @@ -> 插件来源:[https://ext.dcloud.net.cn/plugin?id=3594](https://ext.dcloud.net.cn/plugin?id=3594) -##### 以下是作者写的插件介绍: - -# Clipper 图片裁剪 -> uniapp 图片裁剪,可用于图片头像等裁剪处理 -> [查看更多](http://liangei.gitee.io/limeui/#/clipper)
-> Q群:458377637 - - -## 平台兼容 - -| H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ 小程序 | App | -| --- | ---------- | ------------ | ---------- | ---------- | --------- | --- | -| √ | √ | √ | 未测 | √ | √ | √ | - - -## 代码演示 -### 基本用法 -`@success` 事件点击 👉 **确定** 后会返回生成的图片信息,包含 `url`、`width`、`height` - -```html - - - -``` - -```js -// 非uni_modules引入 -import lClipper from '@/components/lime-clipper/' -// uni_modules引入 -import lClipper from '@/uni_modules/lime-clipper/components/lime-clipper/' -export default { - components: {lClipper}, - data() { - return { - show: false, - url: '', - } - } -} -``` - - -### 传入图片 -`image-url`可传入**相对路径**、**临时路径**、**本地路径**、**网络图片**
- -* **当为网络地址时** -* H5:👉 需要解决跨域问题。
-* 小程序:👉 需要配置 downloadFile 域名
- - -```html - - - -``` - -```js -export default { - components: {lClipper}, - data() { - return { - imageUrl: 'https://img12.360buyimg.com/pop/s1180x940_jfs/t1/97205/26/1142/87801/5dbac55aEf795d962/48a4d7a63ff80b8b.jpg', - show: false, - url: '', - } - } -} -``` - - -### 确定按钮颜色 -样式变量名:`--l-clipper-confirm-color` -可放到全局样式的 `page` 里或节点的 `style` -```html - -``` -```css -// css 中为组件设置 CSS 变量 -.clipper { - --l-clipper-confirm-color: linear-gradient(to right, #ff6034, #ee0a24) -} -// 全局 -page { - --l-clipper-confirm-color: linear-gradient(to right, #ff6034, #ee0a24) -} -``` - - -### 使用插槽 -共五个插槽 `cancel` 取消按钮、 `photo` 选择图片按钮、 `rotate` 旋转按钮、 `confirm` 确定按钮和默认插槽。 - -```html - - - - 取消 - 选择图片 - 旋转 - 确定 - - - 显示取消按钮 - - - 显示选择图片按钮 - - - 显示旋转按钮 - - - 显示确定按钮 - - - 锁定裁剪框宽度 - - - 锁定裁剪框高度 - - - 锁定裁剪框比例 - - - 限制移动范围 - - - 禁止缩放 - - - 禁止旋转 - - - - - -``` - -```js -export default { - components: {lClipper}, - data() { - return { - show: false, - url: '', - isLockWidth: false, - isLockHeight: false, - isLockRatio: true, - isLimitMove: false, - isDisableScale: false, - isDisableRotate: false, - isShowCancelBtn: true, - isShowPhotoBtn: true, - isShowRotateBtn: true, - isShowConfirmBtn: true - } - } -} -``` - - -## API - -### Props - -| 参数 | 说明 | 类型 | 默认值 | -| ------------- | ------------ | ---------------- | ------------ | -| image-url | 图片路径 | string | | -| quality | 图片的质量,取值范围为 [0, 1],不在范围内时当作1处理 | number | `1` | -| source | `{album: '从相册中选择'}`key为图片来源类型,value为选项说明 | Object | | -| width | 裁剪框宽度,单位为 `rpx` | number | `400` | -| height | 裁剪框高度 | number | `400` | -| min-width | 裁剪框最小宽度 | number | `200` | -| min-height |裁剪框最小高度 | number | `200` | -| max-width | 裁剪框最大宽度 | number | `600` | -| max-height | 裁剪框最大宽度 | number | `600` | -| min-ratio | 图片最小缩放比 | number | `0.5` | -| max-ratio | 图片最大缩放比 | number | `2` | -| rotate-angle | 旋转按钮每次旋转的角度 | number | `90` | -| scale-ratio | 生成图片相对于裁剪框的比例, **比例越高生成图片越清晰** | number | `1` | -| is-lock-width | 是否锁定裁剪框宽度 | boolean | `false` | -| is-lock-height | 是否锁定裁剪框高度上 | boolean | `false` | -| is-lock-ratio | 是否锁定裁剪框比例 | boolean | `true` | -| is-disable-scale | 是否禁止缩放 | boolean | `false` | -| is-disable-rotate | 是否禁止旋转 | boolean | `false` | -| is-limit-move | 是否限制移动范围 | boolean | `false` | -| is-show-photo-btn | 是否显示选择图片按钮 | boolean | `true` | -| is-show-rotate-btn | 是否显示转按钮 | boolean | `true` | -| is-show-confirm-btn | 是否显示确定按钮 | boolean | `true` | -| is-show-cancel-btn | 是否显示关闭按钮 | boolean | `true` | - - - -### 事件 Events - -| 事件名 | 说明 | 回调 | -| ------- | ------------ | -------------- | -| success | 生成图片成功 | {`width`, `height`, `url`} | -| fail | 生成图片失败 | `error` | -| cancel | 关闭 | `false` | -| ready | 图片加载完成 | {`width`, `height`, `path`, `orientation`, `type`} | -| change | 图片大小改变时触发 | {`width`, `height`} | -| rotate | 图片旋转时触发 | `angle` | - -## 常见问题 -> 1、H5端使用网络图片需要解决跨域问题。
-> 2、小程序使用网络图片需要去公众平台增加下载白名单!二级域名也需要配!
-> 3、H5端生成图片是base64,有时显示只有一半可以使用原生标签``
-> 4、IOS APP 请勿使用HBX2.9.3.20201014的版本!这个版本无法生成图片。
-> 5、APP端无成功反馈、也无失败反馈时,请更新基座和HBX。
- - -## 打赏 -如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。
+> 插件来源:[https://ext.dcloud.net.cn/plugin?id=3594](https://ext.dcloud.net.cn/plugin?id=3594) +##### 以下是作者写的插件介绍: + +# Clipper 图片裁剪 +> uniapp 图片裁剪,可用于图片头像等裁剪处理 +> [查看更多](http://liangei.gitee.io/limeui/#/clipper)
+> Q群:458377637 + + +## 平台兼容 + +| H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ 小程序 | App | +| --- | ---------- | ------------ | ---------- | ---------- | --------- | --- | +| √ | √ | √ | 未测 | √ | √ | √ | + + +## 代码演示 +### 基本用法 +`@success` 事件点击 👉 **确定** 后会返回生成的图片信息,包含 `url`、`width`、`height` + +```html + + + +``` + +```js +// 非uni_modules引入 +import lClipper from '@/components/lime-clipper/' +// uni_modules引入 +import lClipper from '@/uni_modules/lime-clipper/components/lime-clipper/' +export default { + components: {lClipper}, + data() { + return { + show: false, + url: '', + } + } +} +``` + + +### 传入图片 +`image-url`可传入**相对路径**、**临时路径**、**本地路径**、**网络图片**
+ +* **当为网络地址时** +* H5:👉 需要解决跨域问题。
+* 小程序:👉 需要配置 downloadFile 域名
+ + +```html + + + +``` + +```js +export default { + components: {lClipper}, + data() { + return { + imageUrl: 'https://img12.360buyimg.com/pop/s1180x940_jfs/t1/97205/26/1142/87801/5dbac55aEf795d962/48a4d7a63ff80b8b.jpg', + show: false, + url: '', + } + } +} +``` + + +### 确定按钮颜色 +样式变量名:`--l-clipper-confirm-color` +可放到全局样式的 `page` 里或节点的 `style` +```html + +``` +```css +// css 中为组件设置 CSS 变量 +.clipper { + --l-clipper-confirm-color: linear-gradient(to right, #ff6034, #ee0a24) +} +// 全局 +page { + --l-clipper-confirm-color: linear-gradient(to right, #ff6034, #ee0a24) +} +``` + + +### 使用插槽 +共五个插槽 `cancel` 取消按钮、 `photo` 选择图片按钮、 `rotate` 旋转按钮、 `confirm` 确定按钮和默认插槽。 + +```html + + + + 取消 + 选择图片 + 旋转 + 确定 + + + 显示取消按钮 + + + 显示选择图片按钮 + + + 显示旋转按钮 + + + 显示确定按钮 + + + 锁定裁剪框宽度 + + + 锁定裁剪框高度 + + + 锁定裁剪框比例 + + + 限制移动范围 + + + 禁止缩放 + + + 禁止旋转 + + + + + +``` + +```js +export default { + components: {lClipper}, + data() { + return { + show: false, + url: '', + isLockWidth: false, + isLockHeight: false, + isLockRatio: true, + isLimitMove: false, + isDisableScale: false, + isDisableRotate: false, + isShowCancelBtn: true, + isShowPhotoBtn: true, + isShowRotateBtn: true, + isShowConfirmBtn: true + } + } +} +``` + + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | +| ------------- | ------------ | ---------------- | ------------ | +| image-url | 图片路径 | string | | +| quality | 图片的质量,取值范围为 [0, 1],不在范围内时当作1处理 | number | `1` | +| source | `{album: '从相册中选择'}`key为图片来源类型,value为选项说明 | Object | | +| width | 裁剪框宽度,单位为 `rpx` | number | `400` | +| height | 裁剪框高度 | number | `400` | +| min-width | 裁剪框最小宽度 | number | `200` | +| min-height |裁剪框最小高度 | number | `200` | +| max-width | 裁剪框最大宽度 | number | `600` | +| max-height | 裁剪框最大宽度 | number | `600` | +| min-ratio | 图片最小缩放比 | number | `0.5` | +| max-ratio | 图片最大缩放比 | number | `2` | +| rotate-angle | 旋转按钮每次旋转的角度 | number | `90` | +| scale-ratio | 生成图片相对于裁剪框的比例, **比例越高生成图片越清晰** | number | `1` | +| is-lock-width | 是否锁定裁剪框宽度 | boolean | `false` | +| is-lock-height | 是否锁定裁剪框高度上 | boolean | `false` | +| is-lock-ratio | 是否锁定裁剪框比例 | boolean | `true` | +| is-disable-scale | 是否禁止缩放 | boolean | `false` | +| is-disable-rotate | 是否禁止旋转 | boolean | `false` | +| is-limit-move | 是否限制移动范围 | boolean | `false` | +| is-show-photo-btn | 是否显示选择图片按钮 | boolean | `true` | +| is-show-rotate-btn | 是否显示转按钮 | boolean | `true` | +| is-show-confirm-btn | 是否显示确定按钮 | boolean | `true` | +| is-show-cancel-btn | 是否显示关闭按钮 | boolean | `true` | + + + +### 事件 Events + +| 事件名 | 说明 | 回调 | +| ------- | ------------ | -------------- | +| success | 生成图片成功 | {`width`, `height`, `url`} | +| fail | 生成图片失败 | `error` | +| cancel | 关闭 | `false` | +| ready | 图片加载完成 | {`width`, `height`, `path`, `orientation`, `type`} | +| change | 图片大小改变时触发 | {`width`, `height`} | +| rotate | 图片旋转时触发 | `angle` | + +## 常见问题 +> 1、H5端使用网络图片需要解决跨域问题。
+> 2、小程序使用网络图片需要去公众平台增加下载白名单!二级域名也需要配!
+> 3、H5端生成图片是base64,有时显示只有一半可以使用原生标签``
+> 4、IOS APP 请勿使用HBX2.9.3.20201014的版本!这个版本无法生成图片。
+> 5、APP端无成功反馈、也无失败反馈时,请更新基座和HBX。
+ + +## 打赏 +如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。
![输入图片说明](https://images.gitee.com/uploads/images/2020/1122/222521_bb543f96_518581.jpeg "微信图片编辑_20201122220352.jpg") \ No newline at end of file diff --git a/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/images/photo.svg b/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/images/photo.svg index 7b4b59058376794d6e6a78035f627678102f96ad..4fd415f2e78b3cad9b5759be7be05a77734db6fe 100644 --- a/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/images/photo.svg +++ b/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/images/photo.svg @@ -1,19 +1,19 @@ - - - - - - - - - + + + + + + + + + diff --git a/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/images/rotate.svg b/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/images/rotate.svg index 0143706ca7adea484ed38339980c2cc23559595e..4cc7dbae8b0df01802f66f0b88f177f1adc96913 100644 --- a/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/images/rotate.svg +++ b/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/images/rotate.svg @@ -1,15 +1,15 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/index.css b/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/index.css index ce542bf1193799b39f006d08e71b4fb3cbecf1cc..3794573a59ec8fb3efd065e9f5020b5a37e63ad2 100644 --- a/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/index.css +++ b/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/index.css @@ -1,160 +1,160 @@ -.flex-auto { - flex: auto; -} -.bg-transparent { - background-color: rgba(0,0,0,0.9); - transition-duration: 0.35s; -} -.l-clipper { - width: 100vw; - height: calc(100vh - var(--window-top)); - background-color: rgba(0,0,0,0.9); - position: fixed; - top: var(--window-top); - left: 0; - z-index: 1; -} -.l-clipper-mask { - position: relative; - z-index: 2; - pointer-events: none; -} -.l-clipper__content { - pointer-events: none; - position: absolute; - border: 1rpx solid rgba(255,255,255,0.3); - box-sizing: border-box; - box-shadow: rgba(0,0,0,0.5) 0 0 0 80vh; - background: transparent; -} -.l-clipper__content::before, -.l-clipper__content::after { - content: ''; - position: absolute; - border: 1rpx dashed rgba(255,255,255,0.3); -} -.l-clipper__content::before { - width: 100%; - top: 33.33%; - height: 33.33%; - border-left: none; - border-right: none; -} -.l-clipper__content::after { - width: 33.33%; - left: 33.33%; - height: 100%; - border-top: none; - border-bottom: none; -} -.l-clipper__edge { - position: absolute; - width: 34rpx; - height: 34rpx; - border: 6rpx solid #fff; - pointer-events: auto; -} -.l-clipper__edge::before { - content: ''; - position: absolute; - width: 40rpx; - height: 40rpx; - background-color: transparent; -} -.l-clipper__edge:nth-child(1) { - left: -6rpx; - top: -6rpx; - border-bottom-width: 0 !important; - border-right-width: 0 !important; -} -.l-clipper__edge:nth-child(1):before { - top: -50%; - left: -50%; -} -.l-clipper__edge:nth-child(2) { - right: -6rpx; - top: -6rpx; - border-bottom-width: 0 !important; - border-left-width: 0 !important; -} -.l-clipper__edge:nth-child(2):before { - top: -50%; - left: 50%; -} -.l-clipper__edge:nth-child(3) { - left: -6rpx; - bottom: -6rpx; - border-top-width: 0 !important; - border-right-width: 0 !important; -} -.l-clipper__edge:nth-child(3):before { - bottom: -50%; - left: -50%; -} -.l-clipper__edge:nth-child(4) { - right: -6rpx; - bottom: -6rpx; - border-top-width: 0 !important; - border-left-width: 0 !important; -} -.l-clipper__edge:nth-child(4):before { - bottom: -50%; - left: 50%; -} -.l-clipper-image { - width: 100%; - border-style: none; - position: absolute; - top: 0; - left: 0; - z-index: 1; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - transform-origin: center; -} -.l-clipper-canvas { - position: fixed; - z-index: 10; - left: -200vw; - top: -200vw; - pointer-events: none; -} -.l-clipper-tools { - position: fixed; - left: 0; - bottom: 10px; - width: 100%; - z-index: 99; - color: #fff; -} -.l-clipper-tools__btns { - font-weight: bold; - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - padding: 20rpx 40rpx; - box-sizing: border-box; -} -.l-clipper-tools__btns .cancel { - width: 112rpx; - height: 60rpx; - text-align: center; - line-height: 60rpx; -} -.l-clipper-tools__btns .confirm { - width: 112rpx; - height: 60rpx; - line-height: 60rpx; - background-color: #07c160; - border-radius: 6rpx; - text-align: center; -} -.l-clipper-tools__btns image { - display: block; - width: 60rpx; - height: 60rpx; -} -.l-clipper-tools__btns { - flex-direction: row; -} +.flex-auto { + flex: auto; +} +.bg-transparent { + background-color: rgba(0,0,0,0.9); + transition-duration: 0.35s; +} +.l-clipper { + width: 100vw; + height: calc(100vh - var(--window-top)); + background-color: rgba(0,0,0,0.9); + position: fixed; + top: var(--window-top); + left: 0; + z-index: 1; +} +.l-clipper-mask { + position: relative; + z-index: 2; + pointer-events: none; +} +.l-clipper__content { + pointer-events: none; + position: absolute; + border: 1rpx solid rgba(255,255,255,0.3); + box-sizing: border-box; + box-shadow: rgba(0,0,0,0.5) 0 0 0 80vh; + background: transparent; +} +.l-clipper__content::before, +.l-clipper__content::after { + content: ''; + position: absolute; + border: 1rpx dashed rgba(255,255,255,0.3); +} +.l-clipper__content::before { + width: 100%; + top: 33.33%; + height: 33.33%; + border-left: none; + border-right: none; +} +.l-clipper__content::after { + width: 33.33%; + left: 33.33%; + height: 100%; + border-top: none; + border-bottom: none; +} +.l-clipper__edge { + position: absolute; + width: 34rpx; + height: 34rpx; + border: 6rpx solid #fff; + pointer-events: auto; +} +.l-clipper__edge::before { + content: ''; + position: absolute; + width: 40rpx; + height: 40rpx; + background-color: transparent; +} +.l-clipper__edge:nth-child(1) { + left: -6rpx; + top: -6rpx; + border-bottom-width: 0 !important; + border-right-width: 0 !important; +} +.l-clipper__edge:nth-child(1):before { + top: -50%; + left: -50%; +} +.l-clipper__edge:nth-child(2) { + right: -6rpx; + top: -6rpx; + border-bottom-width: 0 !important; + border-left-width: 0 !important; +} +.l-clipper__edge:nth-child(2):before { + top: -50%; + left: 50%; +} +.l-clipper__edge:nth-child(3) { + left: -6rpx; + bottom: -6rpx; + border-top-width: 0 !important; + border-right-width: 0 !important; +} +.l-clipper__edge:nth-child(3):before { + bottom: -50%; + left: -50%; +} +.l-clipper__edge:nth-child(4) { + right: -6rpx; + bottom: -6rpx; + border-top-width: 0 !important; + border-left-width: 0 !important; +} +.l-clipper__edge:nth-child(4):before { + bottom: -50%; + left: 50%; +} +.l-clipper-image { + width: 100%; + border-style: none; + position: absolute; + top: 0; + left: 0; + z-index: 1; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transform-origin: center; +} +.l-clipper-canvas { + position: fixed; + z-index: 10; + left: -200vw; + top: -200vw; + pointer-events: none; +} +.l-clipper-tools { + position: fixed; + left: 0; + bottom: 10px; + width: 100%; + z-index: 99; + color: #fff; +} +.l-clipper-tools__btns { + font-weight: bold; + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + padding: 20rpx 40rpx; + box-sizing: border-box; +} +.l-clipper-tools__btns .cancel { + width: 112rpx; + height: 60rpx; + text-align: center; + line-height: 60rpx; +} +.l-clipper-tools__btns .confirm { + width: 112rpx; + height: 60rpx; + line-height: 60rpx; + background-color: #07c160; + border-radius: 6rpx; + text-align: center; +} +.l-clipper-tools__btns image { + display: block; + width: 60rpx; + height: 60rpx; +} +.l-clipper-tools__btns { + flex-direction: row; +} diff --git a/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/limeClipper.vue b/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/limeClipper.vue index 9caae2dc1e620e89cfde323a349e753393da824c..52f3bd9f772286db2a60dbd3c72de34f8c4acf22 100644 --- a/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/limeClipper.vue +++ b/uni_modules/uni-id-pages/pages/userinfo/cropImage/limeClipper/limeClipper.vue @@ -1,816 +1,816 @@ - - - - - \ No newline at end of file diff --git a/uni_modules/uni-id-pages/pages/userinfo/userinfo.vue b/uni_modules/uni-id-pages/pages/userinfo/userinfo.vue index 2943265e0ed1d7ea1ca6f14c93bf96b1e92d4328..7852f45b7b955b69e97858edbe9c1fb389a3d951 100644 --- a/uni_modules/uni-id-pages/pages/userinfo/userinfo.vue +++ b/uni_modules/uni-id-pages/pages/userinfo/userinfo.vue @@ -1,218 +1,253 @@ - - - - + + + + diff --git a/uni_modules/uni-id-pages/readme.md b/uni_modules/uni-id-pages/readme.md index 1650e459c71e4bb0bf70d721f9b5c4f1e969c71f..1fa072633a3346c5b2dfaa0793ea5b852fbdace5 100644 --- a/uni_modules/uni-id-pages/readme.md +++ b/uni_modules/uni-id-pages/readme.md @@ -1,15 +1,15 @@ -# 文档已移至uni-id-pages文档[https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html](https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html) - - - -关于插件更新的说明: - -所有uni_modules,在HBuilderX里点右键都可以直接升级。或者在插件市场导入覆盖。 - -覆盖时HBuilderX会弹出代码差异比对,可以决定接受哪些更改、拒绝哪些更改。 - -当拒绝局部修改时,注意可能产生兼容性问题。 - -你需要二次开发uni-id-pages的前端页面, -- 如果改动不大,那么每次更新uni-id-pages时,在HBuilderX的对比界面对比一下就好 +# 文档已移至uni-id-pages文档[https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html](https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html) + + + +关于插件更新的说明: + +所有uni_modules,在HBuilderX里点右键都可以直接升级。或者在插件市场导入覆盖。 + +覆盖时HBuilderX会弹出代码差异比对,可以决定接受哪些更改、拒绝哪些更改。 + +当拒绝局部修改时,注意可能产生兼容性问题。 + +你需要二次开发uni-id-pages的前端页面, +- 如果改动不大,那么每次更新uni-id-pages时,在HBuilderX的对比界面对比一下就好 - 如果改动较大,建议复制一套前端页面到自己工程的pages目录下,pages.json里只引用根目录pages下的页面,不引用uni_modules下的页面。然后每次uni-id-pages更新,你对比下比上一版uni-id-pages改了什么,看你是否需要再合并到你自己的pages里。pages.json里不引用uni_modules里的页面的话,打包时不会把这些页面打包进去,不影响发行后的包体积 \ No newline at end of file diff --git a/uni_modules/uni-id-pages/static/limeClipper/photo.svg b/uni_modules/uni-id-pages/static/limeClipper/photo.svg index 7b4b59058376794d6e6a78035f627678102f96ad..4fd415f2e78b3cad9b5759be7be05a77734db6fe 100644 --- a/uni_modules/uni-id-pages/static/limeClipper/photo.svg +++ b/uni_modules/uni-id-pages/static/limeClipper/photo.svg @@ -1,19 +1,19 @@ - - - - - - - - - + + + + + + + + + diff --git a/uni_modules/uni-id-pages/static/limeClipper/rotate.svg b/uni_modules/uni-id-pages/static/limeClipper/rotate.svg index 0143706ca7adea484ed38339980c2cc23559595e..4cc7dbae8b0df01802f66f0b88f177f1adc96913 100644 --- a/uni_modules/uni-id-pages/static/limeClipper/rotate.svg +++ b/uni_modules/uni-id-pages/static/limeClipper/rotate.svg @@ -1,15 +1,15 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/uni_modules/uni-id-pages/static/login/weixin.png b/uni_modules/uni-id-pages/static/login/weixin.png index 913a9d1d6959aef1b0efef8171f74f6878adfd37..6976b691fbeb313301bd55bb3e949722319c228c 100644 Binary files a/uni_modules/uni-id-pages/static/login/weixin.png and b/uni_modules/uni-id-pages/static/login/weixin.png differ diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/constants.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/constants.js index 0322db6a8f548f8fb3f0f210225b4f84ee3d9e03..1e44b98c98e5fe73d71445aac587e3a1bd29935b 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/constants.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/constants.js @@ -1,83 +1,87 @@ -const db = uniCloud.database() -const dbCmd = db.command -const userCollectionName = 'uni-id-users' -const userCollection = db.collection(userCollectionName) -const verifyCollectionName = 'opendb-verify-codes' -const verifyCollection = db.collection(verifyCollectionName) -const deviceCollectionName = 'uni-id-device' -const deviceCollection = db.collection(deviceCollectionName) - -const USER_IDENTIFIER = { - username: 'username', - mobile: 'mobile', - email: 'email', - wx_unionid: 'wechat-account', - 'wx_openid.app': 'wechat-account', - 'wx_openid.mp': 'wechat-account', - 'wx_openid.h5': 'wechat-account', - 'wx_openid.web': 'wechat-account', - qq_unionid: 'qq-account', - 'qq_openid.app': 'qq-account', - 'qq_openid.mp': 'qq-account', - ali_openid: 'alipay-account', - apple_openid: 'alipay-account' -} - -const USER_STATUS = { - NORMAL: 0, - BANNED: 1, - AUDITING: 2, - AUDIT_FAILED: 3, - CLOSED: 4 -} - -const CAPTCHA_SCENE = { - REGISTER: 'register', - LOGIN_BY_PWD: 'login-by-pwd', - LOGIN_BY_SMS: 'login-by-sms', - RESET_PWD_BY_SMS: 'reset-pwd-by-sms', - RESET_PWD_BY_EMAIL: 'reset-pwd-by-email', - SEND_SMS_CODE: 'send-sms-code', - SEND_EMAIL_CODE: 'send-email-code', - BIND_MOBILE_BY_SMS: 'bind-mobile-by-sms' -} - -const LOG_TYPE = { - LOGOUT: 'logout', - LOGIN: 'login', - REGISTER: 'register', - RESET_PWD_BY_SMS: 'reset-pwd', - RESET_PWD_BY_EMAIL: 'reset-pwd', - BIND_MOBILE: 'bind-mobile', - BIND_WEIXIN: 'bind-weixin', - BIND_QQ: 'bind-qq', - BIND_APPLE: 'bind-apple', - BIND_ALIPAY: 'bind-alipay' -} - -const SMS_SCENE = { - LOGIN_BY_SMS: 'login-by-sms', - RESET_PWD_BY_SMS: 'reset-pwd-by-sms', - BIND_MOBILE_BY_SMS: 'bind-mobile-by-sms' -} - -const EMAIL_SCENE = { - REGISTER: 'register', - LOGIN_BY_EMAIL: 'login-by-email', - RESET_PWD_BY_EMAIL: 'reset-pwd-by-email', - BIND_EMAIL: 'bind-email' -} - -module.exports = { - db, - dbCmd, - userCollection, - verifyCollection, - deviceCollection, - USER_IDENTIFIER, - USER_STATUS, - CAPTCHA_SCENE, - LOG_TYPE, - SMS_SCENE, - EMAIL_SCENE -} +const db = uniCloud.database() +const dbCmd = db.command +const userCollectionName = 'uni-id-users' +const userCollection = db.collection(userCollectionName) +const verifyCollectionName = 'opendb-verify-codes' +const verifyCollection = db.collection(verifyCollectionName) +const deviceCollectionName = 'uni-id-device' +const deviceCollection = db.collection(deviceCollectionName) + +const USER_IDENTIFIER = { + username: 'username', + mobile: 'mobile', + email: 'email', + wx_unionid: 'wechat-account', + 'wx_openid.app': 'wechat-account', + 'wx_openid.mp': 'wechat-account', + 'wx_openid.h5': 'wechat-account', + 'wx_openid.web': 'wechat-account', + qq_unionid: 'qq-account', + 'qq_openid.app': 'qq-account', + 'qq_openid.mp': 'qq-account', + ali_openid: 'alipay-account', + apple_openid: 'alipay-account' +} + +const USER_STATUS = { + NORMAL: 0, + BANNED: 1, + AUDITING: 2, + AUDIT_FAILED: 3, + CLOSED: 4 +} + +const CAPTCHA_SCENE = { + REGISTER: 'register', + LOGIN_BY_PWD: 'login-by-pwd', + LOGIN_BY_SMS: 'login-by-sms', + RESET_PWD_BY_SMS: 'reset-pwd-by-sms', + RESET_PWD_BY_EMAIL: 'reset-pwd-by-email', + SEND_SMS_CODE: 'send-sms-code', + SEND_EMAIL_CODE: 'send-email-code', + BIND_MOBILE_BY_SMS: 'bind-mobile-by-sms' +} + +const LOG_TYPE = { + LOGOUT: 'logout', + LOGIN: 'login', + REGISTER: 'register', + RESET_PWD_BY_SMS: 'reset-pwd', + RESET_PWD_BY_EMAIL: 'reset-pwd', + BIND_MOBILE: 'bind-mobile', + BIND_WEIXIN: 'bind-weixin', + BIND_QQ: 'bind-qq', + BIND_APPLE: 'bind-apple', + BIND_ALIPAY: 'bind-alipay', + UNBIND_WEIXIN: 'unbind-weixin', + UNBIND_QQ: 'unbind-qq', + UNBIND_ALIPAY: 'unbind-alipay', + UNBIND_APPLE: 'unbind-apple' +} + +const SMS_SCENE = { + LOGIN_BY_SMS: 'login-by-sms', + RESET_PWD_BY_SMS: 'reset-pwd-by-sms', + BIND_MOBILE_BY_SMS: 'bind-mobile-by-sms' +} + +const EMAIL_SCENE = { + REGISTER: 'register', + LOGIN_BY_EMAIL: 'login-by-email', + RESET_PWD_BY_EMAIL: 'reset-pwd-by-email', + BIND_EMAIL: 'bind-email' +} + +module.exports = { + db, + dbCmd, + userCollection, + verifyCollection, + deviceCollection, + USER_IDENTIFIER, + USER_STATUS, + CAPTCHA_SCENE, + LOG_TYPE, + SMS_SCENE, + EMAIL_SCENE +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/error.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/error.js index 3095e5f72573bddb56a33f3a6c0897c07061f201..ca08116e4abffdb74fd04a21f25b77686771b743 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/error.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/error.js @@ -1,52 +1,57 @@ -const ERROR = { - ACCOUNT_EXISTS: 'uni-id-account-exists', - ACCOUNT_NOT_EXISTS: 'uni-id-account-not-exists', - ACCOUNT_CONFLICT: 'uni-id-account-conflict', - ACCOUNT_BANNED: 'uni-id-account-banned', - ACCOUNT_AUDITING: 'uni-id-account-auditing', - ACCOUNT_AUDIT_FAILED: 'uni-id-account-audit-failed', - ACCOUNT_CLOSED: 'uni-id-account-closed', - CAPTCHA_REQUIRED: 'uni-id-captcha-required', - PASSWORD_ERROR: 'uni-id-password-error', - PASSWORD_ERROR_EXCEED_LIMIT: 'uni-id-password-error-exceed-limit', - INVALID_USERNAME: 'uni-id-invalid-username', - INVALID_PASSWORD: 'uni-id-invalid-password', - INVALID_PASSWORD_SUPER: 'uni-id-invalid-password-super', - INVALID_PASSWORD_STRONG: 'uni-id-invalid-password-strong', - INVALID_PASSWORD_MEDIUM: 'uni-id-invalid-password-medium', - INVALID_PASSWORD_WEAK: 'uni-id-invalid-password-weak', - INVALID_MOBILE: 'uni-id-invalid-mobile', - INVALID_EMAIL: 'uni-id-invalid-email', - INVALID_NICKNAME: 'uni-id-invalid-nickname', - INVALID_PARAM: 'uni-id-invalid-param', - PARAM_REQUIRED: 'uni-id-param-required', - GET_THIRD_PARTY_ACCOUNT_FAILED: 'uni-id-get-third-party-account-failed', - GET_THIRD_PARTY_USER_INFO_FAILED: 'uni-id-get-third-party-user-info-failed', - MOBILE_VERIFY_CODE_ERROR: 'uni-id-mobile-verify-code-error', - EMAIL_VERIFY_CODE_ERROR: 'uni-id-email-verify-code-error', - ADMIN_EXISTS: 'uni-id-admin-exists', - PERMISSION_ERROR: 'uni-id-permission-error', - SYSTEM_ERROR: 'uni-id-system-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' -} - -function isUniIdError (errCode) { - return Object.values(ERROR).includes(errCode) -} - -class UniCloudError extends Error { - constructor (options) { - super(options.message) - this.errMsg = options.message || '' - this.errCode = options.code - } -} - -module.exports = { - ERROR, - isUniIdError, - UniCloudError -} +const ERROR = { + ACCOUNT_EXISTS: 'uni-id-account-exists', + ACCOUNT_NOT_EXISTS: 'uni-id-account-not-exists', + ACCOUNT_CONFLICT: 'uni-id-account-conflict', + ACCOUNT_BANNED: 'uni-id-account-banned', + ACCOUNT_AUDITING: 'uni-id-account-auditing', + ACCOUNT_AUDIT_FAILED: 'uni-id-account-audit-failed', + ACCOUNT_CLOSED: 'uni-id-account-closed', + CAPTCHA_REQUIRED: 'uni-id-captcha-required', + PASSWORD_ERROR: 'uni-id-password-error', + PASSWORD_ERROR_EXCEED_LIMIT: 'uni-id-password-error-exceed-limit', + INVALID_USERNAME: 'uni-id-invalid-username', + INVALID_PASSWORD: 'uni-id-invalid-password', + INVALID_PASSWORD_SUPER: 'uni-id-invalid-password-super', + INVALID_PASSWORD_STRONG: 'uni-id-invalid-password-strong', + INVALID_PASSWORD_MEDIUM: 'uni-id-invalid-password-medium', + INVALID_PASSWORD_WEAK: 'uni-id-invalid-password-weak', + INVALID_MOBILE: 'uni-id-invalid-mobile', + INVALID_EMAIL: 'uni-id-invalid-email', + INVALID_NICKNAME: 'uni-id-invalid-nickname', + INVALID_PARAM: 'uni-id-invalid-param', + PARAM_REQUIRED: 'uni-id-param-required', + GET_THIRD_PARTY_ACCOUNT_FAILED: 'uni-id-get-third-party-account-failed', + GET_THIRD_PARTY_USER_INFO_FAILED: 'uni-id-get-third-party-user-info-failed', + MOBILE_VERIFY_CODE_ERROR: 'uni-id-mobile-verify-code-error', + EMAIL_VERIFY_CODE_ERROR: 'uni-id-email-verify-code-error', + ADMIN_EXISTS: 'uni-id-admin-exists', + PERMISSION_ERROR: 'uni-id-permission-error', + SYSTEM_ERROR: 'uni-id-system-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', + 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) { + return Object.values(ERROR).includes(errCode) +} + +class UniCloudError extends Error { + constructor (options) { + super(options.message) + this.errMsg = options.message || '' + this.errCode = options.code + } +} + +module.exports = { + ERROR, + isUniIdError, + UniCloudError +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/utils.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/utils.js index 432404b933c7d23dc15fbc1947eb04310c6f0a6f..b998f846e604ba830020b1f8276b305b15046b67 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/utils.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/utils.js @@ -1,190 +1,197 @@ -function batchFindObjctValue (obj = {}, keys = []) { - const values = {} - for (let i = 0; i < keys.length; i++) { - const key = keys[i] - const keyPath = key.split('.') - let currentKey = keyPath.shift() - let result = obj - while (currentKey) { - if (!result) { - break - } - result = result[currentKey] - currentKey = keyPath.shift() - } - values[key] = result - } - return values -} - -function getType (val) { - return Object.prototype.toString.call(val).slice(8, -1).toLowerCase() -} - -function hasOwn (obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key) -} - -function isValidString (val) { - return val && getType(val) === 'string' -} - -function isPlainObject (obj) { - return getType(obj) === 'object' -} - -function isFn (fn) { - // 务必注意AsyncFunction - return typeof fn === 'function' -} - -// 获取文件后缀,只添加几种图片类型供客服消息接口使用 -const mime2ext = { - 'image/png': 'png', - 'image/jpeg': 'jpg', - 'image/gif': 'gif', - 'image/svg+xml': 'svg', - 'image/bmp': 'bmp', - 'image/webp': 'webp' -} - -function getExtension (contentType) { - return mime2ext[contentType] -} - -const isSnakeCase = /_(\w)/g -const isCamelCase = /[A-Z]/g - -function snake2camel (value) { - return value.replace(isSnakeCase, (_, c) => (c ? c.toUpperCase() : '')) -} - -function camel2snake (value) { - return value.replace(isCamelCase, str => '_' + str.toLowerCase()) -} - -function parseObjectKeys (obj, type) { - let parserReg, parser - switch (type) { - case 'snake2camel': - parser = snake2camel - parserReg = isSnakeCase - break - case 'camel2snake': - parser = camel2snake - parserReg = isCamelCase - break - } - for (const key in obj) { - if (hasOwn(obj, key)) { - if (parserReg.test(key)) { - const keyCopy = parser(key) - obj[keyCopy] = obj[key] - delete obj[key] - if (isPlainObject(obj[keyCopy])) { - obj[keyCopy] = parseObjectKeys(obj[keyCopy], type) - } else if (Array.isArray(obj[keyCopy])) { - obj[keyCopy] = obj[keyCopy].map((item) => { - return parseObjectKeys(item, type) - }) - } - } - } - } - return obj -} - -function snake2camelJson (obj) { - return parseObjectKeys(obj, 'snake2camel') -} - -function camel2snakeJson (obj) { - return parseObjectKeys(obj, 'camel2snake') -} - -function getOffsetDate (offset) { - return new Date( - Date.now() + (new Date().getTimezoneOffset() + (offset || 0) * 60) * 60000 - ) -} - -function getDateStr (date, separator = '-') { - date = date || new Date() - const dateArr = [] - dateArr.push(date.getFullYear()) - dateArr.push(('00' + (date.getMonth() + 1)).substr(-2)) - dateArr.push(('00' + date.getDate()).substr(-2)) - return dateArr.join(separator) -} - -function getTimeStr (date, separator = ':') { - date = date || new Date() - const timeArr = [] - timeArr.push(('00' + date.getHours()).substr(-2)) - timeArr.push(('00' + date.getMinutes()).substr(-2)) - timeArr.push(('00' + date.getSeconds()).substr(-2)) - return timeArr.join(separator) -} - -function getFullTimeStr (date) { - date = date || new Date() - return getDateStr(date) + ' ' + getTimeStr(date) -} - -function getDistinctArray (arr) { - return Array.from(new Set(arr)) -} - -/** - * 拼接url - * @param {string} base 基础路径 - * @param {string} path 在基础路径上拼接的路径 - * @returns - */ -function resolveUrl (base, path) { - if (/^https?:/.test(path)) { - return path - } - return base + path -} - -function getVerifyCode (len = 6) { - let code = '' - for (let i = 0; i < len; i++) { - code += Math.floor(Math.random() * 10) - } - return code -} - -function coverMobile (mobile) { - if (typeof mobile !== 'string') { - return mobile - } - return mobile.slice(0, 3) + '****' + mobile.slice(7) -} - -function getNonceStr (length = 16) { - let str = '' - while (str.length < length) { - str += Math.random().toString(32).substring(2) - } - return str.substring(0, length) -} - -module.exports = { - getType, - isValidString, - batchFindObjctValue, - isPlainObject, - isFn, - getDistinctArray, - getFullTimeStr, - resolveUrl, - getOffsetDate, - camel2snakeJson, - snake2camelJson, - getExtension, - getVerifyCode, - coverMobile, - getNonceStr -} +function batchFindObjctValue (obj = {}, keys = []) { + const values = {} + for (let i = 0; i < keys.length; i++) { + const key = keys[i] + const keyPath = key.split('.') + let currentKey = keyPath.shift() + let result = obj + while (currentKey) { + if (!result) { + break + } + result = result[currentKey] + currentKey = keyPath.shift() + } + values[key] = result + } + return values +} + +function getType (val) { + return Object.prototype.toString.call(val).slice(8, -1).toLowerCase() +} + +function hasOwn (obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key) +} + +function isValidString (val) { + return val && getType(val) === 'string' +} + +function isPlainObject (obj) { + return getType(obj) === 'object' +} + +function isFn (fn) { + // 务必注意AsyncFunction + return typeof fn === 'function' +} + +// 获取文件后缀,只添加几种图片类型供客服消息接口使用 +const mime2ext = { + 'image/png': 'png', + 'image/jpeg': 'jpg', + 'image/gif': 'gif', + 'image/svg+xml': 'svg', + 'image/bmp': 'bmp', + 'image/webp': 'webp' +} + +function getExtension (contentType) { + return mime2ext[contentType] +} + +const isSnakeCase = /_(\w)/g +const isCamelCase = /[A-Z]/g + +function snake2camel (value) { + return value.replace(isSnakeCase, (_, c) => (c ? c.toUpperCase() : '')) +} + +function camel2snake (value) { + return value.replace(isCamelCase, str => '_' + str.toLowerCase()) +} + +function parseObjectKeys (obj, type) { + let parserReg, parser + switch (type) { + case 'snake2camel': + parser = snake2camel + parserReg = isSnakeCase + break + case 'camel2snake': + parser = camel2snake + parserReg = isCamelCase + break + } + for (const key in obj) { + if (hasOwn(obj, key)) { + if (parserReg.test(key)) { + const keyCopy = parser(key) + obj[keyCopy] = obj[key] + delete obj[key] + if (isPlainObject(obj[keyCopy])) { + obj[keyCopy] = parseObjectKeys(obj[keyCopy], type) + } else if (Array.isArray(obj[keyCopy])) { + obj[keyCopy] = obj[keyCopy].map((item) => { + return parseObjectKeys(item, type) + }) + } + } + } + } + return obj +} + +function snake2camelJson (obj) { + return parseObjectKeys(obj, 'snake2camel') +} + +function camel2snakeJson (obj) { + return parseObjectKeys(obj, 'camel2snake') +} + +function getOffsetDate (offset) { + return new Date( + Date.now() + (new Date().getTimezoneOffset() + (offset || 0) * 60) * 60000 + ) +} + +function getDateStr (date, separator = '-') { + date = date || new Date() + const dateArr = [] + dateArr.push(date.getFullYear()) + dateArr.push(('00' + (date.getMonth() + 1)).substr(-2)) + dateArr.push(('00' + date.getDate()).substr(-2)) + return dateArr.join(separator) +} + +function getTimeStr (date, separator = ':') { + date = date || new Date() + const timeArr = [] + timeArr.push(('00' + date.getHours()).substr(-2)) + timeArr.push(('00' + date.getMinutes()).substr(-2)) + timeArr.push(('00' + date.getSeconds()).substr(-2)) + return timeArr.join(separator) +} + +function getFullTimeStr (date) { + date = date || new Date() + return getDateStr(date) + ' ' + getTimeStr(date) +} + +function getDistinctArray (arr) { + return Array.from(new Set(arr)) +} + +/** + * 拼接url + * @param {string} base 基础路径 + * @param {string} path 在基础路径上拼接的路径 + * @returns + */ +function resolveUrl (base, path) { + if (/^https?:/.test(path)) { + return path + } + return base + path +} + +function getVerifyCode (len = 6) { + let code = '' + for (let i = 0; i < len; i++) { + code += Math.floor(Math.random() * 10) + } + return code +} + +function coverMobile (mobile) { + if (typeof mobile !== 'string') { + return mobile + } + return mobile.slice(0, 3) + '****' + mobile.slice(7) +} + +function getNonceStr (length = 16) { + let str = '' + while (str.length < length) { + str += Math.random().toString(32).substring(2) + } + 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, + batchFindObjctValue, + isPlainObject, + isFn, + getDistinctArray, + getFullTimeStr, + resolveUrl, + getOffsetDate, + camel2snakeJson, + snake2camelJson, + getExtension, + getVerifyCode, + coverMobile, + getNonceStr +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/validator.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/validator.js index 34878ca8b485267aa2aaf3681681fe068077e3a8..d6f06b561b9656fb8da39e9b381fea8c38e21452 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/validator.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/common/validator.js @@ -1,432 +1,432 @@ -const { - isValidString, - getType -} = require('./utils.js') -const { - ERROR -} = require('./error') - -const baseValidator = Object.create(null) - -baseValidator.username = function (username) { - const errCode = ERROR.INVALID_USERNAME - if (!isValidString(username)) { - return { - errCode - } - } - if (/^\d+$/.test(username)) { - // 用户名不能为纯数字 - return { - errCode - } - }; - if (!/^[a-zA-Z0-9_-]+$/.test(username)) { - // 用户名仅能使用数字、字母、“_”及“-” - return { - errCode - } - } -} - -baseValidator.password = function (password) { - const errCode = ERROR.INVALID_PASSWORD - if (!isValidString(password)) { - return { - errCode - } - } - if (password.length < 6) { - // 密码长度不能小于6 - return { - errCode - } - } -} - -baseValidator.mobile = function (mobile) { - const errCode = ERROR.INVALID_MOBILE - if (!isValidString(mobile)) { - return { - errCode - } - } - if (!/^1\d{10}$/.test(mobile)) { - return { - errCode - } - } -} - -baseValidator.email = function (email) { - const errCode = ERROR.INVALID_EMAIL - if (!isValidString(email)) { - return { - errCode - } - } - if (!/@/.test(email)) { - return { - errCode - } - } -} - -baseValidator.nickname = function (nickname) { - const errCode = ERROR.INVALID_NICKNAME - if (nickname.indexOf('@') !== -1) { - // 昵称不允许含@ - return { - errCode - } - }; - if (/^\d+$/.test(nickname)) { - // 昵称不能为纯数字 - return { - errCode - } - }; - if (nickname.length > 100) { - // 昵称不可超过100字符 - return { - errCode - } - } -} - -const baseType = ['string', 'boolean', 'number', 'null'] // undefined不会由客户端提交上来 - -baseType.forEach((type) => { - baseValidator[type] = function (val) { - if (getType(val) === type) { - return - } - return { - errCode: ERROR.INVALID_PARAM - } - } -}) - -function tokenize(name) { - let i = 0 - const result = [] - let token = '' - while (i < name.length) { - const char = name[i] - switch (char) { - case '|': - case '<': - case '>': - token && result.push(token) - result.push(char) - token = '' - break - default: - token += char - break - } - i++ - if (i === name.length && token) { - result.push(token) - } - } - return result -} - -/** - * 处理validator名 - * @param {string} name - */ -function parseValidatorName(name) { - const tokenList = tokenize(name) - let i = 0 - let currentToken = tokenList[i] - const result = { - type: 'root', - children: [], - parent: null - } - let lastRealm = result - while (currentToken) { - switch (currentToken) { - case 'array': { - const currentRealm = { - type: 'array', - children: [], - parent: lastRealm - } - lastRealm.children.push(currentRealm) - lastRealm = currentRealm - break - } - case '<': - if (lastRealm.type !== 'array') { - throw new Error('Invalid validator token "<"') - } - break - case '>': - if (lastRealm.type !== 'array') { - throw new Error('Invalid validator token ">"') - } - lastRealm = lastRealm.parent - break - case '|': - if (lastRealm.type !== 'array' && lastRealm.type !== 'root') { - throw new Error('Invalid validator token "|"') - } - break - default: - lastRealm.children.push({ - type: currentToken - }) - break - } - i++ - currentToken = tokenList[i] - } - return result -} - -function getRuleCategory(rule) { - switch (rule.type) { - case 'array': - return 'array' - case 'root': - return 'root' - default: - return 'base' - } -} - -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 = '~!@#$%^&*_-+=`|\(){}[]:;"\'<>,.?/' -// const specialCharRegExp = /^[~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]$/ -// for (let i = 0, arr = specialChar.split(''); i < arr.length; i++) { -// const char = arr[i] -// if (!specialCharRegExp.test(char)) { -// throw new Error('check special character error: ' + char) -// } -// } - -// 密码强度表达式 -const passwordRules = { - // 密码必须包含大小写字母、数字和特殊符号 - super: /^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/])[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{8,16}$/, - // 密码必须包含字母、数字和特殊符号 - strong: /^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/])[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{8,16}$/, - // 密码必须为字母、数字和特殊符号任意两种的组合 - medium: /^(?![0-9]+$)(?![a-zA-Z]+$)(?![~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]+$)[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{8,16}$/, - // 密码必须包含字母和数字 - weak: /^(?=.*[0-9])(?=.*[a-zA-Z])[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{6,16}$/, - -} - -function createPasswordVerifier({ - passwordStrength = '' -} = {}) { - return function (password) { - const passwordRegExp = passwordRules[passwordStrength] - if (!passwordRegExp) { - throw new Error('Invalid password strength config: ' + passwordStrength) - } - const errCode = ERROR.INVALID_PASSWORD - if (!isValidString(password)) { - return { - errCode - } - } - if (!passwordRegExp.test(password)) { - return { - errCode: errCode + '-' + passwordStrength - } - } - } -} - -class Validator { - constructor({ - passwordStrength = '' - } = {}) { - this.baseValidator = baseValidator - this.customValidator = Object.create(null) - if (passwordStrength) { - this.mixin( - 'password', - createPasswordVerifier({ - passwordStrength - }) - ) - } - } - - mixin(type, handler) { - this.customValidator[type] = handler - } - - getRealBaseValidator(type) { - return this.customValidator[type] || this.baseValidator[type] - } - - get validator() { - return new Proxy({}, { - get: (_, prop) => { - if (typeof prop !== 'string') { - return - } - const realBaseValidator = this.getRealBaseValidator(prop) - if (realBaseValidator) { - return realBaseValidator - } - const rule = parseValidatorName(prop) - return function (val) { - if (!isMatchUnionType(val, rule)) { - return { - errCode: ERROR.INVALID_PARAM - } - } - } - } - }) - } - - validate(value = {}, schema = {}) { - for (const schemaKey in schema) { - let schemaValue = schema[schemaKey] - if (getType(schemaValue) === 'string') { - schemaValue = { - required: true, - type: schemaValue - } - } - const { - required, - type - } = schemaValue - // value内未传入了schemaKey或对应值为undefined - if (value[schemaKey] === undefined) { - if (required) { - return { - errCode: ERROR.PARAM_REQUIRED, - errMsgValue: { - param: schemaKey - }, - schemaKey - } - } else { - continue - } - } - const validateMethod = this.validator[type] - if (!validateMethod) { - throw new Error(`invalid schema type: ${type}`) - } - const validateRes = validateMethod(value[schemaKey]) - if (validateRes) { - validateRes.schemaKey = schemaKey - return validateRes - } - } - } -} - -function checkClientInfo(clientInfo) { - const stringNotRequired = { - required: false, - type: 'string' - } - const numberNotRequired = { - required: false, - type: 'number' - } - const numberOrStringNotRequired = { - required: false, - type: 'number|string' - } - const schema = { - uniPlatform: 'string', - appId: 'string', - deviceId: stringNotRequired, - osName: stringNotRequired, - locale: stringNotRequired, - clientIP: stringNotRequired, - appName: stringNotRequired, - appVersion: stringNotRequired, - appVersionCode: numberOrStringNotRequired, - channel: numberOrStringNotRequired, - userAgent: stringNotRequired, - uniIdToken: stringNotRequired, - deviceBrand: stringNotRequired, - deviceModel: stringNotRequired, - osVersion: stringNotRequired, - osLanguage: stringNotRequired, - osTheme: stringNotRequired, - romName: stringNotRequired, - romVersion: stringNotRequired, - devicePixelRatio: numberNotRequired, - windowWidth: numberNotRequired, - windowHeight: numberNotRequired, - screenWidth: numberNotRequired, - screenHeight: numberNotRequired - } - const validateRes = new Validator().validate(clientInfo, schema) - if (validateRes) { - if (validateRes.errCode === ERROR.PARAM_REQUIRED) { - console.warn('- 如果使用HBuilderX运行本地云函数/云对象功能时出现此提示,请改为使用客户端调用本地云函数方式调试,或更新HBuilderX到3.4.12及以上版本。\n- 如果是缺少clientInfo.appId,请检查项目manifest.json内是否配置了DCloud AppId') - throw new Error(`"clientInfo.${validateRes.schemaKey}" is required.`) - } else { - throw new Error(`Invalid client info: clienInfo.${validateRes.schemaKey}`) - } - } -} - -module.exports = { - Validator, - checkClientInfo -} +const { + isValidString, + getType +} = require('./utils.js') +const { + ERROR +} = require('./error') + +const baseValidator = Object.create(null) + +baseValidator.username = function (username) { + const errCode = ERROR.INVALID_USERNAME + if (!isValidString(username)) { + return { + errCode + } + } + if (/^\d+$/.test(username)) { + // 用户名不能为纯数字 + return { + errCode + } + }; + if (!/^[a-zA-Z0-9_-]+$/.test(username)) { + // 用户名仅能使用数字、字母、“_”及“-” + return { + errCode + } + } +} + +baseValidator.password = function (password) { + const errCode = ERROR.INVALID_PASSWORD + if (!isValidString(password)) { + return { + errCode + } + } + if (password.length < 6) { + // 密码长度不能小于6 + return { + errCode + } + } +} + +baseValidator.mobile = function (mobile) { + const errCode = ERROR.INVALID_MOBILE + if (!isValidString(mobile)) { + return { + errCode + } + } + if (!/^1\d{10}$/.test(mobile)) { + return { + errCode + } + } +} + +baseValidator.email = function (email) { + const errCode = ERROR.INVALID_EMAIL + if (!isValidString(email)) { + return { + errCode + } + } + if (!/@/.test(email)) { + return { + errCode + } + } +} + +baseValidator.nickname = function (nickname) { + const errCode = ERROR.INVALID_NICKNAME + if (nickname.indexOf('@') !== -1) { + // 昵称不允许含@ + return { + errCode + } + }; + if (/^\d+$/.test(nickname)) { + // 昵称不能为纯数字 + return { + errCode + } + }; + if (nickname.length > 100) { + // 昵称不可超过100字符 + return { + errCode + } + } +} + +const baseType = ['string', 'boolean', 'number', 'null'] // undefined不会由客户端提交上来 + +baseType.forEach((type) => { + baseValidator[type] = function (val) { + if (getType(val) === type) { + return + } + return { + errCode: ERROR.INVALID_PARAM + } + } +}) + +function tokenize(name) { + let i = 0 + const result = [] + let token = '' + while (i < name.length) { + const char = name[i] + switch (char) { + case '|': + case '<': + case '>': + token && result.push(token) + result.push(char) + token = '' + break + default: + token += char + break + } + i++ + if (i === name.length && token) { + result.push(token) + } + } + return result +} + +/** + * 处理validator名 + * @param {string} name + */ +function parseValidatorName(name) { + const tokenList = tokenize(name) + let i = 0 + let currentToken = tokenList[i] + const result = { + type: 'root', + children: [], + parent: null + } + let lastRealm = result + while (currentToken) { + switch (currentToken) { + case 'array': { + const currentRealm = { + type: 'array', + children: [], + parent: lastRealm + } + lastRealm.children.push(currentRealm) + lastRealm = currentRealm + break + } + case '<': + if (lastRealm.type !== 'array') { + throw new Error('Invalid validator token "<"') + } + break + case '>': + if (lastRealm.type !== 'array') { + throw new Error('Invalid validator token ">"') + } + lastRealm = lastRealm.parent + break + case '|': + if (lastRealm.type !== 'array' && lastRealm.type !== 'root') { + throw new Error('Invalid validator token "|"') + } + break + default: + lastRealm.children.push({ + type: currentToken + }) + break + } + i++ + currentToken = tokenList[i] + } + return result +} + +function getRuleCategory(rule) { + switch (rule.type) { + case 'array': + return 'array' + case 'root': + return 'root' + default: + return 'base' + } +} + +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 = '~!@#$%^&*_-+=`|\(){}[]:;"\'<>,.?/' +// const specialCharRegExp = /^[~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]$/ +// for (let i = 0, arr = specialChar.split(''); i < arr.length; i++) { +// const char = arr[i] +// if (!specialCharRegExp.test(char)) { +// throw new Error('check special character error: ' + char) +// } +// } + +// 密码强度表达式 +const passwordRules = { + // 密码必须包含大小写字母、数字和特殊符号 + super: /^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/])[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{8,16}$/, + // 密码必须包含字母、数字和特殊符号 + strong: /^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/])[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{8,16}$/, + // 密码必须为字母、数字和特殊符号任意两种的组合 + medium: /^(?![0-9]+$)(?![a-zA-Z]+$)(?![~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]+$)[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{8,16}$/, + // 密码必须包含字母和数字 + weak: /^(?=.*[0-9])(?=.*[a-zA-Z])[0-9a-zA-Z~!@#$%^&*_\-+=`|\\(){}[\]:;"'<>,.?/]{6,16}$/, + +} + +function createPasswordVerifier({ + passwordStrength = '' +} = {}) { + return function (password) { + const passwordRegExp = passwordRules[passwordStrength] + if (!passwordRegExp) { + throw new Error('Invalid password strength config: ' + passwordStrength) + } + const errCode = ERROR.INVALID_PASSWORD + if (!isValidString(password)) { + return { + errCode + } + } + if (!passwordRegExp.test(password)) { + return { + errCode: errCode + '-' + passwordStrength + } + } + } +} + +class Validator { + constructor({ + passwordStrength = '' + } = {}) { + this.baseValidator = baseValidator + this.customValidator = Object.create(null) + if (passwordStrength) { + this.mixin( + 'password', + createPasswordVerifier({ + passwordStrength + }) + ) + } + } + + mixin(type, handler) { + this.customValidator[type] = handler + } + + getRealBaseValidator(type) { + return this.customValidator[type] || this.baseValidator[type] + } + + get validator() { + return new Proxy({}, { + get: (_, prop) => { + if (typeof prop !== 'string') { + return + } + const realBaseValidator = this.getRealBaseValidator(prop) + if (realBaseValidator) { + return realBaseValidator + } + const rule = parseValidatorName(prop) + return function (val) { + if (!isMatchUnionType(val, rule)) { + return { + errCode: ERROR.INVALID_PARAM + } + } + } + } + }) + } + + validate(value = {}, schema = {}) { + for (const schemaKey in schema) { + let schemaValue = schema[schemaKey] + if (getType(schemaValue) === 'string') { + schemaValue = { + required: true, + type: schemaValue + } + } + const { + required, + type + } = schemaValue + // value内未传入了schemaKey或对应值为undefined + if (value[schemaKey] === undefined) { + if (required) { + return { + errCode: ERROR.PARAM_REQUIRED, + errMsgValue: { + param: schemaKey + }, + schemaKey + } + } else { + continue + } + } + const validateMethod = this.validator[type] + if (!validateMethod) { + throw new Error(`invalid schema type: ${type}`) + } + const validateRes = validateMethod(value[schemaKey]) + if (validateRes) { + validateRes.schemaKey = schemaKey + return validateRes + } + } + } +} + +function checkClientInfo(clientInfo) { + const stringNotRequired = { + required: false, + type: 'string' + } + const numberNotRequired = { + required: false, + type: 'number' + } + const numberOrStringNotRequired = { + required: false, + type: 'number|string' + } + const schema = { + uniPlatform: 'string', + appId: 'string', + deviceId: stringNotRequired, + osName: stringNotRequired, + locale: stringNotRequired, + clientIP: stringNotRequired, + appName: stringNotRequired, + appVersion: stringNotRequired, + appVersionCode: numberOrStringNotRequired, + channel: numberOrStringNotRequired, + userAgent: stringNotRequired, + uniIdToken: stringNotRequired, + deviceBrand: stringNotRequired, + deviceModel: stringNotRequired, + osVersion: stringNotRequired, + osLanguage: stringNotRequired, + osTheme: stringNotRequired, + romName: stringNotRequired, + romVersion: stringNotRequired, + devicePixelRatio: numberNotRequired, + windowWidth: numberNotRequired, + windowHeight: numberNotRequired, + screenWidth: numberNotRequired, + screenHeight: numberNotRequired + } + const validateRes = new Validator().validate(clientInfo, schema) + if (validateRes) { + if (validateRes.errCode === ERROR.PARAM_REQUIRED) { + console.warn('- 如果使用HBuilderX运行本地云函数/云对象功能时出现此提示,请改为使用客户端调用本地云函数方式调试,或更新HBuilderX到3.4.12及以上版本。\n- 如果是缺少clientInfo.appId,请检查项目manifest.json内是否配置了DCloud AppId') + throw new Error(`"clientInfo.${validateRes.schemaKey}" is required.`) + } else { + throw new Error(`Invalid client info: clienInfo.${validateRes.schemaKey}`) + } + } +} + +module.exports = { + Validator, + checkClientInfo +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/config/permission.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/config/permission.js index f67725c6880d56611b9f236a82645671d05e3d90..0bc2661e08421805b0e52251e3b480898877fb98 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/config/permission.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/config/permission.js @@ -1,66 +1,78 @@ -// 各接口权限配置,未配置接口表示允许任何用户访问(包括未登录用户) -module.exports = { - // 管理接口 - addUser: { - // auth: true // 已登录用户方可操作,配置角色或权限时此项可不写 - role: ['admin'] // 允许进行此操作的角色,包含任一角色均可操作。 - // permission: [] // 允许进行此操作的权限,包含任一权限均可操作。 - // 权限角色均配置时,用户拥有任一权限或任一角色均可操作 - }, - updateUser: { - role: ['admin'] - }, - authorizeAppLogin: { - role: ['admin'] - }, - removeAuthorizedApp: { - role: ['admin'] - }, - setAuthorizedApp: { - role: ['admin'] - }, - - // 用户接口 - closeAccount: { - auth: true - }, - updatePwd: { - auth: true - }, - logout: { - auth: true - }, - bindMobileBySms: { - auth: true - }, - bindMobileByUniverify: { - auth: true - }, - bindMobileByMpWeixin: { - auth: true - }, - bindAlipay: { - auth: true - }, - bindApple: { - auth: true - }, - bindQQ: { - auth: true - }, - bindWeixin: { - auth: true - }, - acceptInvite: { - auth: true - }, - getInvitedUser: { - auth: true - }, - setPushCid: { - auth: true - }, - getAccountInfo: { - auth: true - } -} +// 各接口权限配置,未配置接口表示允许任何用户访问(包括未登录用户) +module.exports = { + // 管理接口 + addUser: { + // auth: true // 已登录用户方可操作,配置角色或权限时此项可不写 + role: ['admin'] // 允许进行此操作的角色,包含任一角色均可操作。 + // permission: [] // 允许进行此操作的权限,包含任一权限均可操作。 + // 权限角色均配置时,用户拥有任一权限或任一角色均可操作 + }, + updateUser: { + role: ['admin'] + }, + authorizeAppLogin: { + role: ['admin'] + }, + removeAuthorizedApp: { + role: ['admin'] + }, + setAuthorizedApp: { + role: ['admin'] + }, + + // 用户接口 + closeAccount: { + auth: true + }, + updatePwd: { + auth: true + }, + logout: { + auth: true + }, + bindMobileBySms: { + auth: true + }, + bindMobileByUniverify: { + auth: true + }, + bindMobileByMpWeixin: { + auth: true + }, + bindAlipay: { + auth: true + }, + bindApple: { + auth: true + }, + bindQQ: { + auth: true + }, + bindWeixin: { + auth: true + }, + acceptInvite: { + auth: true + }, + getInvitedUser: { + auth: true + }, + setPushCid: { + auth: true + }, + getAccountInfo: { + auth: true + }, + unbindWeixin: { + auth: true + }, + unbindAlipay: { + auth: true + }, + unbindQQ: { + auth: true + }, + unbindApple: { + auth: true + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/index.obj.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/index.obj.js index c8a3f112d87174a6cbcd080bf66168c2fc3a32fc..24cbbc7b4d78dbf5ffcbe1cc3a92ef8e01da4e75 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/index.obj.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/index.obj.js @@ -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 } diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/en.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/en.js index 1ef455ab1e419227ffbdfd1bdf52512659be57f4..99c445d4ce17620a8f7c4cfbbe8da60cb7eda986 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/en.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/en.js @@ -1,44 +1,49 @@ -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-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': 'Username or 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' -} - -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-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' +} + +module.exports = { + ...word, + ...sentence +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/index.js index 1f22998929e37bcd713a0d0b0ef31060bc1576b8..557575d7eea78351ef2e87f4b7b3d4b1fa0538ef 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/index.js @@ -1,22 +1,22 @@ -let lang = { - 'zh-Hans': require('./zh-hans'), - en: require('./en') -} - -function mergeLanguage (lang1, lang2) { - const localeList = Object.keys(lang1) - localeList.push(...Object.keys(lang2)) - const result = {} - for (let i = 0; i < localeList.length; i++) { - const locale = localeList[i] - result[locale] = Object.assign({}, lang1[locale], lang2[locale]) - } - return result -} - -try { - const langPath = require.resolve('uni-config-center/uni-id/lang/index.js') - lang = mergeLanguage(lang, require(langPath)) -} catch (error) { } - -module.exports = lang +let lang = { + 'zh-Hans': require('./zh-hans'), + en: require('./en') +} + +function mergeLanguage (lang1, lang2) { + const localeList = Object.keys(lang1) + localeList.push(...Object.keys(lang2)) + const result = {} + for (let i = 0; i < localeList.length; i++) { + const locale = localeList[i] + result[locale] = Object.assign({}, lang1[locale], lang2[locale]) + } + return result +} + +try { + const langPath = require.resolve('uni-config-center/uni-id/lang/index.js') + lang = mergeLanguage(lang, require(langPath)) +} catch (error) { } + +module.exports = lang diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/zh-hans.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/zh-hans.js index 5bd2443f045ab895c4a33d98ab4f22e6c697c8b4..923d2af8f40c1360780789fb6a83a3b4221a5231 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/zh-hans.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lang/zh-hans.js @@ -1,44 +1,49 @@ -const word = { - login: '登录', - 'verify-mobile': '验证手机号' -} - -const sentence = { - 'uni-id-account-exists': '此账号已注册', - 'uni-id-account-not-exists': '此账号未注册', - 'uni-id-account-conflict': '用户账号冲突', - 'uni-id-account-banned': '此账号已封禁', - 'uni-id-account-auditing': '此账号正在审核中', - 'uni-id-account-audit-failed': '此账号审核失败', - 'uni-id-account-closed': '此账号已注销', - 'uni-id-captcha-required': '请输入图形验证码', - 'uni-id-password-error': '用户名或密码错误', - 'uni-id-password-error-exceed-limit': '密码错误次数过多,请稍后再试', - 'uni-id-invalid-username': '用户名不合法', - 'uni-id-invalid-password': '密码不合法', - 'uni-id-invalid-password-super': '密码必须包含大小写字母、数字和特殊符号,长度8-16位', - 'uni-id-invalid-password-strong': '密码必须包含字母、数字和特殊符号,长度8-16位不合法', - 'uni-id-invalid-password-medium': '密码必须为字母、数字和特殊符号任意两种的组合,长度8-16位', - 'uni-id-invalid-password-weak': '密码必须包含字母和数字,长度6-16位', - 'uni-id-invalid-mobile': '手机号码不合法', - 'uni-id-invalid-email': '邮箱不合法', - 'uni-id-invalid-nickname': '昵称不合法', - 'uni-id-invalid-param': '参数错误', - 'uni-id-param-required': '缺少参数: {param}', - 'uni-id-get-third-party-account-failed': '获取第三方账号失败', - 'uni-id-get-third-party-user-info-failed': '获取用户信息失败', - 'uni-id-mobile-verify-code-error': '手机验证码错误或已过期', - 'uni-id-email-verify-code-error': '邮箱验证码错误或已过期', - 'uni-id-admin-exists': '超级管理员已存在', - 'uni-id-permission-error': '权限错误', - 'uni-id-system-error': '系统错误', - 'uni-id-set-invite-code-failed': '设置邀请码失败', - 'uni-id-invalid-invite-code': '邀请码不可用', - 'uni-id-change-inviter-forbidden': '禁止修改邀请人', - 'uni-id-bind-conflict': '此账号已被绑定' -} - -module.exports = { - ...word, - ...sentence -} +const word = { + login: '登录', + 'verify-mobile': '验证手机号' +} + +const sentence = { + 'uni-id-account-exists': '此账号已注册', + 'uni-id-account-not-exists': '此账号未注册', + 'uni-id-account-conflict': '用户账号冲突', + 'uni-id-account-banned': '此账号已封禁', + 'uni-id-account-auditing': '此账号正在审核中', + 'uni-id-account-audit-failed': '此账号审核失败', + 'uni-id-account-closed': '此账号已注销', + 'uni-id-captcha-required': '请输入图形验证码', + 'uni-id-password-error': '密码错误', + 'uni-id-password-error-exceed-limit': '密码错误次数过多,请稍后再试', + 'uni-id-invalid-username': '用户名不合法', + 'uni-id-invalid-password': '密码不合法', + 'uni-id-invalid-password-super': '密码必须包含大小写字母、数字和特殊符号,长度8-16位', + 'uni-id-invalid-password-strong': '密码必须包含字母、数字和特殊符号,长度8-16位不合法', + 'uni-id-invalid-password-medium': '密码必须为字母、数字和特殊符号任意两种的组合,长度8-16位', + 'uni-id-invalid-password-weak': '密码必须包含字母和数字,长度6-16位', + 'uni-id-invalid-mobile': '手机号码不合法', + 'uni-id-invalid-email': '邮箱不合法', + 'uni-id-invalid-nickname': '昵称不合法', + 'uni-id-invalid-param': '参数错误', + 'uni-id-param-required': '缺少参数: {param}', + 'uni-id-get-third-party-account-failed': '获取第三方账号失败', + 'uni-id-get-third-party-user-info-failed': '获取用户信息失败', + 'uni-id-mobile-verify-code-error': '手机验证码错误或已过期', + 'uni-id-email-verify-code-error': '邮箱验证码错误或已过期', + 'uni-id-admin-exists': '超级管理员已存在', + 'uni-id-permission-error': '权限错误', + 'uni-id-system-error': '系统错误', + 'uni-id-set-invite-code-failed': '设置邀请码失败', + 'uni-id-invalid-invite-code': '邀请码不可用', + 'uni-id-change-inviter-forbidden': '禁止修改邀请人', + '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 = { + ...word, + ...sentence +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/README.md b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/README.md index 47d8c4c87b02177f27b712d2f1bedde53fcbc7e8..69e66178b341a9490d5023ab401f6bd560f3b668 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/README.md +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/README.md @@ -1,3 +1,3 @@ -# 说明 - +# 说明 + 此目录内为uni-id-co基础能力,不建议直接修改。如果你发现有些逻辑加入会更好,或者此部分代码有Bug可以向我们提交PR,仓库地址:[]()。如果有特殊的需求也可以在[论坛](https://ask.dcloud.net.cn/)提出,我们可以讨论下如何实现。 \ No newline at end of file diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/account/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/account/index.js index dbec0817811ad8e36f4745f842a30712ea672525..fd4c7beda00b3ecdba548087be1c8e677aea7688 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/account/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/account/index.js @@ -1,16 +1,16 @@ -const AlipayBase = require('../alipayBase') -const protocols = require('./protocols') -module.exports = class Auth extends AlipayBase { - constructor (options) { - super(options) - this._protocols = protocols - } - - async code2Session (code) { - const result = await this._exec('alipay.system.oauth.token', { - grantType: 'authorization_code', - code - }) - return result - } -} +const AlipayBase = require('../alipayBase') +const protocols = require('./protocols') +module.exports = class Auth extends AlipayBase { + constructor (options) { + super(options) + this._protocols = protocols + } + + async code2Session (code) { + const result = await this._exec('alipay.system.oauth.token', { + grantType: 'authorization_code', + code + }) + return result + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/account/protocols.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/account/protocols.js index cff351d830562ba14ce52482daa54f82d490b714..17c9860d6b588fe333c353842435225b6143b249 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/account/protocols.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/account/protocols.js @@ -1,10 +1,10 @@ -module.exports = { - code2Session: { - // args (fromArgs) { - // return fromArgs - // }, - returnValue: { - openid: 'userId' - } - } -} +module.exports = { + code2Session: { + // args (fromArgs) { + // return fromArgs + // }, + returnValue: { + openid: 'userId' + } + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/alipayBase.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/alipayBase.js index 1462b046d1aae1f355a54f26c3e1739360fb2f76..8b18706ac573fab33fdcb04a7969529d80190192 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/alipayBase.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/alipay/alipayBase.js @@ -1,231 +1,231 @@ -const { - camel2snakeJson, - snake2camelJson, - getOffsetDate, - getFullTimeStr -} = require('../../../common/utils') -const crypto = require('crypto') - -const ALIPAY_ALGORITHM_MAPPING = { - RSA: 'RSA-SHA1', - RSA2: 'RSA-SHA256' -} - -module.exports = class AlipayBase { - constructor (options = {}) { - if (!options.appId) throw new Error('appId required') - if (!options.privateKey) throw new Error('privateKey required') - const defaultOptions = { - gateway: 'https://openapi.alipay.com/gateway.do', - timeout: 5000, - charset: 'utf-8', - version: '1.0', - signType: 'RSA2', - timeOffset: -new Date().getTimezoneOffset() / 60, - keyType: 'PKCS8' - } - - if (options.sandbox) { - options.gateway = 'https://openapi.alipaydev.com/gateway.do' - } - - this.options = Object.assign({}, defaultOptions, options) - - const privateKeyType = - this.options.keyType === 'PKCS8' ? 'PRIVATE KEY' : 'RSA PRIVATE KEY' - - this.options.privateKey = this._formatKey( - this.options.privateKey, - privateKeyType - ) - if (this.options.alipayPublicKey) { - this.options.alipayPublicKey = this._formatKey( - this.options.alipayPublicKey, - 'PUBLIC KEY' - ) - } - } - - _formatKey (key, type) { - return `-----BEGIN ${type}-----\n${key}\n-----END ${type}-----` - } - - _formatUrl (url, params) { - let requestUrl = url - // 需要放在 url 中的参数列表 - const urlArgs = [ - 'app_id', - 'method', - 'format', - 'charset', - 'sign_type', - 'sign', - 'timestamp', - 'version', - 'notify_url', - 'return_url', - 'auth_token', - 'app_auth_token' - ] - - for (const key in params) { - if (urlArgs.indexOf(key) > -1) { - const val = encodeURIComponent(params[key]) - requestUrl = `${requestUrl}${requestUrl.includes('?') ? '&' : '?' - }${key}=${val}` - // 删除 postData 中对应的数据 - delete params[key] - } - } - - return { execParams: params, url: requestUrl } - } - - _getSign (method, params) { - const bizContent = params.bizContent || null - delete params.bizContent - - const signParams = Object.assign({ - method, - appId: this.options.appId, - charset: this.options.charset, - version: this.options.version, - signType: this.options.signType, - timestamp: getFullTimeStr(getOffsetDate(this.options.timeOffset)) - }, params) - - if (bizContent) { - signParams.bizContent = JSON.stringify(camel2snakeJson(bizContent)) - } - - // params key 驼峰转下划线 - const decamelizeParams = camel2snakeJson(signParams) - - // 排序 - const signStr = Object.keys(decamelizeParams) - .sort() - .map((key) => { - let data = decamelizeParams[key] - if (Array.prototype.toString.call(data) !== '[object String]') { - data = JSON.stringify(data) - } - return `${key}=${data}` - }) - .join('&') - - // 计算签名 - const sign = crypto - .createSign(ALIPAY_ALGORITHM_MAPPING[this.options.signType]) - .update(signStr, 'utf8') - .sign(this.options.privateKey, 'base64') - - return Object.assign(decamelizeParams, { sign }) - } - - async _exec (method, params = {}, option = {}) { - // 计算签名 - const signData = this._getSign(method, params) - const { url, execParams } = this._formatUrl(this.options.gateway, signData) - const { status, data } = await uniCloud.httpclient.request(url, { - method: 'POST', - data: execParams, - // 按 text 返回(为了验签) - dataType: 'text', - timeout: this.options.timeout - }) - if (status !== 200) throw new Error('request fail') - /** - * 示例响应格式 - * {"alipay_trade_precreate_response": - * {"code": "10000","msg": "Success","out_trade_no": "111111","qr_code": "https:\/\/"}, - * "sign": "abcde=" - * } - * 或者 - * {"error_response": - * {"code":"40002","msg":"Invalid Arguments","sub_code":"isv.code-invalid","sub_msg":"授权码code无效"}, - * } - */ - const result = JSON.parse(data) - const responseKey = `${method.replace(/\./g, '_')}_response` - const response = result[responseKey] - const errorResponse = result.error_response - if (response) { - // 按字符串验签 - const validateSuccess = option.validateSign ? this._checkResponseSign(data, responseKey) : true - if (validateSuccess) { - if (!response.code || response.code === '10000') { - const errCode = 0 - const errMsg = response.msg || '' - return { - errCode, - errMsg, - ...snake2camelJson(response) - } - } - const msg = response.sub_code ? `${response.sub_code} ${response.sub_msg}` : `${response.msg || 'unkonwn error'}` - throw new Error(msg) - } else { - throw new Error('check sign error') - } - } else if (errorResponse) { - throw new Error(errorResponse.sub_msg || errorResponse.msg || 'request fail') - } - - throw new Error('request fail') - } - - _checkResponseSign (signStr, responseKey) { - if (!this.options.alipayPublicKey || this.options.alipayPublicKey === '') { - console.warn('options.alipayPublicKey is empty') - // 支付宝公钥不存在时不做验签 - return true - } - - // 带验签的参数不存在时返回失败 - if (!signStr) { return false } - - // 根据服务端返回的结果截取需要验签的目标字符串 - const validateStr = this._getSignStr(signStr, responseKey) - // 服务端返回的签名 - const serverSign = JSON.parse(signStr).sign - - // 参数存在,并且是正常的结果(不包含 sub_code)时才验签 - const verifier = crypto.createVerify(ALIPAY_ALGORITHM_MAPPING[this.options.signType]) - verifier.update(validateStr, 'utf8') - return verifier.verify(this.options.alipayPublicKey, serverSign, 'base64') - } - - _getSignStr (originStr, responseKey) { - // 待签名的字符串 - let validateStr = originStr.trim() - // 找到 xxx_response 开始的位置 - const startIndex = originStr.indexOf(`${responseKey}"`) - // 找到最后一个 “"sign"” 字符串的位置(避免) - const lastIndex = originStr.lastIndexOf('"sign"') - - /** - * 删除 xxx_response 及之前的字符串 - * 假设原始字符串为 - * {"xxx_response":{"code":"10000"},"sign":"jumSvxTKwn24G5sAIN"} - * 删除后变为 - * :{"code":"10000"},"sign":"jumSvxTKwn24G5sAIN"} - */ - validateStr = validateStr.substr(startIndex + responseKey.length + 1) - - /** - * 删除最后一个 "sign" 及之后的字符串 - * 删除后变为 - * :{"code":"10000"}, - * {} 之间就是待验签的字符串 - */ - validateStr = validateStr.substr(0, lastIndex) - - // 删除第一个 { 之前的任何字符 - validateStr = validateStr.replace(/^[^{]*{/g, '{') - - // 删除最后一个 } 之后的任何字符 - validateStr = validateStr.replace(/\}([^}]*)$/g, '}') - - return validateStr - } -} +const { + camel2snakeJson, + snake2camelJson, + getOffsetDate, + getFullTimeStr +} = require('../../../common/utils') +const crypto = require('crypto') + +const ALIPAY_ALGORITHM_MAPPING = { + RSA: 'RSA-SHA1', + RSA2: 'RSA-SHA256' +} + +module.exports = class AlipayBase { + constructor (options = {}) { + if (!options.appId) throw new Error('appId required') + if (!options.privateKey) throw new Error('privateKey required') + const defaultOptions = { + gateway: 'https://openapi.alipay.com/gateway.do', + timeout: 5000, + charset: 'utf-8', + version: '1.0', + signType: 'RSA2', + timeOffset: -new Date().getTimezoneOffset() / 60, + keyType: 'PKCS8' + } + + if (options.sandbox) { + options.gateway = 'https://openapi.alipaydev.com/gateway.do' + } + + this.options = Object.assign({}, defaultOptions, options) + + const privateKeyType = + this.options.keyType === 'PKCS8' ? 'PRIVATE KEY' : 'RSA PRIVATE KEY' + + this.options.privateKey = this._formatKey( + this.options.privateKey, + privateKeyType + ) + if (this.options.alipayPublicKey) { + this.options.alipayPublicKey = this._formatKey( + this.options.alipayPublicKey, + 'PUBLIC KEY' + ) + } + } + + _formatKey (key, type) { + return `-----BEGIN ${type}-----\n${key}\n-----END ${type}-----` + } + + _formatUrl (url, params) { + let requestUrl = url + // 需要放在 url 中的参数列表 + const urlArgs = [ + 'app_id', + 'method', + 'format', + 'charset', + 'sign_type', + 'sign', + 'timestamp', + 'version', + 'notify_url', + 'return_url', + 'auth_token', + 'app_auth_token' + ] + + for (const key in params) { + if (urlArgs.indexOf(key) > -1) { + const val = encodeURIComponent(params[key]) + requestUrl = `${requestUrl}${requestUrl.includes('?') ? '&' : '?' + }${key}=${val}` + // 删除 postData 中对应的数据 + delete params[key] + } + } + + return { execParams: params, url: requestUrl } + } + + _getSign (method, params) { + const bizContent = params.bizContent || null + delete params.bizContent + + const signParams = Object.assign({ + method, + appId: this.options.appId, + charset: this.options.charset, + version: this.options.version, + signType: this.options.signType, + timestamp: getFullTimeStr(getOffsetDate(this.options.timeOffset)) + }, params) + + if (bizContent) { + signParams.bizContent = JSON.stringify(camel2snakeJson(bizContent)) + } + + // params key 驼峰转下划线 + const decamelizeParams = camel2snakeJson(signParams) + + // 排序 + const signStr = Object.keys(decamelizeParams) + .sort() + .map((key) => { + let data = decamelizeParams[key] + if (Array.prototype.toString.call(data) !== '[object String]') { + data = JSON.stringify(data) + } + return `${key}=${data}` + }) + .join('&') + + // 计算签名 + const sign = crypto + .createSign(ALIPAY_ALGORITHM_MAPPING[this.options.signType]) + .update(signStr, 'utf8') + .sign(this.options.privateKey, 'base64') + + return Object.assign(decamelizeParams, { sign }) + } + + async _exec (method, params = {}, option = {}) { + // 计算签名 + const signData = this._getSign(method, params) + const { url, execParams } = this._formatUrl(this.options.gateway, signData) + const { status, data } = await uniCloud.httpclient.request(url, { + method: 'POST', + data: execParams, + // 按 text 返回(为了验签) + dataType: 'text', + timeout: this.options.timeout + }) + if (status !== 200) throw new Error('request fail') + /** + * 示例响应格式 + * {"alipay_trade_precreate_response": + * {"code": "10000","msg": "Success","out_trade_no": "111111","qr_code": "https:\/\/"}, + * "sign": "abcde=" + * } + * 或者 + * {"error_response": + * {"code":"40002","msg":"Invalid Arguments","sub_code":"isv.code-invalid","sub_msg":"授权码code无效"}, + * } + */ + const result = JSON.parse(data) + const responseKey = `${method.replace(/\./g, '_')}_response` + const response = result[responseKey] + const errorResponse = result.error_response + if (response) { + // 按字符串验签 + const validateSuccess = option.validateSign ? this._checkResponseSign(data, responseKey) : true + if (validateSuccess) { + if (!response.code || response.code === '10000') { + const errCode = 0 + const errMsg = response.msg || '' + return { + errCode, + errMsg, + ...snake2camelJson(response) + } + } + const msg = response.sub_code ? `${response.sub_code} ${response.sub_msg}` : `${response.msg || 'unkonwn error'}` + throw new Error(msg) + } else { + throw new Error('check sign error') + } + } else if (errorResponse) { + throw new Error(errorResponse.sub_msg || errorResponse.msg || 'request fail') + } + + throw new Error('request fail') + } + + _checkResponseSign (signStr, responseKey) { + if (!this.options.alipayPublicKey || this.options.alipayPublicKey === '') { + console.warn('options.alipayPublicKey is empty') + // 支付宝公钥不存在时不做验签 + return true + } + + // 带验签的参数不存在时返回失败 + if (!signStr) { return false } + + // 根据服务端返回的结果截取需要验签的目标字符串 + const validateStr = this._getSignStr(signStr, responseKey) + // 服务端返回的签名 + const serverSign = JSON.parse(signStr).sign + + // 参数存在,并且是正常的结果(不包含 sub_code)时才验签 + const verifier = crypto.createVerify(ALIPAY_ALGORITHM_MAPPING[this.options.signType]) + verifier.update(validateStr, 'utf8') + return verifier.verify(this.options.alipayPublicKey, serverSign, 'base64') + } + + _getSignStr (originStr, responseKey) { + // 待签名的字符串 + let validateStr = originStr.trim() + // 找到 xxx_response 开始的位置 + const startIndex = originStr.indexOf(`${responseKey}"`) + // 找到最后一个 “"sign"” 字符串的位置(避免) + const lastIndex = originStr.lastIndexOf('"sign"') + + /** + * 删除 xxx_response 及之前的字符串 + * 假设原始字符串为 + * {"xxx_response":{"code":"10000"},"sign":"jumSvxTKwn24G5sAIN"} + * 删除后变为 + * :{"code":"10000"},"sign":"jumSvxTKwn24G5sAIN"} + */ + validateStr = validateStr.substr(startIndex + responseKey.length + 1) + + /** + * 删除最后一个 "sign" 及之后的字符串 + * 删除后变为 + * :{"code":"10000"}, + * {} 之间就是待验签的字符串 + */ + validateStr = validateStr.substr(0, lastIndex) + + // 删除第一个 { 之前的任何字符 + validateStr = validateStr.replace(/^[^{]*{/g, '{') + + // 删除最后一个 } 之后的任何字符 + validateStr = validateStr.replace(/\}([^}]*)$/g, '}') + + return validateStr + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/apple/account/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/apple/account/index.js index 0e51b4dab2e2653d95d043f6cfa29717e7c24dcb..24cd60fc5a57aa7479e4ad82b620db382aad9e6d 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/apple/account/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/apple/account/index.js @@ -1,76 +1,76 @@ -const rsaPublicKeyPem = require('../rsa-public-key-pem') -let authKeysCache = null - -module.exports = class Auth { - constructor (options) { - this.options = Object.assign({ - baseUrl: 'https://appleid.apple.com', - timeout: 10000 - }, options) - } - - async _fetch (url, options) { - const { baseUrl } = this.options - return uniCloud.httpclient.request(baseUrl + url, options) - } - - async verifyIdentityToken (identityToken) { - // 解密出kid,拿取key - const jwtHeader = identityToken.split('.')[0] - const { kid } = JSON.parse(Buffer.from(jwtHeader, 'base64').toString()) - let authKeys - if (authKeysCache) { - authKeys = authKeysCache - } else { - authKeys = await this.getAuthKeys() - authKeysCache = authKeys - } - const usedKey = authKeys.find(item => item.kid === kid) - - /** - * identityToken 格式 - * - * { - * iss: 'https://appleid.apple.com', - * aud: 'io.dcloud.hellouniapp', - * exp: 1610626724, - * iat: 1610540324, - * sub: '000628.30119d332d9b45a3be4a297f9391fd5c.0403', - * c_hash: 'oFfgewoG36cJX00KUbj45A', - * email: 'x2awmap99s@privaterelay.appleid.com', - * email_verified: 'true', - * is_private_email: 'true', - * auth_time: 1610540324, - * nonce_supported: true - * } - */ - const payload = require('jsonwebtoken').verify( - identityToken, - rsaPublicKeyPem(usedKey.n, usedKey.e), - { - algorithms: usedKey.alg - } - ) - - if (payload.iss !== 'https://appleid.apple.com' || payload.aud !== this.options.bundleId) { - throw new Error('Invalid identity token') - } - - return { - openid: payload.sub, - email: payload.email, - emailVerified: payload.email_verified === 'true', - isPrivateEmail: payload.is_private_email === 'true' - } - } - - async getAuthKeys () { - const { status, data } = await this._fetch('/auth/keys', { - method: 'GET', - dataType: 'json', - timeout: this.options.timeout - }) - if (status !== 200) throw new Error('request https://appleid.apple.com/auth/keys fail') - return data.keys - } -} +const rsaPublicKeyPem = require('../rsa-public-key-pem') +let authKeysCache = null + +module.exports = class Auth { + constructor (options) { + this.options = Object.assign({ + baseUrl: 'https://appleid.apple.com', + timeout: 10000 + }, options) + } + + async _fetch (url, options) { + const { baseUrl } = this.options + return uniCloud.httpclient.request(baseUrl + url, options) + } + + async verifyIdentityToken (identityToken) { + // 解密出kid,拿取key + const jwtHeader = identityToken.split('.')[0] + const { kid } = JSON.parse(Buffer.from(jwtHeader, 'base64').toString()) + let authKeys + if (authKeysCache) { + authKeys = authKeysCache + } else { + authKeys = await this.getAuthKeys() + authKeysCache = authKeys + } + const usedKey = authKeys.find(item => item.kid === kid) + + /** + * identityToken 格式 + * + * { + * iss: 'https://appleid.apple.com', + * aud: 'io.dcloud.hellouniapp', + * exp: 1610626724, + * iat: 1610540324, + * sub: '000628.30119d332d9b45a3be4a297f9391fd5c.0403', + * c_hash: 'oFfgewoG36cJX00KUbj45A', + * email: 'x2awmap99s@privaterelay.appleid.com', + * email_verified: 'true', + * is_private_email: 'true', + * auth_time: 1610540324, + * nonce_supported: true + * } + */ + const payload = require('jsonwebtoken').verify( + identityToken, + rsaPublicKeyPem(usedKey.n, usedKey.e), + { + algorithms: usedKey.alg + } + ) + + if (payload.iss !== 'https://appleid.apple.com' || payload.aud !== this.options.bundleId) { + throw new Error('Invalid identity token') + } + + return { + openid: payload.sub, + email: payload.email, + emailVerified: payload.email_verified === 'true', + isPrivateEmail: payload.is_private_email === 'true' + } + } + + async getAuthKeys () { + const { status, data } = await this._fetch('/auth/keys', { + method: 'GET', + dataType: 'json', + timeout: this.options.timeout + }) + if (status !== 200) throw new Error('request https://appleid.apple.com/auth/keys fail') + return data.keys + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/apple/rsa-public-key-pem.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/apple/rsa-public-key-pem.js index e1dbb31db3894f81838a843ec667cda09ec9f23b..8fcc5690e136cb52dffdf807c5d300447fba7bb1 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/apple/rsa-public-key-pem.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/apple/rsa-public-key-pem.js @@ -1,64 +1,64 @@ -// http://stackoverflow.com/questions/18835132/xml-to-pem-in-node-js -/* eslint-disable camelcase */ -function rsaPublicKeyPem (modulus_b64, exponent_b64) { - const modulus = Buffer.from(modulus_b64, 'base64') - const exponent = Buffer.from(exponent_b64, 'base64') - - let modulus_hex = modulus.toString('hex') - let exponent_hex = exponent.toString('hex') - - modulus_hex = prepadSigned(modulus_hex) - exponent_hex = prepadSigned(exponent_hex) - - const modlen = modulus_hex.length / 2 - const explen = exponent_hex.length / 2 - - const encoded_modlen = encodeLengthHex(modlen) - const encoded_explen = encodeLengthHex(explen) - const encoded_pubkey = '30' + - encodeLengthHex( - modlen + - explen + - encoded_modlen.length / 2 + - encoded_explen.length / 2 + 2 - ) + - '02' + encoded_modlen + modulus_hex + - '02' + encoded_explen + exponent_hex - - const der_b64 = Buffer.from(encoded_pubkey, 'hex').toString('base64') - - const pem = '-----BEGIN RSA PUBLIC KEY-----\n' + - der_b64.match(/.{1,64}/g).join('\n') + - '\n-----END RSA PUBLIC KEY-----\n' - - return pem -} - -function prepadSigned (hexStr) { - const msb = hexStr[0] - if (msb < '0' || msb > '7') { - return '00' + hexStr - } else { - return hexStr - } -} - -function toHex (number) { - const nstr = number.toString(16) - if (nstr.length % 2) return '0' + nstr - return nstr -} - -// encode ASN.1 DER length field -// if <=127, short form -// if >=128, long form -function encodeLengthHex (n) { - if (n <= 127) return toHex(n) - else { - const n_hex = toHex(n) - const length_of_length_byte = 128 + n_hex.length / 2 // 0x80+numbytes - return toHex(length_of_length_byte) + n_hex - } -} - -module.exports = rsaPublicKeyPem +// http://stackoverflow.com/questions/18835132/xml-to-pem-in-node-js +/* eslint-disable camelcase */ +function rsaPublicKeyPem (modulus_b64, exponent_b64) { + const modulus = Buffer.from(modulus_b64, 'base64') + const exponent = Buffer.from(exponent_b64, 'base64') + + let modulus_hex = modulus.toString('hex') + let exponent_hex = exponent.toString('hex') + + modulus_hex = prepadSigned(modulus_hex) + exponent_hex = prepadSigned(exponent_hex) + + const modlen = modulus_hex.length / 2 + const explen = exponent_hex.length / 2 + + const encoded_modlen = encodeLengthHex(modlen) + const encoded_explen = encodeLengthHex(explen) + const encoded_pubkey = '30' + + encodeLengthHex( + modlen + + explen + + encoded_modlen.length / 2 + + encoded_explen.length / 2 + 2 + ) + + '02' + encoded_modlen + modulus_hex + + '02' + encoded_explen + exponent_hex + + const der_b64 = Buffer.from(encoded_pubkey, 'hex').toString('base64') + + const pem = '-----BEGIN RSA PUBLIC KEY-----\n' + + der_b64.match(/.{1,64}/g).join('\n') + + '\n-----END RSA PUBLIC KEY-----\n' + + return pem +} + +function prepadSigned (hexStr) { + const msb = hexStr[0] + if (msb < '0' || msb > '7') { + return '00' + hexStr + } else { + return hexStr + } +} + +function toHex (number) { + const nstr = number.toString(16) + if (nstr.length % 2) return '0' + nstr + return nstr +} + +// encode ASN.1 DER length field +// if <=127, short form +// if >=128, long form +function encodeLengthHex (n) { + if (n <= 127) return toHex(n) + else { + const n_hex = toHex(n) + const length_of_length_byte = 128 + n_hex.length / 2 // 0x80+numbytes + return toHex(length_of_length_byte) + n_hex + } +} + +module.exports = rsaPublicKeyPem diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/index.js index 149c7de99cc214c10976e9728efd3b2f7f8a73f5..499265e47418c45867520714974451ae36784bba 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/index.js @@ -1,36 +1,36 @@ -const WxAccount = require('./weixin/account/index') -const QQAccount = require('./qq/account/index') -const AliAccount = require('./alipay/account/index') -const AppleAccount = require('./apple/account/index') - -const createApi = require('./share/create-api') - -module.exports = { - initWeixin: function () { - const oauthConfig = this.configUtils.getOauthConfig({ provider: 'weixin' }) - return createApi(WxAccount, { - appId: oauthConfig.appid, - secret: oauthConfig.appsecret - }) - }, - initQQ: function () { - const oauthConfig = this.configUtils.getOauthConfig({ provider: 'qq' }) - return createApi(QQAccount, { - appId: oauthConfig.appid, - secret: oauthConfig.appsecret - }) - }, - initAlipay: function () { - const oauthConfig = this.configUtils.getOauthConfig({ provider: 'alipay' }) - return createApi(AliAccount, { - appId: oauthConfig.appid, - privateKey: oauthConfig.privateKey - }) - }, - initApple: function () { - const oauthConfig = this.configUtils.getOauthConfig({ provider: 'apple' }) - return createApi(AppleAccount, { - bundleId: oauthConfig.bundleId - }) - } -} +const WxAccount = require('./weixin/account/index') +const QQAccount = require('./qq/account/index') +const AliAccount = require('./alipay/account/index') +const AppleAccount = require('./apple/account/index') + +const createApi = require('./share/create-api') + +module.exports = { + initWeixin: function () { + const oauthConfig = this.configUtils.getOauthConfig({ provider: 'weixin' }) + return createApi(WxAccount, { + appId: oauthConfig.appid, + secret: oauthConfig.appsecret + }) + }, + initQQ: function () { + const oauthConfig = this.configUtils.getOauthConfig({ provider: 'qq' }) + return createApi(QQAccount, { + appId: oauthConfig.appid, + secret: oauthConfig.appsecret + }) + }, + initAlipay: function () { + const oauthConfig = this.configUtils.getOauthConfig({ provider: 'alipay' }) + return createApi(AliAccount, { + appId: oauthConfig.appid, + privateKey: oauthConfig.privateKey + }) + }, + initApple: function () { + const oauthConfig = this.configUtils.getOauthConfig({ provider: 'apple' }) + return createApi(AppleAccount, { + bundleId: oauthConfig.bundleId + }) + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/qq/account/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/qq/account/index.js index 9b4879a0e1481e296f56425900278cf607bb59a0..35a1a335714e40e67290cabafc776ef3c6302afc 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/qq/account/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/qq/account/index.js @@ -1,97 +1,97 @@ -const { - UniCloudError -} = require('../../../../common/error') -const { - resolveUrl -} = require('../../../../common/utils') -const { - callQQOpenApi -} = require('../normalize') - -module.exports = class Auth { - constructor (options) { - this.options = Object.assign({ - baseUrl: 'https://graph.qq.com', - timeout: 5000 - }, options) - } - - async _requestQQOpenapi ({ name, url, data, options }) { - const defaultOptions = { - method: 'GET', - dataType: 'json', - dataAsQueryString: true, - timeout: this.options.timeout - } - const result = await callQQOpenApi({ - name: `auth.${name}`, - url: resolveUrl(this.options.baseUrl, url), - data, - options, - defaultOptions - }) - return result - } - - async getUserInfo ({ - accessToken, - openid - } = {}) { - const url = '/user/get_user_info' - const result = await this._requestQQOpenapi({ - name: 'getUserInfo', - url, - data: { - oauthConsumerKey: this.options.appId, - accessToken, - openid - } - }) - return { - nickname: result.nickname, - avatar: result.figureurl_qq_1 - } - } - - async getOpenidByToken ({ - accessToken - } = {}) { - const url = '/oauth2.0/me' - const result = await this._requestQQOpenapi({ - name: 'getOpenidByToken', - url, - data: { - accessToken, - unionid: 1, - fmt: 'json' - } - }) - if (result.clientId !== this.options.appId) { - throw new UniCloudError({ - code: 'APPID_NOT_MATCH', - message: 'appid not match' - }) - } - return { - openid: result.openid, - unionid: result.unionid - } - } - - async code2Session ({ - code - } = {}) { - const url = 'https://api.q.qq.com/sns/jscode2session' - const result = await this._requestQQOpenapi({ - name: 'getOpenidByToken', - url, - data: { - grant_type: 'authorization_code', - appid: this.options.appId, - secret: this.options.secret, - js_code: code - } - }) - return result - } -} +const { + UniCloudError +} = require('../../../../common/error') +const { + resolveUrl +} = require('../../../../common/utils') +const { + callQQOpenApi +} = require('../normalize') + +module.exports = class Auth { + constructor (options) { + this.options = Object.assign({ + baseUrl: 'https://graph.qq.com', + timeout: 5000 + }, options) + } + + async _requestQQOpenapi ({ name, url, data, options }) { + const defaultOptions = { + method: 'GET', + dataType: 'json', + dataAsQueryString: true, + timeout: this.options.timeout + } + const result = await callQQOpenApi({ + name: `auth.${name}`, + url: resolveUrl(this.options.baseUrl, url), + data, + options, + defaultOptions + }) + return result + } + + async getUserInfo ({ + accessToken, + openid + } = {}) { + const url = '/user/get_user_info' + const result = await this._requestQQOpenapi({ + name: 'getUserInfo', + url, + data: { + oauthConsumerKey: this.options.appId, + accessToken, + openid + } + }) + return { + nickname: result.nickname, + avatar: result.figureurl_qq_1 + } + } + + async getOpenidByToken ({ + accessToken + } = {}) { + const url = '/oauth2.0/me' + const result = await this._requestQQOpenapi({ + name: 'getOpenidByToken', + url, + data: { + accessToken, + unionid: 1, + fmt: 'json' + } + }) + if (result.clientId !== this.options.appId) { + throw new UniCloudError({ + code: 'APPID_NOT_MATCH', + message: 'appid not match' + }) + } + return { + openid: result.openid, + unionid: result.unionid + } + } + + async code2Session ({ + code + } = {}) { + const url = 'https://api.q.qq.com/sns/jscode2session' + const result = await this._requestQQOpenapi({ + name: 'getOpenidByToken', + url, + data: { + grant_type: 'authorization_code', + appid: this.options.appId, + secret: this.options.secret, + js_code: code + } + }) + return result + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/qq/normalize.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/qq/normalize.js index fcfdc1ef87ae27e8c3308fcf82d5cdb1404df89c..ca0ebe60dc991fd0c3e7e314f28e85e6fb2aa919 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/qq/normalize.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/qq/normalize.js @@ -1,85 +1,85 @@ -const { - UniCloudError -} = require('../../../common/error') -const { - camel2snakeJson, - snake2camelJson -} = require('../../../common/utils') - -function generateApiResult (apiName, data) { - if (data.ret || data.error) { - // 这三种都是qq的错误码规范 - const code = data.ret || data.error || data.errcode || -2 - const message = data.msg || data.error_description || data.errmsg || `${apiName} fail` - throw new UniCloudError({ - code, - message - }) - } else { - delete data.ret - delete data.msg - delete data.error - delete data.error_description - delete data.errcode - delete data.errmsg - return { - ...data, - errMsg: `${apiName} ok`, - errCode: 0 - } - } -} - -function nomalizeError (apiName, error) { - throw new UniCloudError({ - code: error.code || -2, - message: error.message || `${apiName} fail` - }) -} - -async function callQQOpenApi ({ - name, - url, - data, - options, - defaultOptions -}) { - options = Object.assign({}, defaultOptions, options, { data: camel2snakeJson(Object.assign({}, data)) }) - let result - try { - result = await uniCloud.httpclient.request(url, options) - } catch (e) { - return nomalizeError(name, e) - } - let resData = result.data - const contentType = result.headers['content-type'] - if ( - Buffer.isBuffer(resData) && - (contentType.indexOf('text/plain') === 0 || - contentType.indexOf('application/json') === 0) - ) { - try { - resData = JSON.parse(resData.toString()) - } catch (e) { - resData = resData.toString() - } - } else if (Buffer.isBuffer(resData)) { - resData = { - buffer: resData, - contentType - } - } - return snake2camelJson( - generateApiResult( - name, - resData || { - errCode: -2, - errMsg: 'Request failed' - } - ) - ) -} - -module.exports = { - callQQOpenApi -} +const { + UniCloudError +} = require('../../../common/error') +const { + camel2snakeJson, + snake2camelJson +} = require('../../../common/utils') + +function generateApiResult (apiName, data) { + if (data.ret || data.error) { + // 这三种都是qq的错误码规范 + const code = data.ret || data.error || data.errcode || -2 + const message = data.msg || data.error_description || data.errmsg || `${apiName} fail` + throw new UniCloudError({ + code, + message + }) + } else { + delete data.ret + delete data.msg + delete data.error + delete data.error_description + delete data.errcode + delete data.errmsg + return { + ...data, + errMsg: `${apiName} ok`, + errCode: 0 + } + } +} + +function nomalizeError (apiName, error) { + throw new UniCloudError({ + code: error.code || -2, + message: error.message || `${apiName} fail` + }) +} + +async function callQQOpenApi ({ + name, + url, + data, + options, + defaultOptions +}) { + options = Object.assign({}, defaultOptions, options, { data: camel2snakeJson(Object.assign({}, data)) }) + let result + try { + result = await uniCloud.httpclient.request(url, options) + } catch (e) { + return nomalizeError(name, e) + } + let resData = result.data + const contentType = result.headers['content-type'] + if ( + Buffer.isBuffer(resData) && + (contentType.indexOf('text/plain') === 0 || + contentType.indexOf('application/json') === 0) + ) { + try { + resData = JSON.parse(resData.toString()) + } catch (e) { + resData = resData.toString() + } + } else if (Buffer.isBuffer(resData)) { + resData = { + buffer: resData, + contentType + } + } + return snake2camelJson( + generateApiResult( + name, + resData || { + errCode: -2, + errMsg: 'Request failed' + } + ) + ) +} + +module.exports = { + callQQOpenApi +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/share/create-api.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/share/create-api.js index c58f1e8dbe1581767d15ffc6f141f5c8c63d4c8c..abb1f4146924e3dc7d57af656ffe59ac892718bf 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/share/create-api.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/share/create-api.js @@ -1,73 +1,73 @@ -const { - isFn, - isPlainObject -} = require('../../../common/utils') - -// 注意:不进行递归处理 -function parseParams (params = {}, rule) { - if (!rule || !params) { - return params - } - const internalKeys = ['_pre', '_purify', '_post'] - // 转换之前的处理 - if (rule._pre) { - params = rule._pre(params) - } - // 净化参数 - let purify = { shouldDelete: new Set([]) } - if (rule._purify) { - const _purify = rule._purify - for (const purifyKey in _purify) { - _purify[purifyKey] = new Set(_purify[purifyKey]) - } - purify = Object.assign(purify, _purify) - } - if (isPlainObject(rule)) { - for (const key in rule) { - const parser = rule[key] - if (isFn(parser) && internalKeys.indexOf(key) === -1) { - params[key] = parser(params) - } else if (typeof parser === 'string' && internalKeys.indexOf(key) === -1) { - // 直接转换属性名称的删除旧属性名 - params[key] = params[parser] - purify.shouldDelete.add(parser) - } - } - } else if (isFn(rule)) { - params = rule(params) - } - - if (purify.shouldDelete) { - for (const item of purify.shouldDelete) { - delete params[item] - } - } - - // 转换之后的处理 - if (rule._post) { - params = rule._post(params) - } - - return params -} - -function createApi (ApiClass, options) { - const apiInstance = new ApiClass(options) - return new Proxy(apiInstance, { - get: function (obj, prop) { - if (typeof obj[prop] === 'function' && prop.indexOf('_') !== 0 && obj._protocols && obj._protocols[prop]) { - const protocol = obj._protocols[prop] - return async function (params) { - params = parseParams(params, protocol.args) - let result = await obj[prop](params) - result = parseParams(result, protocol.returnValue) - return result - } - } else { - return obj[prop] - } - } - }) -} - -module.exports = createApi +const { + isFn, + isPlainObject +} = require('../../../common/utils') + +// 注意:不进行递归处理 +function parseParams (params = {}, rule) { + if (!rule || !params) { + return params + } + const internalKeys = ['_pre', '_purify', '_post'] + // 转换之前的处理 + if (rule._pre) { + params = rule._pre(params) + } + // 净化参数 + let purify = { shouldDelete: new Set([]) } + if (rule._purify) { + const _purify = rule._purify + for (const purifyKey in _purify) { + _purify[purifyKey] = new Set(_purify[purifyKey]) + } + purify = Object.assign(purify, _purify) + } + if (isPlainObject(rule)) { + for (const key in rule) { + const parser = rule[key] + if (isFn(parser) && internalKeys.indexOf(key) === -1) { + params[key] = parser(params) + } else if (typeof parser === 'string' && internalKeys.indexOf(key) === -1) { + // 直接转换属性名称的删除旧属性名 + params[key] = params[parser] + purify.shouldDelete.add(parser) + } + } + } else if (isFn(rule)) { + params = rule(params) + } + + if (purify.shouldDelete) { + for (const item of purify.shouldDelete) { + delete params[item] + } + } + + // 转换之后的处理 + if (rule._post) { + params = rule._post(params) + } + + return params +} + +function createApi (ApiClass, options) { + const apiInstance = new ApiClass(options) + return new Proxy(apiInstance, { + get: function (obj, prop) { + if (typeof obj[prop] === 'function' && prop.indexOf('_') !== 0 && obj._protocols && obj._protocols[prop]) { + const protocol = obj._protocols[prop] + return async function (params) { + params = parseParams(params, protocol.args) + let result = await obj[prop](params) + result = parseParams(result, protocol.returnValue) + return result + } + } else { + return obj[prop] + } + } + }) +} + +module.exports = createApi diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/account/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/account/index.js index 5fafc78e2869937b7ea83579f7eff2cd21b55b82..734f6423b3fead834cd296796ec66281ffe0b5ec 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/account/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/account/index.js @@ -1,89 +1,111 @@ -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 - } - } -} +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 + } + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/normalize.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/normalize.js index 908d916dc6349e5cb326d4f1b8927f24faed9b3c..9749c3838ddb96d7119d99ad65f438df9b612ea3 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/normalize.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/normalize.js @@ -1,95 +1,95 @@ -const { - UniCloudError -} = require('../../../common/error') -const { - camel2snakeJson, snake2camelJson -} = require('../../../common/utils') - -function generateApiResult (apiName, data) { - if (data.errcode) { - throw new UniCloudError({ - code: data.errcode || -2, - message: data.errmsg || `${apiName} fail` - }) - } else { - delete data.errcode - delete data.errmsg - return { - ...data, - errMsg: `${apiName} ok`, - errCode: 0 - } - } -} - -function nomalizeError (apiName, error) { - throw new UniCloudError({ - code: error.code || -2, - message: error.message || `${apiName} fail` - }) -} - -// 微信openapi接口接收蛇形(snake case)参数返回蛇形参数,这里进行转化,如果是formdata里面的参数需要在对应api实现时就转为蛇形 -async function callWxOpenApi ({ - name, - url, - data, - options, - defaultOptions -}) { - let result = {} - // 获取二维码的接口wxacode.get和wxacode.getUnlimited不可以传入access_token(可能有其他接口也不可以),否则会返回data format error - const dataCopy = camel2snakeJson(Object.assign({}, data)) - if (dataCopy && dataCopy.access_token) { - delete dataCopy.access_token - } - try { - options = Object.assign({}, defaultOptions, options, { data: dataCopy }) - result = await uniCloud.httpclient.request(url, options) - } catch (e) { - return nomalizeError(name, e) - } - - // 有几个接口成功返回buffer失败返回json,对这些接口统一成返回buffer,然后分别解析 - let resData = result.data - const contentType = result.headers['content-type'] - if ( - Buffer.isBuffer(resData) && - (contentType.indexOf('text/plain') === 0 || - contentType.indexOf('application/json') === 0) - ) { - try { - resData = JSON.parse(resData.toString()) - } catch (e) { - resData = resData.toString() - } - } else if (Buffer.isBuffer(resData)) { - resData = { - buffer: resData, - contentType - } - } - return snake2camelJson( - generateApiResult( - name, - resData || { - errCode: -2, - errMsg: 'Request failed' - } - ) - ) -} - -function buildUrl (url, data) { - let query = '' - if (data && data.accessToken) { - const divider = url.indexOf('?') > -1 ? '&' : '?' - query = `${divider}access_token=${data.accessToken}` - } - return `${url}${query}` -} - -module.exports = { - callWxOpenApi, - buildUrl -} +const { + UniCloudError +} = require('../../../common/error') +const { + camel2snakeJson, snake2camelJson +} = require('../../../common/utils') + +function generateApiResult (apiName, data) { + if (data.errcode) { + throw new UniCloudError({ + code: data.errcode || -2, + message: data.errmsg || `${apiName} fail` + }) + } else { + delete data.errcode + delete data.errmsg + return { + ...data, + errMsg: `${apiName} ok`, + errCode: 0 + } + } +} + +function nomalizeError (apiName, error) { + throw new UniCloudError({ + code: error.code || -2, + message: error.message || `${apiName} fail` + }) +} + +// 微信openapi接口接收蛇形(snake case)参数返回蛇形参数,这里进行转化,如果是formdata里面的参数需要在对应api实现时就转为蛇形 +async function callWxOpenApi ({ + name, + url, + data, + options, + defaultOptions +}) { + let result = {} + // 获取二维码的接口wxacode.get和wxacode.getUnlimited不可以传入access_token(可能有其他接口也不可以),否则会返回data format error + const dataCopy = camel2snakeJson(Object.assign({}, data)) + if (dataCopy && dataCopy.access_token) { + delete dataCopy.access_token + } + try { + options = Object.assign({}, defaultOptions, options, { data: dataCopy }) + result = await uniCloud.httpclient.request(url, options) + } catch (e) { + return nomalizeError(name, e) + } + + // 有几个接口成功返回buffer失败返回json,对这些接口统一成返回buffer,然后分别解析 + let resData = result.data + const contentType = result.headers['content-type'] + if ( + Buffer.isBuffer(resData) && + (contentType.indexOf('text/plain') === 0 || + contentType.indexOf('application/json') === 0) + ) { + try { + resData = JSON.parse(resData.toString()) + } catch (e) { + resData = resData.toString() + } + } else if (Buffer.isBuffer(resData)) { + resData = { + buffer: resData, + contentType + } + } + return snake2camelJson( + generateApiResult( + name, + resData || { + errCode: -2, + errMsg: 'Request failed' + } + ) + ) +} + +function buildUrl (url, data) { + let query = '' + if (data && data.accessToken) { + const divider = url.indexOf('?') > -1 ? '&' : '?' + query = `${divider}access_token=${data.accessToken}` + } + return `${url}${query}` +} + +module.exports = { + callWxOpenApi, + buildUrl +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/utils.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/utils.js index c1410169a68fe4ffca80d7949d3e54dcd0479b2b..acb053adfd6ab490e06695939150fefcfabb8019 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/utils.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/third-party/weixin/utils.js @@ -1,87 +1,87 @@ -const crypto = require('crypto') -const { - isPlainObject -} = require('../../../common/utils') - -// 退款通知解密key=md5(key) -function decryptData (encryptedData, key, iv = '') { - // 解密 - const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv) - // 设置自动 padding 为 true,删除填充补位 - decipher.setAutoPadding(true) - let decoded = decipher.update(encryptedData, 'base64', 'utf8') - decoded += decipher.final('utf8') - return decoded -} - -function md5 (str, encoding = 'utf8') { - return crypto - .createHash('md5') - .update(str, encoding) - .digest('hex') -} - -function sha256 (str, key, encoding = 'utf8') { - return crypto - .createHmac('sha256', key) - .update(str, encoding) - .digest('hex') -} - -function getSignStr (obj) { - return Object.keys(obj) - .filter(key => key !== 'sign' && obj[key] !== undefined && obj[key] !== '') - .sort() - .map(key => key + '=' + obj[key]) - .join('&') -} - -function getNonceStr (length = 16) { - let str = '' - while (str.length < length) { - str += Math.random().toString(32).substring(2) - } - return str.substring(0, length) -} - -// 简易版Object转XML,只可在微信支付时使用,不支持嵌套 -function buildXML (obj, rootName = 'xml') { - const content = Object.keys(obj).map(item => { - if (isPlainObject(obj[item])) { - return `<${item}>` - } else { - return `<${item}>` - } - }) - return `<${rootName}>${content.join('')}` -} - -function isXML (str) { - const reg = /^(<\?xml.*\?>)?(\r?\n)*(.|\r?\n)*<\/xml>$/i - return reg.test(str.trim()) -}; - -// 简易版XML转Object,只可在微信支付时使用,不支持嵌套 -function parseXML (xml) { - const xmlReg = /<(?:xml|root).*?>([\s|\S]*)<\/(?:xml|root)>/ - const str = xmlReg.exec(xml)[1] - const obj = {} - const nodeReg = /<(.*?)>(?:){0,1}<\/.*?>/g - let matches = null - // eslint-disable-next-line no-cond-assign - while ((matches = nodeReg.exec(str))) { - obj[matches[1]] = matches[2] - } - return obj -} - -module.exports = { - decryptData, - md5, - sha256, - getSignStr, - getNonceStr, - buildXML, - parseXML, - isXML -} +const crypto = require('crypto') +const { + isPlainObject +} = require('../../../common/utils') + +// 退款通知解密key=md5(key) +function decryptData (encryptedData, key, iv = '') { + // 解密 + const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv) + // 设置自动 padding 为 true,删除填充补位 + decipher.setAutoPadding(true) + let decoded = decipher.update(encryptedData, 'base64', 'utf8') + decoded += decipher.final('utf8') + return decoded +} + +function md5 (str, encoding = 'utf8') { + return crypto + .createHash('md5') + .update(str, encoding) + .digest('hex') +} + +function sha256 (str, key, encoding = 'utf8') { + return crypto + .createHmac('sha256', key) + .update(str, encoding) + .digest('hex') +} + +function getSignStr (obj) { + return Object.keys(obj) + .filter(key => key !== 'sign' && obj[key] !== undefined && obj[key] !== '') + .sort() + .map(key => key + '=' + obj[key]) + .join('&') +} + +function getNonceStr (length = 16) { + let str = '' + while (str.length < length) { + str += Math.random().toString(32).substring(2) + } + return str.substring(0, length) +} + +// 简易版Object转XML,只可在微信支付时使用,不支持嵌套 +function buildXML (obj, rootName = 'xml') { + const content = Object.keys(obj).map(item => { + if (isPlainObject(obj[item])) { + return `<${item}>` + } else { + return `<${item}>` + } + }) + return `<${rootName}>${content.join('')}` +} + +function isXML (str) { + const reg = /^(<\?xml.*\?>)?(\r?\n)*(.|\r?\n)*<\/xml>$/i + return reg.test(str.trim()) +}; + +// 简易版XML转Object,只可在微信支付时使用,不支持嵌套 +function parseXML (xml) { + const xmlReg = /<(?:xml|root).*?>([\s|\S]*)<\/(?:xml|root)>/ + const str = xmlReg.exec(xml)[1] + const obj = {} + const nodeReg = /<(.*?)>(?:){0,1}<\/.*?>/g + let matches = null + // eslint-disable-next-line no-cond-assign + while ((matches = nodeReg.exec(str))) { + obj[matches[1]] = matches[2] + } + return obj +} + +module.exports = { + decryptData, + md5, + sha256, + getSignStr, + getNonceStr, + buildXML, + parseXML, + isXML +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/account.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/account.js index c62e3ebff4ea6dc8673aaff6d46c529231b5ecbe..bc87e02997d69c099aee03025a77d069caf96b25 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/account.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/account.js @@ -1,130 +1,130 @@ -const { - db, - dbCmd, - userCollection -} = require('../../common/constants') -const { - USER_IDENTIFIER -} = require('../../common/constants') -const { - batchFindObjctValue, - getType -} = require('../../common/utils') - -/** - * 查询满足条件的用户 - * @param {Object} params - * @param {Object} params.userQuery 用户唯一标识组成的查询条件 - * @param {Object} params.authorizedApp 用户允许登录的应用 - * @returns userMatched 满足条件的用户列表 - */ -async function findUser (params = {}) { - const { - userQuery, - authorizedApp = [] - } = params - const condition = getUserQueryCondition(userQuery) - if (condition.length === 0) { - throw new Error('Invalid user query') - } - const authorizedAppType = getType(authorizedApp) - let appQuery = null - if (authorizedAppType === 'string') { - // 传入authorizedApp为单个appId时 - appQuery = dbCmd.or( - { - dcloud_appid: authorizedApp - }, - { - dcloud_appid: dbCmd.exists(false) - } - ) - } else if (authorizedAppType === 'array') { - if (authorizedApp.length === 0) { - // 传入空数组表示希望获取不能登录任一客户端的用户 - appQuery = { - dcloud_appid: [] - } - } else if (authorizedApp.length === 1) { - appQuery = dbCmd.or( - { - dcloud_appid: authorizedApp[0] - }, - { - dcloud_appid: dbCmd.exists(false) - } - ) - } else { - appQuery = dbCmd.or( - { - dcloud_appid: db.command.in(authorizedApp) - }, - { - dcloud_appid: dbCmd.exists(false) - } - ) - } - } else { - throw new Error('Invalid authorized app') - } - - let finalQuery - - if (condition.length === 1) { - finalQuery = dbCmd.and(condition[0], appQuery) - } else { - finalQuery = dbCmd.and( - dbCmd.or(condition), - appQuery - ) - } - const userQueryRes = await userCollection.where(finalQuery).get() - return userQueryRes.data -} - -function getUserIdentifier (userRecord = {}) { - const keys = Object.keys(USER_IDENTIFIER) - return batchFindObjctValue(userRecord, keys) -} - -function getUserQueryCondition (userRecord = {}) { - const userIdentifier = getUserIdentifier(userRecord) - const condition = [] - for (const key in userIdentifier) { - const value = userIdentifier[key] - if (!value) { - // 过滤所有value为假值的条件,在查询用户时没有意义 - continue - } - const queryItem = { - [key]: value - } - // 为兼容用户老数据用户名及邮箱需要同时查小写及原始大小写数据 - if (key === 'mobile') { - queryItem.mobile_confirmed = 1 - } else if (key === 'email') { - queryItem.email_confirmed = 1 - const email = userIdentifier.email - if (email.toLowerCase() !== email) { - condition.push({ - email: email.toLowerCase(), - email_confirmed: 1 - }) - } - } else if (key === 'username') { - const username = userIdentifier.username - if (username.toLowerCase() !== username) { - condition.push({ - username: username.toLowerCase() - }) - } - } - condition.push(queryItem) - } - return condition -} - -module.exports = { - findUser, - getUserIdentifier -} +const { + db, + dbCmd, + userCollection +} = require('../../common/constants') +const { + USER_IDENTIFIER +} = require('../../common/constants') +const { + batchFindObjctValue, + getType +} = require('../../common/utils') + +/** + * 查询满足条件的用户 + * @param {Object} params + * @param {Object} params.userQuery 用户唯一标识组成的查询条件 + * @param {Object} params.authorizedApp 用户允许登录的应用 + * @returns userMatched 满足条件的用户列表 + */ +async function findUser (params = {}) { + const { + userQuery, + authorizedApp = [] + } = params + const condition = getUserQueryCondition(userQuery) + if (condition.length === 0) { + throw new Error('Invalid user query') + } + const authorizedAppType = getType(authorizedApp) + let appQuery = null + if (authorizedAppType === 'string') { + // 传入authorizedApp为单个appId时 + appQuery = dbCmd.or( + { + dcloud_appid: authorizedApp + }, + { + dcloud_appid: dbCmd.exists(false) + } + ) + } else if (authorizedAppType === 'array') { + if (authorizedApp.length === 0) { + // 传入空数组表示希望获取不能登录任一客户端的用户 + appQuery = { + dcloud_appid: [] + } + } else if (authorizedApp.length === 1) { + appQuery = dbCmd.or( + { + dcloud_appid: authorizedApp[0] + }, + { + dcloud_appid: dbCmd.exists(false) + } + ) + } else { + appQuery = dbCmd.or( + { + dcloud_appid: db.command.in(authorizedApp) + }, + { + dcloud_appid: dbCmd.exists(false) + } + ) + } + } else { + throw new Error('Invalid authorized app') + } + + let finalQuery + + if (condition.length === 1) { + finalQuery = dbCmd.and(condition[0], appQuery) + } else { + finalQuery = dbCmd.and( + dbCmd.or(condition), + appQuery + ) + } + const userQueryRes = await userCollection.where(finalQuery).get() + return userQueryRes.data +} + +function getUserIdentifier (userRecord = {}) { + const keys = Object.keys(USER_IDENTIFIER) + return batchFindObjctValue(userRecord, keys) +} + +function getUserQueryCondition (userRecord = {}) { + const userIdentifier = getUserIdentifier(userRecord) + const condition = [] + for (const key in userIdentifier) { + const value = userIdentifier[key] + if (!value) { + // 过滤所有value为假值的条件,在查询用户时没有意义 + continue + } + const queryItem = { + [key]: value + } + // 为兼容用户老数据用户名及邮箱需要同时查小写及原始大小写数据 + if (key === 'mobile') { + queryItem.mobile_confirmed = 1 + } else if (key === 'email') { + queryItem.email_confirmed = 1 + const email = userIdentifier.email + if (email.toLowerCase() !== email) { + condition.push({ + email: email.toLowerCase(), + email_confirmed: 1 + }) + } + } else if (key === 'username') { + const username = userIdentifier.username + if (username.toLowerCase() !== username) { + condition.push({ + username: username.toLowerCase() + }) + } + } + condition.push(queryItem) + } + return condition +} + +module.exports = { + findUser, + getUserIdentifier +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/captcha.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/captcha.js index 4618fa5de27025243b116cac144618eb0ab37550..726f40608c3ede4c53ecfccf6fd962b8eac56c6a 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/captcha.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/captcha.js @@ -1,76 +1,76 @@ -const { - ERROR -} = require('../../common/error') - -async function getNeedCaptcha ({ - uid, - username, - mobile, - email, - type = 'login', - limitDuration = 7200000, // 两小时 - limitTimes = 3 // 记录次数 -} = {}) { - const db = uniCloud.database() - const dbCmd = db.command - // 当用户最近“2小时内(limitDuration)”登录失败达到3次(limitTimes)时。要求用户提交验证码 - const now = Date.now() - const uniIdLogCollection = db.collection('uni-id-log') - const userIdentifier = { - user_id: uid, - username, - mobile, - email - } - - let totalKey = 0; let deleteKey = 0 - for (const key in userIdentifier) { - totalKey++ - if (!userIdentifier[key] || typeof userIdentifier[key] !== 'string') { - deleteKey++ - delete userIdentifier[key] - } - } - - if (deleteKey === totalKey) { - throw new Error('System error') // 正常情况下不会进入此条件,但是考虑到后续会有其他开发者修改此云对象,在此处做一个判断 - } - - const { - data: recentRecord - } = await uniIdLogCollection.where({ - ip: this.getClientInfo().clientIP, - ...userIdentifier, - type, - create_date: dbCmd.gt(now - limitDuration) - }) - .orderBy('create_date', 'desc') - .limit(limitTimes) - .get() - return recentRecord.length === limitTimes && recentRecord.every(item => item.state === 0) -} - -async function verifyCaptcha (params = {}) { - const { - captcha, - scene - } = params - if (!captcha) { - throw { - errCode: ERROR.CAPTCHA_REQUIRED - } - } - const payload = await this.uniCaptcha.verify({ - deviceId: this.getClientInfo().deviceId, - captcha, - scene - }) - if (payload.errCode) { - throw payload - } -} - -module.exports = { - getNeedCaptcha, - verifyCaptcha -} +const { + ERROR +} = require('../../common/error') + +async function getNeedCaptcha ({ + uid, + username, + mobile, + email, + type = 'login', + limitDuration = 7200000, // 两小时 + limitTimes = 3 // 记录次数 +} = {}) { + const db = uniCloud.database() + const dbCmd = db.command + // 当用户最近“2小时内(limitDuration)”登录失败达到3次(limitTimes)时。要求用户提交验证码 + const now = Date.now() + const uniIdLogCollection = db.collection('uni-id-log') + const userIdentifier = { + user_id: uid, + username, + mobile, + email + } + + let totalKey = 0; let deleteKey = 0 + for (const key in userIdentifier) { + totalKey++ + if (!userIdentifier[key] || typeof userIdentifier[key] !== 'string') { + deleteKey++ + delete userIdentifier[key] + } + } + + if (deleteKey === totalKey) { + throw new Error('System error') // 正常情况下不会进入此条件,但是考虑到后续会有其他开发者修改此云对象,在此处做一个判断 + } + + const { + data: recentRecord + } = await uniIdLogCollection.where({ + ip: this.getClientInfo().clientIP, + ...userIdentifier, + type, + create_date: dbCmd.gt(now - limitDuration) + }) + .orderBy('create_date', 'desc') + .limit(limitTimes) + .get() + return recentRecord.length === limitTimes && recentRecord.every(item => item.state === 0) +} + +async function verifyCaptcha (params = {}) { + const { + captcha, + scene + } = params + if (!captcha) { + throw { + errCode: ERROR.CAPTCHA_REQUIRED + } + } + const payload = await this.uniCaptcha.verify({ + deviceId: this.getClientInfo().deviceId, + captcha, + scene + }) + if (payload.errCode) { + throw payload + } +} + +module.exports = { + getNeedCaptcha, + verifyCaptcha +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/config.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/config.js index fdc71605c3a85cc8570d8ef547635c27bab917d2..47416bec0c0cd9e5401d0d861a58ecefc7a4539e 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/config.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/config.js @@ -1,135 +1,135 @@ -const { - getWeixinPlatform -} = require('./weixin') -const createConfig = require('uni-config-center') - -const requiredConfig = { - 'web.weixin-h5': ['appid', 'appsecret'], - 'web.weixin-web': ['appid', 'appsecret'], - 'app.weixin': ['appid', 'appsecret'], - 'mp-weixin.weixin': ['appid', 'appsecret'], - 'app.qq': ['appid', 'appsecret'], - 'mp-alipay.alipay': ['appid', 'privateKey'], - 'app.apple': ['bundleId'] -} - -const uniIdConfig = createConfig({ - pluginId: 'uni-id' -}) - -class ConfigUtils { - constructor ({ - context - } = {}) { - this.context = context - this.clientInfo = context.getClientInfo() - const { - appId, - uniPlatform - } = this.clientInfo - this.appId = appId - switch (uniPlatform) { - case 'app': - case 'app-plus': - this.platform = 'app' - break - case 'web': - case 'h5': - this.platform = 'web' - break - default: - this.platform = uniPlatform - break - } - } - - getConfigArray () { - let configContent - try { - configContent = require('uni-config-center/uni-id/config.json') - } catch (error) { - throw new Error('Invalid config file\n' + error.message) - } - if (configContent[0]) { - return Object.values(configContent) - } - configContent.isDefaultConfig = true - return [configContent] - } - - getAppConfig () { - const configArray = this.getConfigArray() - return configArray.find(item => item.dcloudAppid === this.appId) || configArray.find(item => item.isDefaultConfig) - } - - getPlatformConfig () { - const appConfig = this.getAppConfig() - if (!appConfig) { - throw new Error( - `Config for current app (${this.appId}) was not found, please check your config file or client appId`) - } - const platform = this.platform - if ( - (this.platform === 'app' && appConfig['app-plus']) || - (this.platform === 'web' && appConfig.h5) - ) { - throw new Error( - `Client platform is ${this.platform}, but ${this.platform === 'web' ? 'h5' : 'app-plus'} was found in config. Please refer to: https://uniapp.dcloud.net.cn/uniCloud/uni-id-summary?id=m-to-co` - ) - } - - const defaultConfig = { - tokenExpiresIn: 7200, - tokenExpiresThreshold: 1200, - passwordErrorLimit: 6, - passwordErrorRetryTime: 3600 - } - return Object.assign(defaultConfig, appConfig, appConfig[platform]) - } - - getOauthProvider ({ - provider - } = {}) { - const clientPlatform = this.platform - let oatuhProivder = provider - if (provider === 'weixin' && clientPlatform === 'web') { - const weixinPlatform = getWeixinPlatform.call(this.context) - if (weixinPlatform === 'h5' || weixinPlatform === 'web') { - oatuhProivder = 'weixin-' + weixinPlatform // weixin-h5 公众号,weixin-web pc端 - } - } - return oatuhProivder - } - - getOauthConfig ({ - provider - } = {}) { - const config = this.getPlatformConfig() - const clientPlatform = this.platform - const oatuhProivder = this.getOauthProvider({ - provider - }) - const requireConfigKey = requiredConfig[`${clientPlatform}.${oatuhProivder}`] || [] - if (!config.oauth || !config.oauth[oatuhProivder]) { - throw new Error(`Config param required: ${clientPlatform}.oauth.${oatuhProivder}`) - } - const oauthConfig = config.oauth[oatuhProivder] - requireConfigKey.forEach((item) => { - if (!oauthConfig[item]) { - throw new Error(`Config param required: ${clientPlatform}.oauth.${oatuhProivder}.${item}`) - } - }) - return oauthConfig - } - - getHooks () { - if (uniIdConfig.hasFile('hooks/index.js')) { - return require( - uniIdConfig.resolve('hooks/index.js') - ) - } - return {} - } -} - -module.exports = ConfigUtils +const { + getWeixinPlatform +} = require('./weixin') +const createConfig = require('uni-config-center') + +const requiredConfig = { + 'web.weixin-h5': ['appid', 'appsecret'], + 'web.weixin-web': ['appid', 'appsecret'], + 'app.weixin': ['appid', 'appsecret'], + 'mp-weixin.weixin': ['appid', 'appsecret'], + 'app.qq': ['appid', 'appsecret'], + 'mp-alipay.alipay': ['appid', 'privateKey'], + 'app.apple': ['bundleId'] +} + +const uniIdConfig = createConfig({ + pluginId: 'uni-id' +}) + +class ConfigUtils { + constructor ({ + context + } = {}) { + this.context = context + this.clientInfo = context.getClientInfo() + const { + appId, + uniPlatform + } = this.clientInfo + this.appId = appId + switch (uniPlatform) { + case 'app': + case 'app-plus': + this.platform = 'app' + break + case 'web': + case 'h5': + this.platform = 'web' + break + default: + this.platform = uniPlatform + break + } + } + + getConfigArray () { + let configContent + try { + configContent = require('uni-config-center/uni-id/config.json') + } catch (error) { + throw new Error('Invalid config file\n' + error.message) + } + if (configContent[0]) { + return Object.values(configContent) + } + configContent.isDefaultConfig = true + return [configContent] + } + + getAppConfig () { + const configArray = this.getConfigArray() + return configArray.find(item => item.dcloudAppid === this.appId) || configArray.find(item => item.isDefaultConfig) + } + + getPlatformConfig () { + const appConfig = this.getAppConfig() + if (!appConfig) { + throw new Error( + `Config for current app (${this.appId}) was not found, please check your config file or client appId`) + } + const platform = this.platform + if ( + (this.platform === 'app' && appConfig['app-plus']) || + (this.platform === 'web' && appConfig.h5) + ) { + throw new Error( + `Client platform is ${this.platform}, but ${this.platform === 'web' ? 'h5' : 'app-plus'} was found in config. Please refer to: https://uniapp.dcloud.net.cn/uniCloud/uni-id-summary?id=m-to-co` + ) + } + + const defaultConfig = { + tokenExpiresIn: 7200, + tokenExpiresThreshold: 1200, + passwordErrorLimit: 6, + passwordErrorRetryTime: 3600 + } + return Object.assign(defaultConfig, appConfig, appConfig[platform]) + } + + getOauthProvider ({ + provider + } = {}) { + const clientPlatform = this.platform + let oatuhProivder = provider + if (provider === 'weixin' && clientPlatform === 'web') { + const weixinPlatform = getWeixinPlatform.call(this.context) + if (weixinPlatform === 'h5' || weixinPlatform === 'web') { + oatuhProivder = 'weixin-' + weixinPlatform // weixin-h5 公众号,weixin-web pc端 + } + } + return oatuhProivder + } + + getOauthConfig ({ + provider + } = {}) { + const config = this.getPlatformConfig() + const clientPlatform = this.platform + const oatuhProivder = this.getOauthProvider({ + provider + }) + const requireConfigKey = requiredConfig[`${clientPlatform}.${oatuhProivder}`] || [] + if (!config.oauth || !config.oauth[oatuhProivder]) { + throw new Error(`Config param required: ${clientPlatform}.oauth.${oatuhProivder}`) + } + const oauthConfig = config.oauth[oatuhProivder] + requireConfigKey.forEach((item) => { + if (!oauthConfig[item]) { + throw new Error(`Config param required: ${clientPlatform}.oauth.${oatuhProivder}.${item}`) + } + }) + return oauthConfig + } + + getHooks () { + if (uniIdConfig.hasFile('hooks/index.js')) { + return require( + uniIdConfig.resolve('hooks/index.js') + ) + } + return {} + } +} + +module.exports = ConfigUtils diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/fission.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/fission.js index 84233c3ed8bb311680ac13d23e7dbcaa50564bf7..65d48e27e3d81e0bcad2340fb07c7a4b695295e1 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/fission.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/fission.js @@ -1,192 +1,192 @@ -const { - dbCmd, - userCollection -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') -/** - * 获取随机邀请码,邀请码由大写字母加数字组成,由于存在手动输入邀请码的场景,从可选字符中去除 0、1、I、O - * @param {number} len 邀请码长度,默认6位 - * @returns {string} 随机邀请码 - */ -function getRandomInviteCode (len = 6) { - const charArr = ['2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] - let code = '' - for (let i = 0; i < len; i++) { - code += charArr[Math.floor(Math.random() * charArr.length)] - } - return code -} - -/** - * 获取可用的邀请码,至多尝试十次以获取可用邀请码。从10亿可选值中随机,碰撞概率较低 - * 也有其他方案可以尝试,比如在数据库内设置一个从0开始计数的数字,每次调用此方法时使用updateAndReturn使数字加1并返回加1后的值,根据这个值生成对应的邀请码,比如(22222A + 1 == 22222B),此方式性能理论更好,但是不适用于旧项目 - * @param {object} param - * @param {string} param.inviteCode 初始随机邀请码 - */ -async function getValidInviteCode () { - let retry = 10 - let code - let codeValid = false - while (retry > 0 && !codeValid) { - retry-- - code = getRandomInviteCode() - const getUserRes = await userCollection.where({ - my_invite_code: code - }).limit(1).get() - if (getUserRes.data.length === 0) { - codeValid = true - break - } - } - if (!codeValid) { - throw { - errCode: ERROR.SET_INVITE_CODE_FAILED - } - } - return code -} - -/** - * 根据邀请码查询邀请人 - * @param {object} param - * @param {string} param.inviteCode 邀请码 - * @param {string} param.queryUid 受邀人id,非空时校验不可被下家或自己邀请 - * @returns - */ -async function findUserByInviteCode ({ - inviteCode, - queryUid -} = {}) { - if (typeof inviteCode !== 'string') { - throw { - errCode: ERROR.SYSTEM_ERROR - } - } - // 根据邀请码查询邀请人 - let getInviterRes - if (queryUid) { - getInviterRes = await userCollection.where({ - _id: dbCmd.neq(queryUid), - inviter_uid: dbCmd.not(dbCmd.all([queryUid])), - my_invite_code: inviteCode - }).get() - } else { - getInviterRes = await userCollection.where({ - my_invite_code: inviteCode - }).get() - } - if (getInviterRes.data.length > 1) { - // 正常情况下不可能进入此条件,以防用户自行修改数据库出错,在此做出判断 - throw { - errCode: ERROR.SYSTEM_ERROR - } - } - const inviterRecord = getInviterRes.data[0] - if (!inviterRecord) { - throw { - errCode: ERROR.INVALID_INVITE_CODE - } - } - return inviterRecord -} - -/** - * 根据邀请码生成邀请信息 - * @param {object} param - * @param {string} param.inviteCode 邀请码 - * @param {string} param.queryUid 受邀人id,非空时校验不可被下家或自己邀请 - * @returns - */ -async function generateInviteInfo ({ - inviteCode, - queryUid -} = {}) { - const inviterRecord = await findUserByInviteCode({ - inviteCode, - queryUid - }) - // 倒叙拼接当前用户邀请链 - const inviterUid = inviterRecord.inviter_uid || [] - inviterUid.unshift(inviterRecord._id) - return { - inviterUid, - inviteTime: Date.now() - } -} - -/** - * 检查当前用户是否可以接受邀请,如果可以返回用户记录 - * @param {string} uid - */ -async function checkInviteInfo (uid) { - // 检查当前用户是否已有邀请人 - const getUserRes = await userCollection.doc(uid).field({ - my_invite_code: true, - inviter_uid: true - }).get() - const userRecord = getUserRes.data[0] - if (!userRecord) { - throw { - errCode: ERROR.ACCOUNT_NOT_EXISTS - } - } - if (userRecord.inviter_uid && userRecord.inviter_uid.length > 0) { - throw { - errCode: ERROR.CHANGE_INVITER_FORBIDDEN - } - } - return userRecord -} - -/** - * 指定用户接受邀请码邀请 - * @param {object} param - * @param {string} param.uid 用户uid - * @param {string} param.inviteCode 邀请人的邀请码 - * @returns - */ -async function acceptInvite ({ - uid, - inviteCode -} = {}) { - await checkInviteInfo(uid) - const { - inviterUid, - inviteTime - } = await generateInviteInfo({ - inviteCode, - queryUid: uid - }) - - if (inviterUid === uid) { - throw { - errCode: ERROR.INVALID_INVITE_CODE - } - } - - // 更新当前用户的邀请人信息 - await userCollection.doc(uid).update({ - inviter_uid: inviterUid, - invite_time: inviteTime - }) - - // 更新当前用户邀请的用户的邀请人信息,这步可能较为耗时 - await userCollection.where({ - inviter_uid: uid - }).update({ - inviter_uid: dbCmd.push(inviterUid) - }) - - return { - errCode: 0, - errMsg: '' - } -} - -module.exports = { - acceptInvite, - generateInviteInfo, - getValidInviteCode -} +const { + dbCmd, + userCollection +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') +/** + * 获取随机邀请码,邀请码由大写字母加数字组成,由于存在手动输入邀请码的场景,从可选字符中去除 0、1、I、O + * @param {number} len 邀请码长度,默认6位 + * @returns {string} 随机邀请码 + */ +function getRandomInviteCode (len = 6) { + const charArr = ['2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] + let code = '' + for (let i = 0; i < len; i++) { + code += charArr[Math.floor(Math.random() * charArr.length)] + } + return code +} + +/** + * 获取可用的邀请码,至多尝试十次以获取可用邀请码。从10亿可选值中随机,碰撞概率较低 + * 也有其他方案可以尝试,比如在数据库内设置一个从0开始计数的数字,每次调用此方法时使用updateAndReturn使数字加1并返回加1后的值,根据这个值生成对应的邀请码,比如(22222A + 1 == 22222B),此方式性能理论更好,但是不适用于旧项目 + * @param {object} param + * @param {string} param.inviteCode 初始随机邀请码 + */ +async function getValidInviteCode () { + let retry = 10 + let code + let codeValid = false + while (retry > 0 && !codeValid) { + retry-- + code = getRandomInviteCode() + const getUserRes = await userCollection.where({ + my_invite_code: code + }).limit(1).get() + if (getUserRes.data.length === 0) { + codeValid = true + break + } + } + if (!codeValid) { + throw { + errCode: ERROR.SET_INVITE_CODE_FAILED + } + } + return code +} + +/** + * 根据邀请码查询邀请人 + * @param {object} param + * @param {string} param.inviteCode 邀请码 + * @param {string} param.queryUid 受邀人id,非空时校验不可被下家或自己邀请 + * @returns + */ +async function findUserByInviteCode ({ + inviteCode, + queryUid +} = {}) { + if (typeof inviteCode !== 'string') { + throw { + errCode: ERROR.SYSTEM_ERROR + } + } + // 根据邀请码查询邀请人 + let getInviterRes + if (queryUid) { + getInviterRes = await userCollection.where({ + _id: dbCmd.neq(queryUid), + inviter_uid: dbCmd.not(dbCmd.all([queryUid])), + my_invite_code: inviteCode + }).get() + } else { + getInviterRes = await userCollection.where({ + my_invite_code: inviteCode + }).get() + } + if (getInviterRes.data.length > 1) { + // 正常情况下不可能进入此条件,以防用户自行修改数据库出错,在此做出判断 + throw { + errCode: ERROR.SYSTEM_ERROR + } + } + const inviterRecord = getInviterRes.data[0] + if (!inviterRecord) { + throw { + errCode: ERROR.INVALID_INVITE_CODE + } + } + return inviterRecord +} + +/** + * 根据邀请码生成邀请信息 + * @param {object} param + * @param {string} param.inviteCode 邀请码 + * @param {string} param.queryUid 受邀人id,非空时校验不可被下家或自己邀请 + * @returns + */ +async function generateInviteInfo ({ + inviteCode, + queryUid +} = {}) { + const inviterRecord = await findUserByInviteCode({ + inviteCode, + queryUid + }) + // 倒叙拼接当前用户邀请链 + const inviterUid = inviterRecord.inviter_uid || [] + inviterUid.unshift(inviterRecord._id) + return { + inviterUid, + inviteTime: Date.now() + } +} + +/** + * 检查当前用户是否可以接受邀请,如果可以返回用户记录 + * @param {string} uid + */ +async function checkInviteInfo (uid) { + // 检查当前用户是否已有邀请人 + const getUserRes = await userCollection.doc(uid).field({ + my_invite_code: true, + inviter_uid: true + }).get() + const userRecord = getUserRes.data[0] + if (!userRecord) { + throw { + errCode: ERROR.ACCOUNT_NOT_EXISTS + } + } + if (userRecord.inviter_uid && userRecord.inviter_uid.length > 0) { + throw { + errCode: ERROR.CHANGE_INVITER_FORBIDDEN + } + } + return userRecord +} + +/** + * 指定用户接受邀请码邀请 + * @param {object} param + * @param {string} param.uid 用户uid + * @param {string} param.inviteCode 邀请人的邀请码 + * @returns + */ +async function acceptInvite ({ + uid, + inviteCode +} = {}) { + await checkInviteInfo(uid) + const { + inviterUid, + inviteTime + } = await generateInviteInfo({ + inviteCode, + queryUid: uid + }) + + if (inviterUid === uid) { + throw { + errCode: ERROR.INVALID_INVITE_CODE + } + } + + // 更新当前用户的邀请人信息 + await userCollection.doc(uid).update({ + inviter_uid: inviterUid, + invite_time: inviteTime + }) + + // 更新当前用户邀请的用户的邀请人信息,这步可能较为耗时 + await userCollection.where({ + inviter_uid: uid + }).update({ + inviter_uid: dbCmd.push(inviterUid) + }) + + return { + errCode: 0, + errMsg: '' + } +} + +module.exports = { + acceptInvite, + generateInviteInfo, + getValidInviteCode +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/login.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/login.js index 203bec431c9e130a8a7669fdd664f3a30c11bd51..07bd0442178145fe9406c22b5bfe0d806d35bbf2 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/login.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/login.js @@ -1,231 +1,232 @@ -const { - findUser -} = require('./account') -const { - userCollection, - LOG_TYPE -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') -const { - logout -} = require('./logout') -const PasswordUtils = require('./password') - -async function realPreLogin (params = {}) { - const { - user - } = params - const appId = this.getClientInfo().appId - const userMatched = await findUser({ - userQuery: user, - authorizedApp: appId - }) - if (userMatched.length === 0) { - throw { - errCode: ERROR.ACCOUNT_NOT_EXISTS - } - } else if (userMatched.length > 1) { - throw { - errCode: ERROR.ACCOUNT_CONFLICT - } - } - const userRecord = userMatched[0] - checkLoginUserRecord(userRecord) - return userRecord -} - -async function preLogin (params = {}) { - const { - user - } = params - try { - const user = await realPreLogin.call(this, params) - return user - } catch (error) { - await this.middleware.uniIdLog({ - success: false, - data: user, - type: LOG_TYPE.LOGIN - }) - throw error - } -} - -async function preLoginWithPassword (params = {}) { - const { - user, - password - } = params - try { - const userRecord = await realPreLogin.call(this, params) - const { - passwordErrorLimit, - passwordErrorRetryTime - } = this.config - const { - clientIP - } = this.getClientInfo() - // 根据ip地址,密码错误次数过多,锁定登录 - let loginIPLimit = userRecord.login_ip_limit || [] - // 清理无用记录 - loginIPLimit = loginIPLimit.filter(item => item.last_error_time > Date.now() - passwordErrorRetryTime * 1000) - let currentIPLimit = loginIPLimit.find(item => item.ip === clientIP) - if (currentIPLimit && currentIPLimit.error_times >= passwordErrorLimit) { - throw { - errCode: ERROR.PASSWORD_ERROR_EXCEED_LIMIT - } - } - const passwordUtils = new PasswordUtils({ - passwordSecret: this.config.passwordSecret - }) - - const { - success: checkPasswordSuccess, - refreshPasswordInfo - } = passwordUtils.checkUserPassword({ - password, - passwordHash: userRecord.password, - passwordSecretVersion: userRecord.password_secret_version - }) - if (!checkPasswordSuccess) { - // 更新用户ip对应的密码错误记录 - if (!currentIPLimit) { - currentIPLimit = { - ip: clientIP, - error_times: 1, - last_error_time: Date.now() - } - loginIPLimit.push(currentIPLimit) - } else { - currentIPLimit.error_times++ - currentIPLimit.last_error_time = Date.now() - } - await userCollection.doc(userRecord._id).update({ - login_ip_limit: loginIPLimit - }) - throw { - errCode: ERROR.PASSWORD_ERROR - } - } - const extraData = {} - if (refreshPasswordInfo) { - extraData.password = refreshPasswordInfo.passwordHash - extraData.password_secret_version = refreshPasswordInfo.version - } - - const currentIPLimitIndex = loginIPLimit.indexOf(currentIPLimit) - if (currentIPLimitIndex > -1) { - loginIPLimit.splice(currentIPLimitIndex, 1) - } - extraData.login_ip_limit = loginIPLimit - return { - user: userRecord, - extraData - } - } catch (error) { - await this.middleware.uniIdLog({ - success: false, - data: user, - type: LOG_TYPE.LOGIN - }) - throw error - } -} - -function checkLoginUserRecord (user) { - switch (user.status) { - case undefined: - case 0: - break - case 1: - throw { - errCode: ERROR.ACCOUNT_BANNED - } - case 2: - throw { - errCode: ERROR.ACCOUNT_AUDITING - } - case 3: - throw { - errCode: ERROR.ACCOUNT_AUDIT_FAILED - } - case 4: - throw { - errCode: ERROR.ACCOUNT_CLOSED - } - default: - break - } -} - -async function thirdPartyLogin (params = {}) { - const { - user - } = params - return { - mobileComfirmd: user.mobile_comfirmd, - emailComfirmd: user.email_comfirmd - } -} - -async function postLogin (params = {}) { - const { - user, - extraData, - isThirdParty = false - } = params - const { - clientIP, - uniIdToken - } = this.getClientInfo() - const uid = user._id - const updateData = { - last_login_date: Date.now(), - last_login_ip: clientIP, - ...extraData - } - const { - token, - tokenExpired - } = await this.uniIdCommon.createToken({ - uid - }) - - if (uniIdToken) { - try { - await logout.call(this) - } catch (error) {} - } - - await userCollection.doc(uid).update(updateData) - await this.middleware.uniIdLog({ - data: { - user_id: uid - }, - type: LOG_TYPE.LOGIN - }) - return { - errCode: 0, - newToken: { - token, - tokenExpired - }, - uid, - ...( - isThirdParty - ? thirdPartyLogin({ - user - }) - : {} - ) - } -} - -module.exports = { - preLogin, - postLogin, - checkLoginUserRecord, - preLoginWithPassword -} +const { + findUser +} = require('./account') +const { + userCollection, + LOG_TYPE +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') +const { + logout +} = require('./logout') +const PasswordUtils = require('./password') + +async function realPreLogin (params = {}) { + const { + user + } = params + const appId = this.getClientInfo().appId + const userMatched = await findUser({ + userQuery: user, + authorizedApp: appId + }) + if (userMatched.length === 0) { + throw { + errCode: ERROR.ACCOUNT_NOT_EXISTS + } + } else if (userMatched.length > 1) { + throw { + errCode: ERROR.ACCOUNT_CONFLICT + } + } + const userRecord = userMatched[0] + checkLoginUserRecord(userRecord) + return userRecord +} + +async function preLogin (params = {}) { + const { + user + } = params + try { + const user = await realPreLogin.call(this, params) + return user + } catch (error) { + await this.middleware.uniIdLog({ + success: false, + data: user, + type: LOG_TYPE.LOGIN + }) + throw error + } +} + +async function preLoginWithPassword (params = {}) { + const { + user, + password + } = params + try { + const userRecord = await realPreLogin.call(this, params) + const { + passwordErrorLimit, + passwordErrorRetryTime + } = this.config + const { + clientIP + } = this.getClientInfo() + // 根据ip地址,密码错误次数过多,锁定登录 + let loginIPLimit = userRecord.login_ip_limit || [] + // 清理无用记录 + loginIPLimit = loginIPLimit.filter(item => item.last_error_time > Date.now() - passwordErrorRetryTime * 1000) + let currentIPLimit = loginIPLimit.find(item => item.ip === clientIP) + if (currentIPLimit && currentIPLimit.error_times >= passwordErrorLimit) { + throw { + errCode: ERROR.PASSWORD_ERROR_EXCEED_LIMIT + } + } + const passwordUtils = new PasswordUtils({ + passwordSecret: this.config.passwordSecret + }) + + const { + success: checkPasswordSuccess, + refreshPasswordInfo + } = passwordUtils.checkUserPassword({ + password, + passwordHash: userRecord.password, + passwordSecretVersion: userRecord.password_secret_version + }) + if (!checkPasswordSuccess) { + // 更新用户ip对应的密码错误记录 + if (!currentIPLimit) { + currentIPLimit = { + ip: clientIP, + error_times: 1, + last_error_time: Date.now() + } + loginIPLimit.push(currentIPLimit) + } else { + currentIPLimit.error_times++ + currentIPLimit.last_error_time = Date.now() + } + await userCollection.doc(userRecord._id).update({ + login_ip_limit: loginIPLimit + }) + throw { + errCode: ERROR.PASSWORD_ERROR + } + } + const extraData = {} + if (refreshPasswordInfo) { + extraData.password = refreshPasswordInfo.passwordHash + extraData.password_secret_version = refreshPasswordInfo.version + } + + const currentIPLimitIndex = loginIPLimit.indexOf(currentIPLimit) + if (currentIPLimitIndex > -1) { + loginIPLimit.splice(currentIPLimitIndex, 1) + } + extraData.login_ip_limit = loginIPLimit + return { + user: userRecord, + extraData + } + } catch (error) { + await this.middleware.uniIdLog({ + success: false, + data: user, + type: LOG_TYPE.LOGIN + }) + throw error + } +} + +function checkLoginUserRecord (user) { + switch (user.status) { + case undefined: + case 0: + break + case 1: + throw { + errCode: ERROR.ACCOUNT_BANNED + } + case 2: + throw { + errCode: ERROR.ACCOUNT_AUDITING + } + case 3: + throw { + errCode: ERROR.ACCOUNT_AUDIT_FAILED + } + case 4: + throw { + errCode: ERROR.ACCOUNT_CLOSED + } + default: + break + } +} + +async function thirdPartyLogin (params = {}) { + const { + user + } = params + return { + mobileComfirmd: user.mobile_comfirmd, + emailComfirmd: user.email_comfirmd + } +} + +async function postLogin (params = {}) { + const { + user, + extraData, + isThirdParty = false + } = params + const { + clientIP, + uniIdToken + } = this.getClientInfo() + const uid = user._id + const updateData = { + last_login_date: Date.now(), + last_login_ip: clientIP, + ...extraData + } + const { + token, + tokenExpired + } = await this.uniIdCommon.createToken({ + uid + }) + + if (uniIdToken) { + try { + await logout.call(this) + } catch (error) {} + } + + await userCollection.doc(uid).update(updateData) + await this.middleware.uniIdLog({ + data: { + user_id: uid + }, + type: LOG_TYPE.LOGIN + }) + return { + errCode: 0, + newToken: { + token, + tokenExpired + }, + uid, + ...( + isThirdParty + ? thirdPartyLogin({ + user + }) + : {} + ), + passwordConfirmed: !!user.password + } +} + +module.exports = { + preLogin, + postLogin, + checkLoginUserRecord, + preLoginWithPassword +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/logout.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/logout.js index dc49fc7c97d71de625d1cbadcb32fb8180008039..5cd9c617057b34d877709130e362fb6b7a495152 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/logout.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/logout.js @@ -1,47 +1,47 @@ -const { - dbCmd, - LOG_TYPE, - deviceCollection, - userCollection -} = require('../../common/constants') - -async function logout() { - const { - uniIdToken, - deviceId - } = this.getClientInfo() - const { - uid - } = await this.uniIdCommon.checkToken( - uniIdToken, - { - autoRefresh: false - } - ) - - // 删除token - await userCollection.doc(uid).update({ - token: dbCmd.pull(uniIdToken) - }) - - // 仅当device表的device_id和user_id均对应时才进行更新 - await deviceCollection.where({ - device_id: deviceId, - user_id: uid - }).update({ - token_expired: 0 - }) - await this.middleware.uniIdLog({ - data: { - user_id: uid - }, - type: LOG_TYPE.LOGOUT - }) - return { - errCode: 0 - } -} - -module.exports = { - logout +const { + dbCmd, + LOG_TYPE, + deviceCollection, + userCollection +} = require('../../common/constants') + +async function logout() { + const { + uniIdToken, + deviceId + } = this.getClientInfo() + const { + uid + } = await this.uniIdCommon.checkToken( + uniIdToken, + { + autoRefresh: false + } + ) + + // 删除token + await userCollection.doc(uid).update({ + token: dbCmd.pull(uniIdToken) + }) + + // 仅当device表的device_id和user_id均对应时才进行更新 + await deviceCollection.where({ + device_id: deviceId, + user_id: uid + }).update({ + token_expired: 0 + }) + await this.middleware.uniIdLog({ + data: { + user_id: uid + }, + type: LOG_TYPE.LOGOUT + }) + return { + errCode: 0 + } +} + +module.exports = { + logout } \ No newline at end of file diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/password.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/password.js index 19ee9205249380741fcd780634d440327ae06056..b1da3842c3dbe114f6f555d95bb564721733240c 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/password.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/password.js @@ -1,116 +1,116 @@ -const { - getType -} = require('../../common/utils') -const crypto = require('crypto') - -const PasswordHashMethod = { - 'hmac-sha1': function (content, secret) { - const hmac = crypto.createHmac('sha1', secret.toString('ascii')) - hmac.update(content) - return hmac.digest('hex') - } -} - -class PasswordUtils { - constructor ({ - passwordSecret - } = {}) { - const passwordSecretType = getType(passwordSecret) - if (passwordSecretType === 'array') { - this.passwordSecret = passwordSecret.sort((a, b) => { - return a.version - b.version - }) - } else if (passwordSecretType === 'string') { - this.passwordSecret = [{ value: passwordSecret }] - } else { - throw new Error('Invalid password secret') - } - } - - getSecretByVersion (params = {}) { - const { - version - } = params - if (!version && version !== 0) { - return this.getOldestSecret() - } - if (this.passwordSecret.length === 1) { - return this.passwordSecret[0] - } - return this.passwordSecret.find(item => item.version === version) - } - - getLastestSecret () { - return this.passwordSecret[this.passwordSecret.length - 1] - } - - getOldestSecret () { - return this.passwordSecret[0] - } - - checkUserPassword (params = {}) { - const { - password, - passwordHash: passwordHashToCheck, - passwordSecretVersion, - autoRefresh = true - } = params - const currentPasswordSecret = this.getSecretByVersion({ - version: passwordSecretVersion - }) - if (!currentPasswordSecret) { - throw new Error('Invalid password version') - } - const { - value: passwordSecret - } = currentPasswordSecret - const { - passwordHash - } = this.generatePasswordHash({ - password, - passwordSecret, - passwordSecretVersion - }) - if (passwordHashToCheck !== passwordHash) { - return { - success: false - } - } - let refreshPasswordInfo - if (autoRefresh && passwordSecretVersion !== this.getLastestSecret().version) { - refreshPasswordInfo = this.generatePasswordHash({ - password - }) - } - return { - success: true, - refreshPasswordInfo - } - } - - generatePasswordHash (params = {}) { - let { - password, - passwordSecret, - passwordSecretVersion - } = params - if (getType(password) !== 'string') { - throw new Error('Invalid password') - } - password = password && password.trim() - if (!password) { - throw new Error('Invalid password') - } - if (!passwordSecret) { - const lastestSecret = this.getLastestSecret() - passwordSecret = lastestSecret.value - passwordSecretVersion = lastestSecret.version - } - return { - passwordHash: PasswordHashMethod['hmac-sha1'](password, passwordSecret), - version: passwordSecretVersion - } - } -} - -module.exports = PasswordUtils +const { + getType +} = require('../../common/utils') +const crypto = require('crypto') + +const PasswordHashMethod = { + 'hmac-sha1': function (content, secret) { + const hmac = crypto.createHmac('sha1', secret.toString('ascii')) + hmac.update(content) + return hmac.digest('hex') + } +} + +class PasswordUtils { + constructor ({ + passwordSecret + } = {}) { + const passwordSecretType = getType(passwordSecret) + if (passwordSecretType === 'array') { + this.passwordSecret = passwordSecret.sort((a, b) => { + return a.version - b.version + }) + } else if (passwordSecretType === 'string') { + this.passwordSecret = [{ value: passwordSecret }] + } else { + throw new Error('Invalid password secret') + } + } + + getSecretByVersion (params = {}) { + const { + version + } = params + if (!version && version !== 0) { + return this.getOldestSecret() + } + if (this.passwordSecret.length === 1) { + return this.passwordSecret[0] + } + return this.passwordSecret.find(item => item.version === version) + } + + getLastestSecret () { + return this.passwordSecret[this.passwordSecret.length - 1] + } + + getOldestSecret () { + return this.passwordSecret[0] + } + + checkUserPassword (params = {}) { + const { + password, + passwordHash: passwordHashToCheck, + passwordSecretVersion, + autoRefresh = true + } = params + const currentPasswordSecret = this.getSecretByVersion({ + version: passwordSecretVersion + }) + if (!currentPasswordSecret) { + throw new Error('Invalid password version') + } + const { + value: passwordSecret + } = currentPasswordSecret + const { + passwordHash + } = this.generatePasswordHash({ + password, + passwordSecret, + passwordSecretVersion + }) + if (passwordHashToCheck !== passwordHash) { + return { + success: false + } + } + let refreshPasswordInfo + if (autoRefresh && passwordSecretVersion !== this.getLastestSecret().version) { + refreshPasswordInfo = this.generatePasswordHash({ + password + }) + } + return { + success: true, + refreshPasswordInfo + } + } + + generatePasswordHash (params = {}) { + let { + password, + passwordSecret, + passwordSecretVersion + } = params + if (getType(password) !== 'string') { + throw new Error('Invalid password') + } + password = password && password.trim() + if (!password) { + throw new Error('Invalid password') + } + if (!passwordSecret) { + const lastestSecret = this.getLastestSecret() + passwordSecret = lastestSecret.value + passwordSecretVersion = lastestSecret.version + } + return { + passwordHash: PasswordHashMethod['hmac-sha1'](password, passwordSecret), + version: passwordSecretVersion + } + } +} + +module.exports = PasswordUtils diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/qq.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/qq.js index ebacbb1a99832aa263130ddeeceb78b2867d6e23..08da035674560158d984e3e5799ed0c34c57c8aa 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/qq.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/qq.js @@ -1,152 +1,152 @@ -const { - userCollection -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') - -function getQQPlatform() { - const platform = this.clientPlatform - switch (platform) { - case 'app': - case 'app-plus': - return 'app' - case 'mp-qq': - return 'mp' - default: - throw new Error('Unsupported qq platform') - } -} - -async function saveQQUserKey({ - openid, - sessionKey, // QQ小程序用户sessionKey - accessToken, // App端QQ用户accessToken - accessTokenExpired // App端QQ用户accessToken过期时间 -} = {}) { - // 微信公众平台、开放平台refreshToken有效期均为30天(微信没有在网络请求里面返回30天这个值,务必注意未来可能出现调整,需及时更新此处逻辑)。 - // 此前QQ开放平台有调整过accessToken的过期时间:[access_token有效期由90天缩短至30天](https://wiki.connect.qq.com/%E3%80%90qq%E4%BA%92%E8%81%94%E3%80%91access_token%E6%9C%89%E6%95%88%E6%9C%9F%E8%B0%83%E6%95%B4) - const appId = this.getClientInfo().appId - const qqPlatform = getQQPlatform.call(this) - const keyObj = { - dcloudAppid: appId, - openid, - platform: 'qq-' + qqPlatform - } - switch (qqPlatform) { - case 'mp': - await this.uniOpenBridge.setSessionKey(keyObj, { - session_key: sessionKey - }, 30 * 24 * 60 * 60) - break - case 'app': - case 'h5': - case 'web': - await this.uniOpenBridge.setUserAccessToken(keyObj, { - access_token: accessToken, - access_token_expired: accessTokenExpired - }, accessTokenExpired ? - Math.floor((accessTokenExpired - Date.now()) / 1000) : - 30 * 24 * 60 * 60 - ) - break - default: - break - } -} - -function generateQQCache({ - sessionKey, // QQ小程序用户sessionKey - accessToken, // App端QQ用户accessToken - accessTokenExpired // App端QQ用户accessToken过期时间 -} = {}) { - const platform = getQQPlatform.call(this) - let cache - switch (platform) { - case 'app': - cache = { - access_token: accessToken, - access_token_expired: accessTokenExpired - } - break - case 'mp': - cache = { - session_key: sessionKey - } - break - default: - throw new Error('Unsupported qq platform') - } - return { - third_party: { - [`${platform}_qq`]: cache - } - } -} - -function getQQOpenid({ - userRecord -} = {}) { - const qqPlatform = getQQPlatform.call(this) - const appId = this.getClientInfo().appId - const qqOpenidObj = userRecord.qq_openid - if (!qqOpenidObj) { - return - } - return qqOpenidObj[`${qqPlatform}_${appId}`] || qqOpenidObj[qqPlatform] -} - -async function getQQCacheFallback({ - userRecord, - key -} = {}) { - const platform = getQQPlatform.call(this) - const thirdParty = userRecord && userRecord.third_party - if (!thirdParty) { - return - } - const qqCache = thirdParty[`${platform}_qq`] - return qqCache && qqCache[key] -} - -async function getQQCache({ - uid, - userRecord, - key -} = {}) { - const qqPlatform = getQQPlatform.call(this) - const appId = this.getClientInfo().appId - - if (!userRecord) { - const getUserRes = await userCollection.doc(uid).get() - userRecord = getUserRes.data[0] - } - if (!userRecord) { - throw { - errCode: ERROR.ACCOUNT_NOT_EXISTS - } - } - const openid = getQQOpenid.call(this, { - userRecord - }) - const getCacheMethod = qqPlatform === 'mp' ? 'getSessionKey' : 'getUserAccessToken' - const userKey = await this.uniOpenBridge[getCacheMethod]({ - dcloudAppid: appId, - platform: 'qq-' + qqPlatform, - openid - }) - if (userKey) { - return userKey[key] - } - return getQQCacheFallback({ - userRecord, - key - }) -} - -module.exports = { - getQQPlatform, - generateQQCache, - getQQCache, - saveQQUserKey -} +const { + userCollection +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') + +function getQQPlatform() { + const platform = this.clientPlatform + switch (platform) { + case 'app': + case 'app-plus': + return 'app' + case 'mp-qq': + return 'mp' + default: + throw new Error('Unsupported qq platform') + } +} + +async function saveQQUserKey({ + openid, + sessionKey, // QQ小程序用户sessionKey + accessToken, // App端QQ用户accessToken + accessTokenExpired // App端QQ用户accessToken过期时间 +} = {}) { + // 微信公众平台、开放平台refreshToken有效期均为30天(微信没有在网络请求里面返回30天这个值,务必注意未来可能出现调整,需及时更新此处逻辑)。 + // 此前QQ开放平台有调整过accessToken的过期时间:[access_token有效期由90天缩短至30天](https://wiki.connect.qq.com/%E3%80%90qq%E4%BA%92%E8%81%94%E3%80%91access_token%E6%9C%89%E6%95%88%E6%9C%9F%E8%B0%83%E6%95%B4) + const appId = this.getClientInfo().appId + const qqPlatform = getQQPlatform.call(this) + const keyObj = { + dcloudAppid: appId, + openid, + platform: 'qq-' + qqPlatform + } + switch (qqPlatform) { + case 'mp': + await this.uniOpenBridge.setSessionKey(keyObj, { + session_key: sessionKey + }, 30 * 24 * 60 * 60) + break + case 'app': + case 'h5': + case 'web': + await this.uniOpenBridge.setUserAccessToken(keyObj, { + access_token: accessToken, + access_token_expired: accessTokenExpired + }, accessTokenExpired ? + Math.floor((accessTokenExpired - Date.now()) / 1000) : + 30 * 24 * 60 * 60 + ) + break + default: + break + } +} + +function generateQQCache({ + sessionKey, // QQ小程序用户sessionKey + accessToken, // App端QQ用户accessToken + accessTokenExpired // App端QQ用户accessToken过期时间 +} = {}) { + const platform = getQQPlatform.call(this) + let cache + switch (platform) { + case 'app': + cache = { + access_token: accessToken, + access_token_expired: accessTokenExpired + } + break + case 'mp': + cache = { + session_key: sessionKey + } + break + default: + throw new Error('Unsupported qq platform') + } + return { + third_party: { + [`${platform}_qq`]: cache + } + } +} + +function getQQOpenid({ + userRecord +} = {}) { + const qqPlatform = getQQPlatform.call(this) + const appId = this.getClientInfo().appId + const qqOpenidObj = userRecord.qq_openid + if (!qqOpenidObj) { + return + } + return qqOpenidObj[`${qqPlatform}_${appId}`] || qqOpenidObj[qqPlatform] +} + +async function getQQCacheFallback({ + userRecord, + key +} = {}) { + const platform = getQQPlatform.call(this) + const thirdParty = userRecord && userRecord.third_party + if (!thirdParty) { + return + } + const qqCache = thirdParty[`${platform}_qq`] + return qqCache && qqCache[key] +} + +async function getQQCache({ + uid, + userRecord, + key +} = {}) { + const qqPlatform = getQQPlatform.call(this) + const appId = this.getClientInfo().appId + + if (!userRecord) { + const getUserRes = await userCollection.doc(uid).get() + userRecord = getUserRes.data[0] + } + if (!userRecord) { + throw { + errCode: ERROR.ACCOUNT_NOT_EXISTS + } + } + const openid = getQQOpenid.call(this, { + userRecord + }) + const getCacheMethod = qqPlatform === 'mp' ? 'getSessionKey' : 'getUserAccessToken' + const userKey = await this.uniOpenBridge[getCacheMethod]({ + dcloudAppid: appId, + platform: 'qq-' + qqPlatform, + openid + }) + if (userKey) { + return userKey[key] + } + return getQQCacheFallback({ + userRecord, + key + }) +} + +module.exports = { + getQQPlatform, + generateQQCache, + getQQCache, + saveQQUserKey +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/register.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/register.js index 2ecd186e32133dc40cf09fab4d777bea6ec0f440..274713c62a335cf6ed807432bb65565702e12f48 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/register.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/register.js @@ -1,211 +1,211 @@ -const { - userCollection, - LOG_TYPE -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') -const { - findUser -} = require('./account') -const { - getValidInviteCode, - generateInviteInfo -} = require('./fission') -const { - logout -} = require('./logout') -const PasswordUtils = require('./password') -const merge = require('lodash.merge') - -async function realPreRegister(params = {}) { - const { - user - } = params - const userMatched = await findUser({ - userQuery: user, - authorizedApp: this.getClientInfo().appId - }) - if (userMatched.length > 0) { - throw { - errCode: ERROR.ACCOUNT_EXISTS - } - } -} - -async function preRegister(params = {}) { - try { - await realPreRegister.call(this, params) - } catch (error) { - await this.middleware.uniIdLog({ - success: false, - type: LOG_TYPE.REGISTER - }) - throw error - } -} - -async function preRegisterWithPassword(params = {}) { - const { - user, - password - } = params - await preRegister.call(this, { - user - }) - const passwordUtils = new PasswordUtils({ - passwordSecret: this.config.passwordSecret - }) - const { - passwordHash, - version - } = passwordUtils.generatePasswordHash({ - password - }) - const extraData = { - password: passwordHash, - password_secret_version: version - } - return { - user, - extraData - } -} - -async function thirdPartyRegister({ - user = {} -} = {}) { - return { - mobileConfirmed: !!(user.mobile && user.mobile_confirmed) || false, - emailConfirmed: !!(user.email && user.email_confirmed) || false - } -} - -async function postRegister(params = {}) { - const { - user, - extraData = {}, - isThirdParty = false, - inviteCode - } = params - const { - appId, - appName, - appVersion, - appVersionCode, - channel, - scene, - clientIP, - osName, - uniIdToken - } = this.getClientInfo() - - merge(user, extraData) - - const registerChannel = channel || scene - user.register_env = { - appid: appId || '', - uni_platform: this.clientPlatform || '', - os_name: osName || '', - app_name: appName || '', - app_version: appVersion || '', - app_version_code: appVersionCode || '', - channel: registerChannel ? registerChannel + '' : '', // channel可能为数字,统一存为字符串 - client_ip: clientIP || '' - } - - user.register_date = Date.now() - user.dcloud_appid = [appId] - - if (user.username) { - user.username = user.username.toLowerCase() - } - if (user.email) { - user.email = user.email.toLowerCase() - } - - const { - autoSetInviteCode, // 注册时自动设置邀请码 - forceInviteCode // 必须有邀请码才允许注册,注意此逻辑不可对admin生效 - } = this.config - if (autoSetInviteCode) { - user.my_invite_code = await getValidInviteCode() - } - - const isAdmin = user.role && user.role.includes('admin') - - if (forceInviteCode && !isAdmin && !inviteCode) { - throw { - errCode: ERROR.INVALID_INVITE_CODE - } - } - - if (inviteCode) { - const { - inviterUid, - inviteTime - } = await generateInviteInfo({ - inviteCode - }) - user.inviter_uid = inviterUid - user.invite_time = inviteTime - } - - if (uniIdToken) { - try { - await logout.call(this) - } catch (error) {} - } - - const beforeRegister = this.hooks.beforeRegister - let userRecord = user - if (beforeRegister) { - userRecord = await beforeRegister({ - userRecord, - clientInfo: this.getClientInfo() - }) - } - - const { - id: uid - } = await userCollection.add(userRecord) - - const { - token, - tokenExpired - } = await this.uniIdCommon.createToken({ - uid - }) - - await this.middleware.uniIdLog({ - data: { - user_id: uid - }, - type: LOG_TYPE.REGISTER - }) - - return { - errCode: 0, - uid, - newToken: { - token, - tokenExpired - }, - ...( - isThirdParty - ? thirdPartyRegister({ - user: { - ...userRecord, - _id: uid - } - }) - : {} - ) - } -} - -module.exports = { - preRegister, - preRegisterWithPassword, - postRegister -} +const { + userCollection, + LOG_TYPE +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') +const { + findUser +} = require('./account') +const { + getValidInviteCode, + generateInviteInfo +} = require('./fission') +const { + logout +} = require('./logout') +const PasswordUtils = require('./password') +const merge = require('lodash.merge') + +async function realPreRegister(params = {}) { + const { + user + } = params + const userMatched = await findUser({ + userQuery: user, + authorizedApp: this.getClientInfo().appId + }) + if (userMatched.length > 0) { + throw { + errCode: ERROR.ACCOUNT_EXISTS + } + } +} + +async function preRegister(params = {}) { + try { + await realPreRegister.call(this, params) + } catch (error) { + await this.middleware.uniIdLog({ + success: false, + type: LOG_TYPE.REGISTER + }) + throw error + } +} + +async function preRegisterWithPassword(params = {}) { + const { + user, + password + } = params + await preRegister.call(this, { + user + }) + const passwordUtils = new PasswordUtils({ + passwordSecret: this.config.passwordSecret + }) + const { + passwordHash, + version + } = passwordUtils.generatePasswordHash({ + password + }) + const extraData = { + password: passwordHash, + password_secret_version: version + } + return { + user, + extraData + } +} + +async function thirdPartyRegister({ + user = {} +} = {}) { + return { + mobileConfirmed: !!(user.mobile && user.mobile_confirmed) || false, + emailConfirmed: !!(user.email && user.email_confirmed) || false + } +} + +async function postRegister(params = {}) { + const { + user, + extraData = {}, + isThirdParty = false, + inviteCode + } = params + const { + appId, + appName, + appVersion, + appVersionCode, + channel, + scene, + clientIP, + osName, + uniIdToken + } = this.getClientInfo() + + merge(user, extraData) + + const registerChannel = channel || scene + user.register_env = { + appid: appId || '', + uni_platform: this.clientPlatform || '', + os_name: osName || '', + app_name: appName || '', + app_version: appVersion || '', + app_version_code: appVersionCode || '', + channel: registerChannel ? registerChannel + '' : '', // channel可能为数字,统一存为字符串 + client_ip: clientIP || '' + } + + user.register_date = Date.now() + user.dcloud_appid = [appId] + + if (user.username) { + user.username = user.username.toLowerCase() + } + if (user.email) { + user.email = user.email.toLowerCase() + } + + const { + autoSetInviteCode, // 注册时自动设置邀请码 + forceInviteCode // 必须有邀请码才允许注册,注意此逻辑不可对admin生效 + } = this.config + if (autoSetInviteCode) { + user.my_invite_code = await getValidInviteCode() + } + + const isAdmin = user.role && user.role.includes('admin') + + if (forceInviteCode && !isAdmin && !inviteCode) { + throw { + errCode: ERROR.INVALID_INVITE_CODE + } + } + + if (inviteCode) { + const { + inviterUid, + inviteTime + } = await generateInviteInfo({ + inviteCode + }) + user.inviter_uid = inviterUid + user.invite_time = inviteTime + } + + if (uniIdToken) { + try { + await logout.call(this) + } catch (error) {} + } + + const beforeRegister = this.hooks.beforeRegister + let userRecord = user + if (beforeRegister) { + userRecord = await beforeRegister({ + userRecord, + clientInfo: this.getClientInfo() + }) + } + + const { + id: uid + } = await userCollection.add(userRecord) + + const { + token, + tokenExpired + } = await this.uniIdCommon.createToken({ + uid + }) + + await this.middleware.uniIdLog({ + data: { + user_id: uid + }, + type: LOG_TYPE.REGISTER + }) + + return { + errCode: 0, + uid, + newToken: { + token, + tokenExpired + }, + ...( + isThirdParty + ? thirdPartyRegister({ + user: { + ...userRecord, + _id: uid + } + }) + : {} + ) + } +} + +module.exports = { + preRegister, + preRegisterWithPassword, + postRegister +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/relate.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/relate.js index efd55e53e5531aff025c63697af26c615d1d0e01..e095780ac60591c416defcc8298e43e7d8decbcf 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/relate.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/relate.js @@ -1,62 +1,162 @@ -const { - findUser -} = require('./account') -const { - ERROR -} = require('../../common/error') -const { - userCollection -} = require('../../common/constants') -const merge = require('lodash.merge') - -/** - * - * @param {object} param - * @param {string} param.uid 用户id - * @param {string} param.bindAccount 要绑定的三方账户、手机号或邮箱 - */ -async function preBind ({ - uid, - bindAccount, - logType -} = {}) { - const userMatched = await findUser({ - userQuery: bindAccount, - authorizedApp: this.getClientInfo().appId - }) - if (userMatched.length > 0) { - await this.middleware.uniIdLog({ - data: { - user_id: uid - }, - type: logType, - success: false - }) - throw { - errCode: ERROR.BIND_CONFLICT - } - } -} - -async function postBind ({ - uid, - extraData = {}, - bindAccount, - logType -} = {}) { - await userCollection.doc(uid).update(merge(bindAccount, extraData)) - await this.middleware.uniIdLog({ - data: { - user_id: uid - }, - type: logType - }) - return { - errCode: 0 - } -} - -module.exports = { - preBind, - postBind -} +const { + findUser +} = require('./account') +const { + ERROR +} = require('../../common/error') +const { + userCollection, dbCmd, USER_IDENTIFIER +} = require('../../common/constants') +const { + getUserIdentifier +} = require('../../lib/utils/account') + +const { + batchFindObjctValue +} = require('../../common/utils') +const merge = require('lodash.merge') + +/** + * + * @param {object} param + * @param {string} param.uid 用户id + * @param {string} param.bindAccount 要绑定的三方账户、手机号或邮箱 + */ +async function preBind ({ + uid, + bindAccount, + logType +} = {}) { + const userMatched = await findUser({ + userQuery: bindAccount, + authorizedApp: this.getClientInfo().appId + }) + if (userMatched.length > 0) { + await this.middleware.uniIdLog({ + data: { + user_id: uid + }, + type: logType, + success: false + }) + throw { + errCode: ERROR.BIND_CONFLICT + } + } +} + +async function postBind ({ + uid, + extraData = {}, + bindAccount, + logType +} = {}) { + await userCollection.doc(uid).update(merge(bindAccount, extraData)) + await this.middleware.uniIdLog({ + data: { + user_id: uid + }, + type: logType + }) + return { + errCode: 0 + } +} + +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, + preUnBind, + postUnBind +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/sms.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/sms.js index 1f45a7004c436ae66b7335685490020047b05363..9caecaa2888a2a59ea8dad0cbfb46a895bec0e5a 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/sms.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/sms.js @@ -1,81 +1,81 @@ -const { - setMobileVerifyCode -} = require('./verify-code') -const { - getVerifyCode -} = require('../../common/utils') - -/** - * 发送短信 - * @param {object} param - * @param {string} param.mobile 手机号 - * @param {object} param.code 可选,验证码 - * @param {object} param.scene 短信场景 - * @param {object} param.templateId 可选,短信模板id - * @returns - */ -async function sendSmsCode ({ - mobile, - code, - scene, - templateId -} = {}) { - const requiredParams = [ - 'name', - 'smsKey', - 'smsSecret', - 'codeExpiresIn' - ] - const smsConfig = (this.config.service && this.config.service.sms) || {} - for (let i = 0; i < requiredParams.length; i++) { - const key = requiredParams[i] - if (!smsConfig[key]) { - throw new Error(`Missing config param: service.sms.${key}`) - } - } - if (!code) { - code = getVerifyCode() - } - let action - switch (scene) { - case 'login-by-sms': - action = this.t('login') - break - default: - action = this.t('verify-mobile') - break - } - const sceneConfig = smsConfig.scene || {} - if (!templateId) { - templateId = sceneConfig.templateId - } - if (!templateId) { - throw new Error('"templateId" is required') - } - const codeExpiresIn = sceneConfig.codeExpiresIn || smsConfig.codeExpiresIn - await setMobileVerifyCode.call(this, { - mobile, - code, - expiresIn: codeExpiresIn, - scene - }) - await uniCloud.sendSms({ - smsKey: smsConfig.smsKey, - smsSecret: smsConfig.smsSecret, - phone: mobile, - templateId, - data: { - name: smsConfig.name, - code, - action, - expMinute: '' + Math.round(codeExpiresIn / 60) - } - }) - return { - errCode: 0 - } -} - -module.exports = { - sendSmsCode -} +const { + setMobileVerifyCode +} = require('./verify-code') +const { + getVerifyCode +} = require('../../common/utils') + +/** + * 发送短信 + * @param {object} param + * @param {string} param.mobile 手机号 + * @param {object} param.code 可选,验证码 + * @param {object} param.scene 短信场景 + * @param {object} param.templateId 可选,短信模板id + * @returns + */ +async function sendSmsCode ({ + mobile, + code, + scene, + templateId +} = {}) { + const requiredParams = [ + 'name', + 'smsKey', + 'smsSecret', + 'codeExpiresIn' + ] + const smsConfig = (this.config.service && this.config.service.sms) || {} + for (let i = 0; i < requiredParams.length; i++) { + const key = requiredParams[i] + if (!smsConfig[key]) { + throw new Error(`Missing config param: service.sms.${key}`) + } + } + if (!code) { + code = getVerifyCode() + } + let action + switch (scene) { + case 'login-by-sms': + action = this.t('login') + break + default: + action = this.t('verify-mobile') + break + } + const sceneConfig = (smsConfig.scene || {})[scene] || {} + if (!templateId) { + templateId = sceneConfig.templateId + } + if (!templateId) { + throw new Error('"templateId" is required') + } + const codeExpiresIn = sceneConfig.codeExpiresIn || smsConfig.codeExpiresIn + await setMobileVerifyCode.call(this, { + mobile, + code, + expiresIn: codeExpiresIn, + scene + }) + await uniCloud.sendSms({ + smsKey: smsConfig.smsKey, + smsSecret: smsConfig.smsSecret, + phone: mobile, + templateId, + data: { + name: smsConfig.name, + code, + action, + expMinute: '' + Math.round(codeExpiresIn / 60) + } + }) + return { + errCode: 0 + } +} + +module.exports = { + sendSmsCode +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/unified-login.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/unified-login.js index cd758fe5bb718051a416a5a7f7cc7d296a310a25..3665fe9f4742b412ae038fbbc09aecda9092be9b 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/unified-login.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/unified-login.js @@ -1,98 +1,98 @@ -const { - checkLoginUserRecord, - postLogin -} = require('./login') -const { - postRegister -} = require('./register') -const { - findUser -} = require('./account') -const { - ERROR -} = require('../../common/error') - -async function realPreUnifiedLogin (params = {}) { - const { - user, - type - } = params - const appId = this.getClientInfo().appId - const userMatched = await findUser({ - userQuery: user, - authorizedApp: appId - }) - if (userMatched.length === 0) { - if (type === 'login') { - throw { - errCode: ERROR.ACCOUNT_NOT_EXISTS - } - } - return { - type: 'register', - user - } - } if (userMatched.length === 1) { - if (type === 'register') { - throw { - errCode: ERROR.ACCOUNT_EXISTS - } - } - const userRecord = userMatched[0] - checkLoginUserRecord(userRecord) - return { - type: 'login', - user: userRecord - } - } else if (userMatched.length > 1) { - throw { - errCode: ERROR.ACCOUNT_CONFLICT - } - } -} - -async function preUnifiedLogin (params = {}) { - try { - const result = await realPreUnifiedLogin.call(this, params) - return result - } catch (error) { - await this.middleware.uniIdLog({ - success: false - }) - throw error - } -} - -async function postUnifiedLogin (params = {}) { - const { - user, - extraData = {}, - isThirdParty = false, - type, - inviteCode - } = params - let result - if (type === 'login') { - result = await postLogin.call(this, { - user, - extraData, - isThirdParty - }) - } else if (type === 'register') { - result = await postRegister.call(this, { - user, - extraData, - isThirdParty, - inviteCode - }) - } - return { - ...result, - type - } -} - -module.exports = { - preUnifiedLogin, - postUnifiedLogin -} +const { + checkLoginUserRecord, + postLogin +} = require('./login') +const { + postRegister +} = require('./register') +const { + findUser +} = require('./account') +const { + ERROR +} = require('../../common/error') + +async function realPreUnifiedLogin (params = {}) { + const { + user, + type + } = params + const appId = this.getClientInfo().appId + const userMatched = await findUser({ + userQuery: user, + authorizedApp: appId + }) + if (userMatched.length === 0) { + if (type === 'login') { + throw { + errCode: ERROR.ACCOUNT_NOT_EXISTS + } + } + return { + type: 'register', + user + } + } if (userMatched.length === 1) { + if (type === 'register') { + throw { + errCode: ERROR.ACCOUNT_EXISTS + } + } + const userRecord = userMatched[0] + checkLoginUserRecord(userRecord) + return { + type: 'login', + user: userRecord + } + } else if (userMatched.length > 1) { + throw { + errCode: ERROR.ACCOUNT_CONFLICT + } + } +} + +async function preUnifiedLogin (params = {}) { + try { + const result = await realPreUnifiedLogin.call(this, params) + return result + } catch (error) { + await this.middleware.uniIdLog({ + success: false + }) + throw error + } +} + +async function postUnifiedLogin (params = {}) { + const { + user, + extraData = {}, + isThirdParty = false, + type, + inviteCode + } = params + let result + if (type === 'login') { + result = await postLogin.call(this, { + user, + extraData, + isThirdParty + }) + } else if (type === 'register') { + result = await postRegister.call(this, { + user, + extraData, + isThirdParty, + inviteCode + }) + } + return { + ...result, + type + } +} + +module.exports = { + preUnifiedLogin, + postUnifiedLogin +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/univerify.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/univerify.js index ba3cb440b7c2591acb09e111165f948f6fe0e23d..2ba70baa58e9c37a2173950e2f2ead8cdca4747b 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/univerify.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/univerify.js @@ -1,27 +1,27 @@ -async function getPhoneNumber ({ - // eslint-disable-next-line camelcase - access_token, - openid -} = {}) { - const requiredParams = ['apiKey', 'apiSecret'] - const univerifyConfig = (this.config.service && this.config.service.univerify) || {} - for (let i = 0; i < requiredParams.length; i++) { - const key = requiredParams[i] - if (!univerifyConfig[key]) { - throw new Error(`Missing config param: service.univerify.${key}`) - } - } - return uniCloud.getPhoneNumber({ - provider: 'univerify', - appid: this.getClientInfo().appId, - apiKey: univerifyConfig.apiKey, - apiSecret: univerifyConfig.apiSecret, - // eslint-disable-next-line camelcase - access_token, - openid - }) -} - -module.exports = { - getPhoneNumber -} +async function getPhoneNumber ({ + // eslint-disable-next-line camelcase + access_token, + openid +} = {}) { + const requiredParams = ['apiKey', 'apiSecret'] + const univerifyConfig = (this.config.service && this.config.service.univerify) || {} + for (let i = 0; i < requiredParams.length; i++) { + const key = requiredParams[i] + if (!univerifyConfig[key]) { + throw new Error(`Missing config param: service.univerify.${key}`) + } + } + return uniCloud.getPhoneNumber({ + provider: 'univerify', + appid: this.getClientInfo().appId, + apiKey: univerifyConfig.apiKey, + apiSecret: univerifyConfig.apiSecret, + // eslint-disable-next-line camelcase + access_token, + openid + }) +} + +module.exports = { + getPhoneNumber +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/update-user-info.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/update-user-info.js index ced33b9f5624192ac3aecef5b917c7fb9aa775cc..c2ebb1b4dac7cd4cd39273b478452d2680104ec6 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/update-user-info.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/update-user-info.js @@ -1,25 +1,25 @@ -const { - userCollection -} = require('../../common/constants') -const { - USER_STATUS -} = require('../../common/constants') -async function setUserStatus (uid, status) { - const updateData = { - status - } - if (status !== USER_STATUS.NORMAL) { - updateData.valid_token_date = Date.now() - } - await userCollection.doc(uid).update({ - status - }) - // TODO 此接口尚不完善,例如注销后其他客户端可能存在有效token,支持Redis后此处会补充额外逻辑 - return { - errCode: 0 - } -} - -module.exports = { - setUserStatus -} +const { + userCollection +} = require('../../common/constants') +const { + USER_STATUS +} = require('../../common/constants') +async function setUserStatus (uid, status) { + const updateData = { + status + } + if (status !== USER_STATUS.NORMAL) { + updateData.valid_token_date = Date.now() + } + await userCollection.doc(uid).update({ + status + }) + // TODO 此接口尚不完善,例如注销后其他客户端可能存在有效token,支持Redis后此处会补充额外逻辑 + return { + errCode: 0 + } +} + +module.exports = { + setUserStatus +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/verify-code.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/verify-code.js index acebc6bdac3aed5d86c7ba28ae93285888bf5686..cc80004c9f10a2f3b79a21175ee5241739bd80e9 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/verify-code.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/verify-code.js @@ -1,152 +1,152 @@ -const { - dbCmd, - verifyCollection -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') -const { - getVerifyCode -} = require('../../common/utils') - -async function setVerifyCode ({ - mobile, - email, - code, - expiresIn, - scene -} = {}) { - const now = Date.now() - const record = { - mobile, - email, - scene, - code: code || getVerifyCode(), - state: 0, - ip: this.getClientInfo().clientIP, - created_date: now, - expired_date: now + expiresIn * 1000 - } - await verifyCollection.add(record) - return { - errCode: 0 - } -} - -async function setEmailVerifyCode ({ - email, - code, - expiresIn, - scene -} = {}) { - email = email && email.trim() - if (!email) { - throw { - errCode: ERROR.INVALID_EMAIL - } - } - email = email.toLowerCase() - return setVerifyCode.call(this, { - email, - code, - expiresIn, - scene - }) -} - -async function setMobileVerifyCode ({ - mobile, - code, - expiresIn, - scene -} = {}) { - mobile = mobile && mobile.trim() - if (!mobile) { - throw { - errCode: ERROR.INVALID_MOBILE - } - } - return setVerifyCode.call(this, { - mobile, - code, - expiresIn, - scene - }) -} - -async function verifyEmailCode ({ - email, - code, - scene -} = {}) { - email = email && email.trim() - if (!email) { - throw { - errCode: ERROR.INVALID_EMAIL - } - } - email = email.toLowerCase() - const { - data: codeRecord - } = await verifyCollection.where({ - email, - scene, - code, - state: 0, - expired_date: dbCmd.gt(Date.now()) - }).limit(1).get() - - if (codeRecord.length === 0) { - throw { - errCode: ERROR.EMAIL_VERIFY_CODE_ERROR - } - } - await verifyCollection.doc(codeRecord[0]._id).update({ - state: 1 - }) - return { - errCode: 0 - } -} - -async function verifyMobileCode ({ - mobile, - code, - scene -} = {}) { - mobile = mobile && mobile.trim() - if (!mobile) { - throw { - errCode: ERROR.INVALID_MOBILE - } - } - const { - data: codeRecord - } = await verifyCollection.where({ - mobile, - scene, - code, - state: 0, - expired_date: dbCmd.gt(Date.now()) - }).limit(1).get() - - if (codeRecord.length === 0) { - throw { - errCode: ERROR.MOBILE_VERIFY_CODE_ERROR - } - } - - await verifyCollection.doc(codeRecord[0]._id).update({ - state: 1 - }) - return { - errCode: 0 - } -} - -module.exports = { - verifyEmailCode, - verifyMobileCode, - setEmailVerifyCode, - setMobileVerifyCode -} +const { + dbCmd, + verifyCollection +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') +const { + getVerifyCode +} = require('../../common/utils') + +async function setVerifyCode ({ + mobile, + email, + code, + expiresIn, + scene +} = {}) { + const now = Date.now() + const record = { + mobile, + email, + scene, + code: code || getVerifyCode(), + state: 0, + ip: this.getClientInfo().clientIP, + created_date: now, + expired_date: now + expiresIn * 1000 + } + await verifyCollection.add(record) + return { + errCode: 0 + } +} + +async function setEmailVerifyCode ({ + email, + code, + expiresIn, + scene +} = {}) { + email = email && email.trim() + if (!email) { + throw { + errCode: ERROR.INVALID_EMAIL + } + } + email = email.toLowerCase() + return setVerifyCode.call(this, { + email, + code, + expiresIn, + scene + }) +} + +async function setMobileVerifyCode ({ + mobile, + code, + expiresIn, + scene +} = {}) { + mobile = mobile && mobile.trim() + if (!mobile) { + throw { + errCode: ERROR.INVALID_MOBILE + } + } + return setVerifyCode.call(this, { + mobile, + code, + expiresIn, + scene + }) +} + +async function verifyEmailCode ({ + email, + code, + scene +} = {}) { + email = email && email.trim() + if (!email) { + throw { + errCode: ERROR.INVALID_EMAIL + } + } + email = email.toLowerCase() + const { + data: codeRecord + } = await verifyCollection.where({ + email, + scene, + code, + state: 0, + expired_date: dbCmd.gt(Date.now()) + }).limit(1).get() + + if (codeRecord.length === 0) { + throw { + errCode: ERROR.EMAIL_VERIFY_CODE_ERROR + } + } + await verifyCollection.doc(codeRecord[0]._id).update({ + state: 1 + }) + return { + errCode: 0 + } +} + +async function verifyMobileCode ({ + mobile, + code, + scene +} = {}) { + mobile = mobile && mobile.trim() + if (!mobile) { + throw { + errCode: ERROR.INVALID_MOBILE + } + } + const { + data: codeRecord + } = await verifyCollection.where({ + mobile, + scene, + code, + state: 0, + expired_date: dbCmd.gt(Date.now()) + }).limit(1).get() + + if (codeRecord.length === 0) { + throw { + errCode: ERROR.MOBILE_VERIFY_CODE_ERROR + } + } + + await verifyCollection.doc(codeRecord[0]._id).update({ + state: 1 + }) + return { + errCode: 0 + } +} + +module.exports = { + verifyEmailCode, + verifyMobileCode, + setEmailVerifyCode, + setMobileVerifyCode +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/weixin.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/weixin.js index 8ff178f3c88a65c011773f11cc5947e234c6d086..3bfbdfe3116cf66ea589aa1f5977579c8f05381b 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/weixin.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/weixin.js @@ -1,186 +1,198 @@ -const crypto = require('crypto') -const { - userCollection -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') - -function decryptWeixinData ({ - encryptedData, - sessionKey, - iv -} = {}) { - const oauthConfig = this.configUtils.getOauthConfig({ - provider: 'weixin' - }) - const decipher = crypto.createDecipheriv( - 'aes-128-cbc', - Buffer.from(sessionKey, 'base64'), - Buffer.from(iv, 'base64') - ) - // 设置自动 padding 为 true,删除填充补位 - decipher.setAutoPadding(true) - let decoded - decoded = decipher.update(encryptedData, 'base64', 'utf8') - decoded += decipher.final('utf8') - decoded = JSON.parse(decoded) - if (decoded.watermark.appid !== oauthConfig.appid) { - throw new Error('Invalid wechat appid in decode content') - } - return decoded -} - -function getWeixinPlatform () { - const platform = this.clientPlatform - const userAgent = this.getClientInfo().userAgent - switch (platform) { - case 'app': - case 'app-plus': - return 'app' - case 'mp-weixin': - return 'mp' - case 'h5': - case 'web': - return userAgent.indexOf('MicroMessenger') > -1 ? 'h5' : 'web' - default: - throw new Error('Unsupported weixin platform') - } -} - -async function saveWeixinUserKey ({ - openid, - sessionKey, // 微信小程序用户sessionKey - accessToken, // App端微信用户accessToken - refreshToken, // App端微信用户refreshToken - accessTokenExpired // App端微信用户accessToken过期时间 -} = {}) { - // 微信公众平台、开放平台refreshToken有效期均为30天(微信没有在网络请求里面返回30天这个值,务必注意未来可能出现调整,需及时更新此处逻辑)。 - // 此前QQ开放平台有调整过accessToken的过期时间:[access_token有效期由90天缩短至30天](https://wiki.connect.qq.com/%E3%80%90qq%E4%BA%92%E8%81%94%E3%80%91access_token%E6%9C%89%E6%95%88%E6%9C%9F%E8%B0%83%E6%95%B4) - - const appId = this.getClientInfo().appId - const weixinPlatform = getWeixinPlatform.call(this) - const keyObj = { - dcloudAppid: appId, - openid, - platform: 'weixin-' + weixinPlatform - } - switch (weixinPlatform) { - case 'mp': - await this.uniOpenBridge.setSessionKey(keyObj, { - session_key: sessionKey - }, 30 * 24 * 60 * 60) - break - case 'app': - case 'h5': - case 'web': - await this.uniOpenBridge.setUserAccessToken(keyObj, { - access_token: accessToken, - refresh_token: refreshToken, - access_token_expired: accessTokenExpired - }, 30 * 24 * 60 * 60) - break - default: - break - } -} - -function generateWeixinCache ({ - sessionKey, // 微信小程序用户sessionKey - accessToken, // App端微信用户accessToken - refreshToken, // App端微信用户refreshToken - accessTokenExpired // App端微信用户accessToken过期时间 -} = {}) { - const platform = getWeixinPlatform.call(this) - let cache - switch (platform) { - case 'app': - case 'h5': - case 'web': - cache = { - access_token: accessToken, - refresh_token: refreshToken, - access_token_expired: accessTokenExpired - } - break - case 'mp': - cache = { - session_key: sessionKey - } - break - default: - throw new Error('Unsupported weixin platform') - } - return { - third_party: { - [`${platform}_weixin`]: cache - } - } -} - -function getWeixinOpenid ({ - userRecord -} = {}) { - const weixinPlatform = getWeixinPlatform.call(this) - const appId = this.getClientInfo().appId - const wxOpenidObj = userRecord.wx_openid - if (!wxOpenidObj) { - return - } - return wxOpenidObj[`${weixinPlatform}_${appId}`] || wxOpenidObj[weixinPlatform] -} - -async function getWeixinCacheFallback ({ - userRecord, - key -} = {}) { - const platform = getWeixinPlatform.call(this) - const thirdParty = userRecord && userRecord.third_party - if (!thirdParty) { - return - } - const weixinCache = thirdParty[`${platform}_weixin`] - return weixinCache && weixinCache[key] -} - -async function getWeixinCache ({ - uid, - userRecord, - key -} = {}) { - const weixinPlatform = getWeixinPlatform.call(this) - const appId = this.getClientInfo().appId - if (!userRecord) { - const getUserRes = await userCollection.doc(uid).get() - userRecord = getUserRes.data[0] - } - if (!userRecord) { - throw { - errCode: ERROR.ACCOUNT_NOT_EXISTS - } - } - const openid = getWeixinOpenid.call(this, { - userRecord - }) - const getCacheMethod = weixinPlatform === 'mp' ? 'getSessionKey' : 'getUserAccessToken' - const userKey = await this.uniOpenBridge[getCacheMethod]({ - dcloudAppid: appId, - platform: 'weixin-' + weixinPlatform, - openid - }) - if (userKey) { - return userKey[key] - } - return getWeixinCacheFallback({ - userRecord, - key - }) -} - -module.exports = { - decryptWeixinData, - getWeixinPlatform, - generateWeixinCache, - getWeixinCache, - saveWeixinUserKey -} +const crypto = require('crypto') +const { + userCollection +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') + +function decryptWeixinData ({ + encryptedData, + sessionKey, + iv +} = {}) { + const oauthConfig = this.configUtils.getOauthConfig({ + provider: 'weixin' + }) + const decipher = crypto.createDecipheriv( + 'aes-128-cbc', + Buffer.from(sessionKey, 'base64'), + Buffer.from(iv, 'base64') + ) + // 设置自动 padding 为 true,删除填充补位 + decipher.setAutoPadding(true) + let decoded + decoded = decipher.update(encryptedData, 'base64', 'utf8') + decoded += decipher.final('utf8') + decoded = JSON.parse(decoded) + if (decoded.watermark.appid !== oauthConfig.appid) { + throw new Error('Invalid wechat appid in decode content') + } + return decoded +} + +function getWeixinPlatform () { + const platform = this.clientPlatform + const userAgent = this.getClientInfo().userAgent + switch (platform) { + case 'app': + case 'app-plus': + return 'app' + case 'mp-weixin': + return 'mp' + case 'h5': + case 'web': + return userAgent.indexOf('MicroMessenger') > -1 ? 'h5' : 'web' + default: + throw new Error('Unsupported weixin platform') + } +} + +async function saveWeixinUserKey ({ + openid, + sessionKey, // 微信小程序用户sessionKey + accessToken, // App端微信用户accessToken + refreshToken, // App端微信用户refreshToken + accessTokenExpired // App端微信用户accessToken过期时间 +} = {}) { + // 微信公众平台、开放平台refreshToken有效期均为30天(微信没有在网络请求里面返回30天这个值,务必注意未来可能出现调整,需及时更新此处逻辑)。 + // 此前QQ开放平台有调整过accessToken的过期时间:[access_token有效期由90天缩短至30天](https://wiki.connect.qq.com/%E3%80%90qq%E4%BA%92%E8%81%94%E3%80%91access_token%E6%9C%89%E6%95%88%E6%9C%9F%E8%B0%83%E6%95%B4) + + const appId = this.getClientInfo().appId + const weixinPlatform = getWeixinPlatform.call(this) + const keyObj = { + dcloudAppid: appId, + openid, + platform: 'weixin-' + weixinPlatform + } + switch (weixinPlatform) { + case 'mp': + await this.uniOpenBridge.setSessionKey(keyObj, { + session_key: sessionKey + }, 30 * 24 * 60 * 60) + break + case 'app': + case 'h5': + case 'web': + await this.uniOpenBridge.setUserAccessToken(keyObj, { + access_token: accessToken, + refresh_token: refreshToken, + access_token_expired: accessTokenExpired + }, 30 * 24 * 60 * 60) + break + default: + break + } +} + +function generateWeixinCache ({ + sessionKey, // 微信小程序用户sessionKey + accessToken, // App端微信用户accessToken + refreshToken, // App端微信用户refreshToken + accessTokenExpired // App端微信用户accessToken过期时间 +} = {}) { + const platform = getWeixinPlatform.call(this) + let cache + switch (platform) { + case 'app': + case 'h5': + case 'web': + cache = { + access_token: accessToken, + refresh_token: refreshToken, + access_token_expired: accessTokenExpired + } + break + case 'mp': + cache = { + session_key: sessionKey + } + break + default: + throw new Error('Unsupported weixin platform') + } + return { + third_party: { + [`${platform}_weixin`]: cache + } + } +} + +function getWeixinOpenid ({ + userRecord +} = {}) { + const weixinPlatform = getWeixinPlatform.call(this) + const appId = this.getClientInfo().appId + const wxOpenidObj = userRecord.wx_openid + if (!wxOpenidObj) { + return + } + return wxOpenidObj[`${weixinPlatform}_${appId}`] || wxOpenidObj[weixinPlatform] +} + +async function getWeixinCacheFallback ({ + userRecord, + key +} = {}) { + const platform = getWeixinPlatform.call(this) + const thirdParty = userRecord && userRecord.third_party + if (!thirdParty) { + return + } + const weixinCache = thirdParty[`${platform}_weixin`] + return weixinCache && weixinCache[key] +} + +async function getWeixinCache ({ + uid, + userRecord, + key +} = {}) { + const weixinPlatform = getWeixinPlatform.call(this) + const appId = this.getClientInfo().appId + if (!userRecord) { + const getUserRes = await userCollection.doc(uid).get() + userRecord = getUserRes.data[0] + } + if (!userRecord) { + throw { + errCode: ERROR.ACCOUNT_NOT_EXISTS + } + } + const openid = getWeixinOpenid.call(this, { + userRecord + }) + const getCacheMethod = weixinPlatform === 'mp' ? 'getSessionKey' : 'getUserAccessToken' + const userKey = await this.uniOpenBridge[getCacheMethod]({ + dcloudAppid: appId, + platform: 'weixin-' + weixinPlatform, + openid + }) + if (userKey) { + return userKey[key] + } + return getWeixinCacheFallback({ + userRecord, + key + }) +} + +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, + getWeixinAccessToken +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/access-control.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/access-control.js index e333fe01f2689e67f71e841195f8657e14290c02..6041ffa6aca936c506ae26c142247108d21ea572 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/access-control.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/access-control.js @@ -1,59 +1,59 @@ -const methodPermission = require('../config/permission') -const { - ERROR -} = require('../common/error') - -function isAccessAllowed (user, setting) { - const { - role: userRole = [], - permission: userPermission = [] - } = user - const { - role: settingRole = [], - permission: settingPermission = [] - } = setting - if (userRole.includes('admin')) { - return - } - if ( - settingRole.length > 0 && - settingRole.every(item => !userRole.includes(item)) - ) { - throw { - errCode: ERROR.PERMISSION_ERROR - } - } - if ( - settingPermission.length > 0 && - settingPermission.every(item => !userPermission.includes(item)) - ) { - throw { - errCode: ERROR.PERMISSION_ERROR - } - } -} - -module.exports = async function () { - const methodName = this.getMethodName() - if (!(methodName in methodPermission)) { - return - } - const { - auth, - role, - permission - } = methodPermission[methodName] - if (auth || role || permission) { - await this.middleware.auth() - } - if (role && role.length === 0) { - throw new Error('[AccessControl]Empty role array is not supported') - } - if (permission && permission.length === 0) { - throw new Error('[AccessControl]Empty permission array is not supported') - } - return isAccessAllowed(this.authInfo, { - role, - permission - }) -} +const methodPermission = require('../config/permission') +const { + ERROR +} = require('../common/error') + +function isAccessAllowed (user, setting) { + const { + role: userRole = [], + permission: userPermission = [] + } = user + const { + role: settingRole = [], + permission: settingPermission = [] + } = setting + if (userRole.includes('admin')) { + return + } + if ( + settingRole.length > 0 && + settingRole.every(item => !userRole.includes(item)) + ) { + throw { + errCode: ERROR.PERMISSION_ERROR + } + } + if ( + settingPermission.length > 0 && + settingPermission.every(item => !userPermission.includes(item)) + ) { + throw { + errCode: ERROR.PERMISSION_ERROR + } + } +} + +module.exports = async function () { + const methodName = this.getMethodName() + if (!(methodName in methodPermission)) { + return + } + const { + auth, + role, + permission + } = methodPermission[methodName] + if (auth || role || permission) { + await this.middleware.auth() + } + if (role && role.length === 0) { + throw new Error('[AccessControl]Empty role array is not supported') + } + if (permission && permission.length === 0) { + throw new Error('[AccessControl]Empty permission array is not supported') + } + return isAccessAllowed(this.authInfo, { + role, + permission + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/auth.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/auth.js index 4c78b24d56ed0dc30bef102a6a7438b4c1c14a72..945e6a1aa81ee6b643b543e27ee88a6d51424d40 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/auth.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/auth.js @@ -1,17 +1,17 @@ -module.exports = async function () { - if (this.authInfo) { // 多次执行auth时如果第一次成功后续不再执行 - return - } - const token = this.getUniIdToken() - const payload = await this.uniIdCommon.checkToken(token) - if (payload.errCode) { - throw payload - } - this.authInfo = payload - if (payload.token) { - this.response.newToken = { - token: payload.token, - tokenExpired: payload.tokenExpired - } - } -} +module.exports = async function () { + if (this.authInfo) { // 多次执行auth时如果第一次成功后续不再执行 + return + } + const token = this.getUniIdToken() + const payload = await this.uniIdCommon.checkToken(token) + if (payload.errCode) { + throw payload + } + this.authInfo = payload + if (payload.token) { + this.response.newToken = { + token: payload.token, + tokenExpired: payload.tokenExpired + } + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/index.js index 0af498a4dfb9bb9a21b72ada7f14efeb30c0aaa0..cccac6f58e331f2999ca8ac2e93f0b33cf42be73 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/index.js @@ -1,7 +1,7 @@ -module.exports = { - auth: require('./auth'), - uniIdLog: require('./uni-id-log'), - validate: require('./validate'), - accessControl: require('./access-control'), - ...require('./rbac') -} +module.exports = { + auth: require('./auth'), + uniIdLog: require('./uni-id-log'), + validate: require('./validate'), + accessControl: require('./access-control'), + ...require('./rbac') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/rbac.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/rbac.js index f42ef8d9fea154c7766279efa4d82454620d9896..32fe0f8097b9e528eb4ad304747cd68a95ebb1ac 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/rbac.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/rbac.js @@ -1,39 +1,39 @@ -const { - ERROR -} = require('../common/error') - -function hasRole (...roleList) { - const userRole = this.authInfo.role || [] - if (userRole.includes('admin')) { - return - } - const isMatch = roleList.every(roleItem => { - return userRole.includes(roleItem) - }) - if (!isMatch) { - throw { - errCode: ERROR.PERMISSION_ERROR - } - } -} - -function hasPermission (...permissionList) { - const userRole = this.authInfo.role || [] - const userPermission = this.authInfo.permission || [] - if (userRole.includes('admin')) { - return - } - const isMatch = permissionList.every(permissionItem => { - return userPermission.includes(permissionItem) - }) - if (!isMatch) { - throw { - errCode: ERROR.PERMISSION_ERROR - } - } -} - -module.exports = { - hasRole, - hasPermission -} +const { + ERROR +} = require('../common/error') + +function hasRole (...roleList) { + const userRole = this.authInfo.role || [] + if (userRole.includes('admin')) { + return + } + const isMatch = roleList.every(roleItem => { + return userRole.includes(roleItem) + }) + if (!isMatch) { + throw { + errCode: ERROR.PERMISSION_ERROR + } + } +} + +function hasPermission (...permissionList) { + const userRole = this.authInfo.role || [] + const userPermission = this.authInfo.permission || [] + if (userRole.includes('admin')) { + return + } + const isMatch = permissionList.every(permissionItem => { + return userPermission.includes(permissionItem) + }) + if (!isMatch) { + throw { + errCode: ERROR.PERMISSION_ERROR + } + } +} + +module.exports = { + hasRole, + hasPermission +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/uni-id-log.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/uni-id-log.js index 37ce6552929d1527ab274775e5ae21cf7cd1506f..8202d587e5682169a1915d349c012e92108356eb 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/uni-id-log.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/uni-id-log.js @@ -1,39 +1,39 @@ -const db = uniCloud.database() -module.exports = async function ({ - data = {}, - success = true, - type = 'login' -} = {}) { - const now = Date.now() - const uniIdLogCollection = db.collection('uni-id-log') - const requiredDataKeyList = ['user_id', 'username', 'email', 'mobile'] - const dataCopy = {} - for (let i = 0; i < requiredDataKeyList.length; i++) { - const key = requiredDataKeyList[i] - if (key in data && typeof data[key] === 'string') { - dataCopy[key] = data[key] - } - } - const { - appId, - clientIP, - deviceId, - userAgent - } = this.getClientInfo() - const logData = { - appid: appId, - device_id: deviceId, - ip: clientIP, - type, - ua: userAgent, - create_date: now, - ...dataCopy - } - - if (success) { - logData.state = 1 - } else { - logData.state = 0 - } - return uniIdLogCollection.add(logData) -} +const db = uniCloud.database() +module.exports = async function ({ + data = {}, + success = true, + type = 'login' +} = {}) { + const now = Date.now() + const uniIdLogCollection = db.collection('uni-id-log') + const requiredDataKeyList = ['user_id', 'username', 'email', 'mobile'] + const dataCopy = {} + for (let i = 0; i < requiredDataKeyList.length; i++) { + const key = requiredDataKeyList[i] + if (key in data && typeof data[key] === 'string') { + dataCopy[key] = data[key] + } + } + const { + appId, + clientIP, + deviceId, + userAgent + } = this.getClientInfo() + const logData = { + appid: appId, + device_id: deviceId, + ip: clientIP, + type, + ua: userAgent, + create_date: now, + ...dataCopy + } + + if (success) { + logData.state = 1 + } else { + logData.state = 0 + } + return uniIdLogCollection.add(logData) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/validate.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/validate.js index 52ff04769c0f4498a90111b7cf79313cb4683823..a58e8b473a6801d8dc943cccf30364f536b42872 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/validate.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/middleware/validate.js @@ -1,7 +1,7 @@ -module.exports = function (value = {}, schema = {}) { - const validateRes = this.validator.validate(value, schema) - if (validateRes) { - delete validateRes.schemaKey - throw validateRes - } -} +module.exports = function (value = {}, schema = {}) { + const validateRes = this.validator.validate(value, schema) + if (validateRes) { + delete validateRes.schemaKey + throw validateRes + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/close-account.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/close-account.js index f1bdf9691024f5d71510c912c45e305f8c8e17db..58fdb9d9930c5b395f9b98f8b88f81b74766d3d5 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/close-account.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/close-account.js @@ -1,16 +1,16 @@ -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 { + 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) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/get-account-info.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/get-account-info.js index 7b8599a526446a2d55f70d04bed82e9098f71d53..b57fe00875567a68184011905e57de6261f73569 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/get-account-info.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/get-account-info.js @@ -1,69 +1,69 @@ -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') + +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) + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/index.js index f43cd273ecf3db93a98aabadb3c0f9d2e659b438..7a3a849c52544d59f3fdb75694d9ff7a64d40c61 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/index.js @@ -1,7 +1,7 @@ -module.exports = { - updatePwd: require('./update-pwd'), - resetPwdBySms: require('./reset-pwd-by-sms'), - resetPwdByEmail: require('./reset-pwd-by-email'), - closeAccount: require('./close-account'), - getAccountInfo: require('./get-account-info') -} +module.exports = { + updatePwd: require('./update-pwd'), + resetPwdBySms: require('./reset-pwd-by-sms'), + resetPwdByEmail: require('./reset-pwd-by-email'), + closeAccount: require('./close-account'), + getAccountInfo: require('./get-account-info') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-email.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-email.js index 914a05eed7c79ee3bbf249a473d146cc4f8ed0e7..63611b3d7b2010685b79d5a676a622be15b1969b 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-email.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-email.js @@ -1,119 +1,119 @@ -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 userMatched = await findUser.call(this, { - userQuery: { - email - }, - authorizedApp: [this.getClientInfo().appId] - }) - if (userMatched.length === 0) { - 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({ - 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 userMatched = await findUser.call(this, { + userQuery: { + email + }, + authorizedApp: [this.getClientInfo().appId] + }) + if (userMatched.length === 0) { + 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({ + 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 + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/add-user.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/add-user.js index 6baa5752c017281a02a7250da8d39e0dbf54f55f..5b494e2d1e5956682b299339e7a9d9739405eee8 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/add-user.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/add-user.js @@ -1,118 +1,118 @@ -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' - }, // 指定允许登录的app,传空数组或不传时表示可以不可以在任何端登录 - nickname: { - required: false, - type: 'nickname' - }, - role: { - require: false, - type: 'array' - }, - mobile: { - required: false, - type: 'mobile' - }, - email: { - required: false, - type: 'email' - }, - tags: { - required: false, - type: 'array' - }, - 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({ - 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 - } - - await userCollection.add(data) - 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' + }, // 指定允许登录的app,传空数组或不传时表示可以不可以在任何端登录 + nickname: { + required: false, + type: 'nickname' + }, + role: { + require: false, + type: 'array' + }, + mobile: { + required: false, + type: 'mobile' + }, + email: { + required: false, + type: 'email' + }, + tags: { + required: false, + type: 'array' + }, + 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({ + 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 + } + + await userCollection.add(data) + return { + errCode: 0, + errMsg: '' + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/index.js index c8830f54d386f85177ee549b25af2dc5a5251601..6baff53690413a0b33e5fd8f3783c678d60cf212 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/index.js @@ -1,4 +1,4 @@ -module.exports = { - addUser: require('./add-user'), - updateUser: require('./update-user') -} +module.exports = { + addUser: require('./add-user'), + updateUser: require('./update-user') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/dev/get-supported-login-type.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/dev/get-supported-login-type.js index 476e23427b81752a94c19602ecb41dde16bc689b..7d235fed9ca3dbee0a7a55bdf94b2d3b3a1cde21 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/dev/get-supported-login-type.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/dev/get-supported-login-type.js @@ -1,71 +1,71 @@ -function isMobileCodeSupported () { - const config = this.config - return !!(config.service && config.service.sms && config.service.sms.smsKey) -} - -function isUniverifySupport () { - const config = this.config - return !!(config.service && config.service.univerify && config.service.univerify.apiKey) -} - -function isWeixinSupported () { - this.configUtils.getOauthConfig({ - provider: 'weixin' - }) - return true -} - -function isQQSupported () { - this.configUtils.getOauthConfig({ - provider: 'qq' - }) - return true -} - -function isAppleSupported () { - this.configUtils.getOauthConfig({ - provider: 'apple' - }) - return true -} - -function isAlipaySupported () { - this.configUtils.getOauthConfig({ - provider: 'alipay' - }) - return true -} - -const loginTypeTester = { - 'mobile-code': isMobileCodeSupported, - univerify: isUniverifySupport, - weixin: isWeixinSupported, - qq: isQQSupported, - apple: isAppleSupported, - alipay: isAlipaySupported -} - -/** - * 获取支持的登录方式 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#get-supported-login-type - * @returns - */ -module.exports = async function () { - const supportedLoginType = [ - 'username-password', - 'mobile-password', - 'email-password' - ] - for (const type in loginTypeTester) { - try { - if (loginTypeTester[type].call(this)) { - supportedLoginType.push(type) - } - } catch (error) { } - } - return { - errCode: 0, - errMsg: '', - supportedLoginType - } -} +function isMobileCodeSupported () { + const config = this.config + return !!(config.service && config.service.sms && config.service.sms.smsKey) +} + +function isUniverifySupport () { + const config = this.config + return !!(config.service && config.service.univerify && config.service.univerify.apiKey) +} + +function isWeixinSupported () { + this.configUtils.getOauthConfig({ + provider: 'weixin' + }) + return true +} + +function isQQSupported () { + this.configUtils.getOauthConfig({ + provider: 'qq' + }) + return true +} + +function isAppleSupported () { + this.configUtils.getOauthConfig({ + provider: 'apple' + }) + return true +} + +function isAlipaySupported () { + this.configUtils.getOauthConfig({ + provider: 'alipay' + }) + return true +} + +const loginTypeTester = { + 'mobile-code': isMobileCodeSupported, + univerify: isUniverifySupport, + weixin: isWeixinSupported, + qq: isQQSupported, + apple: isAppleSupported, + alipay: isAlipaySupported +} + +/** + * 获取支持的登录方式 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#get-supported-login-type + * @returns + */ +module.exports = async function () { + const supportedLoginType = [ + 'username-password', + 'mobile-password', + 'email-password' + ] + for (const type in loginTypeTester) { + try { + if (loginTypeTester[type].call(this)) { + supportedLoginType.push(type) + } + } catch (error) { } + } + return { + errCode: 0, + errMsg: '', + supportedLoginType + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/dev/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/dev/index.js index e22f9f2cb4624998e8e5c0a9d98d9a501ee6dacd..d6c28ccfc752a5b2099b4eb97009b875b46718c9 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/dev/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/dev/index.js @@ -1,3 +1,3 @@ -module.exports = { - getSupportedLoginType: require('./get-supported-login-type') -} +module.exports = { + getSupportedLoginType: require('./get-supported-login-type') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/accept-invite.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/accept-invite.js index 2461e061785728ae1cbb39e2d34ddb440be2eeff..c1d3ba97947924306c7f41a63240ea326c77855d 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/accept-invite.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/accept-invite.js @@ -1,25 +1,25 @@ -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 { + 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 + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/get-invited-user.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/get-invited-user.js index 93d46719ca702b115db3e92f7c6c6fe27afad658..d232977d22eb2bde4b4d621930075069cc5157db 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/get-invited-user.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/get-invited-user.js @@ -1,80 +1,80 @@ -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 { + 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 +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/index.js index 4a9bee11743e422d1be4cecda7ccc0cab6788e74..dcca9a34e10c8da7685e5330f167d7f88e0e57cd 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/fission/index.js @@ -1,4 +1,4 @@ -module.exports = { - acceptInvite: require('./accept-invite'), - getInvitedUser: require('./get-invited-user') -} +module.exports = { + acceptInvite: require('./accept-invite'), + getInvitedUser: require('./get-invited-user') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/index.js index e1d8593b5903b005a3d911fb63134b75e7c4ddea..7fbd964477f8e4621045f5f30590e65c69e6672c 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/index.js @@ -1,19 +1,20 @@ -module.exports = { - login: require('./login'), - loginBySms: require('./login-by-sms'), - loginByUniverify: require('./login-by-univerify'), - loginByWeixin: require('./login-by-weixin'), - loginByAlipay: require('./login-by-alipay'), - loginByQQ: require('./login-by-qq'), - loginByApple: require('./login-by-apple'), - loginByBaidu: require('./login-by-baidu'), - loginByDingtalk: require('./login-by-dingtalk'), - loginByToutiao: require('./login-by-toutiao'), - loginByDouyin: require('./login-by-douyin'), - loginByWeibo: require('./login-by-weibo'), - loginByTaobao: require('./login-by-taobao'), - loginByEmailLink: require('./login-by-email-link'), - loginByEmailCode: require('./login-by-email-code'), - loginByFacebook: require('./login-by-facebook'), - loginByGoogle: require('./login-by-google') -} +module.exports = { + login: require('./login'), + loginBySms: require('./login-by-sms'), + loginByUniverify: require('./login-by-univerify'), + loginByWeixin: require('./login-by-weixin'), + loginByAlipay: require('./login-by-alipay'), + loginByQQ: require('./login-by-qq'), + loginByApple: require('./login-by-apple'), + loginByBaidu: require('./login-by-baidu'), + loginByDingtalk: require('./login-by-dingtalk'), + loginByToutiao: require('./login-by-toutiao'), + loginByDouyin: require('./login-by-douyin'), + loginByWeibo: require('./login-by-weibo'), + loginByTaobao: require('./login-by-taobao'), + loginByEmailLink: require('./login-by-email-link'), + loginByEmailCode: require('./login-by-email-code'), + loginByFacebook: require('./login-by-facebook'), + loginByGoogle: require('./login-by-google'), + loginByWeixinMobile: require('./login-by-weixin-mobile') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-alipay.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-alipay.js index d5d463147a1bb805d12c13e38e621169d7b948a9..4611b0cb7a9536e30c26060a5157b12d03b7c242 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-alipay.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-alipay.js @@ -1,70 +1,70 @@ -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 { + 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 + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-apple.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-apple.js index 5f39e62348c673c870b0a4da10a68f544d7c82fa..5a1e2fefa6548b5cc9c074ba77eb935d1fcbefcf 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-apple.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-apple.js @@ -1,77 +1,77 @@ -const { - initApple -} = 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-apple - * @param {Object} params - * @param {String} params.identityToken 苹果登录返回的identityToken - * @param {String} params.nickname 用户昵称 - * @param {String} params.inviteCode 邀请码 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - identityToken: 'string', - nickname: { - required: false, - type: 'nickname' - }, - inviteCode: { - required: false, - type: 'string' - } - } - this.middleware.validate(params, schema) - const { - identityToken, - nickname, - inviteCode - } = params - const appleApi = initApple.call(this) - let verifyResult - try { - verifyResult = await appleApi.verifyIdentityToken(identityToken) - } 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 - } = verifyResult - - const { - type, - user - } = await preUnifiedLogin.call(this, { - user: { - apple_openid: openid - } - }) - return postUnifiedLogin.call(this, { - user, - extraData: { - nickname - }, - isThirdParty: true, - type, - inviteCode - }) -} +const { + initApple +} = 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-apple + * @param {Object} params + * @param {String} params.identityToken 苹果登录返回的identityToken + * @param {String} params.nickname 用户昵称 + * @param {String} params.inviteCode 邀请码 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + identityToken: 'string', + nickname: { + required: false, + type: 'nickname' + }, + inviteCode: { + required: false, + type: 'string' + } + } + this.middleware.validate(params, schema) + const { + identityToken, + nickname, + inviteCode + } = params + const appleApi = initApple.call(this) + let verifyResult + try { + verifyResult = await appleApi.verifyIdentityToken(identityToken) + } 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 + } = verifyResult + + const { + type, + user + } = await preUnifiedLogin.call(this, { + user: { + apple_openid: openid + } + }) + return postUnifiedLogin.call(this, { + user, + extraData: { + nickname + }, + isThirdParty: true, + type, + inviteCode + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-baidu.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-baidu.js index 856449dcaefd02dcc40934fec3fbfec8e8cb6a68..9d4b453993e8f2cf98f45b55d8aafe3be392c308 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-baidu.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-baidu.js @@ -1,9 +1,9 @@ -/** - * 百度登录 - * @param {Object} params - * @returns - */ -module.exports = async function (params = {}) { - // 此接口暂未实现,欢迎向我们提交pr - throw new Error('api[loginByBaidu] is not yet implemented') -} +/** + * 百度登录 + * @param {Object} params + * @returns + */ +module.exports = async function (params = {}) { + // 此接口暂未实现,欢迎向我们提交pr + throw new Error('api[loginByBaidu] is not yet implemented') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-dingtalk.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-dingtalk.js index afe1f016fdf70f0d2e4de01358d6b49294dda3c4..22c2f8b620a589ac772c290f62b9652d83f7691f 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-dingtalk.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-dingtalk.js @@ -1,9 +1,9 @@ -/** - * 钉钉登录 - * @param {Object} params - * @returns - */ -module.exports = async function (params = {}) { - // 此接口暂未实现,欢迎向我们提交pr - throw new Error('api[loginByDingtalk] is not yet implemented') -} +/** + * 钉钉登录 + * @param {Object} params + * @returns + */ +module.exports = async function (params = {}) { + // 此接口暂未实现,欢迎向我们提交pr + throw new Error('api[loginByDingtalk] is not yet implemented') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-douyin.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-douyin.js index 8cd4ab563115eb9b07d85d5f79d185c2ff2ee081..cecf581a652a22e70e1ffc52dfba006c1efb5aa9 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-douyin.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-douyin.js @@ -1,9 +1,9 @@ -/** - * 抖音登录 - * @param {Object} params - * @returns - */ -module.exports = async function (params = {}) { - // 此接口暂未实现,欢迎向我们提交pr - throw new Error('api[loginByDouyin] is not yet implemented') -} +/** + * 抖音登录 + * @param {Object} params + * @returns + */ +module.exports = async function (params = {}) { + // 此接口暂未实现,欢迎向我们提交pr + throw new Error('api[loginByDouyin] is not yet implemented') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-email-code.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-email-code.js index c3af08f0c677ce8214a006aa4fa7a51a6a9909a6..1f3c3a663ba073bcd52647ddd3639a014624504e 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-email-code.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-email-code.js @@ -1,9 +1,9 @@ -/** - * 邮箱验证码登录 - * @param {Object} params - * @returns - */ -module.exports = async function (params = {}) { - // 此接口暂未实现,欢迎向我们提交pr - throw new Error('api[loginByEmailCode] is not yet implemented') -} +/** + * 邮箱验证码登录 + * @param {Object} params + * @returns + */ +module.exports = async function (params = {}) { + // 此接口暂未实现,欢迎向我们提交pr + throw new Error('api[loginByEmailCode] is not yet implemented') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-email-link.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-email-link.js index 0ebbf3acef93d4265e094e35cf49c6fbf1a7538e..a8f9e6ffd3c77d41d00ee2e4274f67bd8c2d7056 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-email-link.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-email-link.js @@ -1,9 +1,9 @@ -/** - * 邮箱点击链接登录 - * @param {Object} params - * @returns - */ -module.exports = async function (params = {}) { - // 此接口暂未实现,欢迎向我们提交pr - throw new Error('api[loginByEmailLink] is not yet implemented') -} +/** + * 邮箱点击链接登录 + * @param {Object} params + * @returns + */ +module.exports = async function (params = {}) { + // 此接口暂未实现,欢迎向我们提交pr + throw new Error('api[loginByEmailLink] is not yet implemented') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-facebook.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-facebook.js index 5c93bd4d242d579923ceed479a1f6bf51e54dc24..1a5eab894faee54904f8f6b4aa9aee5aeab58d66 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-facebook.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-facebook.js @@ -1,9 +1,9 @@ -/** - * Facebook登录 - * @param {Object} params - * @returns - */ -module.exports = async function (params = {}) { - // 此接口暂未实现,欢迎向我们提交pr - throw new Error('api[loginByFacebook] is not yet implemented') -} +/** + * Facebook登录 + * @param {Object} params + * @returns + */ +module.exports = async function (params = {}) { + // 此接口暂未实现,欢迎向我们提交pr + throw new Error('api[loginByFacebook] is not yet implemented') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-google.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-google.js index 8054ece6a4aeb94c85d37d9df7c4bc0aac4a93cc..c12efe3e2385952edf45429ae30c42047f0b40f9 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-google.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-google.js @@ -1,9 +1,9 @@ -/** - * Google登录 - * @param {Object} params - * @returns - */ -module.exports = async function (params = {}) { - // 此接口暂未实现,欢迎向我们提交pr - throw new Error('api[loginByGoogle] is not yet implemented') -} +/** + * Google登录 + * @param {Object} params + * @returns + */ +module.exports = async function (params = {}) { + // 此接口暂未实现,欢迎向我们提交pr + throw new Error('api[loginByGoogle] is not yet implemented') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-qq.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-qq.js index 13379d724a5fbb1593b0c3c3d26318133048cf46..9f7b0cea1aa889ebc6b093f71b134e59b301e16e 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-qq.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-qq.js @@ -1,164 +1,164 @@ -const { - initQQ -} = require('../../lib/third-party/index') -const { - ERROR -} = require('../../common/error') -const { - preUnifiedLogin, - postUnifiedLogin -} = require('../../lib/utils/unified-login') -const { - LOG_TYPE -} = require('../../common/constants') -const { - getQQPlatform, - generateQQCache, - saveQQUserKey -} = require('../../lib/utils/qq') -const url = require('url') - -/** - * QQ登录 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login-by-qq - * @param {Object} params - * @param {String} params.code QQ小程序登录返回的code参数 - * @param {String} params.accessToken App端QQ登录返回的accessToken参数 - * @param {String} params.accessTokenExpired accessToken过期时间,由App端QQ登录返回的expires_in参数计算而来,单位:毫秒 - * @param {String} params.inviteCode 邀请码 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - code: { - type: 'string', - required: false - }, - accessToken: { - type: 'string', - required: false - }, - accessTokenExpired: { - type: 'number', - required: false - }, - inviteCode: { - type: 'string', - required: false - } - } - this.middleware.validate(params, schema) - const { - code, - accessToken, - accessTokenExpired, - inviteCode - } = params - const { - appId - } = this.getClientInfo() - const qqApi = initQQ.call(this) - const qqPlatform = getQQPlatform.call(this) - let apiName - switch (qqPlatform) { - case 'mp': - apiName = 'code2Session' - break - case 'app': - apiName = 'getOpenidByToken' - break - default: - throw new Error('Unsupported qq platform') - } - let getQQAccountResult - try { - getQQAccountResult = await qqApi[apiName]({ - code, - accessToken - }) - } 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, - unionid, - // 保存下面的字段 - sessionKey // QQ小程序用户sessionKey - } = getQQAccountResult - - const { - type, - user - } = await preUnifiedLogin.call(this, { - user: { - qq_openid: { - [qqPlatform]: openid - }, - qq_unionid: unionid - } - }) - const extraData = { - qq_openid: { - [`${qqPlatform}_${appId}`]: openid - } - } - if (type === 'register' && qqPlatform !== 'mp') { - const { - nickname, - avatar - } = await qqApi.getUserInfo({ - accessToken, - openid - }) - // eslint-disable-next-line n/no-deprecated-api - const extName = url.parse(avatar).pathname.split('.').pop() - const cloudPath = `user/avatar/${openid.slice(-8) + Date.now()}-avatar.${extName}` - const getAvatarRes = await uniCloud.httpclient.request(avatar) - if (getAvatarRes.status >= 400) { - throw { - errCode: ERROR.GET_THIRD_PARTY_USER_INFO_FAILED - } - } - const { - fileID - } = await uniCloud.uploadFile({ - cloudPath, - fileContent: getAvatarRes.data - }) - extraData.nickname = nickname - extraData.avatar_file = { - name: cloudPath, - extname: extName, - url: fileID - } - } - await saveQQUserKey.call(this, { - openid, - sessionKey, - accessToken, - accessTokenExpired - }) - return postUnifiedLogin.call(this, { - user, - extraData: { - ...extraData, - ...generateQQCache.call(this, { - openid, - sessionKey, // QQ小程序用户sessionKey - accessToken, // App端QQ用户accessToken - accessTokenExpired // App端QQ用户accessToken过期时间 - }) - }, - isThirdParty: true, - type, - inviteCode - }) -} +const { + initQQ +} = require('../../lib/third-party/index') +const { + ERROR +} = require('../../common/error') +const { + preUnifiedLogin, + postUnifiedLogin +} = require('../../lib/utils/unified-login') +const { + LOG_TYPE +} = require('../../common/constants') +const { + getQQPlatform, + generateQQCache, + saveQQUserKey +} = require('../../lib/utils/qq') +const url = require('url') + +/** + * QQ登录 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login-by-qq + * @param {Object} params + * @param {String} params.code QQ小程序登录返回的code参数 + * @param {String} params.accessToken App端QQ登录返回的accessToken参数 + * @param {String} params.accessTokenExpired accessToken过期时间,由App端QQ登录返回的expires_in参数计算而来,单位:毫秒 + * @param {String} params.inviteCode 邀请码 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + code: { + type: 'string', + required: false + }, + accessToken: { + type: 'string', + required: false + }, + accessTokenExpired: { + type: 'number', + required: false + }, + inviteCode: { + type: 'string', + required: false + } + } + this.middleware.validate(params, schema) + const { + code, + accessToken, + accessTokenExpired, + inviteCode + } = params + const { + appId + } = this.getClientInfo() + const qqApi = initQQ.call(this) + const qqPlatform = getQQPlatform.call(this) + let apiName + switch (qqPlatform) { + case 'mp': + apiName = 'code2Session' + break + case 'app': + apiName = 'getOpenidByToken' + break + default: + throw new Error('Unsupported qq platform') + } + let getQQAccountResult + try { + getQQAccountResult = await qqApi[apiName]({ + code, + accessToken + }) + } 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, + unionid, + // 保存下面的字段 + sessionKey // QQ小程序用户sessionKey + } = getQQAccountResult + + const { + type, + user + } = await preUnifiedLogin.call(this, { + user: { + qq_openid: { + [qqPlatform]: openid + }, + qq_unionid: unionid + } + }) + const extraData = { + qq_openid: { + [`${qqPlatform}_${appId}`]: openid + } + } + if (type === 'register' && qqPlatform !== 'mp') { + const { + nickname, + avatar + } = await qqApi.getUserInfo({ + accessToken, + openid + }) + // eslint-disable-next-line n/no-deprecated-api + const extName = url.parse(avatar).pathname.split('.').pop() + const cloudPath = `user/avatar/${openid.slice(-8) + Date.now()}-avatar.${extName}` + const getAvatarRes = await uniCloud.httpclient.request(avatar) + if (getAvatarRes.status >= 400) { + throw { + errCode: ERROR.GET_THIRD_PARTY_USER_INFO_FAILED + } + } + const { + fileID + } = await uniCloud.uploadFile({ + cloudPath, + fileContent: getAvatarRes.data + }) + extraData.nickname = nickname + extraData.avatar_file = { + name: cloudPath, + extname: extName, + url: fileID + } + } + await saveQQUserKey.call(this, { + openid, + sessionKey, + accessToken, + accessTokenExpired + }) + return postUnifiedLogin.call(this, { + user, + extraData: { + ...extraData, + ...generateQQCache.call(this, { + openid, + sessionKey, // QQ小程序用户sessionKey + accessToken, // App端QQ用户accessToken + accessTokenExpired // App端QQ用户accessToken过期时间 + }) + }, + isThirdParty: true, + type, + inviteCode + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-taobao.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-taobao.js index 6a6d5994e0bc9952c09fcf5274a92082ddca370c..8234fa072fcffaacd2d6b32c1517e3f67f828b0d 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-taobao.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-taobao.js @@ -1,9 +1,9 @@ -/** - * 淘宝登录 - * @param {Object} params - * @returns - */ -module.exports = async function (params = {}) { - // 此接口暂未实现,欢迎向我们提交pr - throw new Error('api[loginByTaobao] is not yet implemented') -} +/** + * 淘宝登录 + * @param {Object} params + * @returns + */ +module.exports = async function (params = {}) { + // 此接口暂未实现,欢迎向我们提交pr + throw new Error('api[loginByTaobao] is not yet implemented') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-toutiao.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-toutiao.js index 133aadbaad31f2a5ba411c7afb5f82f7fc2c00f1..11fda9b404989b7567722f7e98bf0faf38bddbd5 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-toutiao.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-toutiao.js @@ -1,9 +1,9 @@ -/** - * 头条登录 - * @param {Object} params - * @returns - */ -module.exports = async function (params = {}) { - // 此接口暂未实现,欢迎向我们提交pr - throw new Error('api[loginByToutiao] is not yet implemented') -} +/** + * 头条登录 + * @param {Object} params + * @returns + */ +module.exports = async function (params = {}) { + // 此接口暂未实现,欢迎向我们提交pr + throw new Error('api[loginByToutiao] is not yet implemented') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-univerify.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-univerify.js index 53e681c68636dcc4e8f5abeb9f00f9ef0ffab73e..05199b0ae2a364302840bdddf8e0654d0ef2dac3 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-univerify.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-univerify.js @@ -1,69 +1,69 @@ -const { - getPhoneNumber -} = require('../../lib/utils/univerify') -const { - preUnifiedLogin, - postUnifiedLogin -} = require('../../lib/utils/unified-login') -const { - LOG_TYPE -} = require('../../common/constants') - -/** - * App端一键登录 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login-by-univerify - * @param {Object} params - * @param {String} params.access_token APP端一键登录返回的access_token - * @param {String} params.openid APP端一键登录返回的openid - * @param {String} params.inviteCode 邀请码 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - access_token: 'string', - openid: 'string', - inviteCode: { - required: false, - type: 'string' - } - } - this.middleware.validate(params, schema) - const { - // eslint-disable-next-line camelcase - access_token, - openid, - inviteCode - } = params - - let mobile - try { - const phoneInfo = await getPhoneNumber.call(this, { - // eslint-disable-next-line camelcase - access_token, - openid - }) - mobile = phoneInfo.phoneNumber - } catch (error) { - await this.middleware.uniIdLog({ - success: false, - type: LOG_TYPE.LOGIN - }) - throw error - } - const { - user, - type - } = await preUnifiedLogin.call(this, { - user: { - mobile - } - }) - return postUnifiedLogin.call(this, { - user, - extraData: { - mobile_confirmed: 1 - }, - type, - inviteCode - }) -} +const { + getPhoneNumber +} = require('../../lib/utils/univerify') +const { + preUnifiedLogin, + postUnifiedLogin +} = require('../../lib/utils/unified-login') +const { + LOG_TYPE +} = require('../../common/constants') + +/** + * App端一键登录 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login-by-univerify + * @param {Object} params + * @param {String} params.access_token APP端一键登录返回的access_token + * @param {String} params.openid APP端一键登录返回的openid + * @param {String} params.inviteCode 邀请码 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + access_token: 'string', + openid: 'string', + inviteCode: { + required: false, + type: 'string' + } + } + this.middleware.validate(params, schema) + const { + // eslint-disable-next-line camelcase + access_token, + openid, + inviteCode + } = params + + let mobile + try { + const phoneInfo = await getPhoneNumber.call(this, { + // eslint-disable-next-line camelcase + access_token, + openid + }) + mobile = phoneInfo.phoneNumber + } catch (error) { + await this.middleware.uniIdLog({ + success: false, + type: LOG_TYPE.LOGIN + }) + throw error + } + const { + user, + type + } = await preUnifiedLogin.call(this, { + user: { + mobile + } + }) + return postUnifiedLogin.call(this, { + user, + extraData: { + mobile_confirmed: 1 + }, + type, + inviteCode + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weibo.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weibo.js index 496cdb4b262e60ad861b64f207f3e3ac8a377102..b12a17f2abede705641f7ed01026b5813cc45b44 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weibo.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weibo.js @@ -1,9 +1,9 @@ -/** - * 微博登录 - * @param {Object} params - * @returns - */ -module.exports = async function (params = {}) { - // 此接口暂未实现,欢迎向我们提交pr - throw new Error('api[loginByWeibo] is not yet implemented') -} +/** + * 微博登录 + * @param {Object} params + * @returns + */ +module.exports = async function (params = {}) { + // 此接口暂未实现,欢迎向我们提交pr + throw new Error('api[loginByWeibo] is not yet implemented') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin-mobile.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin-mobile.js new file mode 100644 index 0000000000000000000000000000000000000000..f26b2b030d7213bdf294200a0152bcd698acfca9 --- /dev/null +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin-mobile.js @@ -0,0 +1,109 @@ +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 + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin.js index 84c7ddc1f254894ea224ca2d3cc1e401b0135052..d2a4bcf57c686fb25bc6c8dde21d1a917f31be31 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login-by-weixin.js @@ -1,154 +1,154 @@ -const { - initWeixin -} = require('../../lib/third-party/index') -const { - ERROR -} = require('../../common/error') -const { - preUnifiedLogin, - postUnifiedLogin -} = require('../../lib/utils/unified-login') -const { - generateWeixinCache, - getWeixinPlatform, - saveWeixinUserKey -} = require('../../lib/utils/weixin') -const { - LOG_TYPE -} = require('../../common/constants') -const url = require('url') - -/** - * 微信登录 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login-by-weixin - * @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 { - appId - } = this.getClientInfo() - const weixinApi = initWeixin.call(this) - const weixinPlatform = getWeixinPlatform.call(this) - let apiName - switch (weixinPlatform) { - case 'mp': - apiName = 'code2Session' - break - case 'app': - case 'h5': - case 'web': - apiName = 'getOauthAccessToken' - break - default: - throw new Error('Unsupported weixin platform') - } - let getWeixinAccountResult - try { - getWeixinAccountResult = await weixinApi[apiName](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, - unionid, - // 保存下面四个字段 - sessionKey, // 微信小程序用户sessionKey - accessToken, // App端微信用户accessToken - refreshToken, // App端微信用户refreshToken - expired: accessTokenExpired // App端微信用户accessToken过期时间 - } = getWeixinAccountResult - - const { - type, - user - } = await preUnifiedLogin.call(this, { - user: { - wx_openid: { - [weixinPlatform]: openid - }, - wx_unionid: unionid - } - }) - const extraData = { - wx_openid: { - [`${weixinPlatform}_${appId}`]: openid - } - } - if (type === 'register' && weixinPlatform !== 'mp') { - const { - nickname, - avatar - } = await weixinApi.getUserInfo({ - accessToken, - openid - }) - // eslint-disable-next-line n/no-deprecated-api - const avatarPath = url.parse(avatar).pathname - const extName = avatarPath.indexOf('.') > -1 ? url.parse(avatar).pathname.split('.').pop() : 'jpg' - const cloudPath = `user/avatar/${openid.slice(-8) + Date.now()}-avatar.${extName}` - const getAvatarRes = await uniCloud.httpclient.request(avatar) - if (getAvatarRes.status >= 400) { - throw { - errCode: ERROR.GET_THIRD_PARTY_USER_INFO_FAILED - } - } - const { - fileID - } = await uniCloud.uploadFile({ - cloudPath, - fileContent: getAvatarRes.data - }) - extraData.nickname = nickname - extraData.avatar_file = { - name: cloudPath, - extname: extName, - url: fileID - } - } - await saveWeixinUserKey.call(this, { - openid, - sessionKey, - accessToken, - refreshToken, - accessTokenExpired - }) - return postUnifiedLogin.call(this, { - user, - extraData: { - ...extraData, - ...generateWeixinCache.call(this, { - openid, - sessionKey, // 微信小程序用户sessionKey - accessToken, // App端微信用户accessToken - refreshToken, // App端微信用户refreshToken - accessTokenExpired // App端微信用户accessToken过期时间 - }) - }, - isThirdParty: true, - type, - inviteCode - }) -} +const { + initWeixin +} = require('../../lib/third-party/index') +const { + ERROR +} = require('../../common/error') +const { + preUnifiedLogin, + postUnifiedLogin +} = require('../../lib/utils/unified-login') +const { + generateWeixinCache, + getWeixinPlatform, + saveWeixinUserKey +} = require('../../lib/utils/weixin') +const { + LOG_TYPE +} = require('../../common/constants') +const url = require('url') + +/** + * 微信登录 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login-by-weixin + * @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 { + appId + } = this.getClientInfo() + const weixinApi = initWeixin.call(this) + const weixinPlatform = getWeixinPlatform.call(this) + let apiName + switch (weixinPlatform) { + case 'mp': + apiName = 'code2Session' + break + case 'app': + case 'h5': + case 'web': + apiName = 'getOauthAccessToken' + break + default: + throw new Error('Unsupported weixin platform') + } + let getWeixinAccountResult + try { + getWeixinAccountResult = await weixinApi[apiName](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, + unionid, + // 保存下面四个字段 + sessionKey, // 微信小程序用户sessionKey + accessToken, // App端微信用户accessToken + refreshToken, // App端微信用户refreshToken + expired: accessTokenExpired // App端微信用户accessToken过期时间 + } = getWeixinAccountResult + + const { + type, + user + } = await preUnifiedLogin.call(this, { + user: { + wx_openid: { + [weixinPlatform]: openid + }, + wx_unionid: unionid + } + }) + const extraData = { + wx_openid: { + [`${weixinPlatform}_${appId}`]: openid + } + } + if (type === 'register' && weixinPlatform !== 'mp') { + const { + nickname, + avatar + } = await weixinApi.getUserInfo({ + accessToken, + openid + }) + // eslint-disable-next-line n/no-deprecated-api + const avatarPath = url.parse(avatar).pathname + const extName = avatarPath.indexOf('.') > -1 ? url.parse(avatar).pathname.split('.').pop() : 'jpg' + const cloudPath = `user/avatar/${openid.slice(-8) + Date.now()}-avatar.${extName}` + const getAvatarRes = await uniCloud.httpclient.request(avatar) + if (getAvatarRes.status >= 400) { + throw { + errCode: ERROR.GET_THIRD_PARTY_USER_INFO_FAILED + } + } + const { + fileID + } = await uniCloud.uploadFile({ + cloudPath, + fileContent: getAvatarRes.data + }) + extraData.nickname = nickname + extraData.avatar_file = { + name: cloudPath, + extname: extName, + url: fileID + } + } + await saveWeixinUserKey.call(this, { + openid, + sessionKey, + accessToken, + refreshToken, + accessTokenExpired + }) + return postUnifiedLogin.call(this, { + user, + extraData: { + ...extraData, + ...generateWeixinCache.call(this, { + openid, + sessionKey, // 微信小程序用户sessionKey + accessToken, // App端微信用户accessToken + refreshToken, // App端微信用户refreshToken + accessTokenExpired // App端微信用户accessToken过期时间 + }) + }, + isThirdParty: true, + type, + inviteCode + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login.js index 97e9cfea7ec33c546196fd03cf03464179954a50..8419ee8b0e85bc873c94284ceff6e3238c4f1b1b 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/login/login.js @@ -1,94 +1,94 @@ -const { - preLoginWithPassword, - postLogin -} = require('../../lib/utils/login') -const { - getNeedCaptcha, - verifyCaptcha -} = require('../../lib/utils/captcha') -const { - CAPTCHA_SCENE -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') - -/** - * 用户名密码登录 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login - * @param {Object} params - * @param {String} params.username 用户名 - * @param {String} params.mobile 手机号 - * @param {String} params.email 邮箱 - * @param {String} params.password 密码 - * @param {String} params.captcha 图形验证码 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - username: { - required: false, - type: 'username' - }, - mobile: { - required: false, - type: 'mobile' - }, - email: { - required: false, - type: 'email' - }, - password: 'password', - captcha: { - required: false, - type: 'string' - } - } - this.middleware.validate(params, schema) - const { - username, - mobile, - email, - password, - captcha - } = params - if (!username && !mobile && !email) { - throw { - errCode: ERROR.INVALID_USERNAME - } - } else if ( - (username && email) || - (username && mobile) || - (email && mobile) - ) { - throw { - errCode: ERROR.INVALID_PARAM - } - } - const needCaptcha = await getNeedCaptcha.call(this, { - username, - mobile, - email - }) - if (needCaptcha) { - await verifyCaptcha.call(this, { - captcha, - scene: CAPTCHA_SCENE.LOGIN_BY_PWD - }) - } - const { - user, - extraData - } = await preLoginWithPassword.call(this, { - user: { - username, - mobile, - email - }, - password - }) - return postLogin.call(this, { - user, - extraData - }) -} +const { + preLoginWithPassword, + postLogin +} = require('../../lib/utils/login') +const { + getNeedCaptcha, + verifyCaptcha +} = require('../../lib/utils/captcha') +const { + CAPTCHA_SCENE +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') + +/** + * 用户名密码登录 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#login + * @param {Object} params + * @param {String} params.username 用户名 + * @param {String} params.mobile 手机号 + * @param {String} params.email 邮箱 + * @param {String} params.password 密码 + * @param {String} params.captcha 图形验证码 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + username: { + required: false, + type: 'username' + }, + mobile: { + required: false, + type: 'mobile' + }, + email: { + required: false, + type: 'email' + }, + password: 'password', + captcha: { + required: false, + type: 'string' + } + } + this.middleware.validate(params, schema) + const { + username, + mobile, + email, + password, + captcha + } = params + if (!username && !mobile && !email) { + throw { + errCode: ERROR.INVALID_USERNAME + } + } else if ( + (username && email) || + (username && mobile) || + (email && mobile) + ) { + throw { + errCode: ERROR.INVALID_PARAM + } + } + const needCaptcha = await getNeedCaptcha.call(this, { + username, + mobile, + email + }) + if (needCaptcha) { + await verifyCaptcha.call(this, { + captcha, + scene: CAPTCHA_SCENE.LOGIN_BY_PWD + }) + } + const { + user, + extraData + } = await preLoginWithPassword.call(this, { + user: { + username, + mobile, + email + }, + password + }) + return postLogin.call(this, { + user, + extraData + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/logout/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/logout/index.js index 544be2b715a7beb3b51e15e028b5231a6016b3be..897cc1c6e2e37f83faa9fbbe0b06373c0352f4c5 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/logout/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/logout/index.js @@ -1,3 +1,3 @@ -module.exports = { - logout: require('./logout') -} +module.exports = { + logout: require('./logout') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/logout/logout.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/logout/logout.js index 7d491c61d3d3702a7370354ac4f8de217d9f1223..f11b4374e3e190ab78e7183748fd60fc61851e65 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/logout/logout.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/logout/logout.js @@ -1,15 +1,15 @@ -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 - } -} +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 + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/authorize-app-login.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/authorize-app-login.js index 8f8a167b1720f7e981e2fd955f647521c53253d0..c6861381fe706b6c5f36f6cf1642da29238e18f0 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/authorize-app-login.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/authorize-app-login.js @@ -1,37 +1,37 @@ -const { - isAuthorizeApproved -} = require('./utils') -const { - dbCmd, - userCollection -} = require('../../common/constants') - -/** - * 授权用户登录应用 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#authorize-app-login - * @param {Object} params - * @param {String} params.uid 用户id - * @param {String} params.appId 授权的应用的AppId - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - uid: 'string', - appId: 'string' - } - this.middleware.validate(params, schema) - const { - uid, - appId - } = params - await isAuthorizeApproved({ - uid, - appIdList: [appId] - }) - await userCollection.doc(uid).update({ - dcloud_appid: dbCmd.push(appId) - }) - return { - errCode: 0 - } -} +const { + isAuthorizeApproved +} = require('./utils') +const { + dbCmd, + userCollection +} = require('../../common/constants') + +/** + * 授权用户登录应用 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#authorize-app-login + * @param {Object} params + * @param {String} params.uid 用户id + * @param {String} params.appId 授权的应用的AppId + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + uid: 'string', + appId: 'string' + } + this.middleware.validate(params, schema) + const { + uid, + appId + } = params + await isAuthorizeApproved({ + uid, + appIdList: [appId] + }) + await userCollection.doc(uid).update({ + dcloud_appid: dbCmd.push(appId) + }) + return { + errCode: 0 + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/index.js index ce9cc7b07ae9c8300b8a25e6eb14ba49e89af56b..ee4dd44bdb84f1b4dae704800b2223dfca77a1c4 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/index.js @@ -1,5 +1,5 @@ -module.exports = { - authorizeAppLogin: require('./authorize-app-login'), - removeAuthorizedApp: require('./remove-authorized-app'), - setAuthorizedApp: require('./set-authorized-app') -} +module.exports = { + authorizeAppLogin: require('./authorize-app-login'), + removeAuthorizedApp: require('./remove-authorized-app'), + setAuthorizedApp: require('./set-authorized-app') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/remove-authorized-app.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/remove-authorized-app.js index df82184fa2c9e26c5db32910ca2110a0cb81eab0..4fa69dc647ec9ecdaeb7e6e785b9a3df9b658262 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/remove-authorized-app.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/remove-authorized-app.js @@ -1,30 +1,30 @@ -const { - dbCmd, - userCollection -} = require('../../common/constants') - -/** - * 移除用户登录授权 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#remove-authorized-app - * @param {Object} params - * @param {String} params.uid 用户id - * @param {String} params.appId 取消授权的应用的AppId - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - uid: 'string', - appId: 'string' - } - this.middleware.validate(params, schema) - const { - uid, - appId - } = params - await userCollection.doc(uid).update({ - dcloud_appid: dbCmd.pull(appId) - }) - return { - errCode: 0 - } -} +const { + dbCmd, + userCollection +} = require('../../common/constants') + +/** + * 移除用户登录授权 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#remove-authorized-app + * @param {Object} params + * @param {String} params.uid 用户id + * @param {String} params.appId 取消授权的应用的AppId + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + uid: 'string', + appId: 'string' + } + this.middleware.validate(params, schema) + const { + uid, + appId + } = params + await userCollection.doc(uid).update({ + dcloud_appid: dbCmd.pull(appId) + }) + return { + errCode: 0 + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/set-authorized-app.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/set-authorized-app.js index a438ef998052f3d1b66ebe5a3792ad194625ce71..774ececf1f0eaf1957e69c6d7372f9f8bc30859b 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/set-authorized-app.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/set-authorized-app.js @@ -1,36 +1,36 @@ -const { - isAuthorizeApproved -} = require('./utils') -const { - userCollection -} = require('../../common/constants') - -/** - * 设置用户允许登录的应用列表 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#set-authorized-app - * @param {Object} params - * @param {String} params.uid 用户id - * @param {Array} params.appIdList 允许登录的应用AppId列表 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - uid: 'string', - appIdList: 'array' - } - this.middleware.validate(params, schema) - const { - uid, - appIdList - } = params - await isAuthorizeApproved({ - uid, - appIdList - }) - await userCollection.doc(uid).update({ - dcloud_appid: appIdList - }) - return { - errCode: 0 - } -} +const { + isAuthorizeApproved +} = require('./utils') +const { + userCollection +} = require('../../common/constants') + +/** + * 设置用户允许登录的应用列表 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#set-authorized-app + * @param {Object} params + * @param {String} params.uid 用户id + * @param {Array} params.appIdList 允许登录的应用AppId列表 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + uid: 'string', + appIdList: 'array' + } + this.middleware.validate(params, schema) + const { + uid, + appIdList + } = params + await isAuthorizeApproved({ + uid, + appIdList + }) + await userCollection.doc(uid).update({ + dcloud_appid: appIdList + }) + return { + errCode: 0 + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/utils.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/utils.js index 0c0eb859e68d97c72d77bebdee92f08faeb13e45..364304d8bf082c8df7255e7653dc4f5cd140cf2a 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/utils.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/multi-end/utils.js @@ -1,36 +1,36 @@ -const { - userCollection -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') -const { - findUser -} = require('../../lib/utils/account') - -async function isAuthorizeApproved ({ - uid, - appIdList -} = {}) { - const getUserRes = await userCollection.doc(uid).get() - const userRecord = getUserRes.data[0] - if (!userRecord) { - throw { - errCode: ERROR.ACCOUNT_NOT_EXISTS - } - } - const userMatched = await findUser({ - userQuery: userRecord, - authorizedApp: appIdList - }) - - if (userMatched.some(item => item._id !== uid)) { - throw { - errCode: ERROR.ACCOUNT_CONFLICT - } - } -} - -module.exports = { - isAuthorizeApproved -} +const { + userCollection +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') +const { + findUser +} = require('../../lib/utils/account') + +async function isAuthorizeApproved ({ + uid, + appIdList +} = {}) { + const getUserRes = await userCollection.doc(uid).get() + const userRecord = getUserRes.data[0] + if (!userRecord) { + throw { + errCode: ERROR.ACCOUNT_NOT_EXISTS + } + } + const userMatched = await findUser({ + userQuery: userRecord, + authorizedApp: appIdList + }) + + if (userMatched.some(item => item._id !== uid)) { + throw { + errCode: ERROR.ACCOUNT_CONFLICT + } + } +} + +module.exports = { + isAuthorizeApproved +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/index.js index 64ff603cd9e0a0b8878006775cacc8be452dd22d..319210fa18f94ae614ae1967c516f25d65e2c1f4 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/index.js @@ -1,5 +1,5 @@ -module.exports = { - registerUser: require('./register-user'), - registerAdmin: require('./register-admin'), - registerUserByEmail: require('./register-user-by-email') -} +module.exports = { + registerUser: require('./register-user'), + registerAdmin: require('./register-admin'), + registerUserByEmail: require('./register-user-by-email') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/register-admin.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/register-admin.js index d9b8f330246031e307e29f2dbb6881609272dfec..21ca0913cfb679e1bab59d40d8d06f58fa5e1828 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/register-admin.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/register-admin.js @@ -1,62 +1,72 @@ -const { - userCollection -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') -const { - preRegisterWithPassword, - postRegister -} = require('../../lib/utils/register') - -/** - * 注册管理员 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#register-admin - * @param {Object} params - * @param {String} params.username 用户名 - * @param {String} params.password 密码 - * @param {String} params.nickname 昵称 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - username: 'username', - password: 'password', - nickname: { - type: 'nickname', - required: false - } - } - this.middleware.validate(params, schema) - const { - username, - password, - nickname - } = params - const getAdminRes = await userCollection.where({ - role: 'admin' - }).limit(1).get() - if (getAdminRes.data.length > 0) { - return { - errCode: ERROR.ADMIN_EXISTS, - errMsg: this.t('uni-id-admin-exists') - } - } - const { - user, - extraData - } = await preRegisterWithPassword.call(this, { - user: { - username - }, - password - }) - return postRegister.call(this, { - user, - extraData: { - ...extraData, - nickname, - role: ['admin'] - } - }) -} +const { + userCollection +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') +const { + preRegisterWithPassword, + postRegister +} = require('../../lib/utils/register') + +/** + * 注册管理员 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#register-admin + * @param {Object} params + * @param {String} params.username 用户名 + * @param {String} params.password 密码 + * @param {String} params.nickname 昵称 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + username: 'username', + password: 'password', + nickname: { + type: 'nickname', + required: false + } + } + this.middleware.validate(params, schema) + const { + username, + password, + nickname + } = params + const getAdminRes = await userCollection.where({ + role: 'admin' + }).limit(1).get() + if (getAdminRes.data.length > 0) { + 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 { + user, + extraData + } = await preRegisterWithPassword.call(this, { + user: { + username + }, + password + }) + return postRegister.call(this, { + user, + extraData: { + ...extraData, + nickname, + role: ['admin'] + } + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/register-user-by-email.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/register-user-by-email.js index b52c1d2513c28617e144edb34121c26b7270f5f8..f5a54c53993c47789444cd35aec3daac9b1991d3 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/register-user-by-email.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/register/register-user-by-email.js @@ -1,87 +1,87 @@ -const { - postRegister, - preRegisterWithPassword -} = require('../../lib/utils/register') -const { - verifyCaptcha -} = require('../../lib/utils/captcha') -const { - CAPTCHA_SCENE, - EMAIL_SCENE, - LOG_TYPE -} = require('../../common/constants') -const { - verifyEmailCode -} = require('../../lib/utils/verify-code') - -/** - * 通过邮箱+验证码注册普通用户 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#register-user-by-email - * @param {Object} params - * @param {String} params.email 邮箱 - * @param {String} params.password 密码 - * @param {String} params.nickname 昵称 - * @param {String} params.code 邮箱验证码 - * @param {String} params.inviteCode 邀请码 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - email: 'email', - password: 'password', - nickname: { - required: false, - type: 'nickname' - }, - code: 'string', - inviteCode: { - required: false, - type: 'string' - } - } - this.middleware.validate(params, schema) - const { - email, - password, - nickname, - code, - inviteCode - } = params - - try { - // 验证邮箱验证码,验证不通过时写入失败日志 - await verifyEmailCode({ - email, - code, - scene: EMAIL_SCENE.REGISTER - }) - } catch (error) { - await this.middleware.uniIdLog({ - data: { - email - }, - type: LOG_TYPE.REGISTER, - success: false - }) - throw error - } - - const { - user, - extraData - } = await preRegisterWithPassword.call(this, { - user: { - email - }, - password - }) - return postRegister.call(this, { - user, - extraData: { - ...extraData, - nickname, - email_confirmed: 1 - }, - inviteCode - }) -} +const { + postRegister, + preRegisterWithPassword +} = require('../../lib/utils/register') +const { + verifyCaptcha +} = require('../../lib/utils/captcha') +const { + CAPTCHA_SCENE, + EMAIL_SCENE, + LOG_TYPE +} = require('../../common/constants') +const { + verifyEmailCode +} = require('../../lib/utils/verify-code') + +/** + * 通过邮箱+验证码注册普通用户 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#register-user-by-email + * @param {Object} params + * @param {String} params.email 邮箱 + * @param {String} params.password 密码 + * @param {String} params.nickname 昵称 + * @param {String} params.code 邮箱验证码 + * @param {String} params.inviteCode 邀请码 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + email: 'email', + password: 'password', + nickname: { + required: false, + type: 'nickname' + }, + code: 'string', + inviteCode: { + required: false, + type: 'string' + } + } + this.middleware.validate(params, schema) + const { + email, + password, + nickname, + code, + inviteCode + } = params + + try { + // 验证邮箱验证码,验证不通过时写入失败日志 + await verifyEmailCode({ + email, + code, + scene: EMAIL_SCENE.REGISTER + }) + } catch (error) { + await this.middleware.uniIdLog({ + data: { + email + }, + type: LOG_TYPE.REGISTER, + success: false + }) + throw error + } + + const { + user, + extraData + } = await preRegisterWithPassword.call(this, { + user: { + email + }, + password + }) + return postRegister.call(this, { + user, + extraData: { + ...extraData, + nickname, + email_confirmed: 1 + }, + inviteCode + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-alipay.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-alipay.js index 7c0c399bdf48f258e0ba896e115b2f9f27c11beb..76e12477368e8467510752f4bddb09340f320c00 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-alipay.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-alipay.js @@ -1,63 +1,63 @@ -const { - preBind, - postBind -} = require('../../lib/utils/relate') -const { - LOG_TYPE -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') -const { - initAlipay -} = require('../../lib/third-party/index') - -/** - * 绑定支付宝账号 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#bind-alipay - * @param {Object} params - * @param {String} params.code 支付宝小程序登录返回的code参数 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - code: 'string' - } - this.middleware.validate(params, schema) - const uid = this.authInfo.uid - const { - code - } = params - const alipayApi = initAlipay.call(this) - let getAlipayAccountResult - try { - getAlipayAccountResult = await alipayApi().code2Session(code) - } catch (error) { - await this.middleware.uniIdLog({ - success: false, - type: LOG_TYPE.BIND_ALIPAY - }) - throw { - errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED - } - } - - const { - openid - } = getAlipayAccountResult - - const bindAccount = { - apple_openid: openid - } - await preBind.call(this, { - uid, - bindAccount, - logType: LOG_TYPE.BIND_APPLE - }) - return postBind.call(this, { - uid, - bindAccount, - extraData: {}, - logType: LOG_TYPE.BIND_APPLE - }) -} +const { + preBind, + postBind +} = require('../../lib/utils/relate') +const { + LOG_TYPE +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') +const { + initAlipay +} = require('../../lib/third-party/index') + +/** + * 绑定支付宝账号 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#bind-alipay + * @param {Object} params + * @param {String} params.code 支付宝小程序登录返回的code参数 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + code: 'string' + } + this.middleware.validate(params, schema) + const uid = this.authInfo.uid + const { + code + } = params + const alipayApi = initAlipay.call(this) + let getAlipayAccountResult + try { + getAlipayAccountResult = await alipayApi().code2Session(code) + } catch (error) { + await this.middleware.uniIdLog({ + success: false, + type: LOG_TYPE.BIND_ALIPAY + }) + throw { + errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED + } + } + + const { + openid + } = getAlipayAccountResult + + const bindAccount = { + ali_openid: openid + } + await preBind.call(this, { + uid, + bindAccount, + logType: LOG_TYPE.BIND_APPLE + }) + return postBind.call(this, { + uid, + bindAccount, + extraData: {}, + logType: LOG_TYPE.BIND_APPLE + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-apple.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-apple.js index eb87f8b7efe75e9ce85ad4890039702ad882639f..b87ac80428c4fab262fe9750f0970758fb0308fa 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-apple.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-apple.js @@ -1,62 +1,62 @@ -const { - preBind, - postBind -} = require('../../lib/utils/relate') -const { - LOG_TYPE -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') -const { - initApple -} = require('../../lib/third-party/index') - -/** - * 绑定苹果账号 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#bind-apple - * @param {Object} params - * @param {String} params.identityToken 苹果登录返回identityToken - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - identityToken: 'string' - } - this.middleware.validate(params, schema) - const uid = this.authInfo.uid - const { - identityToken - } = params - const appleApi = initApple.call(this) - let verifyResult - try { - verifyResult = await appleApi.verifyIdentityToken(identityToken) - } catch (error) { - await this.middleware.uniIdLog({ - success: false, - type: LOG_TYPE.BIND_APPLE - }) - throw { - errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED - } - } - const { - openid - } = verifyResult - - const bindAccount = { - apple_openid: openid - } - await preBind.call(this, { - uid, - bindAccount, - logType: LOG_TYPE.BIND_APPLE - }) - return postBind.call(this, { - uid, - bindAccount, - extraData: {}, - logType: LOG_TYPE.BIND_APPLE - }) -} +const { + preBind, + postBind +} = require('../../lib/utils/relate') +const { + LOG_TYPE +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') +const { + initApple +} = require('../../lib/third-party/index') + +/** + * 绑定苹果账号 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#bind-apple + * @param {Object} params + * @param {String} params.identityToken 苹果登录返回identityToken + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + identityToken: 'string' + } + this.middleware.validate(params, schema) + const uid = this.authInfo.uid + const { + identityToken + } = params + const appleApi = initApple.call(this) + let verifyResult + try { + verifyResult = await appleApi.verifyIdentityToken(identityToken) + } catch (error) { + await this.middleware.uniIdLog({ + success: false, + type: LOG_TYPE.BIND_APPLE + }) + throw { + errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED + } + } + const { + openid + } = verifyResult + + const bindAccount = { + apple_openid: openid + } + await preBind.call(this, { + uid, + bindAccount, + logType: LOG_TYPE.BIND_APPLE + }) + return postBind.call(this, { + uid, + bindAccount, + extraData: {}, + logType: LOG_TYPE.BIND_APPLE + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-mobile-by-mp-weixin.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-mobile-by-mp-weixin.js index 5da72590bb8a367ac2631257085f6707183ce44d..2e9a9915e48a3bee964f7831015597189b374210 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-mobile-by-mp-weixin.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-mobile-by-mp-weixin.js @@ -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 diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-mobile-by-univerify.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-mobile-by-univerify.js index 2970c61cedc73f2a73c402c49db44e1e284d72d3..b38d1bc818aea79df271ad12e5f02b0bd7cc9c52 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-mobile-by-univerify.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-mobile-by-univerify.js @@ -1,70 +1,70 @@ -const { - getPhoneNumber -} = require('../../lib/utils/univerify') -const { - LOG_TYPE -} = require('../../common/constants') -const { - preBind, - postBind -} = require('../../lib/utils/relate') - -/** - * 通过一键登录绑定手机号 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#bind-mobile-by-univerify - * @param {Object} params - * @param {String} params.openid APP端一键登录返回的openid - * @param {String} params.access_token APP端一键登录返回的access_token - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - openid: 'string', - access_token: 'string' - } - const { - openid, - // eslint-disable-next-line camelcase - access_token - } = params - this.middleware.validate(params, schema) - const uid = this.authInfo.uid - let mobile - try { - const phoneInfo = await getPhoneNumber.call(this, { - // eslint-disable-next-line camelcase - access_token, - openid - }) - mobile = phoneInfo.phoneNumber - } catch (error) { - await this.middleware.uniIdLog({ - success: false, - data: { - user_id: uid - }, - type: LOG_TYPE.BIND_MOBILE - }) - throw error - } - - const bindAccount = { - mobile - } - await preBind.call(this, { - uid, - bindAccount, - logType: LOG_TYPE.BIND_MOBILE - }) - await postBind.call(this, { - uid, - bindAccount, - extraData: { - mobile_confirmed: 1 - }, - logType: LOG_TYPE.BIND_MOBILE - }) - return { - errCode: 0 - } -} +const { + getPhoneNumber +} = require('../../lib/utils/univerify') +const { + LOG_TYPE +} = require('../../common/constants') +const { + preBind, + postBind +} = require('../../lib/utils/relate') + +/** + * 通过一键登录绑定手机号 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#bind-mobile-by-univerify + * @param {Object} params + * @param {String} params.openid APP端一键登录返回的openid + * @param {String} params.access_token APP端一键登录返回的access_token + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + openid: 'string', + access_token: 'string' + } + const { + openid, + // eslint-disable-next-line camelcase + access_token + } = params + this.middleware.validate(params, schema) + const uid = this.authInfo.uid + let mobile + try { + const phoneInfo = await getPhoneNumber.call(this, { + // eslint-disable-next-line camelcase + access_token, + openid + }) + mobile = phoneInfo.phoneNumber + } catch (error) { + await this.middleware.uniIdLog({ + success: false, + data: { + user_id: uid + }, + type: LOG_TYPE.BIND_MOBILE + }) + throw error + } + + const bindAccount = { + mobile + } + await preBind.call(this, { + uid, + bindAccount, + logType: LOG_TYPE.BIND_MOBILE + }) + await postBind.call(this, { + uid, + bindAccount, + extraData: { + mobile_confirmed: 1 + }, + logType: LOG_TYPE.BIND_MOBILE + }) + return { + errCode: 0 + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-qq.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-qq.js index ef801a23fdbd5893abba0729a2e65df80449316f..370eefb97dffa677e108a33e6fa29e94f1b450a3 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-qq.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-qq.js @@ -1,110 +1,110 @@ -const { - preBind, - postBind -} = require('../../lib/utils/relate') -const { - LOG_TYPE -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') -const { - initQQ -} = require('../../lib/third-party/index') -const { - generateQQCache, - getQQPlatform, - saveQQUserKey -} = require('../../lib/utils/qq') - -/** - * 绑定QQ - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#bind-qq - * @param {Object} params - * @param {String} params.code 小程序端QQ登录返回的code - * @param {String} params.accessToken APP端QQ登录返回的accessToken - * @param {String} params.accessTokenExpired accessToken过期时间,由App端QQ登录返回的expires_in参数计算而来,单位:毫秒 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - code: { - type: 'string', - required: false - }, - accessToken: { - type: 'string', - required: false - }, - accessTokenExpired: { - type: 'number', - required: false - } - } - this.middleware.validate(params, schema) - const uid = this.authInfo.uid - const { - code, - accessToken, - accessTokenExpired - } = params - const qqPlatform = getQQPlatform.call(this) - const appId = this.getClientInfo().appId - const qqApi = initQQ.call(this) - const clientPlatform = this.clientPlatform - const apiName = clientPlatform === 'mp-qq' ? 'code2Session' : 'getOpenidByToken' - let getQQAccountResult - try { - getQQAccountResult = await qqApi[apiName]({ - code, - accessToken - }) - } catch (error) { - await this.middleware.uniIdLog({ - success: false, - type: LOG_TYPE.BIND_QQ - }) - throw { - errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED - } - } - - const { - openid, - unionid, - // 保存下面四个字段 - sessionKey // 微信小程序用户sessionKey - } = getQQAccountResult - - const bindAccount = { - qq_openid: { - [clientPlatform]: openid - }, - qq_unionid: unionid - } - await preBind.call(this, { - uid, - bindAccount, - logType: LOG_TYPE.BIND_QQ - }) - await saveQQUserKey.call(this, { - openid, - sessionKey, - accessToken, - accessTokenExpired - }) - return postBind.call(this, { - uid, - bindAccount, - extraData: { - qq_openid: { - [`${qqPlatform}_${appId}`]: openid - }, - ...generateQQCache.call(this, { - openid, - sessionKey - }) - }, - logType: LOG_TYPE.BIND_QQ - }) -} +const { + preBind, + postBind +} = require('../../lib/utils/relate') +const { + LOG_TYPE +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') +const { + initQQ +} = require('../../lib/third-party/index') +const { + generateQQCache, + getQQPlatform, + saveQQUserKey +} = require('../../lib/utils/qq') + +/** + * 绑定QQ + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#bind-qq + * @param {Object} params + * @param {String} params.code 小程序端QQ登录返回的code + * @param {String} params.accessToken APP端QQ登录返回的accessToken + * @param {String} params.accessTokenExpired accessToken过期时间,由App端QQ登录返回的expires_in参数计算而来,单位:毫秒 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + code: { + type: 'string', + required: false + }, + accessToken: { + type: 'string', + required: false + }, + accessTokenExpired: { + type: 'number', + required: false + } + } + this.middleware.validate(params, schema) + const uid = this.authInfo.uid + const { + code, + accessToken, + accessTokenExpired + } = params + const qqPlatform = getQQPlatform.call(this) + const appId = this.getClientInfo().appId + const qqApi = initQQ.call(this) + const clientPlatform = this.clientPlatform + const apiName = clientPlatform === 'mp-qq' ? 'code2Session' : 'getOpenidByToken' + let getQQAccountResult + try { + getQQAccountResult = await qqApi[apiName]({ + code, + accessToken + }) + } catch (error) { + await this.middleware.uniIdLog({ + success: false, + type: LOG_TYPE.BIND_QQ + }) + throw { + errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED + } + } + + const { + openid, + unionid, + // 保存下面四个字段 + sessionKey // 微信小程序用户sessionKey + } = getQQAccountResult + + const bindAccount = { + qq_openid: { + [clientPlatform]: openid + }, + qq_unionid: unionid + } + await preBind.call(this, { + uid, + bindAccount, + logType: LOG_TYPE.BIND_QQ + }) + await saveQQUserKey.call(this, { + openid, + sessionKey, + accessToken, + accessTokenExpired + }) + return postBind.call(this, { + uid, + bindAccount, + extraData: { + qq_openid: { + [`${qqPlatform}_${appId}`]: openid + }, + ...generateQQCache.call(this, { + openid, + sessionKey + }) + }, + logType: LOG_TYPE.BIND_QQ + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-weixin.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-weixin.js index b0165077c7fc0f140f78b33c070da18fa9065b27..f94f6dcdbd686334cf3ac8e30390887a4303a980 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-weixin.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/bind-weixin.js @@ -1,100 +1,100 @@ -const { - preBind, - postBind -} = require('../../lib/utils/relate') -const { - LOG_TYPE -} = require('../../common/constants') -const { - generateWeixinCache, - saveWeixinUserKey, - getWeixinPlatform -} = require('../../lib/utils/weixin') -const { - initWeixin -} = require('../../lib/third-party/index') -const { - ERROR -} = require('../../common/error') - -/** - * 绑定微信 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#bind-weixin - * @param {Object} params - * @param {String} params.code 微信登录返回的code - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - code: 'string' - } - this.middleware.validate(params, schema) - const uid = this.authInfo.uid - const { - code - } = params - const weixinPlatform = getWeixinPlatform.call(this) - const appId = this.getClientInfo().appId - - const weixinApi = initWeixin.call(this) - const clientPlatform = this.clientPlatform - const apiName = clientPlatform === 'mp-weixin' ? 'code2Session' : 'getOauthAccessToken' - let getWeixinAccountResult - try { - getWeixinAccountResult = await weixinApi[apiName](code) - } catch (error) { - await this.middleware.uniIdLog({ - success: false, - type: LOG_TYPE.BIND_WEIXIN - }) - throw { - errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED - } - } - - const { - openid, - unionid, - // 保存下面四个字段 - sessionKey, // 微信小程序用户sessionKey - accessToken, // App端微信用户accessToken - refreshToken, // App端微信用户refreshToken - expired: accessTokenExpired // App端微信用户accessToken过期时间 - } = getWeixinAccountResult - - const bindAccount = { - wx_openid: { - [clientPlatform]: openid - }, - wx_unionid: unionid - } - await preBind.call(this, { - uid, - bindAccount, - logType: LOG_TYPE.BIND_WEIXIN - }) - await saveWeixinUserKey.call(this, { - openid, - sessionKey, - accessToken, - refreshToken, - accessTokenExpired - }) - return postBind.call(this, { - uid, - bindAccount, - extraData: { - wx_openid: { - [`${weixinPlatform}_${appId}`]: openid - }, - ...generateWeixinCache.call(this, { - openid, - sessionKey, // 微信小程序用户sessionKey - accessToken, // App端微信用户accessToken - refreshToken, // App端微信用户refreshToken - accessTokenExpired // App端微信用户accessToken过期时间 - }) - }, - logType: LOG_TYPE.BIND_WEIXIN - }) -} +const { + preBind, + postBind +} = require('../../lib/utils/relate') +const { + LOG_TYPE +} = require('../../common/constants') +const { + generateWeixinCache, + saveWeixinUserKey, + getWeixinPlatform +} = require('../../lib/utils/weixin') +const { + initWeixin +} = require('../../lib/third-party/index') +const { + ERROR +} = require('../../common/error') + +/** + * 绑定微信 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#bind-weixin + * @param {Object} params + * @param {String} params.code 微信登录返回的code + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + code: 'string' + } + this.middleware.validate(params, schema) + const uid = this.authInfo.uid + const { + code + } = params + const weixinPlatform = getWeixinPlatform.call(this) + const appId = this.getClientInfo().appId + + const weixinApi = initWeixin.call(this) + const clientPlatform = this.clientPlatform + const apiName = clientPlatform === 'mp-weixin' ? 'code2Session' : 'getOauthAccessToken' + let getWeixinAccountResult + try { + getWeixinAccountResult = await weixinApi[apiName](code) + } catch (error) { + await this.middleware.uniIdLog({ + success: false, + type: LOG_TYPE.BIND_WEIXIN + }) + throw { + errCode: ERROR.GET_THIRD_PARTY_ACCOUNT_FAILED + } + } + + const { + openid, + unionid, + // 保存下面四个字段 + sessionKey, // 微信小程序用户sessionKey + accessToken, // App端微信用户accessToken + refreshToken, // App端微信用户refreshToken + expired: accessTokenExpired // App端微信用户accessToken过期时间 + } = getWeixinAccountResult + + const bindAccount = { + wx_openid: { + [clientPlatform]: openid + }, + wx_unionid: unionid + } + await preBind.call(this, { + uid, + bindAccount, + logType: LOG_TYPE.BIND_WEIXIN + }) + await saveWeixinUserKey.call(this, { + openid, + sessionKey, + accessToken, + refreshToken, + accessTokenExpired + }) + return postBind.call(this, { + uid, + bindAccount, + extraData: { + wx_openid: { + [`${weixinPlatform}_${appId}`]: openid + }, + ...generateWeixinCache.call(this, { + openid, + sessionKey, // 微信小程序用户sessionKey + accessToken, // App端微信用户accessToken + refreshToken, // App端微信用户refreshToken + accessTokenExpired // App端微信用户accessToken过期时间 + }) + }, + logType: LOG_TYPE.BIND_WEIXIN + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/index.js index 5352792029a447de179156aa1713af1de4cdde94..a587e76f2904d99e3068add8cd838837b74e99df 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/index.js @@ -1,9 +1,13 @@ -module.exports = { - bindMobileBySms: require('./bind-mobile-by-sms'), - bindMobileByUniverify: require('./bind-mobile-by-univerify'), - bindMobileByMpWeixin: require('./bind-mobile-by-mp-weixin'), - bindAlipay: require('./bind-alipay'), - bindApple: require('./bind-apple'), - bindQQ: require('./bind-qq'), - bindWeixin: require('./bind-weixin') -} +module.exports = { + bindMobileBySms: require('./bind-mobile-by-sms'), + bindMobileByUniverify: require('./bind-mobile-by-univerify'), + bindMobileByMpWeixin: require('./bind-mobile-by-mp-weixin'), + bindAlipay: require('./bind-alipay'), + bindApple: require('./bind-apple'), + bindQQ: require('./bind-qq'), + bindWeixin: require('./bind-weixin'), + unbindWeixin: require('./unbind-weixin'), + unbindAlipay: require('./unbind-alipay'), + unbindQQ: require('./unbind-qq'), + unbindApple: require('./unbind-apple') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-alipay.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-alipay.js new file mode 100644 index 0000000000000000000000000000000000000000..db7b1a64041d3752bb7fdd754e407b6022423670 --- /dev/null +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-alipay.js @@ -0,0 +1,32 @@ +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 + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-apple.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-apple.js new file mode 100644 index 0000000000000000000000000000000000000000..c966e3f6862ad295ce83e4aa4d8518267bf7766e --- /dev/null +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-apple.js @@ -0,0 +1,32 @@ +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 + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-qq.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-qq.js new file mode 100644 index 0000000000000000000000000000000000000000..372a4f071a1af2e575a38ce2283b191491e0ef2f --- /dev/null +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-qq.js @@ -0,0 +1,46 @@ +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 + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-weixin.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-weixin.js new file mode 100644 index 0000000000000000000000000000000000000000..9174bef446ef7352556e3d78d07a55ba6316a51e --- /dev/null +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/relate/unbind-weixin.js @@ -0,0 +1,40 @@ +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 + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/index.js index 11729f6b943df4fcac6c01fd32397fb7a33b4f79..de12366f9e8c77cedc49a30502e5a32a9d0ca93d 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/index.js @@ -1,4 +1,4 @@ -module.exports = { - refreshToken: require('./refresh-token'), - setPushCid: require('./set-push-cid') -} +module.exports = { + refreshToken: require('./refresh-token'), + setPushCid: require('./set-push-cid') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/refresh-token.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/refresh-token.js index 0c1837e692cbe0a1db8716c45c03f1cc29287cc2..3d50dbdec98260cc986739528adbcbc682b4bfdc 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/refresh-token.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/refresh-token.js @@ -1,19 +1,19 @@ -/** - * 刷新token - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#refresh-token - */ -module.exports = async function () { - const { - token, - tokenExpired - } = await this.uniIdCommon.refreshToken({ - token: this.getUniIdToken() - }) - return { - errCode: 0, - newToken: { - token, - tokenExpired - } - } -} +/** + * 刷新token + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#refresh-token + */ +module.exports = async function () { + const { + token, + tokenExpired + } = await this.uniIdCommon.refreshToken({ + token: this.getUniIdToken() + }) + return { + errCode: 0, + newToken: { + token, + tokenExpired + } + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/set-push-cid.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/set-push-cid.js index 68c18c62475b29a82fc10746f7786088472fd041..fbf424b2ece7d752a1a84db1e40ed91ed35e689f 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/set-push-cid.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/utils/set-push-cid.js @@ -1,141 +1,141 @@ -const { - deviceCollection -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') - -async function setOpendbDevice ({ - pushClientId -} = {}) { - // 仅新增,如果存在进行更新操作 - const { - appId, - deviceId, - deviceBrand, - deviceModel, - osName, - osVersion, - osLanguage, - osTheme, - devicePixelRatio, - windowWidth, - windowHeight, - screenWidth, - screenHeight, - romName, - romVersion - } = this.getClientInfo() - const platform = this.clientPlatform - const now = Date.now() - - const db = uniCloud.database() - const opendbDeviceCollection = db.collection('opendb-device') - const getDeviceRes = await opendbDeviceCollection.where({ - device_id: deviceId - }).get() - const data = { - appid: appId, - device_id: deviceId, - vendor: deviceBrand, - model: deviceModel, - uni_platform: platform, - os_name: osName, - os_version: osVersion, - os_language: osLanguage, - os_theme: osTheme, - pixel_ratio: devicePixelRatio, - window_width: windowWidth, - window_height: windowHeight, - screen_width: screenWidth, - screen_height: screenHeight, - rom_name: romName, - rom_version: romVersion, - last_update_date: now, - push_clientid: pushClientId - } - if (getDeviceRes.data.length > 0) { - await opendbDeviceCollection.where({ - device_id: deviceId - }).update(data) - return - } - data.create_date = now - await opendbDeviceCollection.add(data) -} - -/** - * 更新device表的push_clien_id - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#set-push-cid - * @param {object} params - * @param {string} params.pushClientId 客户端pushClientId - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - pushClientId: 'string' - } - this.middleware.validate(params, schema) - const { - deviceId, - appId, - osName - } = this.getClientInfo() - let platform = this.clientPlatform - if (platform === 'app') { - platform += osName - } - - const { - uid, - exp - } = this.authInfo - const { pushClientId } = params - const tokenExpired = exp * 1000 - const getDeviceRes = await deviceCollection.where({ - device_id: deviceId - }).get() - console.log(getDeviceRes) - if (getDeviceRes.data.length > 1) { - return { - errCode: ERROR.SYSTEM_ERROR - } - } - const deviceRecord = getDeviceRes.data[0] - await setOpendbDevice.call(this, { - pushClientId - }) - if (!deviceRecord) { - await deviceCollection.add({ - user_id: uid, - device_id: deviceId, - token_expired: tokenExpired, - push_clientid: pushClientId, - appid: appId - }) - return { - errCode: 0 - } - } - // 同一用户允许更新token_expired,不同用户在token_expired小于Date.now()时允许更新。搭配逻辑:用户退出登录时将token_expired置0 - if ( - deviceRecord.user_id === uid || - (deviceRecord.token_expired < Date.now()) - ) { - await deviceCollection.where({ - device_id: deviceId - }).update({ - user_id: uid, - token_expired: tokenExpired, - push_clientid: pushClientId, - appid: appId - }) - return { - errCode: 0 - } - } - - return { - errCode: ERROR.SYSTEM_ERROR - } -} +const { + deviceCollection +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') + +async function setOpendbDevice ({ + pushClientId +} = {}) { + // 仅新增,如果存在进行更新操作 + const { + appId, + deviceId, + deviceBrand, + deviceModel, + osName, + osVersion, + osLanguage, + osTheme, + devicePixelRatio, + windowWidth, + windowHeight, + screenWidth, + screenHeight, + romName, + romVersion + } = this.getClientInfo() + const platform = this.clientPlatform + const now = Date.now() + + const db = uniCloud.database() + const opendbDeviceCollection = db.collection('opendb-device') + const getDeviceRes = await opendbDeviceCollection.where({ + device_id: deviceId + }).get() + const data = { + appid: appId, + device_id: deviceId, + vendor: deviceBrand, + model: deviceModel, + uni_platform: platform, + os_name: osName, + os_version: osVersion, + os_language: osLanguage, + os_theme: osTheme, + pixel_ratio: devicePixelRatio, + window_width: windowWidth, + window_height: windowHeight, + screen_width: screenWidth, + screen_height: screenHeight, + rom_name: romName, + rom_version: romVersion, + last_update_date: now, + push_clientid: pushClientId + } + if (getDeviceRes.data.length > 0) { + await opendbDeviceCollection.where({ + device_id: deviceId + }).update(data) + return + } + data.create_date = now + await opendbDeviceCollection.add(data) +} + +/** + * 更新device表的push_clien_id + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#set-push-cid + * @param {object} params + * @param {string} params.pushClientId 客户端pushClientId + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + pushClientId: 'string' + } + this.middleware.validate(params, schema) + const { + deviceId, + appId, + osName + } = this.getClientInfo() + let platform = this.clientPlatform + if (platform === 'app') { + platform += osName + } + + const { + uid, + exp + } = this.authInfo + const { pushClientId } = params + const tokenExpired = exp * 1000 + const getDeviceRes = await deviceCollection.where({ + device_id: deviceId + }).get() + console.log(getDeviceRes) + if (getDeviceRes.data.length > 1) { + return { + errCode: ERROR.SYSTEM_ERROR + } + } + const deviceRecord = getDeviceRes.data[0] + await setOpendbDevice.call(this, { + pushClientId + }) + if (!deviceRecord) { + await deviceCollection.add({ + user_id: uid, + device_id: deviceId, + token_expired: tokenExpired, + push_clientid: pushClientId, + appid: appId + }) + return { + errCode: 0 + } + } + // 同一用户允许更新token_expired,不同用户在token_expired小于Date.now()时允许更新。搭配逻辑:用户退出登录时将token_expired置0 + if ( + deviceRecord.user_id === uid || + (deviceRecord.token_expired < Date.now()) + ) { + await deviceCollection.where({ + device_id: deviceId + }).update({ + user_id: uid, + token_expired: tokenExpired, + push_clientid: pushClientId, + appid: appId + }) + return { + errCode: 0 + } + } + + return { + errCode: ERROR.SYSTEM_ERROR + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/create-captcha.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/create-captcha.js index 1d77f5e5a3b67ad6953039bcca032d81feaf35c8..81b60649e0e9a607f8bf72fbca378f14b853890c 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/create-captcha.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/create-captcha.js @@ -1,34 +1,34 @@ -const { - CAPTCHA_SCENE -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') - -/** - * 创建图形验证码 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#create-captcha - * @param {Object} params - * @param {String} params.scene 图形验证码使用场景 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - scene: 'string' - } - this.middleware.validate(params, schema) - - const deviceId = this.getClientInfo().deviceId - const { - scene - } = params - if (!(Object.values(CAPTCHA_SCENE).includes(scene))) { - throw { - errCode: ERROR.INVALID_PARAM - } - } - return this.uniCaptcha.create({ - deviceId, - scene - }) -} +const { + CAPTCHA_SCENE +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') + +/** + * 创建图形验证码 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#create-captcha + * @param {Object} params + * @param {String} params.scene 图形验证码使用场景 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + scene: 'string' + } + this.middleware.validate(params, schema) + + const deviceId = this.getClientInfo().deviceId + const { + scene + } = params + if (!(Object.values(CAPTCHA_SCENE).includes(scene))) { + throw { + errCode: ERROR.INVALID_PARAM + } + } + return this.uniCaptcha.create({ + deviceId, + scene + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/index.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/index.js index fba352403d93b49e23eca46a5bc22545843267f7..297dc2bb3ec7680ad19bb0dd0a318207be83b0e6 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/index.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/index.js @@ -1,7 +1,7 @@ -module.exports = { - createCaptcha: require('./create-captcha'), - refreshCaptcha: require('./refresh-captcha'), - sendSmsCode: require('./send-sms-code'), - sendEmailLink: require('./send-email-link'), - sendEmailCode: require('./send-email-code') -} +module.exports = { + createCaptcha: require('./create-captcha'), + refreshCaptcha: require('./refresh-captcha'), + sendSmsCode: require('./send-sms-code'), + sendEmailLink: require('./send-email-link'), + sendEmailCode: require('./send-email-code') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/refresh-captcha.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/refresh-captcha.js index e5df246280ade7d3fbc1eed6b01470e1ba11406c..6cbbbddea3c40871a53b9784ba68e9e29ec72402 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/refresh-captcha.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/refresh-captcha.js @@ -1,34 +1,34 @@ -const { - CAPTCHA_SCENE -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') - -/** - * 刷新图形验证码 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#refresh-captcha - * @param {Object} params - * @param {String} params.scene 图形验证码使用场景 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - scene: 'string' - } - this.middleware.validate(params, schema) - - const deviceId = this.getClientInfo().deviceId - const { - scene - } = params - if (!(Object.values(CAPTCHA_SCENE).includes(scene))) { - throw { - errCode: ERROR.INVALID_PARAM - } - } - return this.uniCaptcha.refresh({ - deviceId, - scene - }) -} +const { + CAPTCHA_SCENE +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') + +/** + * 刷新图形验证码 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#refresh-captcha + * @param {Object} params + * @param {String} params.scene 图形验证码使用场景 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + scene: 'string' + } + this.middleware.validate(params, schema) + + const deviceId = this.getClientInfo().deviceId + const { + scene + } = params + if (!(Object.values(CAPTCHA_SCENE).includes(scene))) { + throw { + errCode: ERROR.INVALID_PARAM + } + } + return this.uniCaptcha.refresh({ + deviceId, + scene + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-email-code.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-email-code.js index 5ed867c75bb0279a5fe11d7be1c3947ed4777a02..03af1ad78ec4c431e16cdfa975f428e684cb13b2 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-email-code.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-email-code.js @@ -1,60 +1,60 @@ -const { - verifyCaptcha -} = require('../../lib/utils/captcha') -const { - EMAIL_SCENE -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') -/** - * 发送邮箱验证码,可用于登录、注册、绑定邮箱、修改密码等操作 - * @tutorial - * @param {Object} params - * @param {String} params.email 邮箱 - * @param {String} params.captcha 图形验证码 - * @param {String} params.scene 使用场景 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - email: 'email', - captcha: 'string', - scene: 'string' - } - this.middleware.validate(params, schema) - - const { - email, - captcha, - scene - } = params - - if (!(Object.values(EMAIL_SCENE).includes(scene))) { - throw { - errCode: ERROR.INVALID_PARAM - } - } - - await verifyCaptcha.call(this, { - scene: 'send-email-code', - captcha - }) - - // -- 测试代码 - require('../../lib/utils/verify-code') - .setEmailVerifyCode.call(this, { - email, - code: '123456', - expiresIn: 180, - scene - }) - return { - errCode: 'uni-id-invalid-mail-template', - errMsg: `已启动测试模式,直接使用:123456作为邮箱验证码即可。\n如果是正式项目,需自行实现发送邮件的相关功能` - } - // -- 测试代码 - - - //发送邮件--需自行实现 -} +const { + verifyCaptcha +} = require('../../lib/utils/captcha') +const { + EMAIL_SCENE +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') +/** + * 发送邮箱验证码,可用于登录、注册、绑定邮箱、修改密码等操作 + * @tutorial + * @param {Object} params + * @param {String} params.email 邮箱 + * @param {String} params.captcha 图形验证码 + * @param {String} params.scene 使用场景 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + email: 'email', + captcha: 'string', + scene: 'string' + } + this.middleware.validate(params, schema) + + const { + email, + captcha, + scene + } = params + + if (!(Object.values(EMAIL_SCENE).includes(scene))) { + throw { + errCode: ERROR.INVALID_PARAM + } + } + + await verifyCaptcha.call(this, { + scene: 'send-email-code', + captcha + }) + + // -- 测试代码 + require('../../lib/utils/verify-code') + .setEmailVerifyCode.call(this, { + email, + code: '123456', + expiresIn: 180, + scene + }) + return { + errCode: 'uni-id-invalid-mail-template', + errMsg: `已启动测试模式,直接使用:123456作为邮箱验证码即可。\n如果是正式项目,需自行实现发送邮件的相关功能` + } + // -- 测试代码 + + + //发送邮件--需自行实现 +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-email-link.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-email-link.js index f643434a436ac4b6041bf901e7144aff5bc63bc8..d48ac068f9eaab7ded3e14f90cfc95c1005e4c21 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-email-link.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-email-link.js @@ -1,12 +1,12 @@ -/** - * 发送邮箱链接,可用于登录、注册、绑定邮箱、修改密码等操作 - * @tutorial - * @param {Object} params - * @param {String} params.email 邮箱 - * @param {String} params.scene 使用场景 - * @returns - */ -module.exports = async function (params = {}) { - // 此接口暂未实现,欢迎向我们提交pr - throw new Error('api[sendEmailLink] is not yet implemented') -} +/** + * 发送邮箱链接,可用于登录、注册、绑定邮箱、修改密码等操作 + * @tutorial + * @param {Object} params + * @param {String} params.email 邮箱 + * @param {String} params.scene 使用场景 + * @returns + */ +module.exports = async function (params = {}) { + // 此接口暂未实现,欢迎向我们提交pr + throw new Error('api[sendEmailLink] is not yet implemented') +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-sms-code.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-sms-code.js index a29c1011dec0f6402289de185f3e89a8f7532293..e589999ec6fd2bdb172e3352017dc022eebdb486 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-sms-code.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-sms-code.js @@ -1,71 +1,71 @@ -const { - sendSmsCode -} = require('../../lib/utils/sms') -const { - verifyCaptcha -} = require('../../lib/utils/captcha') -const { - SMS_SCENE -} = require('../../common/constants') -const { - ERROR -} = require('../../common/error') - -/** - * 发送短信验证码 - * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#send-sms-code - * @param {Object} params - * @param {String} params.mobile 手机号 - * @param {String} params.captcha 图形验证码 - * @param {String} params.scene 短信验证码使用场景 - * @returns - */ -module.exports = async function (params = {}) { - const schema = { - mobile: 'mobile', - captcha: 'string', - scene: 'string' - } - this.middleware.validate(params, schema) - const { - mobile, - captcha, - scene - } = params - if (!(Object.values(SMS_SCENE).includes(scene))) { - throw { - errCode: ERROR.INVALID_PARAM - } - } - await verifyCaptcha.call(this, { - scene: 'send-sms-code', - captcha - }) - - // -- 测试代码 - const { - templateId - } = (this.config.service && - this.config.service.sms && - this.config.service.sms.scene && - this.config.service.sms.scene[scene]) || {} - if (!templateId) { - require('../../lib/utils/verify-code') - .setMobileVerifyCode.call(this, { - mobile: params.mobile, - code: '123456', - expiresIn: 180, - scene - }) - return { - errCode: 'uni-id-invalid-sms-template-id', - errMsg: `未找到scene=${scene},的短信模版templateId。\n已启动测试模式,直接使用:123456作为短信验证码即可。\n如果是正式项目,请在路径:/common/uni-config-center/uni-id/config.json中service->sms中配置密钥等信息\n更多详情:https://uniapp.dcloud.io/uniCloud/uni-id.html#config` - } - } - // -- 测试代码 - - return sendSmsCode.call(this, { - mobile, - scene - }) -} +const { + sendSmsCode +} = require('../../lib/utils/sms') +const { + verifyCaptcha +} = require('../../lib/utils/captcha') +const { + SMS_SCENE +} = require('../../common/constants') +const { + ERROR +} = require('../../common/error') + +/** + * 发送短信验证码 + * @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-id-pages.html#send-sms-code + * @param {Object} params + * @param {String} params.mobile 手机号 + * @param {String} params.captcha 图形验证码 + * @param {String} params.scene 短信验证码使用场景 + * @returns + */ +module.exports = async function (params = {}) { + const schema = { + mobile: 'mobile', + captcha: 'string', + scene: 'string' + } + this.middleware.validate(params, schema) + const { + mobile, + captcha, + scene + } = params + if (!(Object.values(SMS_SCENE).includes(scene))) { + throw { + errCode: ERROR.INVALID_PARAM + } + } + await verifyCaptcha.call(this, { + scene: 'send-sms-code', + captcha + }) + + // -- 测试代码 + const { + templateId + } = (this.config.service && + this.config.service.sms && + this.config.service.sms.scene && + this.config.service.sms.scene[scene]) || {} + if (!templateId) { + require('../../lib/utils/verify-code') + .setMobileVerifyCode.call(this, { + mobile: params.mobile, + code: '123456', + expiresIn: 180, + scene + }) + return { + errCode: 'uni-id-invalid-sms-template-id', + errMsg: `未找到scene=${scene},的短信模版templateId。\n已启动测试模式,直接使用:123456作为短信验证码即可。\n如果是正式项目,请在路径:/common/uni-config-center/uni-id/config.json中service->sms中配置密钥等信息\n更多详情:https://uniapp.dcloud.io/uniCloud/uni-id.html#config` + } + } + // -- 测试代码 + + return sendSmsCode.call(this, { + mobile, + scene + }) +} diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json index 6cdd385979248855baa5462fcf15571e8c3d77dd..1c6e40a599bdc77f8abded9c1caf2e492869ee89 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json @@ -1,17 +1,19 @@ -{ - "name": "uni-id-co", - "version": "1.0.19", - "description": "", - "main": "index.js", - "keywords": [], - "author": "DCloud", - "dependencies": { - "jsonwebtoken": "8.5.1", - "lodash.merge": "^4.6.2", - "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" - }, - "extensions": {} -} +{ + "name": "uni-id-co", + "version": "1.0.26", + "description": "", + "main": "index.js", + "keywords": [], + "author": "DCloud", + "dependencies": { + "jsonwebtoken": "8.5.1", + "lodash.merge": "^4.6.2", + "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" + }, + "extensions": { + "uni-cloud-sms": {} + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/database/opendb-device.schema.json b/uni_modules/uni-id-pages/uniCloud/database/opendb-device.schema.json index c3591cc1f135350f01944d73c6451178a617605f..163e7c1445f8b082143b686279d2c880cd41c434 100644 --- a/uni_modules/uni-id-pages/uniCloud/database/opendb-device.schema.json +++ b/uni_modules/uni-id-pages/uniCloud/database/opendb-device.schema.json @@ -1,142 +1,142 @@ -{ - "bsonType": "object", - "required": [], - "permission": { - "read": false, - "create": true, - "update": false, - "delete": false - }, - "properties": { - "_id": { - "description": "ID,系统自动生成" - }, - "appid": { - "bsonType": "string", - "description": "DCloud appid" - }, - "device_id": { - "bsonType": "string", - "description": "设备唯一标识" - }, - "vendor": { - "bsonType": "string", - "description": "设备厂商" - }, - "push_clientid": { - "bsonType": "string", - "description": "推送设备客户端标识" - }, - "imei": { - "bsonType": "string", - "description": "国际移动设备识别码IMEI(International Mobile Equipment Identity)" - }, - "oaid": { - "bsonType": "string", - "description": "移动智能设备标识公共服务平台提供的匿名设备标识符(OAID)" - }, - "idfa": { - "bsonType": "string", - "description": "iOS平台配置应用使用广告标识(IDFA)" - }, - "imsi": { - "bsonType": "string", - "description": "国际移动用户识别码(International Mobile Subscriber Identification Number)" - }, - "model": { - "bsonType": "string", - "description": "设备型号" - }, - "platform": { - "bsonType": "string", - "description": "平台类型" - }, - "uni_platform": { - "bsonType": "string", - "description": "uni-app 运行平台,与条件编译平台相同。" - }, - "os_name": { - "bsonType": "string", - "description": "ios|android|windows|mac|linux " - }, - "os_version": { - "bsonType": "string", - "description": "操作系统版本号 " - }, - "os_language": { - "bsonType": "string", - "description": "操作系统语言 " - }, - "os_theme": { - "bsonType": "string", - "description": "操作系统主题 light|dark" - }, - "pixel_ratio": { - "bsonType": "string", - "description": "设备像素比 " - }, - "network_model": { - "bsonType": "string", - "description": "设备网络型号wifi\/3G\/4G\/" - }, - "window_width": { - "bsonType": "string", - "description": "设备窗口宽度 " - }, - "window_height": { - "bsonType": "string", - "description": "设备窗口高度" - }, - "screen_width": { - "bsonType": "string", - "description": "设备屏幕宽度" - }, - "screen_height": { - "bsonType": "string", - "description": "设备屏幕高度" - }, - "rom_name": { - "bsonType": "string", - "description": "rom 名称" - }, - "rom_version": { - "bsonType": "string", - "description": "rom 版本" - }, - "location_latitude": { - "bsonType": "double", - "description": "纬度" - }, - "location_longitude": { - "bsonType": "double", - "description": "经度" - }, - "location_country": { - "bsonType": "string", - "description": "国家" - }, - "location_province": { - "bsonType": "string", - "description": "省份" - }, - "location_city": { - "bsonType": "string", - "description": "城市" - }, - "create_date": { - "bsonType": "timestamp", - "description": "创建时间", - "forceDefaultValue": { - "$env": "now" - } - }, - "last_update_date": { - "bsonType": "timestamp", - "description": "最后一次修改时间", - "forceDefaultValue": { - "$env": "now" - } - } - }, - "version": "0.0.1" +{ + "bsonType": "object", + "required": [], + "permission": { + "read": false, + "create": true, + "update": false, + "delete": false + }, + "properties": { + "_id": { + "description": "ID,系统自动生成" + }, + "appid": { + "bsonType": "string", + "description": "DCloud appid" + }, + "device_id": { + "bsonType": "string", + "description": "设备唯一标识" + }, + "vendor": { + "bsonType": "string", + "description": "设备厂商" + }, + "push_clientid": { + "bsonType": "string", + "description": "推送设备客户端标识" + }, + "imei": { + "bsonType": "string", + "description": "国际移动设备识别码IMEI(International Mobile Equipment Identity)" + }, + "oaid": { + "bsonType": "string", + "description": "移动智能设备标识公共服务平台提供的匿名设备标识符(OAID)" + }, + "idfa": { + "bsonType": "string", + "description": "iOS平台配置应用使用广告标识(IDFA)" + }, + "imsi": { + "bsonType": "string", + "description": "国际移动用户识别码(International Mobile Subscriber Identification Number)" + }, + "model": { + "bsonType": "string", + "description": "设备型号" + }, + "platform": { + "bsonType": "string", + "description": "平台类型" + }, + "uni_platform": { + "bsonType": "string", + "description": "uni-app 运行平台,与条件编译平台相同。" + }, + "os_name": { + "bsonType": "string", + "description": "ios|android|windows|mac|linux " + }, + "os_version": { + "bsonType": "string", + "description": "操作系统版本号 " + }, + "os_language": { + "bsonType": "string", + "description": "操作系统语言 " + }, + "os_theme": { + "bsonType": "string", + "description": "操作系统主题 light|dark" + }, + "pixel_ratio": { + "bsonType": "string", + "description": "设备像素比 " + }, + "network_model": { + "bsonType": "string", + "description": "设备网络型号wifi\/3G\/4G\/" + }, + "window_width": { + "bsonType": "string", + "description": "设备窗口宽度 " + }, + "window_height": { + "bsonType": "string", + "description": "设备窗口高度" + }, + "screen_width": { + "bsonType": "string", + "description": "设备屏幕宽度" + }, + "screen_height": { + "bsonType": "string", + "description": "设备屏幕高度" + }, + "rom_name": { + "bsonType": "string", + "description": "rom 名称" + }, + "rom_version": { + "bsonType": "string", + "description": "rom 版本" + }, + "location_latitude": { + "bsonType": "double", + "description": "纬度" + }, + "location_longitude": { + "bsonType": "double", + "description": "经度" + }, + "location_country": { + "bsonType": "string", + "description": "国家" + }, + "location_province": { + "bsonType": "string", + "description": "省份" + }, + "location_city": { + "bsonType": "string", + "description": "城市" + }, + "create_date": { + "bsonType": "timestamp", + "description": "创建时间", + "forceDefaultValue": { + "$env": "now" + } + }, + "last_update_date": { + "bsonType": "timestamp", + "description": "最后一次修改时间", + "forceDefaultValue": { + "$env": "now" + } + } + }, + "version": "0.0.1" } \ No newline at end of file diff --git a/uni_modules/uni-id-pages/uniCloud/database/uni-id-device.schema.json b/uni_modules/uni-id-pages/uniCloud/database/uni-id-device.schema.json index 4981d75215fc48da914738bca125aedbe0aefac8..356a6e23957b5b580a1d0a27811250ec7f12ba3c 100644 --- a/uni_modules/uni-id-pages/uniCloud/database/uni-id-device.schema.json +++ b/uni_modules/uni-id-pages/uniCloud/database/uni-id-device.schema.json @@ -1,83 +1,83 @@ -{ - "bsonType": "object", - "required": [ - "user_id" - ], - "properties": { - "_id": { - "description": "ID,系统自动生成" - }, - "user_id": { - "bsonType": "string", - "description": "用户id,参考uni-id-users表" - }, - "ua": { - "bsonType": "string", - "description": "userAgent" - }, - "uuid": { - "bsonType": "string", - "description": "设备唯一标识(需要加密存储)" - }, - "os_name": { - "bsonType": "string", - "description": "ios|android|windows|mac|linux " - }, - "os_version": { - "bsonType": "string", - "description": "操作系统版本号 " - }, - "os_language": { - "bsonType": "string", - "description": "操作系统语言 " - }, - "os_theme": { - "bsonType": "string", - "description": "操作系统主题 light|dark" - }, - "vendor": { - "bsonType": "string", - "description": "设备厂商" - }, - "push_clientid": { - "bsonType": "string", - "description": "推送设备客户端标识" - }, - "imei": { - "bsonType": "string", - "description": "国际移动设备识别码IMEI(International Mobile Equipment Identity)" - }, - "oaid": { - "bsonType": "string", - "description": "移动智能设备标识公共服务平台提供的匿名设备标识符(OAID)" - }, - "idfa": { - "bsonType": "string", - "description": "iOS平台配置应用使用广告标识(IDFA)" - }, - "model": { - "bsonType": "string", - "description": "设备型号" - }, - "platform": { - "bsonType": "string", - "description": "平台类型" - }, - "create_date": { - "bsonType": "timestamp", - "description": "创建时间", - "forceDefaultValue": { - "$env": "now" - } - }, - "last_active_date": { - "bsonType": "timestamp", - "description": "最后登录时间" - }, - "last_active_ip": { - "bsonType": "string", - "description": "最后登录IP" - } - }, - "version": "0.0.1" +{ + "bsonType": "object", + "required": [ + "user_id" + ], + "properties": { + "_id": { + "description": "ID,系统自动生成" + }, + "user_id": { + "bsonType": "string", + "description": "用户id,参考uni-id-users表" + }, + "ua": { + "bsonType": "string", + "description": "userAgent" + }, + "uuid": { + "bsonType": "string", + "description": "设备唯一标识(需要加密存储)" + }, + "os_name": { + "bsonType": "string", + "description": "ios|android|windows|mac|linux " + }, + "os_version": { + "bsonType": "string", + "description": "操作系统版本号 " + }, + "os_language": { + "bsonType": "string", + "description": "操作系统语言 " + }, + "os_theme": { + "bsonType": "string", + "description": "操作系统主题 light|dark" + }, + "vendor": { + "bsonType": "string", + "description": "设备厂商" + }, + "push_clientid": { + "bsonType": "string", + "description": "推送设备客户端标识" + }, + "imei": { + "bsonType": "string", + "description": "国际移动设备识别码IMEI(International Mobile Equipment Identity)" + }, + "oaid": { + "bsonType": "string", + "description": "移动智能设备标识公共服务平台提供的匿名设备标识符(OAID)" + }, + "idfa": { + "bsonType": "string", + "description": "iOS平台配置应用使用广告标识(IDFA)" + }, + "model": { + "bsonType": "string", + "description": "设备型号" + }, + "platform": { + "bsonType": "string", + "description": "平台类型" + }, + "create_date": { + "bsonType": "timestamp", + "description": "创建时间", + "forceDefaultValue": { + "$env": "now" + } + }, + "last_active_date": { + "bsonType": "timestamp", + "description": "最后登录时间" + }, + "last_active_ip": { + "bsonType": "string", + "description": "最后登录IP" + } + }, + "version": "0.0.1" } \ No newline at end of file diff --git a/uni_modules/uni-id-pages/uniCloud/database/uni-id-log.schema.json b/uni_modules/uni-id-pages/uniCloud/database/uni-id-log.schema.json index ff4f7973239e6aaa467c3278f96462312ca2d71c..1b3dc611da9055165b1837c0f68c8c2fe9eac0e7 100644 --- a/uni_modules/uni-id-pages/uniCloud/database/uni-id-log.schema.json +++ b/uni_modules/uni-id-pages/uniCloud/database/uni-id-log.schema.json @@ -1,71 +1,71 @@ -{ - "bsonType": "object", - "required": ["user_id"], - "permission": { - "read": "'READ_UNI_ID_LOG' in auth.permission" - }, - "properties": { - "_id": { - "description": "ID,系统自动生成" - }, - "create_date": { - "bsonType": "timestamp", - "description": "创建时间", - "forceDefaultValue": { - "$env": "now" - } - }, - "device_uuid": { - "bsonType": "string", - "description": "设备唯一标识" - }, - "ip": { - "bsonType": "string", - "description": "ip地址" - }, - "state": { - "bsonType": "int", - "description": "结果:0 失败、1 成功" - }, - "type": { - "bsonType": "string", - "description": "操作类型", - "enum": [ - "logout", - "login", - "register", - "reset-pwd", - "bind-mobile", - "bind-weixin", - "bind-qq", - "bind-apple", - "bind-alipay" - ] - }, - "ua": { - "bsonType": "string", - "description": "userAgent" - }, - "user_id": { - "bsonType": "string", - "foreignKey": "uni-id-users._id", - "description": "用户id,参考uni-id-users表" - }, - "username": { - "bsonType": "string", - "description": "用户名" - }, - "email": { - "bsonType": "string", - "description": "邮箱" - }, - "mobile": { - "bsonType": "string", - "description": "手机号" - }, - "appid": { - "bsonType": "string", - "description": "客户端DCloud AppId" - } - } -} +{ + "bsonType": "object", + "required": ["user_id"], + "permission": { + "read": "'READ_UNI_ID_LOG' in auth.permission" + }, + "properties": { + "_id": { + "description": "ID,系统自动生成" + }, + "create_date": { + "bsonType": "timestamp", + "description": "创建时间", + "forceDefaultValue": { + "$env": "now" + } + }, + "device_uuid": { + "bsonType": "string", + "description": "设备唯一标识" + }, + "ip": { + "bsonType": "string", + "description": "ip地址" + }, + "state": { + "bsonType": "int", + "description": "结果:0 失败、1 成功" + }, + "type": { + "bsonType": "string", + "description": "操作类型", + "enum": [ + "logout", + "login", + "register", + "reset-pwd", + "bind-mobile", + "bind-weixin", + "bind-qq", + "bind-apple", + "bind-alipay" + ] + }, + "ua": { + "bsonType": "string", + "description": "userAgent" + }, + "user_id": { + "bsonType": "string", + "foreignKey": "uni-id-users._id", + "description": "用户id,参考uni-id-users表" + }, + "username": { + "bsonType": "string", + "description": "用户名" + }, + "email": { + "bsonType": "string", + "description": "邮箱" + }, + "mobile": { + "bsonType": "string", + "description": "手机号" + }, + "appid": { + "bsonType": "string", + "description": "客户端DCloud AppId" + } + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/database/uni-id-permissions.schema.json b/uni_modules/uni-id-pages/uniCloud/database/uni-id-permissions.schema.json index 25209cbae804642e5065a89148d90de550965666..0178d2568d702e5c156fe32992bc45b6c22a9fbb 100644 --- a/uni_modules/uni-id-pages/uniCloud/database/uni-id-permissions.schema.json +++ b/uni_modules/uni-id-pages/uniCloud/database/uni-id-permissions.schema.json @@ -1,52 +1,52 @@ -{ - "bsonType": "object", - "required": ["permission_id", "permission_name"], - "permission": { - "read": "'READ_UNI_ID_PERMISSIONS' in auth.permission", - "create": "'CREATE_UNI_ID_PERMISSIONS' in auth.permission", - "update": "'UPDATE_UNI_ID_PERMISSIONS' in auth.permission", - "delete": "'DELETE_UNI_ID_PERMISSIONS' in auth.permission" - }, - "properties": { - "_id": { - "description": "存储文档 ID,系统自动生成" - }, - "comment": { - "bsonType": "string", - "component": { - "name": "textarea" - }, - "description": "备注", - "label": "备注", - "title": "备注", - "trim": "both" - }, - "create_date": { - "bsonType": "timestamp", - "description": "创建时间", - "forceDefaultValue": { - "$env": "now" - } - }, - "permission_id": { - "bsonType": "string", - "component": { - "name": "input" - }, - "description": "权限唯一标识,不可修改,不允许重复", - "label": "权限标识", - "title": "权限ID", - "trim": "both" - }, - "permission_name": { - "bsonType": "string", - "component": { - "name": "input" - }, - "description": "权限名称", - "label": "权限名称", - "title": "权限名称", - "trim": "both" - } - } -} +{ + "bsonType": "object", + "required": ["permission_id", "permission_name"], + "permission": { + "read": "'READ_UNI_ID_PERMISSIONS' in auth.permission", + "create": "'CREATE_UNI_ID_PERMISSIONS' in auth.permission", + "update": "'UPDATE_UNI_ID_PERMISSIONS' in auth.permission", + "delete": "'DELETE_UNI_ID_PERMISSIONS' in auth.permission" + }, + "properties": { + "_id": { + "description": "存储文档 ID,系统自动生成" + }, + "comment": { + "bsonType": "string", + "component": { + "name": "textarea" + }, + "description": "备注", + "label": "备注", + "title": "备注", + "trim": "both" + }, + "create_date": { + "bsonType": "timestamp", + "description": "创建时间", + "forceDefaultValue": { + "$env": "now" + } + }, + "permission_id": { + "bsonType": "string", + "component": { + "name": "input" + }, + "description": "权限唯一标识,不可修改,不允许重复", + "label": "权限标识", + "title": "权限ID", + "trim": "both" + }, + "permission_name": { + "bsonType": "string", + "component": { + "name": "input" + }, + "description": "权限名称", + "label": "权限名称", + "title": "权限名称", + "trim": "both" + } + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/database/uni-id-roles.schema.json b/uni_modules/uni-id-pages/uniCloud/database/uni-id-roles.schema.json index e2fe3220ccdd6e695ebb70909c2595c1f3242a0a..b9289c81e103afc465c3f0598bd742ef55b0e9b4 100644 --- a/uni_modules/uni-id-pages/uniCloud/database/uni-id-roles.schema.json +++ b/uni_modules/uni-id-pages/uniCloud/database/uni-id-roles.schema.json @@ -1,50 +1,50 @@ -{ - "bsonType": "object", - "required": ["role_id", "role_name"], - "permission": { - "read": "'READ_UNI_ID_ROLES' in auth.permission", - "create": "'CREATE_UNI_ID_ROLES' in auth.permission", - "update": "'UPDATE_UNI_ID_ROLES' in auth.permission", - "delete": "'DELETE_UNI_ID_ROLES' in auth.permission" - }, - "properties": { - "_id": { - "description": "存储文档 ID,系统自动生成" - }, - "comment": { - "title": "备注", - "bsonType": "string", - "description": "备注", - "trim": "both" - }, - "create_date": { - "bsonType": "timestamp", - "description": "创建时间", - "forceDefaultValue": { - "$env": "now" - } - }, - "permission": { - "title": "权限", - "bsonType": "array", - "foreignKey": "uni-id-permissions.permission_id", - "description": "角色拥有的权限列表", - "enum": { - "collection": "uni-id-permissions", - "field": "permission_name as text, permission_id as value" - } - }, - "role_id": { - "title": "唯一ID", - "bsonType": "string", - "description": "角色唯一标识,不可修改,不允许重复", - "trim": "both" - }, - "role_name": { - "title": "名称", - "bsonType": "string", - "description": "角色名称", - "trim": "both" - } - } -} +{ + "bsonType": "object", + "required": ["role_id", "role_name"], + "permission": { + "read": "'READ_UNI_ID_ROLES' in auth.permission", + "create": "'CREATE_UNI_ID_ROLES' in auth.permission", + "update": "'UPDATE_UNI_ID_ROLES' in auth.permission", + "delete": "'DELETE_UNI_ID_ROLES' in auth.permission" + }, + "properties": { + "_id": { + "description": "存储文档 ID,系统自动生成" + }, + "comment": { + "title": "备注", + "bsonType": "string", + "description": "备注", + "trim": "both" + }, + "create_date": { + "bsonType": "timestamp", + "description": "创建时间", + "forceDefaultValue": { + "$env": "now" + } + }, + "permission": { + "title": "权限", + "bsonType": "array", + "foreignKey": "uni-id-permissions.permission_id", + "description": "角色拥有的权限列表", + "enum": { + "collection": "uni-id-permissions", + "field": "permission_name as text, permission_id as value" + } + }, + "role_id": { + "title": "唯一ID", + "bsonType": "string", + "description": "角色唯一标识,不可修改,不允许重复", + "trim": "both" + }, + "role_name": { + "title": "名称", + "bsonType": "string", + "description": "角色名称", + "trim": "both" + } + } +} diff --git a/uni_modules/uni-id-pages/uniCloud/database/uni-id-users.schema.json b/uni_modules/uni-id-pages/uniCloud/database/uni-id-users.schema.json index 84f7230def77728e758fb1359c8260e249f4a27e..8231c65dff5c1c4d59e2adaadfca7a49bda1802e 100644 --- a/uni_modules/uni-id-pages/uniCloud/database/uni-id-users.schema.json +++ b/uni_modules/uni-id-pages/uniCloud/database/uni-id-users.schema.json @@ -1,6 +1,5 @@ { "bsonType": "object", - "required": ["username", "password"], "permission": { "read": true, "create": "'CREATE_UNI_ID_USERS' in auth.permission", @@ -15,28 +14,36 @@ "bsonType": "string", "description": "支付宝平台openid", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "apple_openid": { "bsonType": "string", "description": "苹果登录openid", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "avatar": { "bsonType": "string", "description": "头像地址", "title": "头像地址", - "trim": "both" + "trim": "both", + "permission": { + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "doc._id == auth.uid || 'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" + } }, "avatar_file": { "bsonType": "file", "description": "用file类型方便使用uni-file-picker组件", - "title": "头像文件" + "title": "头像文件", + "permission": { + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "doc._id == auth.uid || 'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" + } }, "comment": { "bsonType": "string", @@ -44,8 +51,8 @@ "title": "备注", "trim": "both", "permission": { - "write": false, - "read": false + "read": "'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "dcloud_appid": { @@ -53,8 +60,8 @@ "description": "允许登录的客户端的appid列表", "foreignKey": "opendb-app-list.appid", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "department_id": { @@ -68,8 +75,8 @@ "enumType": "tree", "title": "部门", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "email": { @@ -79,8 +86,8 @@ "title": "邮箱", "trim": "both", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "email_confirmed": { @@ -98,8 +105,8 @@ ], "title": "邮箱验证状态", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "gender": { @@ -121,16 +128,16 @@ ], "title": "性别", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "invite_time": { "bsonType": "timestamp", "description": "受邀时间", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "inviter_uid": { @@ -138,24 +145,24 @@ "description": "用户全部上级邀请者", "trim": "both", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "last_login_date": { "bsonType": "timestamp", "description": "最后登录时间", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "last_login_ip": { "bsonType": "string", "description": "最后登录时 IP 地址", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "mobile": { @@ -165,8 +172,8 @@ "title": "手机号码", "trim": "both", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "mobile_confirmed": { @@ -184,49 +191,49 @@ ], "title": "手机号验证状态", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "my_invite_code": { "bsonType": "string", "description": "用户自身邀请码", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "nickname": { "bsonType": "string", "description": "用户昵称", "title": "昵称", - "trim": "both" + "trim": "both", + "permission": { + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "doc._id == auth.uid || 'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" + } }, "password": { "bsonType": "password", "description": "密码,加密存储", "title": "密码", - "trim": "both", - "permission": { - "write": false, - "read": false - } + "trim": "both" }, "password_secret_version": { "bsonType": "int", "description": "密码使用的passwordSecret版本", "title": "passwordSecret", "permission": { - "write": false, - "read": false + "read": false, + "write": false } }, "realname_auth": { "bsonType": "object", "description": "实名认证信息", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" }, "properties": { "auth_date": { @@ -291,16 +298,22 @@ "bsonType": "timestamp", "description": "注册时间", "forceDefaultValue": { - "$env": "now", - "read": "doc._id == auth.uid" + "$env": "now" + }, + "permission": { + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "register_ip": { "bsonType": "string", "description": "注册时 IP 地址", "forceDefaultValue": { - "$env": "clientIP", - "read": "doc._id == auth.uid" + "$env": "clientIP" + }, + "permission": { + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "role": { @@ -312,8 +325,8 @@ }, "foreignKey": "uni-id-roles.role_id", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" }, "title": "角色" }, @@ -321,8 +334,8 @@ "bsonType": "int", "description": "用户积分,积分变更记录可参考:uni-id-scores表定义", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "status": { @@ -330,8 +343,8 @@ "defaultValue": 0, "description": "用户状态:0 正常 1 禁用 2 审核中 3 审核拒绝", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" }, "enum": [{ "text": "正常", @@ -356,7 +369,8 @@ "bsonType": "array", "description": "用户token", "permission": { - "read": "doc._id == auth.uid" + "read": "'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "username": { @@ -365,7 +379,8 @@ "title": "用户名", "trim": "both", "permission": { - "write": false + "read": "doc._id == auth.uid || 'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "wx_openid": { @@ -390,16 +405,16 @@ } }, "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "wx_unionid": { "bsonType": "string", "description": "微信unionid", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "qq_openid": { @@ -416,17 +431,26 @@ } }, "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" } }, "qq_unionid": { "bsonType": "string", "description": "QQ unionid", "permission": { - "write": false, - "read": "doc._id == auth.uid" + "read": "'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" + } + }, + "third_party": { + "bsonType": "object", + "description": "三方平台凭证", + "permission": { + "read": false, + "write": false } } - } -} + }, + "required": [] +} \ No newline at end of file