¶ 自定义代码
自定义代码节点可以让您编写非常灵活的自定义逻辑,包括但不限于:
- 进行复杂的数据转换;
- 发送网络请求;
- 抛出自定义异常,手动终止流程等等。
Authing 自定义代码运行在 Node.js 14 的隔离沙箱环境中,支持 async/await 和最新 ES6 (opens new window) 语法。我们为开发者提供了很多开箱即用的 Library 和工具类:
- 网络请求:axios (opens new window)
- 数据操作:lodash (opens new window)、ramda (opens new window)
- 数据库操作:pg (opens new window)、mysql2 (opens new window)、mysql2/promise (opens new window)、mongodb (opens new window)
- 数据加密:bcrypt (opens new window)、crypto (opens new window)
- 日期工具:moment (opens new window)、dayjs (opens new window)
- 其他:faker (opens new window)、validator (opens new window)、qs (opens new window)、jsonwebtoken (opens new window)、uuid (opens new window)、js-yaml (opens new window)
- Authing 内置工具类:utils(详情见下文)
¶ 创建自定义代码节点
你可以在 Authing 身份自动化应用列表中添加自定义代码节点:
自定义代码节点的配置分为两部分:输入数据和函数体。比如你在输入数据中中定义了一个变量 data,你可以在代码中通过 data 引用此数据。如果此自定义代码有返回值,需要使用 return 语句返回结果。
¶ Authing 内置工具类
¶ async utils.generateSerialNumber
函数描述:生成一个用户池隔离级别的的自增序列。
函数定义:async utils.generateSerialNumber(length, start)
参数描述:
- length:自增序列长度,比如设置为 6 位,则没调用一次,就会生成出如 000001、000002 的数据。
- start:自增序列的起始值,默认为 0,即生成的第一个序列值为 000001。
使用场景:
- 给用户生成一个自增的工号。
代码示例:如下面的示例代码所示,会生成一个格式为 E000001、E000002 的自增序列。
return "E" + await utils.generateSerialNumber(6, 0);
¶ async utils.rsaEncrypt
函数描述:使用 RSA 公钥对内容进行加密
函数定义:async utils.rsaEncrypt(plainText, publicKey)
参数描述:
- plainText:需要加密的明文
- publicKey:RSA 公钥,如
-----BEGIN PUBLIC KEY-----
xxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxx
-----END PUBLIC KEY-----
¶ async utils.rsaDecrypt
函数描述:使用 RSA 私钥对内容进行解密
函数定义:async utils.rsaDecrypt(encrypted, privateKey)
参数描述:
- encrypted:需要解密的密文
- privateKey:RSA 密钥,如
-----BEGIN RSA PRIVATE KEY-----
xxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxx
-----END RSA PRIVATE KEY-----
¶ 常见场景示例
在编写自定义代码节点之前,我们使用传入 JSON 数据点节点 Mock 一份数据:
[
{
"login": "mojombo",
"id": 1,
"node_id": "MDQ6VXNlcjE=",
"avatar_url": "https://avatars.githubusercontent.com/u/1?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/mojombo",
"html_url": "https://github.com/mojombo",
"followers_url": "https://api.github.com/users/mojombo/followers",
"following_url": "https://api.github.com/users/mojombo/following{/other_user}",
"gists_url": "https://api.github.com/users/mojombo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/mojombo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/mojombo/subscriptions",
"organizations_url": "https://api.github.com/users/mojombo/orgs",
"repos_url": "https://api.github.com/users/mojombo/repos",
"events_url": "https://api.github.com/users/mojombo/events{/privacy}",
"received_events_url": "https://api.github.com/users/mojombo/received_events",
"type": "User",
"site_admin": false
},
{
"login": "defunkt",
"id": 2,
"node_id": "MDQ6VXNlcjI=",
"avatar_url": "https://avatars.githubusercontent.com/u/2?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/defunkt",
"html_url": "https://github.com/defunkt",
"followers_url": "https://api.github.com/users/defunkt/followers",
"following_url": "https://api.github.com/users/defunkt/following{/other_user}",
"gists_url": "https://api.github.com/users/defunkt/gists{/gist_id}",
"starred_url": "https://api.github.com/users/defunkt/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/defunkt/subscriptions",
"organizations_url": "https://api.github.com/users/defunkt/orgs",
"repos_url": "https://api.github.com/users/defunkt/repos",
"events_url": "https://api.github.com/users/defunkt/events{/privacy}",
"received_events_url": "https://api.github.com/users/defunkt/received_events",
"type": "User",
"site_admin": false
}
]
然后在自定义代码节点装配此数据:
¶ 示例一:遍历输入数据,进行数据处理
在自定义代码中可以使用 Node.js 的 map、filter 等方法,以及 for 循环,对输入的数据进行一系列处理:
如:给传入的每个元素添加一个字段 source,值为 "github"
return data.map(item => {
item.source = "github";
return item;
});
你还可以引入 lodash (opens new window) 包:
const _ = require("lodash");
return _.map(data, x => {
x.source = "github";
return x;
});
如:过滤出 id 小于等于 1 的元素
return data.filter(item => {
return item.id <= 1;
});
¶ 示例二:在自定义代码中发送网络请求
Authing 自定义代码节点内置了 axios (opens new window) 网络请求库,你可以用它来发送网络请求,如下所示:我们遍历了输入的数据的每个元素,然后请求 followers_url 字段,获取此 github 用户的 Followers 列表:
const axios = require("axios");
const getFollowers = async (url) => {
const { data } = await axios.get(url);
return data;
};
for (const item of data) {
const { followers_url } = item;
const followers = await getFollowers(followers_url);
item.followers = followers;
}
return data;
¶ 示例三:过滤在 7 天内有更新过的用户
在下面这个示例中,我们在自定义代码节点之前通过 Authing 节点的「获取用户列表」拉取用户数据,并将结果输入到自定义代码节点中:
我们内置了 moment (opens new window),可以很方便得对日期进行一系列操作:
const moment = require("moment");
const targetDate = moment().subtract(7,'d');
return users.filter(user => {
const { updatedAt } = user;
return new Date(updatedAt) > targetDate;
});
¶ 注意事项
- 不能在自定义代码块中使用 Node.js 的 Buffer,如果你需要在自定义代码中操作 Buffer,推荐开你的服务器开发一个接口,然后使用 HTTP 节点去调用。
- Authing 内置的工具类函数中,都是 async 异步函数,需要使用 await。