insite-users-server 1.0.334 → 1.0.336

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/orgs/Orgs.js DELETED
@@ -1,232 +0,0 @@
1
- import { debounce } from "@nesvet/n";
2
- import { ObjectId } from "insite-db";
3
- import { Org } from "./Org";
4
- import { basisSchema } from "./schema";
5
-
6
-
7
- const indexes = [
8
- [ { owners: 1 } ]
9
- ];
10
-
11
- function sortOrgs(a, b) {
12
- return (
13
- (b.slaveOrgs.size - a.slaveOrgs.size) || (
14
- a.title > b.title ?
15
- 1 :
16
- a.title < b.title ?
17
- -1 :
18
- 0
19
- )
20
- );
21
- }
22
-
23
- function preventDirectDelete() {
24
- throw new Error("Direct usage of orgs collection.deleteOne or .deleteMany is forbidden. Use orgs.collectionDelete instead.");
25
- }
26
-
27
-
28
- export class Orgs extends Map {
29
- constructor(users, options = {}) {
30
- super();
31
-
32
- const {
33
- schema: customSchema,
34
- indexes: customIndexes,
35
- null: nullProps
36
- } = options;
37
-
38
- this.users = users;
39
- this.collections = users.collections;
40
-
41
- if (customSchema) {
42
- customSchema.required?.removeAll(basisSchema.required);
43
- if (customSchema.properties)
44
- Object.delete(customSchema, ...Object.keys(basisSchema.properties));
45
- }
46
-
47
- const jsonSchema = {
48
- ...basisSchema,
49
- ...customSchema,
50
- required: [ ...basisSchema.required, ...customSchema?.required ?? [] ],
51
- properties: { ...basisSchema.properties, ...customSchema?.properties }
52
- };
53
-
54
- return (async () => {
55
-
56
- this.collection = await this.collections.ensure("orgs", { jsonSchema });
57
-
58
- this.collection.ensureIndexes([ ...indexes, ...customIndexes ?? [] ]);
59
-
60
- this.collection.deleteOne =
61
- this.collection.deleteMany =
62
- preventDirectDelete;
63
-
64
- this.null = new Org(this, {
65
- ...nullProps,
66
- _id: null,
67
- title: "",
68
- displayLabel: "",
69
- note: "",
70
- owners: [],
71
- createdAt: Date.now()
72
- });
73
-
74
- this.null.ownerIds = new Array.Empty();
75
- this.null.ownerOrgs = new Set.Empty();
76
- this.null.ownerUsers = new Set.Empty();
77
- this.null.slaveOrgs = new Set.Empty();
78
-
79
- return this;
80
- })();
81
- }
82
-
83
- load(orgDoc) {
84
- new Org(this, orgDoc);
85
-
86
- }
87
-
88
- static resolve(org, slaveOrgs) {
89
- slaveOrgs = [ org, ...slaveOrgs ];
90
-
91
- for (const ownerOrg of org.ownerOrgs) {
92
- Orgs.resolve(ownerOrg, slaveOrgs);
93
- ownerOrg.slaveOrgs.addAll(slaveOrgs);
94
- }
95
-
96
- }
97
-
98
- sorted = [];
99
-
100
- async update() {
101
-
102
- const array = [ ...this.values() ];
103
- const sorted = [];
104
-
105
- for (const org of array) {
106
- org.ownerOrgs.clear();
107
- org.ownerUsers.clear();
108
- org.slaveOrgs.clear();
109
-
110
- for (const ownerId of org.ownerIds) {
111
- const ownerOrg = this.get(ownerId);
112
- if (ownerOrg)
113
- org.ownerOrgs.add(ownerOrg);
114
- else {
115
- const ownerUser = this.users.get(ownerId);
116
- if (ownerUser)
117
- org.ownerUsers.add(ownerUser);
118
- }
119
- }
120
-
121
- if (!org.ownerOrgs.size && org._id)
122
- sorted.push(org);
123
- }
124
-
125
- for (const org of array)
126
- if (!array.some(anotherOrg => anotherOrg.ownerOrgs.has(org)))
127
- Orgs.resolve(org, []);
128
-
129
- sorted.sort(sortOrgs);
130
- for (const org of array)
131
- org.slaveOrgs.sort(sortOrgs);
132
-
133
- for (let i = 0; i < sorted.length; i++) {
134
- const org = sorted[i];
135
- for (const slaveOrg of [ ...org.slaveOrgs ].reverse())
136
- if (slaveOrg.ownerOrgs.has(org)) {
137
- const slaveOrgIndex = sorted.indexOf(slaveOrg);
138
- if (~slaveOrgIndex) {
139
- sorted.splice(slaveOrgIndex, 1);
140
- i--;
141
- }
142
- sorted.splice(i + 1, 0, slaveOrg);
143
- }
144
- }
145
- for (let o = 0, { length } = sorted; o < length;)
146
- sorted[o]._o = o++;
147
-
148
- this.sorted = sorted;
149
-
150
- this.users.emit("orgs-update");
151
-
152
- if (this.users.isInited) {
153
- this.users.updateDebounced.clear();
154
- this.users.update();
155
- }
156
-
157
- }
158
-
159
- updateDebounced = debounce(this.update, 250);
160
-
161
- initialLoad = async () => {
162
-
163
- for (const orgDoc of await this.collection.find().toArray())
164
- this.load(orgDoc);
165
-
166
- delete this.initialLoad;
167
-
168
- };
169
-
170
- init = async () => {
171
-
172
- await this.update();
173
-
174
- this.collection.changeListeners.add(next => {
175
- switch (next.operationType) {
176
- case "insert": {
177
- const org = new Org(this, next.fullDocument);
178
- this.users.emit("orgs-org-update", org, next);
179
- break;
180
- }
181
-
182
- case "update":
183
- case "replace":
184
- this.get(next.documentKey._id).update(next.updateDescription?.updatedFields || next.fullDocument, next);
185
- break;
186
-
187
- case "delete":
188
- this.get(next.documentKey._id).delete();
189
- this.users.emit("orgs-org-update", null, next);
190
- }
191
-
192
- });
193
-
194
- delete this.init;
195
-
196
- };
197
-
198
- new({ title, note, ...restProps }, ownerId) {
199
- return this.collection.insertOne({
200
- _id: (new ObjectId()).toString(),
201
- title,
202
- note: note || "",
203
- owners: ownerId ? [ ownerId ] : [],
204
- ...Object.delete(restProps, "_id", "owners"),
205
- createdAt: Date.now()
206
- });
207
- }
208
-
209
- collectionDelete(org) {
210
- const _id = typeof org == "string" ? org : org._id;
211
-
212
- return this.collection.bulkWrite([
213
- { updateMany: { filter: { owners: _id }, update: { $pullAll: { owners: [ _id ] } } } },
214
- { deleteOne: { filter: { _id } } }
215
- ]);
216
- }
217
-
218
- replaceMap = new Map();
219
-
220
- replaceHandlers = new Set();
221
-
222
- async replace(fromId) {
223
- const toId = this.replaceMap.get(fromId) ?? null;
224
- if (toId)
225
- this.replaceMap.delete(fromId);
226
-
227
- for (const handler of this.replaceHandlers)
228
- await handler(fromId, toId);
229
-
230
- }
231
-
232
- }
package/lib/orgs/index.js DELETED
@@ -1 +0,0 @@
1
- export * from "./Orgs";
@@ -1,39 +0,0 @@
1
- import { regexps } from "../lib";
2
-
3
-
4
- export const basisSchema = {
5
- required: [
6
- "_id",
7
- "title",
8
- "note",
9
- "owners",
10
- "createdAt"
11
- ],
12
- properties: {
13
- _id: {
14
- bsonType: "string",
15
- pattern: regexps._id.pattern
16
- },
17
- title: {
18
- bsonType: "string",
19
- maxLength: 512
20
- },
21
- note: {
22
- bsonType: "string",
23
- maxLength: 131072
24
- },
25
- owners: {
26
- bsonType: "array",
27
- uniqueItems: true,
28
- items: {
29
- bsonType: "string",
30
- pattern: regexps._id.pattern
31
- },
32
- additionalItems: false
33
- },
34
- createdAt: {
35
- bsonType: "number"
36
- }
37
- },
38
- additionalProperties: false
39
- };
package/lib/roles/Role.js DELETED
@@ -1,70 +0,0 @@
1
- const snapshots = new Map();
2
-
3
-
4
- export class Role {
5
- constructor(roles, roleDoc) {
6
- this.#roles = roles;
7
-
8
- this._id = roleDoc._id;
9
- roles.set(this._id, this);
10
-
11
- this.update(roleDoc);
12
-
13
- }
14
-
15
- #roles;
16
-
17
- ownInvolves = [];
18
- involves = new Set();
19
- abilities = {};
20
- inheritedAbilities = {};
21
-
22
- update({ _id, involves: ownInvolveIds, abilities: ownAbilities, title, ...restProps }, next) {
23
-
24
- const roles = this.#roles;
25
-
26
- Object.assign(this, restProps);
27
-
28
- if (ownInvolveIds)
29
- this.ownInvolveIds = ownInvolveIds;
30
-
31
- if (ownAbilities)
32
- this.ownAbilities = ownAbilities;
33
-
34
- if (title !== undefined) {
35
- this.title = title;
36
- this.displayTitle = title || this._id;
37
- }
38
-
39
-
40
- if (ownInvolveIds || ownAbilities) {
41
- const snapshot = [
42
- this.ownInvolveIds.join(","),
43
- JSON.stringify(this.ownAbilities)
44
- ].join("\n");
45
-
46
- if (snapshot != snapshots.get(this._id)) {
47
- snapshots.set(this._id, snapshot);
48
-
49
- if (roles.users.isInited)
50
- roles.updateDebounced();
51
-
52
- roles.users.emit("roles-role-update", next);
53
- }
54
- }
55
-
56
- }
57
-
58
- delete() {
59
-
60
- const roles = this.#roles;
61
-
62
- roles.delete(this._id);
63
-
64
- snapshots.delete(this._id);
65
-
66
- roles.updateDebounced();
67
-
68
- }
69
-
70
- }
@@ -1,224 +0,0 @@
1
- import { debounce } from "@nesvet/n";
2
- import { Role } from "./Role";
3
- import { basisSchema } from "./schema";
4
-
5
-
6
- const indexes = [
7
- [ { involves: 1 } ]
8
- ];
9
-
10
- function preventDirectDelete() {
11
- throw new Error("Direct usage of roles collection.deleteOne or .deleteMany is forbidden. Use roles.collectionDelete instead.");
12
- }
13
-
14
- function sortRoles(a, b) {
15
- return (
16
- (b.involves.size - a.involves.size) || (
17
- (a.title && b.title) ?
18
- a.title > b.title ? 1 : a.title < b.title ? -1 : 0 :
19
- a.title ?
20
- -1 :
21
- b.title ?
22
- 1 :
23
- a._id > b._id ?
24
- 1 :
25
- a._id < b._id ?
26
- -1 :
27
- 0
28
-
29
- )
30
- );
31
- }
32
-
33
-
34
- export class Roles extends Map {
35
- constructor(users, options = {}) {
36
- super();
37
-
38
- const {
39
- schema: customSchema,
40
- indexes: customIndexes,
41
- root: rootProps
42
- } = options;
43
-
44
- this.users = users;
45
- this.collections = users.collections;
46
- this.abilities = users.abilities;
47
-
48
- this.root = new Role(this, {
49
- ...rootProps,
50
- _id: "root",
51
- involves: [],
52
- abilities: this.abilities.getMaximum(),
53
- title: "Root",
54
- description: "Root",
55
- createdAt: Date.now()
56
- });
57
-
58
- if (customSchema) {
59
- customSchema.required?.removeAll(basisSchema.required);
60
- if (customSchema.properties)
61
- Object.delete(customSchema, ...Object.keys(basisSchema.properties));
62
- }
63
-
64
- const jsonSchema = {
65
- ...basisSchema,
66
- ...customSchema,
67
- required: [ ...basisSchema.required, ...customSchema?.required ?? [] ],
68
- properties: { ...basisSchema.properties, ...customSchema?.properties }
69
- };
70
-
71
- return (async () => {
72
-
73
- this.collection = await this.collections.ensure("roles", { jsonSchema });
74
-
75
- this.collection.ensureIndexes([ ...indexes, ...customIndexes ?? [] ]);
76
-
77
- this.collection.deleteOne =
78
- this.collection.deleteMany =
79
- preventDirectDelete;
80
-
81
- return this;
82
- })();
83
- }
84
-
85
- load(roleDoc) {
86
- new Role(this, roleDoc);
87
-
88
- }
89
-
90
- resolve(role, involvedBy) {
91
- involvedBy = [ role, ...involvedBy ];
92
-
93
- for (const involvedRoleId of role.ownInvolveIds) {
94
- const involvedRole = this.get(involvedRoleId);
95
- if (involvedRole) {
96
- for (const involvedByRole of involvedBy) {
97
- involvedByRole.involves.reAdd(involvedRole);
98
- this.abilities.merge(involvedByRole.inheritedAbilities, involvedRole.abilities);
99
- }
100
- if (involvedRole !== role)
101
- this.resolve(involvedRole, involvedBy);
102
- }
103
- }
104
-
105
- }
106
-
107
- sorted = [];
108
-
109
- async update() {
110
-
111
- const array = [ ...this.values() ];
112
-
113
- this.root.ownInvolveIds = [];
114
- for (const role of array) {
115
- if (role !== this.root && !array.some(anotherRole => anotherRole.ownInvolveIds.includes(role._id)))
116
- this.root.ownInvolveIds.push(role._id);
117
- role.involves.clear();
118
- role.abilities = Object.deepClone(role.ownAbilities);
119
- role.inheritedAbilities = {};
120
- }
121
-
122
- this.root.involves.add(this.root);
123
- this.resolve(this.root, []);
124
-
125
- for (const role of array)
126
- role.ownInvolves = this.getAll(role.ownInvolveIds).sort(sortRoles).reverse();
127
-
128
- const sorted = [ this.root ];
129
-
130
- for (let i = 0; i < sorted.length; i++) {
131
- const role = sorted[i];
132
- for (const involvedRole of role.ownInvolves) {
133
- const involvedRoleIndex = sorted.indexOf(involvedRole);
134
- if (~involvedRoleIndex) {
135
- sorted.splice(involvedRoleIndex, 1);
136
- i--;
137
- }
138
- sorted.splice(i + 1, 0, involvedRole);
139
- }
140
- }
141
-
142
- let _o = 0;
143
- for (const role of sorted) {
144
- this.abilities.merge(role.abilities, role.inheritedAbilities);
145
- role._o = _o++;
146
- }
147
-
148
- this.sorted = sorted;
149
-
150
- this.users.emit("roles-update");
151
-
152
- if (this.users.isInited) {
153
- this.users.updateDebounced.clear();
154
- this.users.update(true);
155
- }
156
-
157
- }
158
-
159
- updateDebounced = debounce(this.update, 250);
160
-
161
- init = async () => {
162
-
163
- for (const roleDoc of await this.collection.find().toArray())
164
- this.load(roleDoc);
165
-
166
- await this.update();
167
-
168
- this.collection.changeListeners.add(next => {
169
- switch (next.operationType) {
170
- case "insert":
171
- const role = new Role(this, next.fullDocument);
172
- this.users.emit("roles-role-update", role, next);
173
- break;
174
-
175
- case "update":
176
- case "replace":
177
- this.get(next.documentKey._id).update(next.updateDescription?.updatedFields || next.fullDocument, next);
178
- break;
179
-
180
- case "delete":
181
- this.get(next.documentKey._id).delete();
182
- this.users.emit("roles-role-update", null, next);
183
- }
184
-
185
- });
186
-
187
- delete this.init;
188
-
189
- };
190
-
191
- new({ _id, involves, title, description, ...restProps }) {
192
- return this.collection.insertOne({
193
- _id,
194
- involves: involves || [],
195
- abilities: {},
196
- title: title ?? "",
197
- description: description ?? "",
198
- ...Object.delete(restProps, "abilities"),
199
- createdAt: Date.now()
200
- });
201
- }
202
-
203
- collectionDelete(role) {
204
- const _id = typeof role == "string" ? role : role._id;
205
-
206
- return this.collection.bulkWrite([
207
- { updateMany: { filter: { involves: _id }, update: { $pullAll: { involves: [ _id ] } } } },
208
- { deleteOne: { filter: { _id } } }
209
- ]);
210
- }
211
-
212
- cleanUpIds(ids) {
213
- const roles = this.sorted.intersection(this.getAll(ids));
214
-
215
- const cleanedUpIds = [];
216
-
217
- for (const role of roles)
218
- if (roles.every(anotherRole => anotherRole === role || !anotherRole.involves.has(role)))
219
- cleanedUpIds.push(role._id);
220
-
221
- return cleanedUpIds;
222
- }
223
-
224
- }
@@ -1 +0,0 @@
1
- export * from "./Roles";
@@ -1,45 +0,0 @@
1
- import { regexps } from "../lib";
2
-
3
-
4
- export const basisSchema = {
5
- required: [
6
- "_id",
7
- "involves",
8
- "abilities",
9
- "title",
10
- "description",
11
- "createdAt"
12
- ],
13
- properties: {
14
- _id: {
15
- bsonType: "string",
16
- pattern: regexps.role.pattern,
17
- not: { enum: [ "root" ] }
18
- },
19
- involves: {
20
- bsonType: "array",
21
- uniqueItems: true,
22
- items: {
23
- bsonType: "string",
24
- pattern: regexps.role.pattern,
25
- not: { enum: [ "root" ] }
26
- },
27
- additionalItems: false
28
- },
29
- abilities: {
30
- bsonType: "object"
31
- },
32
- title: {
33
- bsonType: "string",
34
- maxLength: 256
35
- },
36
- description: {
37
- bsonType: "string",
38
- maxLength: 10240
39
- },
40
- createdAt: {
41
- bsonType: "number"
42
- }
43
- },
44
- additionalProperties: false
45
- };
@@ -1,72 +0,0 @@
1
- export class Session {
2
- constructor(sessions, sessionDoc) {
3
- this.#sessions = sessions;
4
-
5
- this._id = sessionDoc._id;
6
- sessions.set(this._id, this);
7
-
8
- this.user = sessions.users.get(sessionDoc.user);
9
- this.user.sessions.add(this);
10
-
11
- sessions.users.bySessionId.set(this._id, this.user);
12
-
13
- this.update(sessionDoc);
14
-
15
- }
16
-
17
- #sessions;
18
-
19
- update({ _id, user, isOnline, ...restProps }) {
20
-
21
- const sessions = this.#sessions;
22
-
23
- if (isOnline !== undefined && this.isOnline != isOnline) {
24
- this.isOnline = isOnline;
25
-
26
- if (sessions.isInited && this.user.isOnline != this.isOnline)
27
- this.user.updateIsOnline();
28
- }
29
-
30
- Object.assign(this, restProps);
31
-
32
- }
33
-
34
- prolong({ _id, user, ...updates }) {
35
-
36
- const sessions = this.#sessions;
37
-
38
- const ts = Date.now();
39
-
40
- updates.prolongedAt = ts;
41
- updates.expiresAt = new Date(ts + (sessions.collection.expireAfterSeconds * 1000));
42
-
43
- this.update(updates);
44
-
45
- return sessions.collection.updateOne({ _id: this._id }, { $set: updates });
46
- }
47
-
48
- offline() {
49
-
50
- const updates = { isOnline: false };
51
-
52
- this.update(updates);
53
-
54
- return this.#sessions.collection.updateOne({ _id: this._id }, { $set: updates });
55
- }
56
-
57
- delete() {
58
-
59
- const sessions = this.#sessions;
60
-
61
- sessions.delete(this._id);
62
- this.user.sessions.delete(this);
63
- sessions.users.bySessionId.delete(this._id);
64
-
65
- sessions.users.emit("session-delete", this);
66
-
67
- if (this.isOnline)
68
- this.user.updateIsOnline();
69
-
70
- }
71
-
72
- }