@blocklet/meta 1.7.8 → 1.7.11
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/lib/parse-navigation.js +1 -1
- package/lib/service-configs/auth.json +66 -0
- package/lib/service.js +101 -0
- package/lib/validate.js +3 -29
- package/lib/verify-multi-sig.js +6 -4
- package/package.json +14 -14
package/lib/parse-navigation.js
CHANGED
|
@@ -17,7 +17,7 @@ const parseNavigation = (navigation, blocklet, prefix = '/', level = 1) => {
|
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
if (nav.link) {
|
|
20
|
-
item.link = normalizePathPrefix(`${prefix}${nav.link || '/'}`);
|
|
20
|
+
item.link = nav.link.startsWith('/') ? normalizePathPrefix(`${prefix}${nav.link || '/'}`) : nav.link;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
if (level === 1) {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "auth",
|
|
3
|
+
"description": "Neat and easy to use user authentication and authorization service for blocklets",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"schema": {
|
|
6
|
+
"JSONSchema": {
|
|
7
|
+
"title": "Config Auth Service",
|
|
8
|
+
"description": "Customize how Auth Service works",
|
|
9
|
+
"type": "object",
|
|
10
|
+
"required": ["profileFields", "webWalletUrl"],
|
|
11
|
+
"properties": {
|
|
12
|
+
"whoCanAccess": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"title": "Who can access the blocklet?",
|
|
15
|
+
"enum": ["owner", "invited", "all"],
|
|
16
|
+
"default": "all"
|
|
17
|
+
},
|
|
18
|
+
"profileFields": {
|
|
19
|
+
"type": "array",
|
|
20
|
+
"title": "What info do you want user to provide when login?",
|
|
21
|
+
"items": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"enum": ["fullName", "email", "avatar", "phone"]
|
|
24
|
+
},
|
|
25
|
+
"default": ["fullName", "email", "avatar"],
|
|
26
|
+
"uniqueItems": true
|
|
27
|
+
},
|
|
28
|
+
"allowSwitchProfile": {
|
|
29
|
+
"type": "boolean",
|
|
30
|
+
"title": "Does you app allow user to switch profile?",
|
|
31
|
+
"default": true
|
|
32
|
+
},
|
|
33
|
+
"webWalletUrl": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"title": "The URL of your preferred web wallet instance",
|
|
36
|
+
"pattern": "^https?://",
|
|
37
|
+
"default": "https://web.abtwallet.io"
|
|
38
|
+
},
|
|
39
|
+
"ignoreUrls": {
|
|
40
|
+
"type": "array",
|
|
41
|
+
"title": "Which URLs do not need to be protected. e.g: /public/**",
|
|
42
|
+
"items": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"minLength": 1
|
|
45
|
+
},
|
|
46
|
+
"default": []
|
|
47
|
+
},
|
|
48
|
+
"blockUnauthenticated": {
|
|
49
|
+
"type": "boolean",
|
|
50
|
+
"title": "Do you want Auth Service block unauthenticated requests for you?",
|
|
51
|
+
"default": false
|
|
52
|
+
},
|
|
53
|
+
"blockUnauthorized": {
|
|
54
|
+
"type": "boolean",
|
|
55
|
+
"title": "Do you want Auth Service block unauthorized requests for you?",
|
|
56
|
+
"default": false
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"UISchema": {
|
|
61
|
+
"profileFields": {
|
|
62
|
+
"ui:widget": "checkboxes"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
package/lib/service.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
const cloneDeep = require('lodash/cloneDeep');
|
|
2
|
+
const Ajv = require('ajv').default;
|
|
3
|
+
|
|
4
|
+
const { NODE_SERVICES } = require('@abtnode/constant');
|
|
5
|
+
|
|
6
|
+
const ajv = new Ajv({
|
|
7
|
+
useDefaults: true,
|
|
8
|
+
removeAdditional: 'all',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const SERVICES = {};
|
|
12
|
+
|
|
13
|
+
const setService = (meta) => {
|
|
14
|
+
const validate = ajv.compile(meta.schema.JSONSchema);
|
|
15
|
+
|
|
16
|
+
// parse empty custom config to get default config
|
|
17
|
+
const defaultConfig = {};
|
|
18
|
+
validate(defaultConfig);
|
|
19
|
+
|
|
20
|
+
SERVICES[meta.name] = {
|
|
21
|
+
meta,
|
|
22
|
+
validate,
|
|
23
|
+
defaultConfig,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
setService(require('./service-configs/auth.json'));
|
|
28
|
+
|
|
29
|
+
// backward compatible
|
|
30
|
+
SERVICES[NODE_SERVICES.AUTH_SERVICE] = {
|
|
31
|
+
...SERVICES[NODE_SERVICES.AUTH],
|
|
32
|
+
meta: {
|
|
33
|
+
...SERVICES[NODE_SERVICES.AUTH].meta,
|
|
34
|
+
name: NODE_SERVICES.AUTH_SERVICE,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const getServiceMetas = ({ stringifySchema = false } = {}) => {
|
|
39
|
+
const list = Object.values(SERVICES).map(({ meta }) => {
|
|
40
|
+
const data = cloneDeep(meta);
|
|
41
|
+
if (stringifySchema) {
|
|
42
|
+
data.schema = JSON.stringify(meta.schema);
|
|
43
|
+
}
|
|
44
|
+
return data;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return list;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const getService = (serviceName) => {
|
|
51
|
+
if (!serviceName) {
|
|
52
|
+
throw new Error('service name should not be empty');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const service = SERVICES[serviceName];
|
|
56
|
+
if (!service) {
|
|
57
|
+
throw new Error(`service ${serviceName} does not exist`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return service;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const getServiceConfig = (serviceName, customConfig, { validate } = {}) => {
|
|
64
|
+
const service = getService(serviceName);
|
|
65
|
+
|
|
66
|
+
const data = cloneDeep(customConfig || {});
|
|
67
|
+
// this method may have side effect thar will fill default value to customConfig
|
|
68
|
+
const valid = service.validate(data || {});
|
|
69
|
+
|
|
70
|
+
if (validate && !valid) {
|
|
71
|
+
const message = service.validate.errors.map((x) => `${x.instancePath} ${x.message}`).join(', ');
|
|
72
|
+
throw new Error(`Invalid blocklet service config: ${message}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return data;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const getDefaultServiceConfig = (serviceName) => {
|
|
79
|
+
const { defaultConfig } = getService(serviceName);
|
|
80
|
+
|
|
81
|
+
return defaultConfig;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const findService = (services, name) => {
|
|
85
|
+
const names = [name];
|
|
86
|
+
|
|
87
|
+
// backward compatible
|
|
88
|
+
if (name === NODE_SERVICES.AUTH) {
|
|
89
|
+
names.push(NODE_SERVICES.AUTH_SERVICE);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (services || []).find((x) => names.includes(x.name));
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
module.exports = {
|
|
96
|
+
getServiceMetas,
|
|
97
|
+
getServiceConfig,
|
|
98
|
+
getDefaultServiceConfig,
|
|
99
|
+
findService,
|
|
100
|
+
setService,
|
|
101
|
+
};
|
package/lib/validate.js
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
const Ajv = require('ajv').default;
|
|
2
|
-
const cloneDeep = require('lodash/cloneDeep');
|
|
3
|
-
|
|
4
1
|
const { createBlockletSchema } = require('./schema');
|
|
2
|
+
const { getServiceConfig } = require('./service');
|
|
5
3
|
|
|
6
|
-
const fixAndValidateService = (meta
|
|
7
|
-
const ajv = new Ajv({
|
|
8
|
-
useDefaults: true,
|
|
9
|
-
removeAdditional: 'all',
|
|
10
|
-
});
|
|
11
|
-
|
|
4
|
+
const fixAndValidateService = (meta) => {
|
|
12
5
|
if (!meta.interfaces) {
|
|
13
6
|
return meta;
|
|
14
7
|
}
|
|
@@ -19,26 +12,7 @@ const fixAndValidateService = (meta, serviceMetas) => {
|
|
|
19
12
|
meta.interfaces.forEach((d) => {
|
|
20
13
|
if (d.services && d.services.length) {
|
|
21
14
|
d.services.forEach((s) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
// validate service.config if serviceMetaList is exist
|
|
25
|
-
if (serviceMetas) {
|
|
26
|
-
const serviceMeta = serviceMetas.find((x) => x.name === s.name);
|
|
27
|
-
if (!serviceMeta) {
|
|
28
|
-
throw new Error(`Invalid blocklet service: ${s.name} does not exist`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const validate = ajv.compile(serviceMeta.schema.JSONSchema);
|
|
32
|
-
// this method may have side effect thar will fill default value to config
|
|
33
|
-
const valid = validate(config);
|
|
34
|
-
|
|
35
|
-
if (!valid) {
|
|
36
|
-
const message = validate.errors.map((x) => `${x.dataPath} ${x.message}`).join(', ');
|
|
37
|
-
throw new Error(`Invalid blocklet service config: ${message}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
s.config = config;
|
|
15
|
+
s.config = getServiceConfig(s.name, s.config, { validate: true });
|
|
42
16
|
});
|
|
43
17
|
}
|
|
44
18
|
});
|
package/lib/verify-multi-sig.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
const
|
|
2
|
-
const stableStringify = require('json-stable-stringify');
|
|
3
|
-
const cloneDeep = require('lodash/cloneDeep');
|
|
1
|
+
const get = require('lodash/get');
|
|
4
2
|
const omit = require('lodash/omit');
|
|
3
|
+
const cloneDeep = require('lodash/cloneDeep');
|
|
4
|
+
const stableStringify = require('json-stable-stringify');
|
|
5
5
|
const { toTypeInfo } = require('@arcblock/did');
|
|
6
6
|
const { fromPublicKey } = require('@ocap/wallet');
|
|
7
7
|
const { verify } = require('@arcblock/jwt');
|
|
8
8
|
const { fromBase64 } = require('@ocap/util');
|
|
9
9
|
|
|
10
|
+
const debug = require('debug')('@blocklet/meta:verifyMultiSig');
|
|
11
|
+
|
|
10
12
|
function verifyDelegationToken(signature) {
|
|
11
13
|
if (signature.delegation) {
|
|
12
14
|
const payload = JSON.parse(fromBase64(signature.delegation.split('.')[1]));
|
|
@@ -21,7 +23,7 @@ function verifyDelegationToken(signature) {
|
|
|
21
23
|
return false;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
if (!payload
|
|
26
|
+
if (!get(payload, 'permissions', []).includes('publish_blocklet')) {
|
|
25
27
|
debug('verify payload.permissions failed', payload);
|
|
26
28
|
return false;
|
|
27
29
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.7.
|
|
6
|
+
"version": "1.7.11",
|
|
7
7
|
"description": "Library to parse/validate/fix blocklet meta",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -18,18 +18,18 @@
|
|
|
18
18
|
"author": "wangshijun <wangshijun2020@gmail.com> (http://github.com/wangshijun)",
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@abtnode/constant": "1.7.
|
|
22
|
-
"@abtnode/util": "1.7.
|
|
23
|
-
"@arcblock/did": "^1.16.
|
|
24
|
-
"@arcblock/did-ext": "^1.16.
|
|
25
|
-
"@arcblock/did-util": "^1.16.
|
|
26
|
-
"@arcblock/jwt": "^1.16.
|
|
27
|
-
"@arcblock/nft": "^1.16.
|
|
28
|
-
"@ocap/asset": "^1.16.
|
|
29
|
-
"@ocap/mcrypto": "^1.16.
|
|
30
|
-
"@ocap/util": "^1.16.
|
|
31
|
-
"@ocap/wallet": "^1.16.
|
|
32
|
-
"ajv": "^
|
|
21
|
+
"@abtnode/constant": "1.7.11",
|
|
22
|
+
"@abtnode/util": "1.7.11",
|
|
23
|
+
"@arcblock/did": "^1.16.5",
|
|
24
|
+
"@arcblock/did-ext": "^1.16.5",
|
|
25
|
+
"@arcblock/did-util": "^1.16.5",
|
|
26
|
+
"@arcblock/jwt": "^1.16.5",
|
|
27
|
+
"@arcblock/nft": "^1.16.5",
|
|
28
|
+
"@ocap/asset": "^1.16.5",
|
|
29
|
+
"@ocap/mcrypto": "^1.16.5",
|
|
30
|
+
"@ocap/util": "^1.16.5",
|
|
31
|
+
"@ocap/wallet": "^1.16.5",
|
|
32
|
+
"ajv": "^8.11.0",
|
|
33
33
|
"cjk-length": "^1.0.0",
|
|
34
34
|
"debug": "^4.3.3",
|
|
35
35
|
"fs-extra": "^10.0.1",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"jest": "^27.4.5"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "84e741e6b37e47d52bf834ce3ace8ed601d0896c"
|
|
50
50
|
}
|