@yeclimeric/nocobase-plugin-dingtalk 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +14 -0
- package/dist/client/auth/DingTalkAuthComponent.d.ts +8 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.js +10 -0
- package/dist/client/locale/index.d.ts +2 -0
- package/dist/externalVersion.js +20 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +48 -0
- package/dist/locale/zh_CN.d.ts +5 -0
- package/dist/locale/zh_CN.js +35 -0
- package/dist/server/actions/dingTalkActions.d.ts +5 -0
- package/dist/server/actions/dingTalkActions.js +75 -0
- package/dist/server/auth/DingTalkAuth.d.ts +20 -0
- package/dist/server/auth/DingTalkAuth.js +135 -0
- package/dist/server/constants.d.ts +3 -0
- package/dist/server/constants.js +42 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +42 -0
- package/dist/server/openapi/dingTalkApi.d.ts +99 -0
- package/dist/server/openapi/dingTalkApi.js +178 -0
- package/dist/server/openapi/dingTalkUtil.js +66 -0
- package/dist/server/plugin.d.ts +11 -0
- package/dist/server/plugin.js +66 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Authenticator } from '@nocobase/plugin-auth/client';
|
|
3
|
+
export declare const DingTalkAuthButton: (props: {
|
|
4
|
+
authenticator: Authenticator;
|
|
5
|
+
}) => React.JSX.Element;
|
|
6
|
+
export declare const DingTalkAuthAdminSettingsForm: (props: {
|
|
7
|
+
authenticator: Authenticator;
|
|
8
|
+
}) => React.JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("@nocobase/plugin-auth/client"),require("@nocobase/client"),require("@ant-design/icons"),require("antd")):"function"==typeof define&&define.amd?define("@yeclimeric/nocobase-plugin-dingtalk",["react","@nocobase/plugin-auth/client","@nocobase/client","@ant-design/icons","antd"],t):"object"==typeof exports?exports["@yeclimeric/nocobase-plugin-dingtalk"]=t(require("react"),require("@nocobase/plugin-auth/client"),require("@nocobase/client"),require("@ant-design/icons"),require("antd")):e["@yeclimeric/nocobase-plugin-dingtalk"]=t(e.react,e["@nocobase/plugin-auth/client"],e["@nocobase/client"],e["@ant-design/icons"],e.antd)}(self,function(e,t,n,r,o){return function(){"use strict";var i={482:function(e){e.exports=r},772:function(e){e.exports=n},689:function(e){e.exports=t},721:function(e){e.exports=o},156:function(t){t.exports=e}},u={};function a(e){var t=u[e];if(void 0!==t)return t.exports;var n=u[e]={exports:{}};return i[e](n,n.exports,a),n.exports}a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,{a:t}),t},a.d=function(e,t){for(var n in t)a.o(t,n)&&!a.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var c={};return!function(){a.r(c),a.d(c,{NocobasePluginDingTalkClient:function(){return w},default:function(){return S}});var e=a(772),t=a(689),n=a.n(t),r=a(156),o=a.n(r),i=a(721),u=a(482);function l(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function s(e,t,n,r,o,i,u){try{var a=e[i](u),c=a.value}catch(e){n(e);return}a.done?t(c):Promise.resolve(c).then(r,o)}var f=function(t){var n,a,c,f=(n=(0,r.useState)(!1),function(e){if(Array.isArray(e))return e}(n)||function(e,t){var n,r,o=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=o){var i=[],u=!0,a=!1;try{for(o=o.call(e);!(u=(n=o.next()).done)&&(i.push(n.value),i.length!==t);u=!0);}catch(e){a=!0,r=e}finally{try{u||null==o.return||o.return()}finally{if(a)throw r}}return i}}(n,2)||function(e,t){if(e){if("string"==typeof e)return l(e,2);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return l(e,t)}}(n,2)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),p=f[0],y=f[1],b=(0,e.useResource)("community-ding-talk"),d=(a=function(){var e;return function(e,t){var n,r,o,i,u={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){var c=[i,a];if(n)throw TypeError("Generator is already executing.");for(;u;)try{if(n=1,r&&(o=2&c[0]?r.return:c[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,c[1])).done)return o;switch(r=0,o&&(c=[2&c[0],o.value]),c[0]){case 0:case 1:o=c;break;case 4:return u.label++,{value:c[1],done:!1};case 5:u.label++,r=c[1],c=[0];continue;case 7:c=u.ops.pop(),u.trys.pop();continue;default:if(!(o=(o=u.trys).length>0&&o[o.length-1])&&(6===c[0]||2===c[0])){u=0;continue}if(3===c[0]&&(!o||c[1]>o[0]&&c[1]<o[3])){u.label=c[1];break}if(6===c[0]&&u.label<o[1]){u.label=o[1],o=c;break}if(o&&u.label<o[2]){u.label=o[2],u.ops.push(c);break}o[2]&&u.ops.pop(),u.trys.pop();continue}c=t.call(e,u)}catch(e){c=[6,e],r=0}finally{n=o=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}}}(this,function(n){switch(n.label){case 0:y(!0),n.label=1;case 1:return n.trys.push([1,,3,4]),[4,b.getAuthUrl({values:{authenticator:t.authenticator.name,redirect:new URLSearchParams(location.search?location.search.substring(1):"").get("redirect")||""}})];case 2:return console.log("uu",e=n.sent(),e.data),location.href=e.data.data,[3,4];case 3:return setTimeout(function(){y(!1)},1e3),[7];case 4:return[2]}})},c=function(){var e=this,t=arguments;return new Promise(function(n,r){var o=a.apply(e,t);function i(e){s(o,n,r,i,u,"next",e)}function u(e){s(o,n,r,i,u,"throw",e)}i(void 0)})},function(){return c.apply(this,arguments)});return o().createElement(i.Button,{loading:p,disabled:p,icon:o().createElement(u.DingtalkOutlined,null),style:{width:"100%"},onClick:d},t.authenticator.title||t.authenticator.name)},p=function(t){return console.log("aaa",t),o().createElement(e.SchemaComponent,{schema:{type:"object",properties:{communityDingTalkAuth:{type:"void",properties:{public:{type:"object",properties:{autoSignup:{"x-decorator":"FormItem",type:"boolean",title:"用户不存在时自动注册",required:!1,"x-component":"Checkbox"}}},internal:{type:"object",properties:{userCheckType:{"x-decorator":"FormItem",type:"string",title:"用户验证方式",required:!0,"x-component":"Select","x-component-props":{options:[{value:"orgEmail",label:"企业邮箱"},{value:"personalEmail",label:"个人邮箱"},{value:"mobile",label:"手机号"}]}},emailDomain:{"x-decorator":"FormItem",type:"string",title:"邮箱域名,多个使用英文逗号分隔",required:!0,"x-component":"Input"},appKey:{"x-decorator":"FormItem",type:"string",title:"应用ID",required:!0,"x-component":"Input"},appSecret:{"x-decorator":"FormItem",type:"string",title:"应用秘钥",required:!0,"x-component":"Password"}}}}}}}})};function y(e,t,n,r,o,i,u){try{var a=e[i](u),c=a.value}catch(e){n(e);return}a.done?t(c):Promise.resolve(c).then(r,o)}function b(e){return function(){var t=this,n=arguments;return new Promise(function(r,o){var i=e.apply(t,n);function u(e){y(i,r,o,u,a,"next",e)}function a(e){y(i,r,o,u,a,"throw",e)}u(void 0)})}}function d(e,t,n){return(d=g()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var o=new(Function.bind.apply(e,r));return n&&m(o,n.prototype),o}).apply(null,arguments)}function h(e){return(h=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function m(e,t){return(m=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function v(e){var t="function"==typeof Map?new Map:void 0;return(v=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return d(e,arguments,h(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),m(n,e)})(e)}function g(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(g=function(){return!!e})()}function x(e,t){var n,r,o,i,u={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){var c=[i,a];if(n)throw TypeError("Generator is already executing.");for(;u;)try{if(n=1,r&&(o=2&c[0]?r.return:c[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,c[1])).done)return o;switch(r=0,o&&(c=[2&c[0],o.value]),c[0]){case 0:case 1:o=c;break;case 4:return u.label++,{value:c[1],done:!1};case 5:u.label++,r=c[1],c=[0];continue;case 7:c=u.ops.pop(),u.trys.pop();continue;default:if(!(o=(o=u.trys).length>0&&o[o.length-1])&&(6===c[0]||2===c[0])){u=0;continue}if(3===c[0]&&(!o||c[1]>o[0]&&c[1]<o[3])){u.label=c[1];break}if(6===c[0]&&u.label<o[1]){u.label=o[1],o=c;break}if(o&&u.label<o[2]){u.label=o[2],u.ops.push(c);break}o[2]&&u.ops.pop(),u.trys.pop();continue}c=t.call(e,u)}catch(e){c=[6,e],r=0}finally{n=o=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}}}var w=function(e){var t;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function r(){var e,t;if(!(this instanceof r))throw TypeError("Cannot call a class as a function");return e=r,t=arguments,e=h(e),function(e,t){var n;if(t&&("object"==((n=t)&&"undefined"!=typeof Symbol&&n.constructor===Symbol?"symbol":typeof n)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,g()?Reflect.construct(e,t||[],h(this).constructor):e.apply(this,t))}return r.prototype=Object.create(e&&e.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),e&&m(r,e),t=[{key:"afterAdd",value:function(){return b(function(){return x(this,function(e){return[2]})})()}},{key:"beforeLoad",value:function(){return b(function(){return x(this,function(e){return[2]})})()}},{key:"load",value:function(){var e=this;return b(function(){return x(this,function(t){return e.app.pm.get(n()).registerType("community-ding-talk-auth",{components:{SignInButton:f,AdminSettingsForm:p}}),[2]})})()}}],function(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(r.prototype,t),r}(v(e.Plugin)),S=w}(),c}()});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
"@nocobase/client": "1.9.26",
|
|
12
|
+
"@nocobase/plugin-auth": "1.9.26",
|
|
13
|
+
"@nocobase/server": "1.9.26",
|
|
14
|
+
"react": "18.3.1",
|
|
15
|
+
"antd": "5.12.8",
|
|
16
|
+
"@ant-design/icons": "5.6.1",
|
|
17
|
+
"react-i18next": "11.18.6",
|
|
18
|
+
"@nocobase/actions": "1.9.26",
|
|
19
|
+
"@nocobase/auth": "1.9.26"
|
|
20
|
+
};
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __create = Object.create;
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
15
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
|
+
var __export = (target, all) => {
|
|
17
|
+
for (var name in all)
|
|
18
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
|
+
};
|
|
20
|
+
var __copyProps = (to, from, except, desc) => {
|
|
21
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
22
|
+
for (let key of __getOwnPropNames(from))
|
|
23
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
24
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
25
|
+
}
|
|
26
|
+
return to;
|
|
27
|
+
};
|
|
28
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
29
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
30
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
31
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
32
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
33
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
34
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
35
|
+
mod
|
|
36
|
+
));
|
|
37
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
38
|
+
var src_exports = {};
|
|
39
|
+
__export(src_exports, {
|
|
40
|
+
default: () => import_server.default
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(src_exports);
|
|
43
|
+
__reExport(src_exports, require("./server"), module.exports);
|
|
44
|
+
var import_server = __toESM(require("./server"));
|
|
45
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
46
|
+
0 && (module.exports = {
|
|
47
|
+
...require("./server")
|
|
48
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var zh_CN_exports = {};
|
|
28
|
+
__export(zh_CN_exports, {
|
|
29
|
+
default: () => zh_CN_default
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(zh_CN_exports);
|
|
32
|
+
var zh_CN_default = {
|
|
33
|
+
"User will be registered automatically if not exists.": "\u7528\u6237\u4E0D\u5B58\u5728\u65F6\u5C06\u81EA\u52A8\u6CE8\u518C\u3002",
|
|
34
|
+
"Sign up automatically when the user does not exist": "\u7528\u6237\u4E0D\u5B58\u5728\u65F6\u81EA\u52A8\u6CE8\u518C"
|
|
35
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var dingTalkActions_exports = {};
|
|
28
|
+
__export(dingTalkActions_exports, {
|
|
29
|
+
dingTalkActions: () => dingTalkActions
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(dingTalkActions_exports);
|
|
32
|
+
function getReqUrl(req) {
|
|
33
|
+
var _a, _b, _c, _d;
|
|
34
|
+
const proto = ((_b = (_a = req.get("X-Forwarded-Proto")) == null ? void 0 : _a.split(",")) == null ? void 0 : _b[0]) || req.protocol;
|
|
35
|
+
const host = ((_d = (_c = req.get("X-Forwarded-Host")) == null ? void 0 : _c.split(",")) == null ? void 0 : _d[0]) || req.host;
|
|
36
|
+
return process.env.APP_URL || `${proto}://${host}${process.env.APP_PUBLIC_PATH || "/"}`;
|
|
37
|
+
}
|
|
38
|
+
const dingTalkActions = {
|
|
39
|
+
getAuthUrl: async (ctx, next) => {
|
|
40
|
+
const { authenticator: authenticatorName, redirect } = ctx.action.params.values;
|
|
41
|
+
if (!authenticatorName) {
|
|
42
|
+
ctx.throw(400, "\u8BA4\u8BC1\u5668\u4E0D\u80FD\u4E3A\u7A7A");
|
|
43
|
+
}
|
|
44
|
+
const app = ctx.app;
|
|
45
|
+
const auth = await app.authManager.get(authenticatorName, ctx);
|
|
46
|
+
const redirectUri = `${getReqUrl(ctx.request)}api/community-ding-talk:redirectAuth?authenticator=${encodeURIComponent(authenticatorName)}&redirect=${encodeURIComponent(redirect || "")}`;
|
|
47
|
+
ctx.body = auth.dingTalkApi.getLoginUrl(redirectUri);
|
|
48
|
+
await next();
|
|
49
|
+
},
|
|
50
|
+
redirectAuth: async (ctx, next) => {
|
|
51
|
+
const { authenticator: authenticatorName, redirect, code, authCode, state } = ctx.action.params;
|
|
52
|
+
if (!authenticatorName) {
|
|
53
|
+
ctx.throw(400, "\u8BA4\u8BC1\u5668\u4E0D\u80FD\u4E3A\u7A7A");
|
|
54
|
+
}
|
|
55
|
+
if (!code) {
|
|
56
|
+
ctx.throw(400, "OAuth 2.0 \u4E34\u65F6\u6388\u6743\u7801\u4E0D\u5B58\u5728");
|
|
57
|
+
}
|
|
58
|
+
const app = ctx.app;
|
|
59
|
+
const auth = await app.authManager.get(authenticatorName, ctx);
|
|
60
|
+
const { user, token } = await auth.signIn();
|
|
61
|
+
let rediretPath = redirect;
|
|
62
|
+
if (rediretPath) {
|
|
63
|
+
if (rediretPath.startsWith("/")) {
|
|
64
|
+
rediretPath = rediretPath.substring(1);
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
rediretPath = "";
|
|
68
|
+
}
|
|
69
|
+
ctx.redirect(`${(process.env.APP_PUBLIC_PATH || "/") + rediretPath}?authenticator=${encodeURIComponent(authenticatorName)}&token=${encodeURIComponent(token)}`);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
73
|
+
0 && (module.exports = {
|
|
74
|
+
dingTalkActions
|
|
75
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BaseAuth, AuthConfig } from '@nocobase/auth';
|
|
2
|
+
import { DingTalkApi } from '../openapi/dingTalkApi';
|
|
3
|
+
export type AuthConfigOptions = {
|
|
4
|
+
public: {
|
|
5
|
+
autoSignup: boolean;
|
|
6
|
+
};
|
|
7
|
+
internal: {
|
|
8
|
+
userCheckType: 'orgEmail' | 'personalEmail' | 'mobile';
|
|
9
|
+
emailDomains: string[];
|
|
10
|
+
appKey?: string;
|
|
11
|
+
appSecret?: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export declare class DingTalkAuth extends BaseAuth {
|
|
15
|
+
#private;
|
|
16
|
+
constructor(config: AuthConfig);
|
|
17
|
+
validate(): Promise<import("@nocobase/database").Model<any, any>>;
|
|
18
|
+
get dingTalkApi(): DingTalkApi;
|
|
19
|
+
get authConfigOptions(): AuthConfigOptions;
|
|
20
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var DingTalkAuth_exports = {};
|
|
28
|
+
__export(DingTalkAuth_exports, {
|
|
29
|
+
DingTalkAuth: () => DingTalkAuth
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(DingTalkAuth_exports);
|
|
32
|
+
var import_auth = require("@nocobase/auth");
|
|
33
|
+
var import_dingTalkApi = require("../openapi/dingTalkApi");
|
|
34
|
+
class DingTalkAuth extends import_auth.BaseAuth {
|
|
35
|
+
#authConfigOptions;
|
|
36
|
+
#dingTalkApi;
|
|
37
|
+
constructor(config) {
|
|
38
|
+
var _a;
|
|
39
|
+
const userCollection = config.ctx.db.getCollection("users");
|
|
40
|
+
super({ ...config, userCollection });
|
|
41
|
+
this.#authConfigOptions = config.options;
|
|
42
|
+
this.#dingTalkApi = new import_dingTalkApi.DingTalkApi(this.#authConfigOptions.internal.appKey, this.#authConfigOptions.internal.appSecret);
|
|
43
|
+
this.#authConfigOptions = {
|
|
44
|
+
...this.#authConfigOptions,
|
|
45
|
+
internal: {
|
|
46
|
+
userCheckType: this.#authConfigOptions.internal.userCheckType,
|
|
47
|
+
emailDomains: ((_a = config.options.internal.emailDomain) == null ? void 0 : _a.split("s*,s*")) || []
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async validate() {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
const ctx = this.ctx;
|
|
54
|
+
const { authenticator: authenticatorName, code, authCode, state } = ctx.action.params;
|
|
55
|
+
if (!authenticatorName) {
|
|
56
|
+
ctx.throw(400, "\u8BA4\u8BC1\u5668\u4E0D\u80FD\u4E3A\u7A7A");
|
|
57
|
+
}
|
|
58
|
+
if (!code) {
|
|
59
|
+
ctx.throw(400, "OAuth 2.0 \u4E34\u65F6\u6388\u6743\u7801\u4E0D\u5B58\u5728");
|
|
60
|
+
}
|
|
61
|
+
const auth = this;
|
|
62
|
+
const tokenRes = await auth.dingTalkApi.oauth2.userAccessToken("authorization_code", code);
|
|
63
|
+
const userRes = await auth.dingTalkApi.contact.getUser("me", tokenRes.accessToken);
|
|
64
|
+
const { userid: userId } = await auth.dingTalkApi.contact.getUserIdByUnionId(userRes.unionId);
|
|
65
|
+
const authenticator = this.authenticator;
|
|
66
|
+
let au = await authenticator.findUser(userId);
|
|
67
|
+
if (au) {
|
|
68
|
+
return au;
|
|
69
|
+
}
|
|
70
|
+
const userDetail = await auth.dingTalkApi.contact.getUserDetail(userId);
|
|
71
|
+
const user = {
|
|
72
|
+
userId,
|
|
73
|
+
unionId: userRes.unionId,
|
|
74
|
+
mobile: userRes.mobile,
|
|
75
|
+
email: userRes.email,
|
|
76
|
+
name: userDetail.name || userRes.nick,
|
|
77
|
+
orgEmail: userDetail.org_email
|
|
78
|
+
};
|
|
79
|
+
let filter;
|
|
80
|
+
if (this.#authConfigOptions.internal.userCheckType === "personalEmail") {
|
|
81
|
+
if (!user.email) {
|
|
82
|
+
ctx.throw(400, "\u7528\u6237\u90AE\u7BB1\u672A\u914D\u7F6E");
|
|
83
|
+
}
|
|
84
|
+
if (!this.#authConfigOptions.internal.emailDomains.some((a) => userDetail.email.endsWith(a))) {
|
|
85
|
+
ctx.throw(400, `\u90AE\u7BB1\u57DF\u540D\u672A\u542F\u7528 ${user.email}`);
|
|
86
|
+
}
|
|
87
|
+
filter = {
|
|
88
|
+
email: user.email
|
|
89
|
+
};
|
|
90
|
+
} else if (this.#authConfigOptions.internal.userCheckType === "orgEmail") {
|
|
91
|
+
if (!user.orgEmail) {
|
|
92
|
+
ctx.throw(400, "\u7528\u6237\u4F01\u4E1A\u90AE\u7BB1\u672A\u914D\u7F6E");
|
|
93
|
+
}
|
|
94
|
+
if (!this.#authConfigOptions.internal.emailDomains.some((a) => userDetail.org_email.endsWith(a))) {
|
|
95
|
+
ctx.throw(400, `\u90AE\u7BB1\u57DF\u540D\u672A\u542F\u7528 ${user.orgEmail}`);
|
|
96
|
+
}
|
|
97
|
+
filter = {
|
|
98
|
+
email: user.orgEmail
|
|
99
|
+
};
|
|
100
|
+
} else {
|
|
101
|
+
filter = {
|
|
102
|
+
phone: user.mobile
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
let ncUser = await this.userRepository.findOne({ filter });
|
|
106
|
+
if (ncUser) {
|
|
107
|
+
await this.authenticator.addUser(user, {
|
|
108
|
+
through: {
|
|
109
|
+
uuid: userId
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
return await authenticator.findUser(userId);
|
|
113
|
+
}
|
|
114
|
+
if (this.#authConfigOptions.public.autoSignup) {
|
|
115
|
+
return await authenticator.findOrCreateUser(userId, {
|
|
116
|
+
nickname: user.name,
|
|
117
|
+
username: ((_b = (_a = filter.email) == null ? void 0 : _a.split("@")) == null ? void 0 : _b[0]) || user.mobile || userId,
|
|
118
|
+
email: filter.email,
|
|
119
|
+
phone: user.mobile,
|
|
120
|
+
meta: JSON.stringify(user)
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
get dingTalkApi() {
|
|
126
|
+
return this.#dingTalkApi;
|
|
127
|
+
}
|
|
128
|
+
get authConfigOptions() {
|
|
129
|
+
return this.#authConfigOptions;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
133
|
+
0 && (module.exports = {
|
|
134
|
+
DingTalkAuth
|
|
135
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var constants_exports = {};
|
|
28
|
+
__export(constants_exports, {
|
|
29
|
+
AuthName: () => AuthName,
|
|
30
|
+
PluginName: () => PluginName,
|
|
31
|
+
ResoureName: () => ResoureName
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(constants_exports);
|
|
34
|
+
const PluginName = "community-ding-talk";
|
|
35
|
+
const AuthName = `${PluginName}-auth`;
|
|
36
|
+
const ResoureName = PluginName;
|
|
37
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
38
|
+
0 && (module.exports = {
|
|
39
|
+
AuthName,
|
|
40
|
+
PluginName,
|
|
41
|
+
ResoureName
|
|
42
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './plugin';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __create = Object.create;
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
15
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
|
+
var __export = (target, all) => {
|
|
17
|
+
for (var name in all)
|
|
18
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
|
+
};
|
|
20
|
+
var __copyProps = (to, from, except, desc) => {
|
|
21
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
22
|
+
for (let key of __getOwnPropNames(from))
|
|
23
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
24
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
25
|
+
}
|
|
26
|
+
return to;
|
|
27
|
+
};
|
|
28
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
29
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
30
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
31
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
32
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
33
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
34
|
+
mod
|
|
35
|
+
));
|
|
36
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
|
+
var server_exports = {};
|
|
38
|
+
__export(server_exports, {
|
|
39
|
+
default: () => import_plugin.default
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(server_exports);
|
|
42
|
+
var import_plugin = __toESM(require("./plugin"));
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export type Res<T> = {
|
|
2
|
+
/** 请求ID。 */
|
|
3
|
+
request_id: string;
|
|
4
|
+
/** 返回码。 */
|
|
5
|
+
errcode: number;
|
|
6
|
+
/** 返回码描述。 */
|
|
7
|
+
errmsg: string;
|
|
8
|
+
/** 返回结果。 */
|
|
9
|
+
result: T;
|
|
10
|
+
};
|
|
11
|
+
export type UserAccessTokenRes = {
|
|
12
|
+
/** 生成的accessToken */
|
|
13
|
+
accessToken?: string;
|
|
14
|
+
/** 生成的refresh_token。可以使用此刷新token,定期的获取用户的accessToken */
|
|
15
|
+
refreshToken?: string;
|
|
16
|
+
/** 超时时间,单位秒。 */
|
|
17
|
+
expireIn?: number;
|
|
18
|
+
/** 所选企业corpId。 */
|
|
19
|
+
corpId?: string;
|
|
20
|
+
};
|
|
21
|
+
export type UserRes = {
|
|
22
|
+
/** 用户的钉钉昵称。 */
|
|
23
|
+
nick?: string;
|
|
24
|
+
/** 头像URL。 */
|
|
25
|
+
avatarUrl?: string;
|
|
26
|
+
/** 用户的手机号。如果要获取用户手机号,需要在钉钉开发者后台申请个人手机号信息权限 */
|
|
27
|
+
mobile?: string;
|
|
28
|
+
/** 用户的openId。 */
|
|
29
|
+
openId?: string;
|
|
30
|
+
/** 用户的unionId。 */
|
|
31
|
+
unionId?: string;
|
|
32
|
+
/** 用户的个人邮箱。 */
|
|
33
|
+
email?: string;
|
|
34
|
+
/** 手机号对应的国家号。 */
|
|
35
|
+
stateCode?: string;
|
|
36
|
+
};
|
|
37
|
+
export type UserDetail = {
|
|
38
|
+
/** 员工的userId。 */
|
|
39
|
+
userid: string;
|
|
40
|
+
/** 员工姓名。 */
|
|
41
|
+
name: string;
|
|
42
|
+
/** 员工邮箱。 */
|
|
43
|
+
email?: string;
|
|
44
|
+
/** 员工的企业邮箱。如果员工的企业邮箱没有开通,返回信息中不包含该数据。第三方企业应用不返回该参数。 */
|
|
45
|
+
org_email?: string;
|
|
46
|
+
};
|
|
47
|
+
export type UserId = {
|
|
48
|
+
/** 联系类型: 0:企业内部员工 1:企业外部联系人 */
|
|
49
|
+
contact_type?: number;
|
|
50
|
+
/** 用户的userid。 */
|
|
51
|
+
userid: string;
|
|
52
|
+
};
|
|
53
|
+
export declare function checkResult<T>(res: Res<T>): T;
|
|
54
|
+
/**
|
|
55
|
+
* 钉钉 API
|
|
56
|
+
*/
|
|
57
|
+
export declare class DingTalkApi {
|
|
58
|
+
#private;
|
|
59
|
+
constructor(appKey: string, appSecret: string);
|
|
60
|
+
get oauth2(): {
|
|
61
|
+
/**
|
|
62
|
+
* 获取用户token
|
|
63
|
+
* @param grantType 如果使用授权码换token,传authorization_code。如果使用刷新token换用户token,传refresh_token。
|
|
64
|
+
* @param code OAuth 2.0 临时授权码,第三方企业应用需要接入统一授权套件/获取登录用户的访问凭证,获取临时授权码authCode。
|
|
65
|
+
* @param refreshToken OAuth2.0刷新令牌,从返回结果里面获取。过期时间是30天。
|
|
66
|
+
* @returns
|
|
67
|
+
*/
|
|
68
|
+
userAccessToken(grantType: "authorization_code" | "refresh_token", code?: string, refreshToken?: string): Promise<UserAccessTokenRes>;
|
|
69
|
+
};
|
|
70
|
+
get contact(): {
|
|
71
|
+
/**
|
|
72
|
+
* 获取用户token
|
|
73
|
+
* @param unionId 用户的unionId。如需获取当前授权人的信息,unionId参数可以传me。
|
|
74
|
+
* @returns
|
|
75
|
+
*/
|
|
76
|
+
getUser(unionId: string, accessToken: string): Promise<UserRes>;
|
|
77
|
+
/**
|
|
78
|
+
* 根据手机号查询用户ID
|
|
79
|
+
* @param mobile 用户的手机号。
|
|
80
|
+
* @returns 员工的userId。
|
|
81
|
+
*/
|
|
82
|
+
getUserIdByMobile(mobile: string): Promise<UserId>;
|
|
83
|
+
/**
|
|
84
|
+
* 根据手机号查询用户ID
|
|
85
|
+
* @param unionid 员工在当前开发者企业账号范围内的唯一标识
|
|
86
|
+
* @returns 员工的userId。
|
|
87
|
+
*/
|
|
88
|
+
getUserIdByUnionId(unionid: string): Promise<UserId>;
|
|
89
|
+
/**
|
|
90
|
+
* 查询用户详情
|
|
91
|
+
* @param userid 用户的userId。
|
|
92
|
+
* @returns 员工的userId。
|
|
93
|
+
*/
|
|
94
|
+
getUserDetail(userid: string): Promise<UserDetail>;
|
|
95
|
+
};
|
|
96
|
+
getLoginUrl(redirectUri: string): string;
|
|
97
|
+
getAccessToken(): Promise<string>;
|
|
98
|
+
doRequest<T>(method: 'GET' | 'POST' | 'PUT' | 'DELETE', path: string, params?: any, body?: any, headers?: any): Promise<T>;
|
|
99
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var dingTalkApi_exports = {};
|
|
28
|
+
__export(dingTalkApi_exports, {
|
|
29
|
+
DingTalkApi: () => DingTalkApi,
|
|
30
|
+
checkResult: () => checkResult
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(dingTalkApi_exports);
|
|
33
|
+
function checkResult(res) {
|
|
34
|
+
if (res.errcode !== 0) {
|
|
35
|
+
throw new Error(JSON.stringify(res));
|
|
36
|
+
}
|
|
37
|
+
return res.result;
|
|
38
|
+
}
|
|
39
|
+
class DingTalkApi {
|
|
40
|
+
/**
|
|
41
|
+
* 获取凭证
|
|
42
|
+
*/
|
|
43
|
+
#oauth2 = /* @__PURE__ */ ((api) => {
|
|
44
|
+
const baseUrl = "https://api.dingtalk.com";
|
|
45
|
+
return {
|
|
46
|
+
/**
|
|
47
|
+
* 获取用户token
|
|
48
|
+
* @param grantType 如果使用授权码换token,传authorization_code。如果使用刷新token换用户token,传refresh_token。
|
|
49
|
+
* @param code OAuth 2.0 临时授权码,第三方企业应用需要接入统一授权套件/获取登录用户的访问凭证,获取临时授权码authCode。
|
|
50
|
+
* @param refreshToken OAuth2.0刷新令牌,从返回结果里面获取。过期时间是30天。
|
|
51
|
+
* @returns
|
|
52
|
+
*/
|
|
53
|
+
async userAccessToken(grantType, code, refreshToken) {
|
|
54
|
+
return api.doRequest("POST", `${baseUrl}/v1.0/oauth2/userAccessToken`, null, {
|
|
55
|
+
clientId: api.#appKey,
|
|
56
|
+
clientSecret: api.#appSecret,
|
|
57
|
+
code,
|
|
58
|
+
refreshToken,
|
|
59
|
+
grantType
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
})(this);
|
|
64
|
+
/**
|
|
65
|
+
* 通讯录
|
|
66
|
+
*/
|
|
67
|
+
#contact = /* @__PURE__ */ ((api) => {
|
|
68
|
+
const baseUrl = "https://api.dingtalk.com";
|
|
69
|
+
return {
|
|
70
|
+
/**
|
|
71
|
+
* 获取用户token
|
|
72
|
+
* @param unionId 用户的unionId。如需获取当前授权人的信息,unionId参数可以传me。
|
|
73
|
+
* @returns
|
|
74
|
+
*/
|
|
75
|
+
async getUser(unionId, accessToken) {
|
|
76
|
+
return api.doRequest("GET", `${baseUrl}/v1.0/contact/users/${unionId}`, void 0, void 0, {
|
|
77
|
+
"x-acs-dingtalk-access-token": accessToken
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* 根据手机号查询用户ID
|
|
82
|
+
* @param mobile 用户的手机号。
|
|
83
|
+
* @returns 员工的userId。
|
|
84
|
+
*/
|
|
85
|
+
async getUserIdByMobile(mobile) {
|
|
86
|
+
return checkResult(await api.doRequest("POST", `https://oapi.dingtalk.com/topapi/v2/user/getbymobile`, {
|
|
87
|
+
access_token: await api.getAccessToken()
|
|
88
|
+
}, {
|
|
89
|
+
mobile
|
|
90
|
+
}));
|
|
91
|
+
},
|
|
92
|
+
/**
|
|
93
|
+
* 根据手机号查询用户ID
|
|
94
|
+
* @param unionid 员工在当前开发者企业账号范围内的唯一标识
|
|
95
|
+
* @returns 员工的userId。
|
|
96
|
+
*/
|
|
97
|
+
async getUserIdByUnionId(unionid) {
|
|
98
|
+
return checkResult(await api.doRequest("POST", `https://oapi.dingtalk.com/topapi/user/getbyunionid`, {
|
|
99
|
+
access_token: await api.getAccessToken()
|
|
100
|
+
}, {
|
|
101
|
+
unionid
|
|
102
|
+
}));
|
|
103
|
+
},
|
|
104
|
+
/**
|
|
105
|
+
* 查询用户详情
|
|
106
|
+
* @param userid 用户的userId。
|
|
107
|
+
* @returns 员工的userId。
|
|
108
|
+
*/
|
|
109
|
+
async getUserDetail(userid) {
|
|
110
|
+
return checkResult(await api.doRequest("POST", `https://oapi.dingtalk.com/topapi/v2/user/get`, {
|
|
111
|
+
access_token: await api.getAccessToken()
|
|
112
|
+
}, {
|
|
113
|
+
userid
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
})(this);
|
|
118
|
+
#appKey;
|
|
119
|
+
#appSecret;
|
|
120
|
+
#accessToken;
|
|
121
|
+
#nextGetAccessTokenTime;
|
|
122
|
+
constructor(appKey, appSecret) {
|
|
123
|
+
this.#appKey = appKey;
|
|
124
|
+
this.#appSecret = appSecret;
|
|
125
|
+
}
|
|
126
|
+
get oauth2() {
|
|
127
|
+
return this.#oauth2;
|
|
128
|
+
}
|
|
129
|
+
get contact() {
|
|
130
|
+
return this.#contact;
|
|
131
|
+
}
|
|
132
|
+
getLoginUrl(redirectUri) {
|
|
133
|
+
return `https://login.dingtalk.com/oauth2/auth?redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code&client_id=${this.#appKey}&scope=openid&state=${(/* @__PURE__ */ new Date()).getTime()}&prompt=consent`;
|
|
134
|
+
}
|
|
135
|
+
async getAccessToken() {
|
|
136
|
+
if (!this.#accessToken || this.#nextGetAccessTokenTime < (/* @__PURE__ */ new Date()).getTime()) {
|
|
137
|
+
const data = await this.doRequest("POST", "https://api.dingtalk.com/v1.0/oauth2/accessToken", null, {
|
|
138
|
+
appKey: this.#appKey,
|
|
139
|
+
appSecret: this.#appSecret
|
|
140
|
+
});
|
|
141
|
+
this.#nextGetAccessTokenTime = (/* @__PURE__ */ new Date()).getTime() + data.expireIn * 1e3 - 1e5;
|
|
142
|
+
this.#accessToken = data.accessToken;
|
|
143
|
+
}
|
|
144
|
+
return this.#accessToken;
|
|
145
|
+
}
|
|
146
|
+
async doRequest(method, path, params, body, headers) {
|
|
147
|
+
const url = `${path}${params ? "?" + toQueryString(params) : ""}`;
|
|
148
|
+
const res = await fetch(url, {
|
|
149
|
+
method,
|
|
150
|
+
headers: {
|
|
151
|
+
"Content-Type": "application/json",
|
|
152
|
+
...headers || {}
|
|
153
|
+
},
|
|
154
|
+
body: body ? JSON.stringify(body) : void 0
|
|
155
|
+
});
|
|
156
|
+
const r = {
|
|
157
|
+
method,
|
|
158
|
+
url,
|
|
159
|
+
headers,
|
|
160
|
+
params,
|
|
161
|
+
body
|
|
162
|
+
};
|
|
163
|
+
if (res.status < 200 || res.status >= 300) {
|
|
164
|
+
const text = await res.text();
|
|
165
|
+
console.error("fetch dingTalk api error: ", r, text);
|
|
166
|
+
throw new Error(text);
|
|
167
|
+
}
|
|
168
|
+
return await res.json();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function toQueryString(params) {
|
|
172
|
+
return Object.keys(params).map((key) => encodeURIComponent(key) + "=" + encodeURIComponent(params[key])).join("&");
|
|
173
|
+
}
|
|
174
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
175
|
+
0 && (module.exports = {
|
|
176
|
+
DingTalkApi,
|
|
177
|
+
checkResult
|
|
178
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const typeMap = {
|
|
11
|
+
"LONG": "number",
|
|
12
|
+
"STRING": "string"
|
|
13
|
+
};
|
|
14
|
+
function apiToType(res) {
|
|
15
|
+
const reqBody = res.data.params.filter((a) => a.position === "BODY").map((a) => {
|
|
16
|
+
var _a;
|
|
17
|
+
return {
|
|
18
|
+
name: a.name,
|
|
19
|
+
desc: ((_a = a.desc) == null ? void 0 : _a.replaceAll("\n", " ")) || "",
|
|
20
|
+
required: a.required,
|
|
21
|
+
type: typeMap[a.type] || "any"
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
const resBody = res.data.rspParams.map((a) => {
|
|
25
|
+
var _a;
|
|
26
|
+
return {
|
|
27
|
+
name: a.name,
|
|
28
|
+
desc: ((_a = a.desc) == null ? void 0 : _a.replaceAll("\n", " ")) || "",
|
|
29
|
+
required: a.required,
|
|
30
|
+
type: typeMap[a.type] || "any"
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
const type = `
|
|
34
|
+
export type Req = {
|
|
35
|
+
${reqBody.map((a) => ` /** ${a.desc} */
|
|
36
|
+
${a.name}${a.required ? "" : "?"}: ${a.type};`).join("\n")}
|
|
37
|
+
}
|
|
38
|
+
export type Res = {
|
|
39
|
+
${resBody.map((a) => ` /** ${a.desc} */
|
|
40
|
+
${a.name}${a.required ? "" : "?"}: ${a.type};`).join("\n")}
|
|
41
|
+
}
|
|
42
|
+
async userAccessToken(taskId: number, projectId?: number) {
|
|
43
|
+
return api.doRequest<null>('POST', \`{baseUrl}/v1.0/oauth2/userAccessToken\`, null, {
|
|
44
|
+
clientId: this.#appKey,
|
|
45
|
+
clientSecret: this.#appSecret,
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
`;
|
|
49
|
+
return type;
|
|
50
|
+
}
|
|
51
|
+
async function genApiDetail(uuid, devType = "org") {
|
|
52
|
+
const fd = new FormData();
|
|
53
|
+
fd.append("uuid", uuid);
|
|
54
|
+
fd.append("devType", devType);
|
|
55
|
+
const res = await fetch("https://open-dev.dingtalk.com/openapi/explorer/getApiDetail", {
|
|
56
|
+
"headers": {},
|
|
57
|
+
"body": fd,
|
|
58
|
+
"method": "POST"
|
|
59
|
+
});
|
|
60
|
+
const data = await res.json();
|
|
61
|
+
return data;
|
|
62
|
+
}
|
|
63
|
+
(async () => {
|
|
64
|
+
const res = await genApiDetail("dingtalk.oapi.v2.user.get");
|
|
65
|
+
console.log(apiToType(res));
|
|
66
|
+
})();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Plugin } from '@nocobase/server';
|
|
2
|
+
export declare class NocobasePluginDingTalkServer extends Plugin {
|
|
3
|
+
afterAdd(): Promise<void>;
|
|
4
|
+
beforeLoad(): Promise<void>;
|
|
5
|
+
load(): Promise<void>;
|
|
6
|
+
install(): Promise<void>;
|
|
7
|
+
afterEnable(): Promise<void>;
|
|
8
|
+
afterDisable(): Promise<void>;
|
|
9
|
+
remove(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export default NocobasePluginDingTalkServer;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var plugin_exports = {};
|
|
28
|
+
__export(plugin_exports, {
|
|
29
|
+
NocobasePluginDingTalkServer: () => NocobasePluginDingTalkServer,
|
|
30
|
+
default: () => plugin_default
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(plugin_exports);
|
|
33
|
+
var import_server = require("@nocobase/server");
|
|
34
|
+
var import_DingTalkAuth = require("./auth/DingTalkAuth");
|
|
35
|
+
var import_dingTalkActions = require("./actions/dingTalkActions");
|
|
36
|
+
var import_constants = require("./constants");
|
|
37
|
+
class NocobasePluginDingTalkServer extends import_server.Plugin {
|
|
38
|
+
async afterAdd() {
|
|
39
|
+
}
|
|
40
|
+
async beforeLoad() {
|
|
41
|
+
}
|
|
42
|
+
async load() {
|
|
43
|
+
this.app.authManager.registerTypes(import_constants.AuthName, {
|
|
44
|
+
title: "\u9489\u9489\u767B\u5F55(\u793E\u533A)",
|
|
45
|
+
auth: import_DingTalkAuth.DingTalkAuth
|
|
46
|
+
});
|
|
47
|
+
this.app.resourceManager.define({
|
|
48
|
+
name: import_constants.ResoureName,
|
|
49
|
+
actions: import_dingTalkActions.dingTalkActions
|
|
50
|
+
});
|
|
51
|
+
this.app.acl.allow(import_constants.ResoureName, "*");
|
|
52
|
+
}
|
|
53
|
+
async install() {
|
|
54
|
+
}
|
|
55
|
+
async afterEnable() {
|
|
56
|
+
}
|
|
57
|
+
async afterDisable() {
|
|
58
|
+
}
|
|
59
|
+
async remove() {
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
var plugin_default = NocobasePluginDingTalkServer;
|
|
63
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
64
|
+
0 && (module.exports = {
|
|
65
|
+
NocobasePluginDingTalkServer
|
|
66
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yeclimeric/nocobase-plugin-dingtalk",
|
|
3
|
+
"version": "1.9.1",
|
|
4
|
+
"displayName": "DingTalk",
|
|
5
|
+
"displayName.zh-CN": "钉钉登录",
|
|
6
|
+
"description": "Integrated DingTalk login function",
|
|
7
|
+
"description.zh-CN": "集成钉钉登录功能",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"plugin",
|
|
10
|
+
"钉钉",
|
|
11
|
+
"dingding",
|
|
12
|
+
"dingtalk",
|
|
13
|
+
"nocobase"
|
|
14
|
+
],
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "不就订个外卖么",
|
|
17
|
+
"email": "yeclimeric@gmail.com"
|
|
18
|
+
},
|
|
19
|
+
"main": "dist/server/index.js",
|
|
20
|
+
"files": [
|
|
21
|
+
"CHANGELOG.md",
|
|
22
|
+
"dist/**"
|
|
23
|
+
],
|
|
24
|
+
"dependencies": {},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"@nocobase/client": "1.x",
|
|
27
|
+
"@nocobase/server": "1.x",
|
|
28
|
+
"@nocobase/test": "1.x"
|
|
29
|
+
}
|
|
30
|
+
}
|