@abtnode/core 1.17.8-beta-20260109-075740-5f484e08 → 1.17.8-beta-20260113-015027-32a1cec4
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/api/team/access-key-manager.js +104 -0
- package/lib/api/team/invitation-manager.js +461 -0
- package/lib/api/team/notification-manager.js +189 -0
- package/lib/api/team/oauth-manager.js +60 -0
- package/lib/api/team/org-crud-manager.js +202 -0
- package/lib/api/team/org-manager.js +56 -0
- package/lib/api/team/org-member-manager.js +403 -0
- package/lib/api/team/org-query-manager.js +126 -0
- package/lib/api/team/org-resource-manager.js +186 -0
- package/lib/api/team/passport-manager.js +670 -0
- package/lib/api/team/rbac-manager.js +335 -0
- package/lib/api/team/session-manager.js +540 -0
- package/lib/api/team/store-manager.js +198 -0
- package/lib/api/team/tag-manager.js +230 -0
- package/lib/api/team/user-auth-manager.js +132 -0
- package/lib/api/team/user-manager.js +78 -0
- package/lib/api/team/user-query-manager.js +299 -0
- package/lib/api/team/user-social-manager.js +354 -0
- package/lib/api/team/user-update-manager.js +224 -0
- package/lib/api/team/verify-code-manager.js +161 -0
- package/lib/api/team.js +439 -3287
- package/lib/blocklet/manager/disk/auth-manager.js +68 -0
- package/lib/blocklet/manager/disk/backup-manager.js +288 -0
- package/lib/blocklet/manager/disk/cleanup-manager.js +157 -0
- package/lib/blocklet/manager/disk/component-manager.js +83 -0
- package/lib/blocklet/manager/disk/config-manager.js +191 -0
- package/lib/blocklet/manager/disk/controller-manager.js +64 -0
- package/lib/blocklet/manager/disk/delete-reset-manager.js +328 -0
- package/lib/blocklet/manager/disk/download-manager.js +96 -0
- package/lib/blocklet/manager/disk/env-config-manager.js +311 -0
- package/lib/blocklet/manager/disk/federated-manager.js +651 -0
- package/lib/blocklet/manager/disk/hook-manager.js +124 -0
- package/lib/blocklet/manager/disk/install-component-manager.js +95 -0
- package/lib/blocklet/manager/disk/install-core-manager.js +448 -0
- package/lib/blocklet/manager/disk/install-download-manager.js +313 -0
- package/lib/blocklet/manager/disk/install-manager.js +36 -0
- package/lib/blocklet/manager/disk/install-upgrade-manager.js +340 -0
- package/lib/blocklet/manager/disk/job-manager.js +467 -0
- package/lib/blocklet/manager/disk/lifecycle-manager.js +26 -0
- package/lib/blocklet/manager/disk/notification-manager.js +343 -0
- package/lib/blocklet/manager/disk/query-manager.js +562 -0
- package/lib/blocklet/manager/disk/settings-manager.js +507 -0
- package/lib/blocklet/manager/disk/start-manager.js +611 -0
- package/lib/blocklet/manager/disk/stop-restart-manager.js +292 -0
- package/lib/blocklet/manager/disk/update-manager.js +153 -0
- package/lib/blocklet/manager/disk.js +669 -5796
- package/lib/blocklet/manager/helper/blue-green-start-blocklet.js +5 -0
- package/lib/blocklet/manager/lock.js +18 -0
- package/lib/event/index.js +28 -24
- package/lib/util/blocklet/app-utils.js +192 -0
- package/lib/util/blocklet/blocklet-loader.js +258 -0
- package/lib/util/blocklet/config-manager.js +232 -0
- package/lib/util/blocklet/did-document.js +240 -0
- package/lib/util/blocklet/environment.js +555 -0
- package/lib/util/blocklet/health-check.js +449 -0
- package/lib/util/blocklet/install-utils.js +365 -0
- package/lib/util/blocklet/logo.js +57 -0
- package/lib/util/blocklet/meta-utils.js +269 -0
- package/lib/util/blocklet/port-manager.js +141 -0
- package/lib/util/blocklet/process-manager.js +504 -0
- package/lib/util/blocklet/runtime-info.js +105 -0
- package/lib/util/blocklet/validation.js +418 -0
- package/lib/util/blocklet.js +98 -3066
- package/lib/util/wallet-app-notification.js +40 -0
- package/package.json +22 -22
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
const { withoutTrailingSlash } = require('ufo');
|
|
2
|
+
const logger = require('@abtnode/logger')('@abtnode/core:api:team:store');
|
|
3
|
+
const ensureServerEndpoint = require('@abtnode/util/lib/ensure-server-endpoint');
|
|
4
|
+
|
|
5
|
+
const StoreUtil = require('../../util/store');
|
|
6
|
+
|
|
7
|
+
const sanitizeUrl = (url) => {
|
|
8
|
+
if (!url) {
|
|
9
|
+
throw new Error('Registry URL should not be empty');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return url.trim();
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Add store
|
|
17
|
+
* @param {Object} api - TeamAPI instance
|
|
18
|
+
* @param {Object} params
|
|
19
|
+
* @param {string} params.teamDid - Team DID
|
|
20
|
+
* @param {string} params.url - Store URL
|
|
21
|
+
* @param {string} params.scope - Scope
|
|
22
|
+
* @param {Object} context
|
|
23
|
+
* @returns {Promise<Object>}
|
|
24
|
+
*/
|
|
25
|
+
// eslint-disable-next-line no-unused-vars
|
|
26
|
+
async function addStore(api, { teamDid, url, scope = '' }, context) {
|
|
27
|
+
logger.info('add store', { teamDid, url, scope });
|
|
28
|
+
|
|
29
|
+
const sanitized = withoutTrailingSlash(await StoreUtil.getStoreUrl(url));
|
|
30
|
+
const storeList = await api.teamManager.getStoreList(teamDid);
|
|
31
|
+
const exists = storeList.some((x) => {
|
|
32
|
+
if (x.url === sanitized) {
|
|
33
|
+
if (!x.scope) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return x.scope === scope;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return false;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (exists) {
|
|
44
|
+
throw new Error(`Blocklet Store already exist: ${sanitized}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const store = await StoreUtil.getStoreMeta(sanitized);
|
|
48
|
+
|
|
49
|
+
storeList.push({ ...store, scope, url: sanitized, protected: false });
|
|
50
|
+
|
|
51
|
+
return api.teamManager.updateStoreList(teamDid, storeList);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Add endpoint
|
|
56
|
+
* @param {Object} api - TeamAPI instance
|
|
57
|
+
* @param {Object} params
|
|
58
|
+
* @param {string} params.teamDid - Team DID
|
|
59
|
+
* @param {string} params.url - Endpoint URL
|
|
60
|
+
* @param {Object} context
|
|
61
|
+
* @returns {Promise<Object>}
|
|
62
|
+
*/
|
|
63
|
+
async function addEndpoint(api, { teamDid, url }, context) {
|
|
64
|
+
const userDid = context?.user?.did;
|
|
65
|
+
const { endpoint, appPid, appName, appDescription } = await ensureServerEndpoint(url);
|
|
66
|
+
const endpointList = await api.teamManager.getEndpointList(teamDid);
|
|
67
|
+
|
|
68
|
+
if (!appPid) {
|
|
69
|
+
throw new Error('current url not blocklet url');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!endpoint) {
|
|
73
|
+
throw new Error('current url not blocklet url');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const index = endpointList.findIndex((x) => x.id === appPid);
|
|
77
|
+
if (index !== -1) {
|
|
78
|
+
endpointList[index].url = url;
|
|
79
|
+
} else {
|
|
80
|
+
endpointList.push({ id: appPid, appName, appDescription, scope: userDid, url, endpoint, protected: false });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return api.teamManager.updateEndpointList(teamDid, endpointList);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Delete endpoint
|
|
88
|
+
* @param {Object} api - TeamAPI instance
|
|
89
|
+
* @param {Object} params
|
|
90
|
+
* @param {string} params.teamDid - Team DID
|
|
91
|
+
* @param {string} params.did - Endpoint DID
|
|
92
|
+
* @param {string} params.projectId - Project ID
|
|
93
|
+
* @param {Object} context
|
|
94
|
+
* @returns {Promise<Object>}
|
|
95
|
+
*/
|
|
96
|
+
async function deleteEndpoint(api, { teamDid, did, projectId }, context) {
|
|
97
|
+
const endpointList = await api.teamManager.getEndpointList(teamDid);
|
|
98
|
+
|
|
99
|
+
const index = endpointList.findIndex((x) => x.id === did);
|
|
100
|
+
if (index === -1) {
|
|
101
|
+
throw new Error(`Blocklet Endpoint does not exist: ${did}`);
|
|
102
|
+
}
|
|
103
|
+
endpointList.splice(index, 1);
|
|
104
|
+
|
|
105
|
+
if (projectId) {
|
|
106
|
+
const { projectState } = await api.teamManager.getProjectState(teamDid);
|
|
107
|
+
await projectState.deleteConnectedEndpoint({ projectId, endpointId: did, createdBy: context?.user?.did });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return api.teamManager.updateEndpointList(teamDid, endpointList);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Check if store exists
|
|
115
|
+
* @param {Object} api - TeamAPI instance
|
|
116
|
+
* @param {Object} params
|
|
117
|
+
* @param {string} params.teamDid - Team DID
|
|
118
|
+
* @param {string} params.url - Store URL
|
|
119
|
+
* @param {string} params.scope - Scope
|
|
120
|
+
* @param {Object} context
|
|
121
|
+
* @returns {Promise<boolean>}
|
|
122
|
+
*/
|
|
123
|
+
async function existsStore(api, { teamDid, url, scope }, context) {
|
|
124
|
+
const sanitized = withoutTrailingSlash(await StoreUtil.getStoreUrl(url));
|
|
125
|
+
const storeList = await api.teamManager.getStoreList(teamDid);
|
|
126
|
+
const did = context?.user?.did;
|
|
127
|
+
const exists = storeList.some((x) => {
|
|
128
|
+
if (x.url !== sanitized) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
if (x.scope && x.scope === did) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
if (!x.scope || x.scope === 'studio') {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
return x.scope === scope;
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
return exists;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Delete store
|
|
145
|
+
* @param {Object} api - TeamAPI instance
|
|
146
|
+
* @param {Object} params
|
|
147
|
+
* @param {string} params.teamDid - Team DID
|
|
148
|
+
* @param {string} params.url - Store URL
|
|
149
|
+
* @param {string} params.projectId - Project ID
|
|
150
|
+
* @param {string} params.scope - Scope
|
|
151
|
+
* @param {Object} context
|
|
152
|
+
* @returns {Promise<Object>}
|
|
153
|
+
*/
|
|
154
|
+
// eslint-disable-next-line no-unused-vars
|
|
155
|
+
async function deleteStore(api, { teamDid, url, projectId, scope }, context) {
|
|
156
|
+
logger.info('delete registry', { url });
|
|
157
|
+
const sanitized = sanitizeUrl(url);
|
|
158
|
+
|
|
159
|
+
const storeList = await api.teamManager.getStoreList(teamDid);
|
|
160
|
+
let storeIndex;
|
|
161
|
+
if (scope) {
|
|
162
|
+
storeIndex = storeList.findIndex((x) => {
|
|
163
|
+
if (x.protected) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
return x.url === sanitized && x.scope === scope;
|
|
167
|
+
});
|
|
168
|
+
if (storeIndex === -1) {
|
|
169
|
+
throw new Error(`No permission to delete the Store registry: ${sanitized}`);
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
storeIndex = storeList.findIndex((x) => x.url === sanitized && !x.scope);
|
|
173
|
+
if (storeIndex === -1) {
|
|
174
|
+
throw new Error(`Store registry does not exist: ${sanitized}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (projectId && scope) {
|
|
179
|
+
const { projectState } = await api.teamManager.getProjectState(teamDid);
|
|
180
|
+
const store = await StoreUtil.getStoreMeta(sanitized);
|
|
181
|
+
await projectState.deleteConnectedStore({
|
|
182
|
+
projectId,
|
|
183
|
+
storeId: store.id,
|
|
184
|
+
createdBy: scope === 'studio' ? null : context?.user?.did,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
storeList.splice(storeIndex, 1);
|
|
188
|
+
return api.teamManager.updateStoreList(teamDid, storeList);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
module.exports = {
|
|
192
|
+
sanitizeUrl,
|
|
193
|
+
addStore,
|
|
194
|
+
addEndpoint,
|
|
195
|
+
deleteEndpoint,
|
|
196
|
+
existsStore,
|
|
197
|
+
deleteStore,
|
|
198
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
const pick = require('lodash/pick');
|
|
2
|
+
const logger = require('@abtnode/logger')('@abtnode/core:api:team:tag');
|
|
3
|
+
const { Joi } = require('@arcblock/validator');
|
|
4
|
+
|
|
5
|
+
const taggingSchema = Joi.object({
|
|
6
|
+
tagId: Joi.number().required(),
|
|
7
|
+
taggableIds: Joi.array().items(Joi.string()).min(1).required().messages({
|
|
8
|
+
'any.required': 'Must specify tagging.taggableIds to create',
|
|
9
|
+
'array.base': 'taggableIds must be an array',
|
|
10
|
+
'array.min': 'taggableIds must contain at least one element',
|
|
11
|
+
}),
|
|
12
|
+
taggableType: Joi.string().required().messages({
|
|
13
|
+
'any.required': 'Must specify tagging.taggableType to create',
|
|
14
|
+
'string.base': 'taggableType must be a string',
|
|
15
|
+
}),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Create tagging
|
|
20
|
+
* @param {Object} api - TeamAPI instance
|
|
21
|
+
* @param {Object} params
|
|
22
|
+
* @param {string} params.teamDid - Team DID
|
|
23
|
+
* @param {Object} params.tagging - Tagging data
|
|
24
|
+
* @returns {Promise<Array>}
|
|
25
|
+
*/
|
|
26
|
+
async function createTagging(api, { teamDid, tagging }) {
|
|
27
|
+
const state = await api.getTaggingState(teamDid);
|
|
28
|
+
|
|
29
|
+
const { error, value } = taggingSchema.validate(tagging, { stripUnknown: true });
|
|
30
|
+
if (error) {
|
|
31
|
+
throw new Error(error.details.map((d) => d.message).join('; '));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const fns = value.taggableIds.map(async (id) => {
|
|
35
|
+
const found = await state.findOne({ tagId: tagging.tagId, taggableId: id });
|
|
36
|
+
if (found) return found;
|
|
37
|
+
|
|
38
|
+
return state.insert({ tagId: tagging.tagId, taggableId: id, taggableType: tagging.taggableType });
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const docs = await Promise.all(fns);
|
|
42
|
+
logger.info('tagging created successfully', { teamDid, tagging });
|
|
43
|
+
return docs;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Delete tagging
|
|
48
|
+
* @param {Object} api - TeamAPI instance
|
|
49
|
+
* @param {Object} params
|
|
50
|
+
* @param {string} params.teamDid - Team DID
|
|
51
|
+
* @param {Object} params.tagging - Tagging data
|
|
52
|
+
* @returns {Promise<Array>}
|
|
53
|
+
*/
|
|
54
|
+
async function deleteTagging(api, { teamDid, tagging }) {
|
|
55
|
+
const { error, value } = taggingSchema.validate(tagging, { stripUnknown: true });
|
|
56
|
+
if (error) {
|
|
57
|
+
throw new Error(error.details.map((d) => d.message).join('; '));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const state = await api.getTaggingState(teamDid);
|
|
61
|
+
|
|
62
|
+
const { tagId, taggableIds } = value;
|
|
63
|
+
const fns = taggableIds.map((id) => {
|
|
64
|
+
return state.remove({ tagId, taggableId: id });
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const docs = await Promise.all(fns);
|
|
68
|
+
logger.info('tagging deleted successfully', { teamDid, tagging });
|
|
69
|
+
|
|
70
|
+
return docs;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get tag
|
|
75
|
+
* @param {Object} api - TeamAPI instance
|
|
76
|
+
* @param {Object} params
|
|
77
|
+
* @param {string} params.teamDid - Team DID
|
|
78
|
+
* @param {Object} params.tag - Tag data
|
|
79
|
+
* @returns {Promise<Object>}
|
|
80
|
+
*/
|
|
81
|
+
async function getTag(api, { teamDid, tag }) {
|
|
82
|
+
const state = await api.getTagState(teamDid);
|
|
83
|
+
return state.findOne({ id: tag.id });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Create tag
|
|
88
|
+
* @param {Object} api - TeamAPI instance
|
|
89
|
+
* @param {Object} params
|
|
90
|
+
* @param {string} params.teamDid - Team DID
|
|
91
|
+
* @param {Object} params.tag - Tag data
|
|
92
|
+
* @param {Object} context
|
|
93
|
+
* @returns {Promise<Object>}
|
|
94
|
+
*/
|
|
95
|
+
async function createTag(api, { teamDid, tag }, context = {}) {
|
|
96
|
+
if (!tag.title) {
|
|
97
|
+
throw new Error('Must specify tag.title to create');
|
|
98
|
+
}
|
|
99
|
+
if (!tag.color || !tag.color.match(/^#[0-9a-f]{6}$/i)) {
|
|
100
|
+
throw new Error('Must specify hex encoded tag.color to create');
|
|
101
|
+
}
|
|
102
|
+
if (!tag.slug) {
|
|
103
|
+
throw new Error('Must specify tag.slug to create');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const state = await api.getTagState(teamDid);
|
|
107
|
+
const tagData = pick(tag, ['title', 'description', 'color', 'slug', 'type', 'componentDid', 'parentId']);
|
|
108
|
+
tagData.createdBy = context.user.did;
|
|
109
|
+
tagData.updatedBy = context.user.did;
|
|
110
|
+
const doc = await state.insert(tagData);
|
|
111
|
+
logger.info('tags created successfully', { teamDid, tag });
|
|
112
|
+
return doc;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Update tag
|
|
117
|
+
* @param {Object} api - TeamAPI instance
|
|
118
|
+
* @param {Object} params
|
|
119
|
+
* @param {string} params.teamDid - Team DID
|
|
120
|
+
* @param {Object} params.tag - Tag data
|
|
121
|
+
* @param {Object} context
|
|
122
|
+
* @returns {Promise<Object>}
|
|
123
|
+
*/
|
|
124
|
+
async function updateTag(api, { teamDid, tag }, context = {}) {
|
|
125
|
+
if (!tag.id) {
|
|
126
|
+
throw new Error('Must specify tag.id to update');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const keys = ['title', 'description', 'color', 'slug', 'type', 'componentDid', 'parentId'];
|
|
130
|
+
const tagData = Object.fromEntries(keys.map((key) => [key, tag[key] ?? null]));
|
|
131
|
+
tagData.updatedBy = context.user.did;
|
|
132
|
+
|
|
133
|
+
const state = await api.getTagState(teamDid);
|
|
134
|
+
const result = await state.updateById(tag.id, tagData);
|
|
135
|
+
logger.info('tags updated successfully', { teamDid, tag, result });
|
|
136
|
+
return state.findOne({ id: tag.id });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Delete tag
|
|
141
|
+
* @param {Object} api - TeamAPI instance
|
|
142
|
+
* @param {Object} params
|
|
143
|
+
* @param {string} params.teamDid - Team DID
|
|
144
|
+
* @param {Object} params.tag - Tag data
|
|
145
|
+
* @param {number} params.moveTo - Move to tag id
|
|
146
|
+
* @returns {Promise<Object>}
|
|
147
|
+
*/
|
|
148
|
+
async function deleteTag(api, { teamDid, tag, moveTo }) {
|
|
149
|
+
if (!tag.id) {
|
|
150
|
+
throw new Error('Must specify tag.id to delete');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const state = await api.getTagState(teamDid);
|
|
154
|
+
const taggingState = await api.getTaggingState(teamDid);
|
|
155
|
+
|
|
156
|
+
if (moveTo) {
|
|
157
|
+
const records = await taggingState.find({ tagId: tag.id });
|
|
158
|
+
const checkPairs = records.map((r) => ({ taggableId: r.taggableId, taggableType: r.taggableType }));
|
|
159
|
+
const existing = await taggingState.find({ tagId: moveTo, $or: checkPairs });
|
|
160
|
+
|
|
161
|
+
const existingSet = new Set(existing.map((e) => `${e.taggableId}:${e.taggableType}`));
|
|
162
|
+
const toUpdate = [];
|
|
163
|
+
const toDelete = [];
|
|
164
|
+
|
|
165
|
+
for (const record of records) {
|
|
166
|
+
const key = `${record.taggableId}:${record.taggableType}`;
|
|
167
|
+
if (existingSet.has(key)) {
|
|
168
|
+
toDelete.push(record);
|
|
169
|
+
logger.info('tag already at moveTo, will delete record', { teamDid, tag, record });
|
|
170
|
+
} else {
|
|
171
|
+
toUpdate.push(record);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (toUpdate.length > 0) {
|
|
176
|
+
await Promise.all(
|
|
177
|
+
toUpdate.map((record) =>
|
|
178
|
+
taggingState
|
|
179
|
+
.update(
|
|
180
|
+
{ tagId: record.tagId, taggableId: record.taggableId, taggableType: record.taggableType },
|
|
181
|
+
{ $set: { tagId: moveTo } }
|
|
182
|
+
)
|
|
183
|
+
.then(() => {
|
|
184
|
+
logger.info('tag moved successfully', { teamDid, tag, record, moveTo });
|
|
185
|
+
})
|
|
186
|
+
)
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (toDelete.length > 0) {
|
|
191
|
+
await Promise.all(
|
|
192
|
+
toDelete.map((record) =>
|
|
193
|
+
taggingState.remove(record).then(() => {
|
|
194
|
+
logger.info('tagging deleted successfully', { teamDid, tag, record });
|
|
195
|
+
})
|
|
196
|
+
)
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const doc = await state.remove({ id: tag.id });
|
|
202
|
+
await taggingState.remove({ tagId: tag.id });
|
|
203
|
+
logger.info('tags deleted successfully', { teamDid, tag });
|
|
204
|
+
return doc;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Get tags
|
|
209
|
+
* @param {Object} api - TeamAPI instance
|
|
210
|
+
* @param {Object} params
|
|
211
|
+
* @param {string} params.teamDid - Team DID
|
|
212
|
+
* @param {Object} params.paging - Paging options
|
|
213
|
+
* @returns {Promise<Object>}
|
|
214
|
+
*/
|
|
215
|
+
async function getTags(api, { teamDid, paging }) {
|
|
216
|
+
const state = await api.getTagState(teamDid);
|
|
217
|
+
const result = await state.paginate({}, { createdAt: -1 }, { pageSize: 20, ...paging });
|
|
218
|
+
return { tags: result.list, paging: result.paging };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
module.exports = {
|
|
222
|
+
taggingSchema,
|
|
223
|
+
createTagging,
|
|
224
|
+
deleteTagging,
|
|
225
|
+
getTag,
|
|
226
|
+
createTag,
|
|
227
|
+
updateTag,
|
|
228
|
+
deleteTag,
|
|
229
|
+
getTags,
|
|
230
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const { joinURL } = require('ufo');
|
|
2
|
+
const logger = require('@abtnode/logger')('@abtnode/core:api:team:user-auth');
|
|
3
|
+
const { ROLES } = require('@abtnode/constant');
|
|
4
|
+
const { TeamEvents } = require('@blocklet/constant');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Send new member notification
|
|
8
|
+
* @param {Object} api - TeamAPI instance
|
|
9
|
+
* @param {Object} user - User
|
|
10
|
+
* @param {Object} nodeInfo - Node info
|
|
11
|
+
* @returns {Promise<void>}
|
|
12
|
+
*/
|
|
13
|
+
async function sendNewMemberNotification(api, user, nodeInfo) {
|
|
14
|
+
if (nodeInfo.nodeOwner && user.did !== nodeInfo.nodeOwner.did) {
|
|
15
|
+
const actionPath = '/team/members';
|
|
16
|
+
const action = process.env.NODE_ENV === 'production' ? joinURL(nodeInfo.routing.adminPath, actionPath) : actionPath;
|
|
17
|
+
await api.teamManager.createNotification({
|
|
18
|
+
title: 'New member join',
|
|
19
|
+
description: `User with Name (${user.fullName}) and DID (${user.did}) has joined this server`,
|
|
20
|
+
entityType: 'node',
|
|
21
|
+
action,
|
|
22
|
+
entityId: user.did,
|
|
23
|
+
severity: 'success',
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Login user
|
|
30
|
+
* @param {Object} api - TeamAPI instance
|
|
31
|
+
* @param {Object} params
|
|
32
|
+
* @param {string} params.teamDid - Team DID
|
|
33
|
+
* @param {Object} params.user - User
|
|
34
|
+
* @param {boolean} params.notify - Send notification
|
|
35
|
+
* @param {boolean} params.force - Force login
|
|
36
|
+
* @returns {Promise<Object>}
|
|
37
|
+
*/
|
|
38
|
+
async function loginUser(api, { teamDid, user, notify = true, force = false }) {
|
|
39
|
+
const state = await api.getUserState(teamDid);
|
|
40
|
+
const nodeInfo = await api.node.read();
|
|
41
|
+
|
|
42
|
+
if (user.role === ROLES.OWNER) {
|
|
43
|
+
if (teamDid !== nodeInfo.did && !force) {
|
|
44
|
+
throw new Error('Cannot add user of owner role');
|
|
45
|
+
}
|
|
46
|
+
if (await state.count({ role: ROLES.OWNER })) {
|
|
47
|
+
throw new Error('The owner already exists');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const { _action, ...doc } = await state.loginUser(user);
|
|
52
|
+
if (_action === 'update') {
|
|
53
|
+
logger.info('user updated successfully', { teamDid, userDid: user.did });
|
|
54
|
+
api.emit(TeamEvents.userUpdated, { teamDid, user: doc });
|
|
55
|
+
} else if (_action === 'add') {
|
|
56
|
+
api.createDefaultOrgForUser({ teamDid, user });
|
|
57
|
+
|
|
58
|
+
if (teamDid === nodeInfo.did && nodeInfo.nodeOwner && user.did !== nodeInfo.nodeOwner.did && notify) {
|
|
59
|
+
await sendNewMemberNotification(api, user, nodeInfo);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
logger.info('user added successfully', { teamDid, userDid: user.did, userPk: user.pk, userName: user.fullName });
|
|
63
|
+
api.emit(TeamEvents.userAdded, { teamDid, user: doc });
|
|
64
|
+
}
|
|
65
|
+
return doc;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Disconnect user account
|
|
70
|
+
* @param {Object} api - TeamAPI instance
|
|
71
|
+
* @param {Object} params
|
|
72
|
+
* @param {string} params.teamDid - Team DID
|
|
73
|
+
* @param {Object} params.connectedAccount - Connected account
|
|
74
|
+
* @returns {Promise<Object>}
|
|
75
|
+
*/
|
|
76
|
+
async function disconnectUserAccount(api, { teamDid, connectedAccount }) {
|
|
77
|
+
const state = await api.getUserState(teamDid);
|
|
78
|
+
const result = await state.disconnectUserAccount(connectedAccount);
|
|
79
|
+
|
|
80
|
+
logger.info('user disconnect account successfully', {
|
|
81
|
+
teamDid,
|
|
82
|
+
connectedAccountDid: connectedAccount.did,
|
|
83
|
+
connectedAccountPk: connectedAccount.pk,
|
|
84
|
+
connectedAccountProvider: connectedAccount.provider,
|
|
85
|
+
});
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Add user
|
|
91
|
+
* @param {Object} api - TeamAPI instance
|
|
92
|
+
* @param {Object} params
|
|
93
|
+
* @param {string} params.teamDid - Team DID
|
|
94
|
+
* @param {Object} params.user - User
|
|
95
|
+
* @param {boolean} params.force - Force add
|
|
96
|
+
* @returns {Promise<Object>}
|
|
97
|
+
*/
|
|
98
|
+
async function addUser(api, { teamDid, user, force = false }) {
|
|
99
|
+
const state = await api.getUserState(teamDid);
|
|
100
|
+
|
|
101
|
+
if (user.role === ROLES.OWNER) {
|
|
102
|
+
const nodeInfo = await api.node.read();
|
|
103
|
+
|
|
104
|
+
if (teamDid !== nodeInfo.did && !force) {
|
|
105
|
+
throw new Error('Cannot add user of owner role');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (await state.count({ role: ROLES.OWNER })) {
|
|
109
|
+
throw new Error('The owner already exists');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const doc = await state.addUser(user);
|
|
114
|
+
|
|
115
|
+
logger.info('user added successfully', { teamDid, userDid: user.did, userPk: user.pk, userName: user.fullName });
|
|
116
|
+
|
|
117
|
+
const nodeInfo = await api.node.read();
|
|
118
|
+
if (teamDid === nodeInfo.did && nodeInfo.nodeOwner && user.did !== nodeInfo.nodeOwner.did) {
|
|
119
|
+
await sendNewMemberNotification(api, user, nodeInfo);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
api.emit(TeamEvents.userAdded, { teamDid, user: doc });
|
|
123
|
+
|
|
124
|
+
return doc;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
module.exports = {
|
|
128
|
+
sendNewMemberNotification,
|
|
129
|
+
loginUser,
|
|
130
|
+
disconnectUserAccount,
|
|
131
|
+
addUser,
|
|
132
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Manager - Orchestrates user management operations
|
|
3
|
+
*
|
|
4
|
+
* This module re-exports functionality from specialized sub-modules:
|
|
5
|
+
* - user-auth-manager.js: User authentication and login operations
|
|
6
|
+
* - user-query-manager.js: User query and search operations
|
|
7
|
+
* - user-social-manager.js: User follow, invite, and webhook operations
|
|
8
|
+
* - user-update-manager.js: User update and modification operations
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const { sendNewMemberNotification, loginUser, disconnectUserAccount, addUser } = require('./user-auth-manager');
|
|
12
|
+
const {
|
|
13
|
+
getUsers,
|
|
14
|
+
getUsersCount,
|
|
15
|
+
getUsersCountPerRole,
|
|
16
|
+
getUser,
|
|
17
|
+
getConnectedAccount,
|
|
18
|
+
isEmailUsed,
|
|
19
|
+
isPhoneUsed,
|
|
20
|
+
getUserByDid,
|
|
21
|
+
isUserValid,
|
|
22
|
+
isPassportValid,
|
|
23
|
+
isConnectedAccount,
|
|
24
|
+
getOwner,
|
|
25
|
+
} = require('./user-query-manager');
|
|
26
|
+
const {
|
|
27
|
+
USER_RELATION_ACTIONS,
|
|
28
|
+
USER_RELATION_QUERIES,
|
|
29
|
+
userFollowAction,
|
|
30
|
+
getUserFollows,
|
|
31
|
+
getUserFollowStats,
|
|
32
|
+
checkFollowing,
|
|
33
|
+
getUserInvites,
|
|
34
|
+
createWebhookDisabledNotification,
|
|
35
|
+
updateWebHookState,
|
|
36
|
+
} = require('./user-social-manager');
|
|
37
|
+
const {
|
|
38
|
+
updateUser,
|
|
39
|
+
updateUserAddress,
|
|
40
|
+
updateUserTags,
|
|
41
|
+
removeUser,
|
|
42
|
+
updateUserApproval,
|
|
43
|
+
switchProfile,
|
|
44
|
+
} = require('./user-update-manager');
|
|
45
|
+
|
|
46
|
+
module.exports = {
|
|
47
|
+
USER_RELATION_ACTIONS,
|
|
48
|
+
USER_RELATION_QUERIES,
|
|
49
|
+
sendNewMemberNotification,
|
|
50
|
+
loginUser,
|
|
51
|
+
disconnectUserAccount,
|
|
52
|
+
addUser,
|
|
53
|
+
getUsers,
|
|
54
|
+
getUsersCount,
|
|
55
|
+
getUsersCountPerRole,
|
|
56
|
+
getUser,
|
|
57
|
+
getConnectedAccount,
|
|
58
|
+
isEmailUsed,
|
|
59
|
+
isPhoneUsed,
|
|
60
|
+
getUserByDid,
|
|
61
|
+
isUserValid,
|
|
62
|
+
isPassportValid,
|
|
63
|
+
isConnectedAccount,
|
|
64
|
+
getOwner,
|
|
65
|
+
userFollowAction,
|
|
66
|
+
getUserFollows,
|
|
67
|
+
getUserFollowStats,
|
|
68
|
+
checkFollowing,
|
|
69
|
+
getUserInvites,
|
|
70
|
+
createWebhookDisabledNotification,
|
|
71
|
+
updateWebHookState,
|
|
72
|
+
updateUser,
|
|
73
|
+
updateUserAddress,
|
|
74
|
+
updateUserTags,
|
|
75
|
+
removeUser,
|
|
76
|
+
updateUserApproval,
|
|
77
|
+
switchProfile,
|
|
78
|
+
};
|