@abtnode/core 1.16.27-beta-725ce3a6 → 1.16.27-beta-d1555a79

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.
@@ -201,6 +201,7 @@ const {
201
201
  updateSelectedResources,
202
202
  connectToStore,
203
203
  publishToStore,
204
+ connectByStudio,
204
205
  } = require('../project');
205
206
 
206
207
  const { formatEnvironments, getBlockletMeta, validateOwner, isCLI } = util;
@@ -2326,57 +2327,61 @@ class DiskBlockletManager extends BaseBlockletManager {
2326
2327
  return this.configSynchronizer.syncAppConfig(did, { serverVersion });
2327
2328
  }
2328
2329
 
2329
- createProject({ did, ...params } = {}) {
2330
- return createProject({ did, ...params, manager: this });
2330
+ createProject({ did, ...params } = {}, context) {
2331
+ return createProject({ did, ...params, context, manager: this });
2331
2332
  }
2332
2333
 
2333
- getProjects({ did, componentDid } = {}) {
2334
- return getProjects({ did, componentDid, manager: this });
2334
+ getProjects({ did, componentDid, tenantScope } = {}, context) {
2335
+ return getProjects({ did, componentDid, tenantScope, context, manager: this });
2335
2336
  }
2336
2337
 
2337
- getProject({ did, projectId } = {}) {
2338
- return getProject({ did, projectId, manager: this });
2338
+ getProject({ did, projectId, messageId } = {}, context) {
2339
+ return getProject({ did, projectId, messageId, context, manager: this });
2339
2340
  }
2340
2341
 
2341
- updateProject({ did, projectId, ...params } = {}) {
2342
- return updateProject({ did, projectId, ...params, manager: this });
2342
+ updateProject({ did, projectId, ...params } = {}, context) {
2343
+ return updateProject({ did, projectId, ...params, context, manager: this });
2343
2344
  }
2344
2345
 
2345
- deleteProject({ did, projectId } = {}) {
2346
- return deleteProject({ did, projectId, manager: this });
2346
+ deleteProject({ did, projectId } = {}, context) {
2347
+ return deleteProject({ did, projectId, context, manager: this });
2347
2348
  }
2348
2349
 
2349
2350
  // eslint-disable-next-line no-unused-vars
2350
2351
  createRelease({ did, projectId, ...params } = {}, context) {
2351
- return createRelease({ did, projectId, ...params, manager: this });
2352
+ return createRelease({ did, projectId, ...params, context, manager: this });
2352
2353
  }
2353
2354
 
2354
- getReleases({ did, projectId } = {}) {
2355
- return getReleases({ did, projectId, manager: this });
2355
+ getReleases({ did, projectId } = {}, context) {
2356
+ return getReleases({ did, projectId, context, manager: this });
2356
2357
  }
2357
2358
 
2358
- getRelease({ did, projectId, releaseId } = {}) {
2359
- return getRelease({ did, projectId, releaseId, manager: this });
2359
+ getRelease({ did, projectId, releaseId } = {}, context) {
2360
+ return getRelease({ did, projectId, releaseId, context, manager: this });
2360
2361
  }
2361
2362
 
2362
- deleteRelease({ did, projectId, releaseId } = {}) {
2363
- return deleteRelease({ did, projectId, releaseId, manager: this });
2363
+ deleteRelease({ did, projectId, releaseId } = {}, context) {
2364
+ return deleteRelease({ did, projectId, releaseId, context, manager: this });
2364
2365
  }
2365
2366
 
2366
2367
  connectToStore(params) {
2367
2368
  return connectToStore({ ...params, manager: this });
2368
2369
  }
2369
2370
 
2370
- publishToStore(params) {
2371
- return publishToStore({ ...params, manager: this });
2371
+ connectByStudio(params, context) {
2372
+ return connectByStudio({ ...params, context, manager: this });
2372
2373
  }
2373
2374
 
2374
- getSelectedResources({ did, projectId, releaseId, componentDid } = {}) {
2375
- return getSelectedResources({ did, projectId, releaseId, componentDid, manager: this });
2375
+ publishToStore(params, context) {
2376
+ return publishToStore({ ...params, context, manager: this });
2376
2377
  }
2377
2378
 
2378
- updateSelectedResources({ did, projectId, releaseId, componentDid, resources } = {}) {
2379
- return updateSelectedResources({ did, projectId, releaseId, componentDid, resources, manager: this });
2379
+ getSelectedResources({ did, projectId, releaseId, componentDid } = {}, context) {
2380
+ return getSelectedResources({ did, projectId, releaseId, componentDid, context, manager: this });
2381
+ }
2382
+
2383
+ updateSelectedResources({ did, projectId, releaseId, componentDid, resources } = {}, context) {
2384
+ return updateSelectedResources({ did, projectId, releaseId, componentDid, resources, context, manager: this });
2380
2385
  }
2381
2386
 
2382
2387
  // ============================================================================================
@@ -0,0 +1,86 @@
1
+ const validUrl = require('valid-url');
2
+
3
+ const { createConnect } = require('@blocklet/store');
4
+
5
+ function sanitizeBlockletTitle(blockletTitle) {
6
+ let sanitizedTitle = blockletTitle.replace(/[^a-zA-Z0-9-_]/g, '');
7
+ sanitizedTitle = sanitizedTitle.replace(/^[^a-zA-Z0-9]+/, '');
8
+ if (sanitizedTitle.length > 128) {
9
+ sanitizedTitle = sanitizedTitle.slice(0, 128);
10
+ }
11
+ if (sanitizedTitle.length < 4) {
12
+ sanitizedTitle = sanitizedTitle.padEnd(4, '0');
13
+ }
14
+ return sanitizedTitle;
15
+ }
16
+
17
+ const connectByStudio = ({
18
+ did,
19
+ componentDid,
20
+ blockletTitle,
21
+ type,
22
+ tenantScope,
23
+ storeName,
24
+ storeId,
25
+ storeUrl,
26
+ messageId,
27
+ manager,
28
+ context,
29
+ }) => {
30
+ if (!did) {
31
+ throw new Error('Invalid did');
32
+ }
33
+ // 校验是否为合法的url地址(必须是 http 或 https 协议),例如:https://store.blocklet.dev/
34
+ if (!validUrl.isWebUri(storeUrl)) {
35
+ throw new Error('Invalid store url:', storeUrl);
36
+ }
37
+
38
+ // eslint-disable-next-line no-async-promise-executor
39
+ return new Promise(async (resolve, reject) => {
40
+ try {
41
+ const fetchData = await createConnect({
42
+ connectUrl: storeUrl,
43
+ connectAction: 'connect-studio',
44
+ enableEncrypt: true,
45
+ // monikers 必须满足一个规则, 而 blockletTitle 是更宽松的规则
46
+ monikers: sanitizeBlockletTitle(blockletTitle) || 'blocklet',
47
+ openPage: (pageUrl) => {
48
+ resolve(pageUrl);
49
+ },
50
+ });
51
+
52
+ if (!fetchData) {
53
+ throw new Error('Failed to connect to store');
54
+ }
55
+
56
+ const { secretKey, developerDid, name, email } = fetchData.developer;
57
+ const { address: blockletDid } = fetchData.blocklet;
58
+
59
+ const { projectState } = await manager._getProjectState(did);
60
+
61
+ const nextStore = {
62
+ storeId,
63
+ storeName,
64
+ storeUrl,
65
+ accessToken: secretKey,
66
+ developerDid,
67
+ developerName: name,
68
+ developerEmail: email,
69
+ };
70
+ await projectState.createProject({
71
+ blockletTitle,
72
+ type,
73
+ tenantScope,
74
+ blockletDid,
75
+ componentDid,
76
+ messageId,
77
+ createdBy: context.user.did,
78
+ connectedStores: [nextStore],
79
+ });
80
+ } catch (error) {
81
+ reject(error);
82
+ }
83
+ });
84
+ };
85
+
86
+ module.exports = connectByStudio;
@@ -1,7 +1,6 @@
1
1
  const validUrl = require('valid-url');
2
2
 
3
3
  const { createConnect } = require('@blocklet/store');
4
- const { STUDIO_CONNECTED_STORE } = require('@abtnode/constant');
5
4
 
6
5
  const connectToStore = ({ did, projectId, storeName, storeId, storeUrl, manager }) => {
7
6
  if (!did) {
@@ -63,16 +62,6 @@ const connectToStore = ({ did, projectId, storeName, storeId, storeUrl, manager
63
62
  }
64
63
 
65
64
  await projectState.updateProject(projectId, project);
66
-
67
- await manager.teamManager.createNotification({
68
- teamDid: did,
69
- title: `Connected ${storeName} successfully`,
70
- description: `You can publish your blocklet to ${storeName} now`,
71
- entityType: 'blocklet',
72
- entityId: did,
73
- meta: { did, eventType: STUDIO_CONNECTED_STORE },
74
- severity: 'success',
75
- });
76
65
  } catch (error) {
77
66
  reject(error);
78
67
  }
@@ -0,0 +1,8 @@
1
+ const { BLOCKLET_TENANT_MODES } = require('@blocklet/constant');
2
+
3
+ const getIsMultipleTenant = async (manager, did) => {
4
+ const env = await manager.getBlockletEnvironments(did);
5
+ return env?.appSystemEnvironments?.BLOCKLET_APP_TENANT_MODE === BLOCKLET_TENANT_MODES.MULTIPLE;
6
+ };
7
+
8
+ module.exports = getIsMultipleTenant;
@@ -12,27 +12,62 @@ const urlPathFriendly = require('@blocklet/meta/lib/url-path-friendly').default;
12
12
  const logger = require('@abtnode/logger')('create-resource-blocklet');
13
13
 
14
14
  const { createReleaseSchema } = require('../../validators/project');
15
+ const getIsMultipleTenant = require('./get-is-multiple-tenant');
15
16
 
16
17
  const { getLogoFile, exportBlockletResources, getResourceList, checkResourceExists } = require('./util');
17
18
  const createPackRelease = require('./create-pack-release');
18
19
  const connectToStore = require('./connect-to-store');
19
20
  const publishToStore = require('./publish-to-store');
21
+ const connectByStudio = require('./connect-by-studio');
20
22
 
21
23
  const COMPONENT_CONFIG_MAP_DIR = '.component_config';
22
24
 
23
25
  // project
24
26
 
25
- const createProject = async ({ did, type, blockletTitle, blockletDid, componentDid, manager }) => {
27
+ const ensureProjectCreateBy = (fn) => {
28
+ return async ({ did, projectId, messageId, context, manager, ...rest }) => {
29
+ const isMultipleTenant = await getIsMultipleTenant(manager, did);
30
+ if (isMultipleTenant) {
31
+ const { projectState } = await manager._getProjectState(did);
32
+ const createdBy = context?.user?.did;
33
+ if (!createdBy) {
34
+ throw new Error('No permission to perform this project');
35
+ }
36
+ const project = await projectState.findOne(messageId ? { messageId, createdBy } : { id: projectId, createdBy });
37
+ if (!project) {
38
+ throw new Error('No permission to perform this project');
39
+ }
40
+ }
41
+ return fn({ did, projectId, messageId, context, manager, ...rest });
42
+ };
43
+ };
44
+
45
+ const createProject = async ({
46
+ did,
47
+ type,
48
+ blockletTitle,
49
+ blockletDid,
50
+ componentDid,
51
+ tenantScope,
52
+ manager,
53
+ context,
54
+ }) => {
26
55
  await titleSchema.validateAsync(blockletTitle);
27
56
  validateNewDid(blockletDid);
28
57
  if (!PROJECT.TYPES[type]) {
29
58
  throw new Error(`type is invalid: ${type}`);
30
59
  }
31
-
32
60
  const blocklet = await manager.getBlocklet(did, { useCache: true });
33
61
  const { projectState } = await manager._getProjectState(did);
34
62
 
35
- const project = await projectState.createProject({ blockletTitle, blockletDid, type, componentDid });
63
+ const project = await projectState.createProject({
64
+ blockletTitle,
65
+ blockletDid,
66
+ type,
67
+ componentDid,
68
+ tenantScope,
69
+ createdBy: context?.user?.did,
70
+ });
36
71
 
37
72
  // create project dir
38
73
  const projectDir = path.join(blocklet.env.dataDir, PROJECT.DIR, `${project.id}`);
@@ -46,15 +81,24 @@ const createProject = async ({ did, type, blockletTitle, blockletDid, componentD
46
81
  return project;
47
82
  };
48
83
 
49
- const getProjects = async ({ did, manager, componentDid, showAccessToken }) => {
84
+ const getProjects = async ({ did, manager, componentDid, showAccessToken, tenantScope, context }) => {
85
+ const isMultipleTenant = await getIsMultipleTenant(manager, did);
86
+ if (isMultipleTenant && componentDid && !tenantScope) {
87
+ throw new Error('Multiple tenant mode in component, tenantScope is required');
88
+ }
50
89
  const { projectState } = await manager._getProjectState(did);
51
- const projects = await projectState.getProjects({ componentDid, showAccessToken });
90
+ const query = { componentDid, showAccessToken };
91
+ if (isMultipleTenant) {
92
+ query.tenantScope = tenantScope;
93
+ query.createdBy = context.user.did;
94
+ }
95
+ const projects = await projectState.getProjects(query);
52
96
  return { projects };
53
97
  };
54
98
 
55
- const getProject = async ({ did, projectId, manager, showAccessToken }) => {
99
+ const getProject = async ({ did, projectId, messageId, showAccessToken, manager }) => {
56
100
  const { projectState } = await manager._getProjectState(did);
57
- const project = await projectState.findOne({ id: projectId });
101
+ const project = await projectState.findOne(messageId ? { messageId } : { id: projectId });
58
102
  if (!showAccessToken) {
59
103
  project.connectedStores?.forEach((store) => {
60
104
  store.accessToken = store.accessToken ? '__encrypted__' : '';
@@ -63,12 +107,13 @@ const getProject = async ({ did, projectId, manager, showAccessToken }) => {
63
107
  return project;
64
108
  };
65
109
 
66
- const updateProject = async ({ did, projectId, manager, ...params }) => {
110
+ const updateProject = async ({ did, projectId, manager, context, ...params }) => {
67
111
  const { projectState } = await manager._getProjectState(did);
68
112
  const project = await projectState.updateProject(projectId, params);
69
113
  return project;
70
114
  };
71
115
 
116
+ // 这个接口不会被前端直接调用
72
117
  const deleteProject = async ({ did, projectId, manager }) => {
73
118
  if (!projectId) {
74
119
  throw new Error('projectId is required');
@@ -104,7 +149,6 @@ const deleteRelease = async ({ did, projectId, releaseId, manager }) => {
104
149
  const blocklet = await manager.getBlocklet(did);
105
150
  const { releaseState } = await manager._getProjectState(did);
106
151
  const releaseDir = path.join(blocklet.env.dataDir, PROJECT.DIR, `${projectId}`, PROJECT.RELEASE_DIR, `${releaseId}`);
107
-
108
152
  await releaseState.remove({ projectId, id: releaseId });
109
153
  await fs.remove(releaseDir);
110
154
  };
@@ -409,15 +453,16 @@ const updateSelectedResources = async ({ did, projectId, releaseId, componentDid
409
453
  module.exports = {
410
454
  createProject,
411
455
  getProjects,
412
- getProject,
413
- updateProject,
456
+ getProject: ensureProjectCreateBy(getProject),
457
+ updateProject: ensureProjectCreateBy(updateProject),
458
+ createRelease: ensureProjectCreateBy(createRelease),
459
+ getReleases: ensureProjectCreateBy(getReleases),
460
+ getRelease: ensureProjectCreateBy(getRelease),
461
+ deleteRelease: ensureProjectCreateBy(deleteRelease),
462
+ getSelectedResources: ensureProjectCreateBy(getSelectedResources),
463
+ updateSelectedResources: ensureProjectCreateBy(updateSelectedResources),
414
464
  deleteProject,
415
- createRelease,
416
- getReleases,
417
- getRelease,
418
- deleteRelease,
419
- getSelectedResources,
420
- updateSelectedResources,
421
465
  connectToStore,
466
+ connectByStudio,
422
467
  publishToStore,
423
468
  };
package/lib/index.js CHANGED
@@ -345,6 +345,7 @@ function ABTNode(options) {
345
345
  updateProject: blockletManager.updateProject.bind(blockletManager),
346
346
  createRelease: blockletManager.createRelease.bind(blockletManager),
347
347
  connectToStore: blockletManager.connectToStore.bind(blockletManager),
348
+ connectByStudio: blockletManager.connectByStudio.bind(blockletManager),
348
349
  publishToStore: blockletManager.publishToStore.bind(blockletManager),
349
350
  getReleases: blockletManager.getReleases.bind(blockletManager),
350
351
  getRelease: blockletManager.getRelease.bind(blockletManager),
@@ -8,20 +8,46 @@ const isUndefinedOrNull = (x) => x === undefined || x === null;
8
8
  * @extends BaseState<import('@abtnode/models').ProjectState>
9
9
  */
10
10
  class Project extends BaseState {
11
- createProject({ type, blockletDid, blockletTitle, componentDid }) {
12
- const doc = { id: blockletDid, type, blockletDid, blockletTitle };
11
+ createProject({
12
+ type,
13
+ blockletDid,
14
+ blockletTitle,
15
+ componentDid,
16
+ tenantScope,
17
+ connectedStores,
18
+ createdBy,
19
+ messageId,
20
+ }) {
21
+ const doc = { id: blockletDid, type, blockletDid, blockletTitle, createdBy };
13
22
  if (componentDid) {
14
23
  doc.componentDid = componentDid;
15
24
  }
16
-
25
+ if (tenantScope) {
26
+ doc.tenantScope = tenantScope;
27
+ }
28
+ if (connectedStores) {
29
+ doc.connectedStores = connectedStores;
30
+ }
31
+ if (messageId) {
32
+ if (messageId.length < 20) {
33
+ throw new Error('Invalid messageId');
34
+ }
35
+ doc.messageId = messageId;
36
+ }
17
37
  return this.insert(doc);
18
38
  }
19
39
 
20
- async getProjects({ componentDid, showAccessToken }) {
40
+ async getProjects({ componentDid, tenantScope, showAccessToken, createdBy }) {
21
41
  const query = {};
22
42
  if (componentDid) {
23
43
  query.componentDid = componentDid;
24
44
  }
45
+ if (tenantScope) {
46
+ query.tenantScope = tenantScope;
47
+ }
48
+ if (createdBy) {
49
+ query.createdBy = createdBy;
50
+ }
25
51
  const projects = await this.find(
26
52
  query,
27
53
  {},
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.27-beta-725ce3a6",
6
+ "version": "1.16.27-beta-d1555a79",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,40 +19,40 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "Apache-2.0",
21
21
  "dependencies": {
22
- "@abtnode/analytics": "1.16.27-beta-725ce3a6",
23
- "@abtnode/auth": "1.16.27-beta-725ce3a6",
24
- "@abtnode/certificate-manager": "1.16.27-beta-725ce3a6",
25
- "@abtnode/constant": "1.16.27-beta-725ce3a6",
26
- "@abtnode/cron": "1.16.27-beta-725ce3a6",
27
- "@abtnode/logger": "1.16.27-beta-725ce3a6",
28
- "@abtnode/models": "1.16.27-beta-725ce3a6",
29
- "@abtnode/queue": "1.16.27-beta-725ce3a6",
30
- "@abtnode/rbac": "1.16.27-beta-725ce3a6",
31
- "@abtnode/router-provider": "1.16.27-beta-725ce3a6",
32
- "@abtnode/static-server": "1.16.27-beta-725ce3a6",
33
- "@abtnode/timemachine": "1.16.27-beta-725ce3a6",
34
- "@abtnode/util": "1.16.27-beta-725ce3a6",
35
- "@arcblock/did": "1.18.120",
36
- "@arcblock/did-auth": "1.18.120",
37
- "@arcblock/did-ext": "^1.18.120",
22
+ "@abtnode/analytics": "1.16.27-beta-d1555a79",
23
+ "@abtnode/auth": "1.16.27-beta-d1555a79",
24
+ "@abtnode/certificate-manager": "1.16.27-beta-d1555a79",
25
+ "@abtnode/constant": "1.16.27-beta-d1555a79",
26
+ "@abtnode/cron": "1.16.27-beta-d1555a79",
27
+ "@abtnode/logger": "1.16.27-beta-d1555a79",
28
+ "@abtnode/models": "1.16.27-beta-d1555a79",
29
+ "@abtnode/queue": "1.16.27-beta-d1555a79",
30
+ "@abtnode/rbac": "1.16.27-beta-d1555a79",
31
+ "@abtnode/router-provider": "1.16.27-beta-d1555a79",
32
+ "@abtnode/static-server": "1.16.27-beta-d1555a79",
33
+ "@abtnode/timemachine": "1.16.27-beta-d1555a79",
34
+ "@abtnode/util": "1.16.27-beta-d1555a79",
35
+ "@arcblock/did": "1.18.121",
36
+ "@arcblock/did-auth": "1.18.121",
37
+ "@arcblock/did-ext": "^1.18.121",
38
38
  "@arcblock/did-motif": "^1.1.13",
39
- "@arcblock/did-util": "1.18.120",
40
- "@arcblock/event-hub": "1.18.120",
41
- "@arcblock/jwt": "^1.18.120",
39
+ "@arcblock/did-util": "1.18.121",
40
+ "@arcblock/event-hub": "1.18.121",
41
+ "@arcblock/jwt": "^1.18.121",
42
42
  "@arcblock/pm2-events": "^0.0.5",
43
- "@arcblock/validator": "^1.18.120",
44
- "@arcblock/vc": "1.18.120",
45
- "@blocklet/constant": "1.16.27-beta-725ce3a6",
46
- "@blocklet/env": "1.16.27-beta-725ce3a6",
47
- "@blocklet/meta": "1.16.27-beta-725ce3a6",
48
- "@blocklet/resolver": "1.16.27-beta-725ce3a6",
49
- "@blocklet/sdk": "1.16.27-beta-725ce3a6",
50
- "@blocklet/store": "1.16.27-beta-725ce3a6",
51
- "@did-space/client": "^0.4.5",
43
+ "@arcblock/validator": "^1.18.121",
44
+ "@arcblock/vc": "1.18.121",
45
+ "@blocklet/constant": "1.16.27-beta-d1555a79",
46
+ "@blocklet/env": "1.16.27-beta-d1555a79",
47
+ "@blocklet/meta": "1.16.27-beta-d1555a79",
48
+ "@blocklet/resolver": "1.16.27-beta-d1555a79",
49
+ "@blocklet/sdk": "1.16.27-beta-d1555a79",
50
+ "@blocklet/store": "1.16.27-beta-d1555a79",
51
+ "@did-space/client": "^0.4.9",
52
52
  "@fidm/x509": "^1.2.1",
53
- "@ocap/mcrypto": "1.18.120",
54
- "@ocap/util": "1.18.120",
55
- "@ocap/wallet": "1.18.120",
53
+ "@ocap/mcrypto": "1.18.121",
54
+ "@ocap/util": "1.18.121",
55
+ "@ocap/wallet": "1.18.121",
56
56
  "@slack/webhook": "^5.0.4",
57
57
  "archiver": "^7.0.1",
58
58
  "axios": "^0.27.2",
@@ -103,5 +103,5 @@
103
103
  "jest": "^29.7.0",
104
104
  "unzipper": "^0.10.11"
105
105
  },
106
- "gitHead": "6110607f520136996b78b8d9c05a0744016dfa21"
106
+ "gitHead": "10055507ae6190a13ee83e2f6446fd64523dd298"
107
107
  }