@blocklet/sdk 1.6.14 → 1.6.18

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 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
- #### client.updateUserRole(did, role)
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` did
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` did
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,7 @@
1
+ const user = require('./user');
2
+ const auth = require('./auth');
3
+
4
+ module.exports = {
5
+ user,
6
+ auth,
7
+ };
@@ -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
+ };
@@ -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 notificationSchema = Joi.alternatives().try(notificationTypeSchema, connectTypeSchema).required();
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: fromSecretKey(process.env.BLOCKLET_APP_SK, type).toJSON(),
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.14",
6
+ "version": "1.6.18",
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.14",
23
- "@abtnode/constant": "1.6.14",
24
- "@arcblock/did-auth": "^1.13.79",
25
- "@arcblock/jwt": "^1.13.79",
26
- "@blocklet/meta": "1.6.14",
22
+ "@abtnode/client": "1.6.18",
23
+ "@abtnode/constant": "1.6.18",
24
+ "@arcblock/did-auth": "^1.14.8",
25
+ "@arcblock/jwt": "^1.14.8",
26
+ "@blocklet/meta": "1.6.18",
27
27
  "@nedb/core": "^1.2.2",
28
- "@ocap/mcrypto": "^1.13.79",
29
- "@ocap/wallet": "^1.13.79",
28
+ "@ocap/mcrypto": "^1.14.8",
29
+ "@ocap/wallet": "^1.14.8",
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": "0ae215d5cf1160631bdd9b64639c8fcf80eb2d5f"
41
+ "gitHead": "2f02f166869d8ebedc0466068f6ed90ab3e07b87"
41
42
  }