@blocklet/sdk 1.6.12 → 1.6.16
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/README.md +137 -8
- package/lib/env.js +9 -0
- package/lib/index.js +6 -0
- package/lib/middlewares/auth.js +54 -0
- package/lib/middlewares/index.js +7 -0
- package/lib/middlewares/user.js +11 -0
- package/lib/util/send-notification.js +7 -1
- package/lib/validators/notification.js +9 -1
- package/lib/wallet-authenticator.js +2 -8
- package/lib/wallet.js +11 -0
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -34,31 +34,99 @@ const { user } = await client.getUser(userDid);
|
|
|
34
34
|
|
|
35
35
|
Get user by user did
|
|
36
36
|
|
|
37
|
-
- **did** `string`
|
|
37
|
+
- _@param_ **did** `string`
|
|
38
|
+
- _@return_ `{ code, user }`
|
|
38
39
|
|
|
39
40
|
#### client.getUsers()
|
|
40
41
|
|
|
41
42
|
Get all users of the team
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- **did** `string`
|
|
46
|
-
- **role** `string`
|
|
44
|
+
- _@return_ `{ code, users }`
|
|
47
45
|
|
|
48
46
|
#### client.getPermissionsByRole(role)
|
|
49
47
|
|
|
50
48
|
Get all permissions of a role
|
|
51
49
|
|
|
52
|
-
- **role** `string`
|
|
50
|
+
- _@param_ **role** `string`
|
|
51
|
+
- _@return_ `{ code, permissions }`
|
|
53
52
|
|
|
54
53
|
#### client.getRoles()
|
|
55
54
|
|
|
56
55
|
Get all roles of the team
|
|
57
56
|
|
|
57
|
+
- _@return_ `{ code, roles }`
|
|
58
|
+
|
|
59
|
+
#### client.createRole({ name, title, description })
|
|
60
|
+
|
|
61
|
+
- _@param_ **name** `string` the key of the role, should be unique
|
|
62
|
+
- _@param_ **title** `string`
|
|
63
|
+
- _@param_ **description** `string`
|
|
64
|
+
- _@return_ `{ code, role }`
|
|
65
|
+
|
|
66
|
+
#### client.updateRole(name, { title, description })
|
|
67
|
+
|
|
68
|
+
- _@param_ **name** `string` the key of the role
|
|
69
|
+
- _@param_ **title** `string`
|
|
70
|
+
- _@param_ **description** `string`
|
|
71
|
+
- _@return_ `{ code, role }`
|
|
72
|
+
|
|
73
|
+
#### client.deleteRole(name, { title, description })
|
|
74
|
+
|
|
75
|
+
- _@param_ **name** `string` the key of the role
|
|
76
|
+
- _@return_ `{ code }`
|
|
77
|
+
|
|
78
|
+
#### client.grantPermissionForRole(role, permission)
|
|
79
|
+
|
|
80
|
+
- _@param_ **role** `string` the name of the role
|
|
81
|
+
- _@param_ **permission** `string` the name of the permission
|
|
82
|
+
- _@return_ `{ code }`
|
|
83
|
+
|
|
84
|
+
#### client.revokePermissionFromRole(role, permission)
|
|
85
|
+
|
|
86
|
+
- _@param_ **role** `string` the name of the role
|
|
87
|
+
- _@param_ **permission** `string` the name of the permission
|
|
88
|
+
- _@return_ `{ code }`
|
|
89
|
+
|
|
90
|
+
#### client.updatePermissionsForRole(role, permissions)
|
|
91
|
+
|
|
92
|
+
Full update permissions of a role
|
|
93
|
+
|
|
94
|
+
- _@param_ **role** `string` the name of the role
|
|
95
|
+
- _@param_ **permissions** `array<string>` name of the permissions
|
|
96
|
+
- _@return_ `{ code, role }`
|
|
97
|
+
|
|
98
|
+
#### client.hasPermission(role, permission)
|
|
99
|
+
|
|
100
|
+
- _@param_ **role** `string` the name of the role
|
|
101
|
+
- _@param_ **permission** `string` the name of the permission
|
|
102
|
+
- _@return_ `{ code, result }`
|
|
103
|
+
- **result** `boolean`
|
|
104
|
+
|
|
58
105
|
#### client.getPermissions()
|
|
59
106
|
|
|
60
107
|
Get all permissions of the team
|
|
61
108
|
|
|
109
|
+
- _@return_ `{ code, permissions }`
|
|
110
|
+
|
|
111
|
+
#### client.createPermission({ name, title, description })
|
|
112
|
+
|
|
113
|
+
- _@param_ **name** `Permission` the key of the permission, should be unique
|
|
114
|
+
- format: `<action>_<resource>`. e.g. `query_article`, `mutate_user`
|
|
115
|
+
- _@param_ **description** `string`
|
|
116
|
+
- _@return_ `{ code, role }`
|
|
117
|
+
|
|
118
|
+
#### client.updatePermission(name, { title, description })
|
|
119
|
+
|
|
120
|
+
- _@param_ **name** `string` the key of the role
|
|
121
|
+
- _@param_ **title** `string`
|
|
122
|
+
- _@param_ **description** `string`
|
|
123
|
+
- _@return_ `{ code }`
|
|
124
|
+
|
|
125
|
+
#### client.deletePermission(name, { title, description })
|
|
126
|
+
|
|
127
|
+
- _@param_ **name** `string` the key of the permission
|
|
128
|
+
- _@return_ `{ code }`
|
|
129
|
+
|
|
62
130
|
## Notification SDK
|
|
63
131
|
|
|
64
132
|
### Usage
|
|
@@ -116,7 +184,7 @@ Send notification to an account
|
|
|
116
184
|
- **type** `string`
|
|
117
185
|
- **message** `string`
|
|
118
186
|
- _type: asset_
|
|
119
|
-
- **did** `string`
|
|
187
|
+
- **did** `string`
|
|
120
188
|
- **chainHost** `string` uri
|
|
121
189
|
- _type: vc_
|
|
122
190
|
- **credential** `object`
|
|
@@ -125,7 +193,7 @@ Send notification to an account
|
|
|
125
193
|
- **address** `string` did
|
|
126
194
|
- **amount** `string`
|
|
127
195
|
- **symbol** `string`
|
|
128
|
-
- **senderDid** `string`
|
|
196
|
+
- **senderDid** `string`
|
|
129
197
|
- **chainHost** `string`
|
|
130
198
|
- **decimal** `integer`
|
|
131
199
|
- **notification.actions** `array<object>`
|
|
@@ -200,3 +268,64 @@ const { Database } = require('@blocklet/sdk');
|
|
|
200
268
|
const data2Extra = await db2.extraFn();
|
|
201
269
|
})();
|
|
202
270
|
```
|
|
271
|
+
|
|
272
|
+
## getWallet
|
|
273
|
+
|
|
274
|
+
### Usage
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
const { getWallet } = require('@blocklet/sdk');
|
|
278
|
+
|
|
279
|
+
// wallet is an instance of @ocap/wallet const { wallet } = env;
|
|
280
|
+
const wallet = getWallet();
|
|
281
|
+
const { address, secretKey, publicKey } = wallet;
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## env
|
|
285
|
+
|
|
286
|
+
### Usage
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
const { env } = require('@blocklet/sdk');
|
|
290
|
+
|
|
291
|
+
const { appId, appName, appDescription, appUrl, isComponent, dataDir, cacheDir } = env;
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## middlewares
|
|
295
|
+
|
|
296
|
+
### Usage
|
|
297
|
+
|
|
298
|
+
```javascript
|
|
299
|
+
const express = require('express');
|
|
300
|
+
const { middlewares } = require('@blocklet/sdk');
|
|
301
|
+
|
|
302
|
+
const app = express();
|
|
303
|
+
|
|
304
|
+
app.get('/', middlewares.user(), (req, res) => {
|
|
305
|
+
const { did, fullName, role } = req.user;
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
app.get('/auth1', middlewares.auth(), (req, res) => {
|
|
309
|
+
// will return 401 if user is not connected
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
app.get('/auth2', middlewares.auth({ roles: ['admin', 'owner'] }), (req, res) => {
|
|
313
|
+
// will return 401 if user is not connected
|
|
314
|
+
// will return 403 if user role is neither owner nor admin
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
app.get('/auth2', middlewares.auth({ permissions: ['mutate_data', 'query_data'] }), (req, res) => {
|
|
318
|
+
// will return 401 if user is not connected
|
|
319
|
+
// will return 403 if neither 'mutate_data' nor 'query data' in user permissions
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
app.get(
|
|
323
|
+
'/auth3',
|
|
324
|
+
middlewares.auth({ roles: ['admin', 'owner'], permissions: ['mutate_data', 'query_data'] }),
|
|
325
|
+
(req, res) => {
|
|
326
|
+
// will return 401 if user is not connected
|
|
327
|
+
// will return 403 if user role is neither owner nor admin
|
|
328
|
+
// will return 403 if neither 'mutate_data' nor 'query data' in user permissions
|
|
329
|
+
}
|
|
330
|
+
);
|
|
331
|
+
```
|
package/lib/env.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
appId: process.env.BLOCKLET_APP_ID,
|
|
3
|
+
appName: process.env.BLOCKLET_APP_NAME,
|
|
4
|
+
appDescription: process.env.BLOCKLET_APP_DESCRIPTION,
|
|
5
|
+
appUrl: process.env.BLOCKLET_APP_URL,
|
|
6
|
+
isComponent: process.env.BLOCKLET_DID !== process.env.BLOCKLET_REAL_DID,
|
|
7
|
+
dataDir: process.env.BLOCKLET_DATA_DIR,
|
|
8
|
+
cacheDir: process.env.BLOCKLET_CACHE_DIR,
|
|
9
|
+
};
|
package/lib/index.js
CHANGED
|
@@ -3,6 +3,9 @@ const NotificationService = require('./service/notification');
|
|
|
3
3
|
const WalletAuthenticator = require('./wallet-authenticator');
|
|
4
4
|
const WalletHandlers = require('./wallet-handler');
|
|
5
5
|
const Database = require('./database');
|
|
6
|
+
const env = require('./env');
|
|
7
|
+
const middlewares = require('./middlewares');
|
|
8
|
+
const getWallet = require('./wallet');
|
|
6
9
|
|
|
7
10
|
module.exports = {
|
|
8
11
|
AuthService,
|
|
@@ -10,4 +13,7 @@ module.exports = {
|
|
|
10
13
|
WalletHandlers,
|
|
11
14
|
WalletAuthenticator,
|
|
12
15
|
Database,
|
|
16
|
+
getWallet,
|
|
17
|
+
env,
|
|
18
|
+
middlewares,
|
|
13
19
|
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const LRU = require('lru-cache');
|
|
2
|
+
const AuthClient = require('../service/auth');
|
|
3
|
+
|
|
4
|
+
const cachedPermissions = new LRU({
|
|
5
|
+
max: 10, // cache at most 10 role
|
|
6
|
+
maxAge: 60 * 1000, // cache for 2min
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const getPermissionsByRole = async (client, role) => {
|
|
10
|
+
const cached = cachedPermissions.get(role);
|
|
11
|
+
if (cached) {
|
|
12
|
+
return cached;
|
|
13
|
+
}
|
|
14
|
+
const res = await client.getPermissionsByRole(role);
|
|
15
|
+
cachedPermissions.set(role, res);
|
|
16
|
+
return res;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {*} _AuthClient Just for test
|
|
21
|
+
*/
|
|
22
|
+
module.exports = ({ roles, permissions, _AuthClient = AuthClient } = {}) => {
|
|
23
|
+
if (roles && !Array.isArray(roles)) {
|
|
24
|
+
throw new Error('roles must be array');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (permissions && !Array.isArray(permissions)) {
|
|
28
|
+
throw new Error('permissions must be array');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const client = new _AuthClient();
|
|
32
|
+
|
|
33
|
+
return async (req, res, next) => {
|
|
34
|
+
if (!req.headers['x-user-did']) {
|
|
35
|
+
res.status(401).json({ code: 'forbidden', error: 'not authorized' });
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (roles && !roles.includes(req.headers['x-user-role'])) {
|
|
40
|
+
res.status(403).json({ code: 'forbidden', error: 'no permission' });
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (permissions) {
|
|
45
|
+
const { permissions: list } = await getPermissionsByRole(client, req.headers['x-user-role']);
|
|
46
|
+
if (!permissions.some((x) => (list || []).some((y) => y.name === x))) {
|
|
47
|
+
res.status(403).json({ code: 'forbidden', error: 'no permission' });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
next();
|
|
53
|
+
};
|
|
54
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module.exports = () => async (req, res, next) => {
|
|
2
|
+
if (req.headers['x-user-did']) {
|
|
3
|
+
req.user = {
|
|
4
|
+
did: req.headers['x-user-did'],
|
|
5
|
+
role: req.headers['x-user-role'],
|
|
6
|
+
fullName: decodeURIComponent(req.headers['x-user-fullname']),
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
next();
|
|
11
|
+
};
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
const axios = require('axios').create({ proxy: false });
|
|
3
3
|
|
|
4
4
|
const JWT = require('@arcblock/jwt');
|
|
5
|
+
const { NODE_MODES } = require('@abtnode/constant');
|
|
5
6
|
|
|
6
7
|
const validators = require('../validators');
|
|
7
8
|
const { AUTH_SERVICE_PREFIX } = require('./constants');
|
|
@@ -10,6 +11,8 @@ const VERSION = require('../../package.json').version; // version of notificatio
|
|
|
10
11
|
|
|
11
12
|
const { validateNotification, validateReceiver } = validators;
|
|
12
13
|
|
|
14
|
+
const SERVER_MODE = process.env.ABT_NODE_MODE;
|
|
15
|
+
|
|
13
16
|
/**
|
|
14
17
|
* @param {String|Array} receiver
|
|
15
18
|
* @param {Object} notification
|
|
@@ -24,7 +27,10 @@ module.exports = async (
|
|
|
24
27
|
port = process.env.ABT_NODE_SERVICE_PORT
|
|
25
28
|
) => {
|
|
26
29
|
await validateReceiver(receiver);
|
|
27
|
-
|
|
30
|
+
|
|
31
|
+
if (SERVER_MODE !== NODE_MODES.DEBUG) {
|
|
32
|
+
await validateNotification(notification);
|
|
33
|
+
}
|
|
28
34
|
|
|
29
35
|
const token = JWT.sign(appId, appSk);
|
|
30
36
|
|
|
@@ -7,6 +7,7 @@ const Joi = JOI.extend(didExtension);
|
|
|
7
7
|
const TYPES = {
|
|
8
8
|
NOTIFICATION: 'notification',
|
|
9
9
|
CONNECT: 'connect',
|
|
10
|
+
FEED: 'feed',
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
const assetSchema = Joi.object({
|
|
@@ -58,7 +59,13 @@ const connectTypeSchema = Joi.object({
|
|
|
58
59
|
checkUrl: Joi.string().uri(),
|
|
59
60
|
}).required();
|
|
60
61
|
|
|
61
|
-
const
|
|
62
|
+
const feedTypeSchema = Joi.object({
|
|
63
|
+
type: Joi.string().valid(TYPES.FEED),
|
|
64
|
+
feedType: Joi.string().required(),
|
|
65
|
+
data: Joi.object().required(),
|
|
66
|
+
}).required();
|
|
67
|
+
|
|
68
|
+
const notificationSchema = Joi.alternatives().try(notificationTypeSchema, connectTypeSchema, feedTypeSchema).required();
|
|
62
69
|
|
|
63
70
|
const receiverSchema = Joi.DID().trim().required();
|
|
64
71
|
|
|
@@ -76,4 +83,5 @@ module.exports = {
|
|
|
76
83
|
assetSchema,
|
|
77
84
|
vcSchema,
|
|
78
85
|
attachmentSchema,
|
|
86
|
+
notificationSchema,
|
|
79
87
|
};
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
const joinUrl = require('url-join');
|
|
2
2
|
const { WalletAuthenticator: Authenticator } = require('@arcblock/did-auth');
|
|
3
|
-
const { fromSecretKey, WalletType } = require('@ocap/wallet');
|
|
4
|
-
const { types } = require('@ocap/mcrypto');
|
|
5
3
|
|
|
4
|
+
const getWallet = require('./wallet');
|
|
6
5
|
const checkBlockletEnv = require('./util/check-blocklet-env');
|
|
7
6
|
const { AUTH_SERVICE_PREFIX } = require('./util/constants');
|
|
8
7
|
|
|
9
|
-
const type =
|
|
10
|
-
process.env.BLOCKLET_WALLET_TYPE !== 'eth'
|
|
11
|
-
? WalletType({ role: types.RoleType.ROLE_APPLICATION, pk: types.KeyType.ED25519, hash: types.HashType.SHA3 })
|
|
12
|
-
: 'eth';
|
|
13
|
-
|
|
14
8
|
// wraps value in closure or returns closure
|
|
15
9
|
const closure = (value) => (typeof value === 'function' ? value : () => value);
|
|
16
10
|
|
|
@@ -19,7 +13,7 @@ class WalletAuthenticator extends Authenticator {
|
|
|
19
13
|
checkBlockletEnv();
|
|
20
14
|
|
|
21
15
|
super({
|
|
22
|
-
wallet:
|
|
16
|
+
wallet: getWallet().toJSON(),
|
|
23
17
|
|
|
24
18
|
chainInfo: () => {
|
|
25
19
|
const chainHost = process.env.CHAIN_HOST;
|
package/lib/wallet.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const { fromSecretKey, WalletType } = require('@ocap/wallet');
|
|
2
|
+
const { types } = require('@ocap/mcrypto');
|
|
3
|
+
|
|
4
|
+
module.exports = () => {
|
|
5
|
+
const type =
|
|
6
|
+
process.env.BLOCKLET_WALLET_TYPE !== 'eth'
|
|
7
|
+
? WalletType({ role: types.RoleType.ROLE_APPLICATION, pk: types.KeyType.ED25519, hash: types.HashType.SHA3 })
|
|
8
|
+
: 'eth';
|
|
9
|
+
|
|
10
|
+
return fromSecretKey(process.env.BLOCKLET_APP_SK, type);
|
|
11
|
+
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.6.
|
|
6
|
+
"version": "1.6.16",
|
|
7
7
|
"description": "graphql client to read/write data on abt node",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,23 +19,24 @@
|
|
|
19
19
|
"author": "linchen1987 <linchen.1987@foxmail.com> (http://github.com/linchen1987)",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/client": "1.6.
|
|
23
|
-
"@abtnode/constant": "1.6.
|
|
24
|
-
"@arcblock/did-auth": "^1.
|
|
25
|
-
"@arcblock/jwt": "^1.
|
|
26
|
-
"@blocklet/meta": "1.6.
|
|
22
|
+
"@abtnode/client": "1.6.16",
|
|
23
|
+
"@abtnode/constant": "1.6.16",
|
|
24
|
+
"@arcblock/did-auth": "^1.14.3",
|
|
25
|
+
"@arcblock/jwt": "^1.14.3",
|
|
26
|
+
"@blocklet/meta": "1.6.16",
|
|
27
27
|
"@nedb/core": "^1.2.2",
|
|
28
|
-
"@ocap/mcrypto": "^1.
|
|
29
|
-
"@ocap/wallet": "^1.
|
|
28
|
+
"@ocap/mcrypto": "^1.14.3",
|
|
29
|
+
"@ocap/wallet": "^1.14.3",
|
|
30
30
|
"axios": "^0.21.4",
|
|
31
31
|
"fs-extra": "^10.0.0",
|
|
32
32
|
"joi": "^17.5.0",
|
|
33
33
|
"lodash": "^4.17.21",
|
|
34
|
+
"lru-cache": "^6.0.0",
|
|
34
35
|
"url-join": "^4.0.1"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"detect-port": "^1.3.0",
|
|
38
39
|
"jest": "^27.4.5"
|
|
39
40
|
},
|
|
40
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "69b08db16aeb75ce23b0e6bb5b9fa396adba2d4b"
|
|
41
42
|
}
|