forked from netless-io/netless-token
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
123 lines (105 loc) · 3.2 KB
/
index.js
File metadata and controls
123 lines (105 loc) · 3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
const { createHmac } = require("crypto");
const { v1: uuidv1 } = require("uuid");
// 数字越小,权限越大
const TokenRole = {
Admin: "0",
Writer: "1",
Reader: "2",
};
module.exports.TokenRole = TokenRole;
const TokenPrefix = {
SDK: "NETLESSSDK_",
ROOM: "NETLESSROOM_",
TASK: "NETLESSTASK_",
};
module.exports.TokenPrefix = TokenPrefix
/**
* buffer 转 base64,且格式化字符
* @param {Buffer} buffer - 要格式化的 buffer 对象
* @return {string}
*/
const bufferToBase64 = buffer => {
return buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
};
/**
* 为对象排序,并把非字符串的 value 转成 string
* @param {Object} object - 要转换的对象
* @return {Object}
*/
const formatJSON = object => {
const keys = Object.keys(object).sort();
const target = {};
for (const key of keys) {
target[key] = String(object[key]);
}
return target;
};
/**
* 序列化对象
* 把 undefined 转为空字符串
* 把 null 转为 "null"
* 最终通过 & 连接成一个字符串
* 实现强参考: https://github.com/sindresorhus/query-string/blob/master/index.js#L284
* @param {Object} object - 将要序列化的对象
* @return {string}
*/
const stringify = (object) => {
return Object.keys(object)
.map(key => {
const value = object[key];
if (value === undefined) {
return "";
}
if (value === null) {
return "null";
}
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
})
.join("&");
};
/**
* sdk token 所需额外参数
* @typedef {Object} SdkToken
* @property {number} [role] - 权限等级,有 0~2,越小权限越大
*/
/**
* room token 所需额外参数
* @typedef {Object} RoomToken
* @property {number} [role] - 权限等级,有 0~2,越小权限越大
* @property {string} [uuid] - uuid
*/
/**
* task token 所需额外参数
* @typedef {Object} TaskToken
* @property {number} [role] - 权限等级,有 0~2,越小权限越大
* @property {string} [uuid] - uuid
*/
/**
* 根据 prefix 生成相应的 token
* @param {"NETLESSSDK_" | "NETLESSROOM_" | "NETLESSTASK_"} prefix - 相关 token 的前缀
* @return {function(string, string, number, SdkToken | RoomToken | TaskToken): string}
*/
const createToken = prefix => {
return (accessKey, secretAccessKey, lifespan, content) => {
const object = {
...content,
ak: accessKey,
nonce: uuidv1(),
};
if (lifespan > 0) {
object.expireAt = `${Date.now() + lifespan}`;
}
const information = JSON.stringify(formatJSON(object));
const hmac = createHmac("sha256", secretAccessKey);
object.sig = hmac.update(information).digest("hex");
const query = stringify(formatJSON(object));
const buffer = Buffer.from(query, "utf8");
return prefix + bufferToBase64(buffer);
};
};
// 生成 sdk token
module.exports.sdkToken = createToken(TokenPrefix.SDK);
// 生成 room token
module.exports.roomToken = createToken(TokenPrefix.ROOM);
// 生成 task token
module.exports.taskToken = createToken(TokenPrefix.TASK);