insite-users-server 2.0.79 → 2.0.80

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/bun.lockb ADDED
Binary file
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/users/Users.ts", "../src/abilities/Map.ts", "../src/orgs/Orgs.ts", "../src/orgs/Org.ts", "../src/lib/regexps.ts", "../src/orgs/schema.ts", "../src/roles/Roles.ts", "../src/roles/Role.ts", "../src/roles/schema.ts", "../src/sessions/Sessions.ts", "../src/sessions/schema.ts", "../src/sessions/Session.ts", "../src/users/avatars/schema.ts", "../src/users/avatars/Avatars.ts", "../src/users/schema.ts", "../src/users/User.ts"],
4
- "sourcesContent": ["import * as argon2 from \"argon2\";\nimport EventEmitter from \"eventemitter3\";\nimport {\n\t_ids,\n\tdebounce,\n\tdeleteProps,\n\tremoveAll\n} from \"@nesvet/n\";\nimport type { AbilitiesSchema } from \"insite-common\";\nimport {\n\tInSiteCollectionIndexes,\n\tInSiteCollections,\n\tInSiteCollectionSchema,\n\tInSiteWatchedCollection,\n\tnewObjectIdString\n} from \"insite-db\";\nimport { AbilitiesMap } from \"../abilities\";\nimport { Orgs } from \"../orgs\";\nimport { Org } from \"../orgs/Org\";\nimport { Roles } from \"../roles\";\nimport { Sessions } from \"../sessions\";\nimport { Session } from \"../sessions/Session\";\nimport type { OrgsOptions } from \"../orgs/types\";\nimport type { RolesOptions } from \"../roles/types\";\nimport type { SessionDoc, SessionsOptions } from \"../sessions/types\";\nimport { Avatars/* , AvatarsOptions */ } from \"./avatars\";\nimport { basisSchema } from \"./schema\";\nimport { User } from \"./User\";\nimport type { UserDoc } from \"./types\";\n\n\nconst indexes: InSiteCollectionIndexes = [\n\t[ { email: 1 }, { unique: true } ],\n\t[ { org: 1 } ]\n];\n\n\nexport type Options<AS> = {\n\tabilities: AS;\n\tindexes?: InSiteCollectionIndexes;\n\tschema?: InSiteCollectionSchema;\n\tinitialRoot?: Partial<UserDoc>;\n\troles?: RolesOptions;\n\torgs?: OrgsOptions;\n\tsessions?: SessionsOptions;\n\t// avatars?: AvatarsOptions;\n};\n\n\nexport class Users<AS extends AbilitiesSchema = AbilitiesSchema> extends Map<string, User<AS>> {\n\tconstructor(collections: InSiteCollections, options: Options<AS>) {\n\t\tsuper();\n\t\t\n\t\tconst eventEmitter = new EventEmitter() as {\n\t\t\t_events: Record<string, object>;\n\t\t\t_eventsCount: number;\n\t\t} & EventEmitter;\n\t\tthis._events = eventEmitter._events;\n\t\tthis._eventsCount = eventEmitter._eventsCount;\n\t\tthis.emit = eventEmitter.emit;\n\t\tthis.on = eventEmitter.on;\n\t\tthis.once = eventEmitter.once;\n\t\tthis.addListener = eventEmitter.addListener;\n\t\tthis.off = eventEmitter.off;\n\t\tthis.removeListener = eventEmitter.removeListener;\n\t\t\n\t\tthis.collections = collections;\n\t\t\n\t\tthis.abilitiesMap = new AbilitiesMap<AS>(options.abilities);\n\t\t\n\t\tthis.initOptions = options;\n\t\t\n\t\tthis.initPromise = this.init!();\n\t\t\n\t}\n\t\n\t_events;\n\t_eventsCount;\n\temit;\n\ton;\n\tonce;\n\taddListener;\n\toff;\n\tremoveListener;\n\t\n\tprivate initOptions?;\n\t\n\tcollections;\n\tabilitiesMap;\n\t\n\tcollection!: InSiteWatchedCollection<UserDoc>;\n\troles!: Roles<AS>;\n\tsessions!: Sessions<AS>;\n\torgs!: Orgs<AS>;\n\tavatars!: Avatars<AS>;\n\t\n\tisInited = false;\n\t\n\tbyEmail = new Map();\n\tbySessionId = new Map();\n\tsorted: User<AS>[] = [];\n\t\n\tisSortRequired = false;\n\t\n\tload(userDoc: UserDoc) {\n\t\tnew User<AS>(this, userDoc);\n\t\t\n\t}\n\t\n\tsort() {\n\t\t\n\t\tthis.isSortRequired = false;\n\t\t\n\t\tthis.sorted = [ ...this.values() ].sort((a, b) => a.name.last > b.name.last ? 1 : a.name.last < b.name.last ? -1 : 0);\n\t\t\n\t}\n\t\n\tsortDebounced = debounce(() => this.sort(), 250);\n\t\n\tupdate(shouldUpdateRoles?: boolean) {\n\t\tif (shouldUpdateRoles)\n\t\t\tfor (const user of this.values())\n\t\t\t\tuser.updateRoles();\n\t\t\n\t\tfor (const user of this.values())\n\t\t\tuser.updatePermissions();\n\t\t\n\t\tif (this.isSortRequired)\n\t\t\tthis.sort();\n\t\t\n\t}\n\t\n\tupdateDebounced = debounce(() => this.update(), 250);\n\t\n\tpreinit? = async () => {\n\t\t\n\t\tconst {\n\t\t\tindexes: customIndexes,\n\t\t\tschema: customSchema,\n\t\t\tinitialRoot: initialRootProps\n\t\t\t// avatars: avatarsOptions\n\t\t} = this.initOptions!;\n\t\t\n\t\tif (customSchema) {\n\t\t\tif (customSchema.required)\n\t\t\t\tremoveAll(customSchema.required as string[], basisSchema.required as string[]);\n\t\t\tif (customSchema.properties)\n\t\t\t\tdeleteProps(customSchema, Object.keys(basisSchema.properties!));\n\t\t}\n\t\t\n\t\tconst jsonSchema = {\n\t\t\t...basisSchema,\n\t\t\t...customSchema,\n\t\t\trequired: [ ...basisSchema.required as string [], ...customSchema?.required as string[] ?? [] ],\n\t\t\tproperties: { ...basisSchema.properties, ...customSchema?.properties }\n\t\t};\n\t\t\n\t\tthis.collection = await this.collections.ensure<UserDoc>(\"users\", { jsonSchema });\n\t\t\n\t\tthis.collection.ensureIndexes([ ...indexes, ...customIndexes ?? [] ]);\n\t\t\n\t\tif (!await this.collection.countDocuments({ roles: \"root\" }))\n\t\t\tawait this.new({\n\t\t\t\temail: process.env.INSITE_ROOT_EMAIL ?? \"insite@root.email\",\n\t\t\t\tpassword: process.env.INSITE_ROOT_PASSWORD ?? \"inSiteRootPassword\",\n\t\t\t\troles: [ \"root\" ],\n\t\t\t\tname: { first: \"Root\" },\n\t\t\t\torg: null,\n\t\t\t\tjob: \"Root\",\n\t\t\t\t...initialRootProps && deleteProps(initialRootProps, [ \"roles\", \"org\" ])\n\t\t\t});\n\t\t\n\t\t\n\t\tfor (const userDoc of await this.collection.find().toArray())\n\t\t\tthis.load(userDoc);\n\t\t\n\t\tdelete this.preinit;\n\t\t\n\t};\n\t\n\tprivate initPromise;\n\t\n\tprivate init? = async () => {\n\t\t\n\t\tconst {\n\t\t\troles: rolesOptions,\n\t\t\torgs: orgsOptions,\n\t\t\tsessions: sessionsOptions\n\t\t// avatars: avatarsOptions\n\t\t} = this.initOptions!;\n\t\t\n\t\tthis.roles = new Roles<AS>(this, rolesOptions);\n\t\tthis.orgs = new Orgs<AS>(this, orgsOptions);\n\t\tthis.sessions = new Sessions<AS>(this, sessionsOptions);\n\t\tthis.avatars = new Avatars<AS>(this/* , avatarsOptions */);\n\t\t\n\t\tawait this.roles.init!();\n\t\tawait this.orgs.preinit!();\n\t\tawait this.preinit!();\n\t\tawait this.orgs.init!();\n\t\tawait this.avatars.init!();\n\t\t\n\t\tthis.isInited = true;\n\t\t\n\t\tthis.update(true);\n\t\t\n\t\tthis.collection.changeListeners.add(next => {\n\t\t\tswitch (next.operationType) {\n\t\t\t\tcase \"insert\":\n\t\t\t\t\tnew User<AS>(this, next.fullDocument);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"replace\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.fullDocument);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"update\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.updateDescription.updatedFields!);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"delete\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.delete();\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\tawait this.sessions.init!();\n\t\t\n\t\tdelete this.initOptions;\n\t\tdelete this.init;\n\t\t\n\t\treturn this;\n\t};\n\t\n\twhenReady() {\n\t\treturn this.initPromise;\n\t}\n\t\n\tasync new({ email, password, roles, name, org, job, ...restProps }: Omit<UserDoc, \"_id\" | \"createdAt\">) {\n\t\tif (this.byEmail.has(email))\n\t\t\tthrow new Error(\"User exists\");\n\t\t\n\t\tawait this.collection.insertOne({\n\t\t\t_id: newObjectIdString(),\n\t\t\temail,\n\t\t\tpassword: await argon2.hash(password),\n\t\t\troles: this.isInited ? this.roles.cleanUpIds(roles) : roles,\n\t\t\tname: {\n\t\t\t\tfirst: name.first ?? \"\",\n\t\t\t\tmiddle: name.middle ?? \"\",\n\t\t\t\tlast: name.last ?? \"\"\n\t\t\t},\n\t\t\torg: org ?? null,\n\t\t\tjob: job ?? \"\",\n\t\t\t...deleteProps(restProps, [ \"_id\" ]),\n\t\t\tcreatedAt: Date.now()\n\t\t});\n\t\t\n\t\treturn true;\n\t}\n\t\n\tasync changePassword(_id: string, newPassword: string) {\n\t\tif (!this.has(_id))\n\t\t\tthrow new Error(\"usernotfound\");\n\t\t\n\t\tif (!newPassword)\n\t\t\tthrow new Error(\"emptypasswordisnotallowed\");\n\t\t\n\t\tawait Promise.all([\n\t\t\tthis.collection.updateOne({ _id }, { $set: { password: await argon2.hash(newPassword) } }),\n\t\t\tthis.sessions.collection.deleteMany({ user: _id })\n\t\t]);\n\t\t\n\t}\n\t\n\tasync login(email: string, password: string, sessionProps: Partial<SessionDoc>) {\n\t\tconst user = this.byEmail.get(email);\n\t\t\n\t\tif (!user)\n\t\t\tthrow new Error(\"usernotfound\");\n\t\t\n\t\tif (!await argon2.verify(user.password, password))\n\t\t\tthrow new Error(\"incorrectpassword\");\n\t\t\n\t\tif (!user.abilities.login)\n\t\t\tthrow new Error(\"userisnotabletologin\");\n\t\t\n\t\treturn this.sessions.new(user, sessionProps);\n\t}\n\t\n\tlogout(session: Session<AS>) {\n\t\tsession.delete();\n\t\t\n\t\treturn this.sessions.collection.deleteOne({ _id: session._id });\n\t}\n\t\n\tprivate sortUsersAndOrgs(a: Org<AS> | User<AS>, b: Org<AS> | User<AS>) {\n\t\treturn (\n\t\t\t(a instanceof User && b instanceof User) ?\n\t\t\t\t(a.name.last && b.name.last) ?\n\t\t\t\t\ta.name.last > b.name.last ?\n\t\t\t\t\t\t1 :\n\t\t\t\t\t\ta.name.last < b.name.last ? -1 : 0 :\n\t\t\t\t\t(!a.name.last && !b.name.last) ?\n\t\t\t\t\t\ta.displayLabel > b.displayLabel ?\n\t\t\t\t\t\t\t1 :\n\t\t\t\t\t\t\ta.displayLabel < b.displayLabel ? -1 : 0 :\n\t\t\t\t\t\ta.name.last ? -1 : 1 :\n\t\t\t\t(a instanceof Org && b instanceof Org) ?\n\t\t\t\t\ta.title > b.title ?\n\t\t\t\t\t\t1 :\n\t\t\t\t\t\ta.title < b.title ? -1 : 0 :\n\t\t\t\t\ta instanceof Org ? -1 : 1\n\t\t);\n\t}\n\t\n\tsortIds(ids: string[]) {\n\t\treturn _ids((\n\t\t\tids\n\t\t\t\t.map(_id => this.get(_id) || this.orgs.get(_id))\n\t\t\t\t.filter(Boolean) as (Org<AS> | User<AS>)[]\n\t\t).sort(this.sortUsersAndOrgs));\n\t}\n\t\n\treplaceMap = new Map<string, string>();\n\t\n\treplaceHandlers = new Set<(fromId: string, toId: null | string) => Promise<void> | void>();\n\t\n\tasync replace(fromId: string) {\n\t\tconst toId = this.replaceMap.get(fromId) ?? null;\n\t\tif (toId)\n\t\t\tthis.replaceMap.delete(fromId);\n\t\t\n\t\tfor (const handler of this.replaceHandlers)\n\t\t\tawait handler(fromId, toId);\n\t\t\n\t}\n\t\n\t\n\tstatic init<IAS extends AbilitiesSchema>(collections: InSiteCollections, options: Options<IAS>) {\n\t\tconst users = new Users(collections, options);\n\t\t\n\t\treturn users.whenReady();\n\t}\n\t\n}\n", "import { empty, intersection } from \"@nesvet/n\";\nimport type { AbilitiesSchema, AbilityParamItemSchema, AbilitySchema } from \"insite-common\";\nimport type { User } from \"../users/User\";\nimport type {\n\tAbility,\n\tAbilityParam,\n\tAbilityParamItems,\n\tAbilityParamNumber,\n\tAbilityWithParams,\n\tGenericAbilities\n} from \"./types\";\n\n\nfunction isAbilityWithParams(value: Ability): value is AbilityWithParams {\n\treturn typeof value == \"object\";\n}\n\nfunction isAbilityParamNumber(value: AbilityParam): value is AbilityParamNumber {\n\treturn typeof value === \"number\";\n}\n\nfunction isAbilityParamItems(value: AbilityParam): value is AbilityParamItems {\n\treturn Array.isArray(value);\n}\n\n\nexport class AbilitiesMap<AS extends AbilitiesSchema = AbilitiesSchema> extends Map<string, AbilitySchema> {\n\tconstructor(schema: AbilitiesSchema) {\n\t\tsuper();\n\t\t\n\t\tthis.schema = schema;\n\t\t\n\t\tthis.parse(this.schema);\n\t\t\n\t}\n\t\n\tschema;\n\t\n\tprivate parse(list: AbilitiesSchema) {\n\t\tfor (const ability of list) {\n\t\t\tthis.set(ability._id, ability);\n\t\t\tif (ability.subAbilities)\n\t\t\t\tthis.parse(ability.subAbilities);\n\t\t}\n\t\t\n\t}\n\t\n\tmerge(target: GenericAbilities, source: GenericAbilities) {\n\t\tfor (const [ abilityId, ability ] of Object.entries(source)) {\n\t\t\tconst schema = this.get(abilityId);\n\t\t\tif (schema) {\n\t\t\t\tif (schema.isInheritable !== false && ability)\n\t\t\t\t\tif (!(abilityId in target))\n\t\t\t\t\t\ttarget[abilityId] = structuredClone(ability);\n\t\t\t\t\telse if (schema.params) {\n\t\t\t\t\t\tconst targetAbility = target[abilityId] as AbilityWithParams;\n\t\t\t\t\t\tconst sourceAbility = ability as AbilityWithParams;\n\t\t\t\t\t\tfor (const param of schema.params)\n\t\t\t\t\t\t\tif (param.isInheritable !== false && param._id in sourceAbility)\n\t\t\t\t\t\t\t\tif (!(param._id in targetAbility))\n\t\t\t\t\t\t\t\t\ttargetAbility[param._id] = structuredClone(sourceAbility[param._id]);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tif (param.type === \"number\") {\n\t\t\t\t\t\t\t\t\t\tif ((targetAbility[param._id] as AbilityParamNumber) < (sourceAbility[param._id] as AbilityParamNumber))\n\t\t\t\t\t\t\t\t\t\t\ttargetAbility[param._id] = sourceAbility[param._id];\n\t\t\t\t\t\t\t\t\t} else if (param.type === \"items\") {\n\t\t\t\t\t\t\t\t\t\tconst targetItems = targetAbility[param._id] as AbilityParamItems;\n\t\t\t\t\t\t\t\t\t\tfor (const itemId of sourceAbility[param._id] as AbilityParamItems)\n\t\t\t\t\t\t\t\t\t\t\tif (!targetItems.includes(itemId))\n\t\t\t\t\t\t\t\t\t\t\t\ttargetItems.push(itemId);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t} else\n\t\t\t\tdelete source[abilityId];\n\t\t}\n\t\t\n\t\treturn target;\n\t}\n\t\n\tgetMinimumOf(_id: string) {\n\t\tconst schema = this.get(_id);\n\t\tif (schema?.params) {\n\t\t\tconst ability: Ability = {};\n\t\t\tfor (const param of schema.params)\n\t\t\t\tif (param.type === \"number\")\n\t\t\t\t\tability[param._id] = param.min ?? 0;\n\t\t\t\telse if (param.type === \"items\")\n\t\t\t\t\tability[param._id] = [];\n\t\t\t\n\t\t\treturn ability;\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n\t\n\tgetMaximum() {\n\t\treturn [ ...this.values() ].reduce((abilities: GenericAbilities, schema: AbilitySchema) => {\n\t\t\tif (schema.params) {\n\t\t\t\tconst ability: Ability = {};\n\t\t\t\tfor (const param of schema.params)\n\t\t\t\t\tif (param.type === \"number\")\n\t\t\t\t\t\tability[param._id] = param.max ?? 0;\n\t\t\t\t\telse if (param.type === \"items\")\n\t\t\t\t\t\tability[param._id] = param.items.map(item => item._id);\n\t\t\t\t\n\t\t\t\tabilities[schema._id] = ability;\n\t\t\t} else\n\t\t\t\tabilities[schema._id as keyof typeof abilities] = true;\n\t\t\t\n\t\t\treturn abilities;\n\t\t}, {});\n\t}\n\t\n\tgetSchemeFor(user: User<AS>) {\n\t\treturn (function resolve(abilitiesSchema: AbilitySchema[]) {\n\t\t\tfor (let i = 0; i < abilitiesSchema.length; i++) {\n\t\t\t\tconst schema = abilitiesSchema[i];\n\t\t\t\tconst userAbility = user.abilities[schema._id as keyof typeof user.abilities];\n\t\t\t\tif (userAbility) {\n\t\t\t\t\tif (schema.params)\n\t\t\t\t\t\tfor (const param of schema.params) {\n\t\t\t\t\t\t\tconst userParam = (userAbility as AbilityWithParams)[param._id];\n\t\t\t\t\t\t\tif (param.type === \"number\") {\n\t\t\t\t\t\t\t\tif (\"max\" in param)\n\t\t\t\t\t\t\t\t\tparam.max = userParam as number;\n\t\t\t\t\t\t\t} else if (param.type === \"items\")\n\t\t\t\t\t\t\t\tfor (let j = 0; j < param.items.length; j++)\n\t\t\t\t\t\t\t\t\tif (!(userParam as AbilityParamItems).includes(param.items[j]._id))\n\t\t\t\t\t\t\t\t\t\t(param.items as AbilityParamItemSchema[]).splice(j--, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\tif (schema.subAbilities)\n\t\t\t\t\t\tresolve(schema.subAbilities as AbilitySchema[]);\n\t\t\t\t} else\n\t\t\t\t\tabilitiesSchema.splice(i--, 1);\n\t\t\t}\n\t\t\t\n\t\t\treturn abilitiesSchema;\n\t\t})(structuredClone(this.schema) as AbilitySchema[]);\n\t}\n\t\n\tadjust(abilities: GenericAbilities) {\n\t\tconst adjustedAbilities: Record<string, unknown> = {};\n\t\tlet isAdjusted = false;\n\t\t\n\t\tfor (const [ _id, ability ] of Object.entries(abilities) as [ string, Ability ][]) {\n\t\t\tconst abilitySchema = this.get(_id);\n\t\t\tif (abilitySchema)\n\t\t\t\tif (abilitySchema.params) {\n\t\t\t\t\tconst adjustedAbility: AbilityWithParams = {};\n\t\t\t\t\t\n\t\t\t\t\tif (isAbilityWithParams(ability)) {\n\t\t\t\t\t\tfor (const paramSchema of abilitySchema.params)\n\t\t\t\t\t\t\tif (paramSchema._id in ability) {\n\t\t\t\t\t\t\t\tlet paramValue = ability[paramSchema._id];\n\t\t\t\t\t\t\t\tif (paramSchema.type === \"number\") {\n\t\t\t\t\t\t\t\t\tif (!isAbilityParamNumber(paramValue))\n\t\t\t\t\t\t\t\t\t\tparamValue = (paramSchema.min ?? 0) as AbilityParamNumber;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tconst adjustedParamValue =\n\t\t\t\t\t\t\t\t\t\tadjustedAbility[paramSchema._id] =\n\t\t\t\t\t\t\t\t\t\t\tMath.max(Math.min(paramValue, paramSchema.max ?? Infinity), paramSchema.min ?? 0);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif (paramValue !== adjustedParamValue)\n\t\t\t\t\t\t\t\t\t\tisAdjusted = true;\n\t\t\t\t\t\t\t\t} else if (paramSchema.type === \"items\") {\n\t\t\t\t\t\t\t\t\tif (!isAbilityParamItems(paramValue))\n\t\t\t\t\t\t\t\t\t\tparamValue = [] as AbilityParamItems;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tconst adjustedParamValue =\n\t\t\t\t\t\t\t\t\t\tadjustedAbility[paramSchema._id] =\n\t\t\t\t\t\t\t\t\t\t\tintersection(paramSchema.items.map(item => item._id), paramValue);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif (paramValue.length !== adjustedParamValue.length || paramValue.some(paramId => !adjustedParamValue.includes(paramId)))\n\t\t\t\t\t\t\t\t\t\tisAdjusted = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (const paramSchema of abilitySchema.params)\n\t\t\t\t\t\t\tif (paramSchema.type === \"number\")\n\t\t\t\t\t\t\t\tadjustedAbility[paramSchema._id] = paramSchema.min ?? 0;\n\t\t\t\t\t\t\telse if (paramSchema.type === \"items\")\n\t\t\t\t\t\t\t\tadjustedAbility[paramSchema._id] = [];\n\t\t\t\t\t\t\n\t\t\t\t\t\tisAdjusted = true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tadjustedAbilities[_id] = adjustedAbility;\n\t\t\t\t} else {\n\t\t\t\t\tadjustedAbilities[_id] = true;\n\t\t\t\t\t\n\t\t\t\t\tif (ability !== true)\n\t\t\t\t\t\tisAdjusted = true;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tisAdjusted = true;\n\t\t}\n\t\t\n\t\tif (isAdjusted) {\n\t\t\tObject.assign(empty(abilities), adjustedAbilities);\n\t\t\t\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n}\n", "import {\n\tdebounce,\n\tdeleteProps,\n\tEmptyArray,\n\tEmptySet,\n\tremoveAll,\n\tsort\n} from \"@nesvet/n\";\nimport type { AbilitiesSchema } from \"insite-common\";\nimport { InSiteCollectionIndexes, InSiteWatchedCollection, newObjectIdString } from \"insite-db\";\nimport { Users } from \"../users\";\nimport { Org } from \"./Org\";\nimport { basisSchema } from \"./schema\";\nimport { OrgDoc, OrgsOptions } from \"./types\";\n\n\nconst indexes: InSiteCollectionIndexes = [\n\t[ { owners: 1 } ]\n];\n\nfunction preventDirectDelete() {\n\tthrow new Error(\"Direct usage of orgs collection.deleteOne or .deleteMany is forbidden. Use orgs.collectionDelete instead.\");\n}\n\n\nexport class Orgs<AS extends AbilitiesSchema = AbilitiesSchema> extends Map<string, Org<AS>> {\n\tconstructor(users: Users<AS>, options: OrgsOptions = {}) {\n\t\tsuper();\n\t\t\n\t\tthis.users = users;\n\t\tthis.collections = users.collections;\n\t\t\n\t\tthis.preinitOptions = options;\n\t\t\n\t}\n\t\n\tusers;\n\tcollections;\n\tpreinitOptions?;\n\t\n\tcollection!: {\n\t\t/** @deprecated Direct usage of roles collection.deleteOne is forbidden. Use orgs.collectionDelete instead. */\n\t\tdeleteOne: typeof preventDirectDelete;\n\t\t\n\t\t/** @deprecated Direct usage of roles collection.deleteMany is forbidden. Use orgs.collectionDelete instead. */\n\t\tdeleteMany: typeof preventDirectDelete;\n\t} & InSiteWatchedCollection<OrgDoc>;\n\t\n\tnull!: { _id: null } & Org<AS>;\n\t\n\tload(orgDoc: OrgDoc) {\n\t\tnew Org<AS>(this, orgDoc);\n\t\t\n\t}\n\t\n\tprivate resolve(org: Org<AS>, slaveOrgs: Org<AS>[]) {\n\t\tslaveOrgs = [ org, ...slaveOrgs ];\n\t\t\n\t\tfor (const ownerOrg of org.ownerOrgs) {\n\t\t\tthis.resolve(ownerOrg, slaveOrgs);\n\t\t\tfor (const slaveOrg of slaveOrgs)\n\t\t\t\townerOrg.slaveOrgs.add(slaveOrg);\n\t\t}\n\t\t\n\t}\n\t\n\tsorted: Org<AS>[] = [];\n\t\n\tupdate() {\n\t\t\n\t\tconst array = [ ...this.values() ];\n\t\tconst sorted = [];\n\t\t\n\t\tfor (const org of array) {\n\t\t\torg.ownerOrgs.clear();\n\t\t\torg.ownerUsers.clear();\n\t\t\torg.slaveOrgs.clear();\n\t\t\t\n\t\t\tfor (const ownerId of org.ownerIds) {\n\t\t\t\tconst ownerOrg = this.get(ownerId);\n\t\t\t\tif (ownerOrg)\n\t\t\t\t\torg.ownerOrgs.add(ownerOrg);\n\t\t\t\telse {\n\t\t\t\t\tconst ownerUser = this.users.get(ownerId);\n\t\t\t\t\tif (ownerUser)\n\t\t\t\t\t\torg.ownerUsers.add(ownerUser);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (!org.ownerOrgs.size && org._id)\n\t\t\t\tsorted.push(org);\n\t\t}\n\t\t\n\t\tfor (const org of array)\n\t\t\tif (!array.some(anotherOrg => anotherOrg.ownerOrgs.has(org)))\n\t\t\t\tthis.resolve(org, []);\n\t\t\n\t\tsorted.sort(this.sortOrgs);\n\t\tfor (const org of array)\n\t\t\tsort(org.slaveOrgs, this.sortOrgs);\n\t\t\n\t\tfor (let i = 0; i < sorted.length; i++) {\n\t\t\tconst org = sorted[i];\n\t\t\tfor (const slaveOrg of [ ...org.slaveOrgs ].reverse())\n\t\t\t\tif (slaveOrg.ownerOrgs.has(org)) {\n\t\t\t\t\tconst slaveOrgIndex = sorted.indexOf(slaveOrg);\n\t\t\t\t\tif (~slaveOrgIndex) {\n\t\t\t\t\t\tsorted.splice(slaveOrgIndex, 1);\n\t\t\t\t\t\ti--;\n\t\t\t\t\t}\n\t\t\t\t\tsorted.splice(i + 1, 0, slaveOrg);\n\t\t\t\t}\n\t\t}\n\t\tfor (let { length } = sorted, o = 0; o < length;)\n\t\t\tsorted[o]._o = o++;\n\t\t\n\t\tthis.sorted = sorted;\n\t\t\n\t\tthis.users.emit(\"orgs-update\");\n\t\t\n\t\tif (this.users.isInited) {\n\t\t\tthis.users.updateDebounced.clear();\n\t\t\tthis.users.update();\n\t\t}\n\t\t\n\t}\n\t\n\tprivate sortOrgs(a: Org<AS>, b: Org<AS>) {\n\t\treturn (\n\t\t\t(b.slaveOrgs.size - a.slaveOrgs.size) || (\n\t\t\t\ta.title > b.title ?\n\t\t\t\t\t1 :\n\t\t\t\t\ta.title < b.title ?\n\t\t\t\t\t\t-1 :\n\t\t\t\t\t\t0\n\t\t\t)\n\t\t);\n\t}\n\t\n\tupdateDebounced = debounce(this.update, 250);\n\t\n\tpreinit? = async () => {\n\t\t\n\t\tconst {\n\t\t\tschema: customSchema,\n\t\t\tindexes: customIndexes,\n\t\t\tnull: nullProps\n\t\t} = this.preinitOptions!;\n\t\t\n\t\tif (customSchema) {\n\t\t\tif (customSchema.required)\n\t\t\t\tremoveAll(customSchema.required as string [], basisSchema.required as string[]);\n\t\t\tif (customSchema.properties)\n\t\t\t\tdeleteProps(customSchema, Object.keys(basisSchema.properties!));\n\t\t}\n\t\t\n\t\tconst jsonSchema = {\n\t\t\t...basisSchema,\n\t\t\t...customSchema,\n\t\t\trequired: [ ...basisSchema.required as string[], ...customSchema?.required as string[] ?? [] ],\n\t\t\tproperties: { ...basisSchema.properties, ...customSchema?.properties }\n\t\t};\n\t\t\n\t\tthis.collection = Object.assign(\n\t\t\tawait this.collections.ensure<OrgDoc>(\"orgs\", { jsonSchema }),\n\t\t\t{\n\t\t\t\tdeleteOne: preventDirectDelete,\n\t\t\t\tdeleteMany: preventDirectDelete\n\t\t\t}\n\t\t);\n\t\t\n\t\tthis.collection.ensureIndexes([ ...indexes, ...customIndexes ?? [] ]);\n\t\t\n\t\tthis.null = Object.assign(\n\t\t\tnew Org<AS>(this, {\n\t\t\t\t...nullProps,\n\t\t\t\t_id: \"\",\n\t\t\t\ttitle: \"\",\n\t\t\t\tnote: \"\",\n\t\t\t\towners: [],\n\t\t\t\tcreatedAt: Date.now()\n\t\t\t}),\n\t\t\t{\n\t\t\t\t_id: null,\n\t\t\t\townerIds: new EmptyArray(),\n\t\t\t\townerOrgs: new EmptySet(),\n\t\t\t\townerUsers: new EmptySet(),\n\t\t\t\tslaveOrgs: new EmptySet()\n\t\t\t}\n\t\t);\n\t\t\n\t\tfor (const orgDoc of await this.collection.find().toArray())\n\t\t\tthis.load(orgDoc);\n\t\t\n\t\tdelete this.preinitOptions;\n\t\tdelete this.preinit;\n\t\t\n\t};\n\t\n\tinit? = async () => {\n\t\t\n\t\tawait this.update();\n\t\t\n\t\tthis.collection.changeListeners.add(next => {\n\t\t\tswitch (next.operationType) {\n\t\t\t\tcase \"insert\": {\n\t\t\t\t\tconst org = new Org<AS>(this, next.fullDocument);\n\t\t\t\t\tthis.users.emit(\"orgs-org-update\", org, next);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase \"replace\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.fullDocument, next);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"update\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.updateDescription.updatedFields!, next);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"delete\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.delete();\n\t\t\t\t\tthis.users.emit(\"orgs-org-update\", null, next);\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\tdelete this.init;\n\t\t\n\t};\n\t\n\tnew({ title, note, ...restProps }: Omit<OrgDoc, \"_id\" | \"createdAt\" | \"owners\">, ownerId: string) {\n\t\treturn this.collection.insertOne({\n\t\t\t_id: newObjectIdString(),\n\t\t\ttitle: title ?? \"\",\n\t\t\tnote: note ?? \"\",\n\t\t\towners: ownerId ? [ ownerId ] : [],\n\t\t\t...deleteProps(restProps, [ \"_id\", \"owners\" ]),\n\t\t\tcreatedAt: Date.now()\n\t\t});\n\t}\n\t\n\tcollectionDelete(org: Org<AS> | string) {\n\t\tconst _id = typeof org == \"string\" ? org : org._id;\n\t\t\n\t\treturn this.collection.bulkWrite([\n\t\t\t{ updateMany: { filter: { owners: _id }, update: { $pullAll: { owners: [ _id ] } } } },\n\t\t\t{ deleteOne: { filter: { _id } } }\n\t\t]);\n\t}\n\t\n\treplaceMap = new Map<string, string>();\n\t\n\treplaceHandlers = new Set<(fromId: string, toId: null | string) => Promise<void> | void>();\n\t\n\tasync replace(fromId: string) {\n\t\tconst toId = this.replaceMap.get(fromId) ?? null;\n\t\tif (toId)\n\t\t\tthis.replaceMap.delete(fromId);\n\t\t\n\t\tfor (const handler of this.replaceHandlers)\n\t\t\tawait handler(fromId, toId);\n\t\t\n\t}\n\t\n}\n", "import type { AbilitiesSchema } from \"insite-common\";\nimport type { ChangeStreamDocument } from \"insite-db\";\nimport { User } from \"../users/User\";\nimport type { Orgs } from \"./Orgs\";\nimport type { OrgDoc } from \"./types\";\n\nconst snapshots = new Map();\n\n\nexport class Org<AS extends AbilitiesSchema = AbilitiesSchema> {\n\tconstructor(orgs: Orgs<AS>, orgDoc: OrgDoc) {\n\t\tthis.orgs = orgs;\n\t\t\n\t\tthis._id = orgDoc._id;\n\t\torgs.set(this._id, this);\n\t\t\n\t\tthis.update(orgDoc);\n\t\t\n\t}\n\t\n\t_id;\n\ttitle = \"\";\n\tinitials = \"\";\n\tdisplayLabel = \"\";\n\t\n\t_o = 0;\n\t\n\torgs;\n\t\n\tisOrg = true;\n\t\n\townerOrgs = new Set<Org<AS>>();\n\townerUsers = new Set<User<AS>>();\n\t\n\tusers = new Set<User<AS>>();\n\t\n\tslaveOrgs = new Set<Org<AS>>();\n\t\n\townerIds: string[] = [];\n\t\n\tupdate({ _id, title, owners: ownerIds, ...restProps }: Partial<OrgDoc>, next?: ChangeStreamDocument<OrgDoc>) {\n\t\t\n\t\tObject.assign(this, restProps);\n\t\t\n\t\tif (title !== undefined) {\n\t\t\tthis.title = title;\n\t\t\tthis.initials = title?.[0]?.toUpperCase() ?? \"\";\n\t\t\tthis.displayLabel = title;\n\t\t}\n\t\t\n\t\tif (ownerIds) {\n\t\t\tthis.ownerIds = ownerIds;\n\t\t\t\n\t\t\t\n\t\t\tconst snapshot = this.ownerIds.join(\",\");\n\t\t\t\n\t\t\tif (snapshot !== snapshots.get(this._id)) {\n\t\t\t\tsnapshots.set(this._id, snapshot);\n\t\t\t\t\n\t\t\t\tif (this.orgs.users.isInited)\n\t\t\t\t\tthis.orgs.updateDebounced();\n\t\t\t\t\n\t\t\t\tthis.orgs.users.emit(\"orgs-org-update\", this, next);\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\tdelete() {\n\t\t\n\t\tthis.orgs.delete(this._id);\n\t\t\n\t\tsnapshots.delete(this._id);\n\t\t\n\t\tthis.orgs.replace(this._id);\n\t\t\n\t\tthis.orgs.updateDebounced();\n\t\t\n\t}\n\t\n}\n", "export const regexps = {\n\t_id: /^[\\dA-Fa-f]{24}$/,\n\temail: /^[^\\s@]{1,63}@[^\\s@]{1,63}\\.[^\\s@]{1,63}$/,\n\targon2: /^\\$argon2(?:i|d|id)\\$v=\\d+\\$m=\\d+,t=\\d+,p=\\d+(?:\\$[\\d+/A-Za-z]+){2}$/,\n\tsessionId: /^[\\dA-Fa-f]{16,32}\\$[\\dA-Fa-f]{16,32}$/,\n\trole: /^[\\d_a-z-]{1,64}$/,\n\tip: /^(?:\\d{1,3}\\.){3}\\d{1,3}$/\n};\n", "import { InSiteCollectionSchema } from \"insite-db\";\nimport { regexps } from \"../lib\";\n\n\nexport const basisSchema: InSiteCollectionSchema = {\n\trequired: [\n\t\t\"_id\",\n\t\t\"title\",\n\t\t\"note\",\n\t\t\"owners\",\n\t\t\"createdAt\"\n\t],\n\tproperties: {\n\t\t_id: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps._id.source\n\t\t},\n\t\ttitle: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 512\n\t\t},\n\t\tnote: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 131072\n\t\t},\n\t\towners: {\n\t\t\tbsonType: \"array\",\n\t\t\tuniqueItems: true,\n\t\t\titems: {\n\t\t\t\tbsonType: \"string\",\n\t\t\t\tpattern: regexps._id.source\n\t\t\t},\n\t\t\tadditionalItems: false\n\t\t},\n\t\tcreatedAt: {\n\t\t\tbsonType: \"number\"\n\t\t}\n\t},\n\tadditionalProperties: false\n};\n", "import {\n\tdebounce,\n\tdeleteProps,\n\tgetAll,\n\tintersection,\n\treAdd,\n\tremoveAll\n} from \"@nesvet/n\";\nimport type { AbilitiesSchema } from \"insite-common\";\nimport type { InSiteCollectionIndexes, InSiteWatchedCollection } from \"insite-db\";\nimport type { GenericAbilities } from \"../abilities/types\";\nimport type { Users } from \"../users\";\nimport { Role } from \"./Role\";\nimport { basisSchema } from \"./schema\";\nimport type { RoleDoc, RolesOptions } from \"./types\";\n\n\nconst indexes: InSiteCollectionIndexes = [\n\t[ { involves: 1 } ]\n];\n\nfunction preventDirectDelete() {\n\tthrow new Error(\"Direct usage of roles collection.deleteOne or .deleteMany is forbidden. Use roles.collectionDelete instead.\");\n}\n\n\nexport class Roles<AS extends AbilitiesSchema = AbilitiesSchema> extends Map<string, Role<AS>> {\n\tconstructor(users: Users<AS>, options: RolesOptions = {}) {\n\t\tsuper();\n\t\t\n\t\tconst {\n\t\t\troot: rootProps,\n\t\t\t...initOptions\n\t\t} = options;\n\t\t\n\t\tthis.users = users;\n\t\tthis.collections = users.collections;\n\t\tthis.abilitiesMap = users.abilitiesMap;\n\t\t\n\t\tthis.root = new Role<AS>(this, {\n\t\t\t...rootProps,\n\t\t\t_id: \"root\",\n\t\t\tinvolves: [],\n\t\t\tabilities: this.abilitiesMap.getMaximum(),\n\t\t\ttitle: \"Root\",\n\t\t\tdescription: \"Root\",\n\t\t\tcreatedAt: Date.now()\n\t\t});\n\t\t\n\t\tthis.initOptions = initOptions;\n\t\t\n\t}\n\t\n\tusers;\n\tcollections;\n\tcollection!: {\n\t\t/** @deprecated Direct usage of roles collection.deleteOne is forbidden. Use roles.collectionDelete instead. */\n\t\tdeleteOne: typeof preventDirectDelete;\n\t\t\n\t\t/** @deprecated Direct usage of roles collection.deleteMany is forbidden. Use roles.collectionDelete instead. */\n\t\tdeleteMany: typeof preventDirectDelete;\n\t} & InSiteWatchedCollection<RoleDoc>;\n\t\n\tabilitiesMap;\n\troot;\n\tinitOptions?;\n\t\n\tload(roleDoc: RoleDoc) {\n\t\tnew Role<AS>(this, roleDoc);\n\t\t\n\t}\n\t\n\tresolve(role: Role<AS>, involvedBy: Role<AS>[]) {\n\t\tinvolvedBy = [ role, ...involvedBy ];\n\t\t\n\t\tfor (const involvedRoleId of role.ownInvolveIds) {\n\t\t\tconst involvedRole = this.get(involvedRoleId);\n\t\t\tif (involvedRole) {\n\t\t\t\tfor (const involvedByRole of involvedBy) {\n\t\t\t\t\treAdd(involvedByRole.involves, involvedRole);\n\t\t\t\t\tthis.abilitiesMap.merge(involvedByRole.inheritedAbilities as GenericAbilities, involvedRole.abilities as GenericAbilities);\n\t\t\t\t}\n\t\t\t\tif (involvedRole !== role)\n\t\t\t\t\tthis.resolve(involvedRole, involvedBy);\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\tsorted: Role<AS>[] = [];\n\t\n\tprivate sortRoles(a: Role<AS>, b: Role<AS>) {\n\t\treturn (\n\t\t\t(b.involves.size - a.involves.size) || (\n\t\t\t\t(a.title && b.title) ?\n\t\t\t\t\ta.title > b.title ? 1 : a.title < b.title ? -1 : 0 :\n\t\t\t\t\ta.title ?\n\t\t\t\t\t\t-1 :\n\t\t\t\t\t\tb.title ?\n\t\t\t\t\t\t\t1 :\n\t\t\t\t\t\t\ta._id > b._id ?\n\t\t\t\t\t\t\t\t1 :\n\t\t\t\t\t\t\t\ta._id < b._id ?\n\t\t\t\t\t\t\t\t\t-1 :\n\t\t\t\t\t\t\t\t\t0\n\t\t\t\t\n\t\t\t)\n\t\t);\n\t}\n\t\n\tupdate() {\n\t\t\n\t\tconst array = [ ...this.values() ];\n\t\t\n\t\tthis.root.ownInvolveIds = [];\n\t\tfor (const role of array) {\n\t\t\tif (role !== this.root && !array.some(anotherRole => anotherRole.ownInvolveIds.includes(role._id)))\n\t\t\t\tthis.root.ownInvolveIds.push(role._id);\n\t\t\trole.involves.clear();\n\t\t\trole.abilities = structuredClone(role.ownAbilities);\n\t\t\trole.inheritedAbilities = {};\n\t\t}\n\t\t\n\t\tthis.root.involves.add(this.root);\n\t\tthis.resolve(this.root, []);\n\t\t\n\t\tfor (const role of array)\n\t\t\trole.ownInvolves = getAll(this, role.ownInvolveIds, true).sort(this.sortRoles).reverse();\n\t\t\n\t\tconst sorted = [ this.root ];\n\t\t\n\t\tfor (let i = 0; i < sorted.length; i++) {\n\t\t\tconst role = sorted[i];\n\t\t\tfor (const involvedRole of role.ownInvolves) {\n\t\t\t\tconst involvedRoleIndex = sorted.indexOf(involvedRole);\n\t\t\t\tif (~involvedRoleIndex) {\n\t\t\t\t\tsorted.splice(involvedRoleIndex, 1);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t\tsorted.splice(i + 1, 0, involvedRole);\n\t\t\t}\n\t\t}\n\t\t\n\t\tlet _o = 0;\n\t\tfor (const role of sorted) {\n\t\t\tthis.abilitiesMap.merge(role.abilities as GenericAbilities, role.inheritedAbilities as GenericAbilities);\n\t\t\trole._o = _o++;\n\t\t}\n\t\t\n\t\tthis.sorted = sorted;\n\t\t\n\t\tthis.users.emit(\"roles-update\");\n\t\t\n\t\tif (this.users.isInited) {\n\t\t\tthis.users.updateDebounced.clear();\n\t\t\tthis.users.update(true);\n\t\t}\n\t\t\n\t}\n\t\n\tupdateDebounced = debounce(this.update, 250);\n\t\n\tinit? = async () => {\n\t\t\n\t\tconst {\n\t\t\tschema: customSchema,\n\t\t\tindexes: customIndexes\n\t\t} = this.initOptions!;\n\t\t\n\t\tif (customSchema) {\n\t\t\tif (customSchema.required)\n\t\t\t\tremoveAll(customSchema.required as string[], basisSchema.required as string[]);\n\t\t\tif (customSchema.properties)\n\t\t\t\tdeleteProps(customSchema, Object.keys(basisSchema.properties!));\n\t\t}\n\t\t\n\t\tconst jsonSchema = {\n\t\t\t...basisSchema,\n\t\t\t...customSchema,\n\t\t\trequired: [ ...basisSchema.required as string[], ...customSchema?.required as string[] ?? [] ],\n\t\t\tproperties: { ...basisSchema.properties, ...customSchema?.properties }\n\t\t};\n\t\t\n\t\tthis.collection = Object.assign(\n\t\t\tawait this.collections.ensure<RoleDoc>(\"roles\", { jsonSchema }),\n\t\t\t{\n\t\t\t\tdeleteOne: preventDirectDelete,\n\t\t\t\tdeleteMany: preventDirectDelete\n\t\t\t}\n\t\t);\n\t\t\n\t\tthis.collection.ensureIndexes([ ...indexes, ...customIndexes ?? [] ]);\n\t\t\n\t\tfor (const roleDoc of await this.collection.find().toArray()) {\n\t\t\tif (this.abilitiesMap.adjust(roleDoc.abilities))\n\t\t\t\tawait this.collection.updateOne({ _id: roleDoc._id }, { $set: { abilities: roleDoc.abilities } });\n\t\t\t\n\t\t\tthis.load(roleDoc);\n\t\t}\n\t\t\n\t\tthis.update();\n\t\t\n\t\tthis.collection.changeListeners.add(next => {\n\t\t\tswitch (next.operationType) {\n\t\t\t\tcase \"insert\": {\n\t\t\t\t\tconst role = new Role<AS>(this, next.fullDocument);\n\t\t\t\t\tthis.users.emit(\"roles-role-update\", role, next);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase \"replace\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.fullDocument, next);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"update\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.updateDescription.updatedFields!, next);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"delete\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.delete();\n\t\t\t\t\tthis.users.emit(\"roles-role-update\", null, next);\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\tdelete this.initOptions;\n\t\tdelete this.init;\n\t\t\n\t};\n\t\n\tnew({ _id, involves, title, description, ...restProps }: Omit<RoleDoc, \"abilities\" | \"createdAt\">) {\n\t\treturn this.collection.insertOne({\n\t\t\t_id,\n\t\t\tinvolves: involves || [],\n\t\t\tabilities: {},\n\t\t\ttitle: title ?? \"\",\n\t\t\tdescription: description ?? \"\",\n\t\t\t...deleteProps(restProps, [ \"abilities\" ]),\n\t\t\tcreatedAt: Date.now()\n\t\t});\n\t}\n\t\n\tcollectionDelete(role: Role<AS> | string) {\n\t\tconst _id = typeof role == \"string\" ? role : role._id;\n\t\t\n\t\treturn this.collection.bulkWrite([\n\t\t\t{ updateMany: { filter: { involves: _id }, update: { $pullAll: { involves: [ _id ] } } } },\n\t\t\t{ deleteOne: { filter: { _id } } }\n\t\t]);\n\t}\n\t\n\tcleanUpIds(ids: string[]) {\n\t\tconst roles = intersection(this.sorted, getAll(this, ids, true));\n\t\t\n\t\tconst cleanedUpIds = [];\n\t\t\n\t\tfor (const role of roles)\n\t\t\tif (roles.every(anotherRole => anotherRole === role || !anotherRole.involves.has(role)))\n\t\t\t\tcleanedUpIds.push(role._id);\n\t\t\n\t\treturn cleanedUpIds;\n\t}\n\t\n}\n", "import type { Abilities, AbilitiesSchema } from \"insite-common\";\nimport type { ChangeStreamDocument } from \"insite-db\";\nimport { Roles } from \"./Roles\";\nimport { RoleDoc } from \"./types\";\n\nconst snapshots = new Map();\n\n\nexport class Role<AS extends AbilitiesSchema = AbilitiesSchema> {\n\tconstructor(roles: Roles<AS>, roleDoc: RoleDoc) {\n\t\tthis.roles = roles;\n\t\t\n\t\tthis._id = roleDoc._id;\n\t\troles.set(this._id, this);\n\t\t\n\t\tthis.update(roleDoc);\n\t\t\n\t}\n\t\n\tprivate roles;\n\t\n\t_id;\n\townInvolveIds!: string[];\n\townAbilities!: Abilities<AS>;\n\ttitle = \"\";\n\tdisplayTitle = \"\";\n\t_o = 0;\n\t\n\townInvolves: Role<AS>[] = [];\n\tinvolves = new Set<Role<AS>>();\n\tabilities: Abilities<AS> = {};\n\tinheritedAbilities: Abilities<AS> = {};\n\t\n\tupdate({ _id, involves: ownInvolveIds, abilities: ownAbilities, title, ...restProps }: Partial<RoleDoc>, next?: ChangeStreamDocument<RoleDoc>) {\n\t\t\n\t\tObject.assign(this, restProps);\n\t\t\n\t\tif (ownInvolveIds)\n\t\t\tthis.ownInvolveIds = ownInvolveIds;\n\t\t\n\t\tif (ownAbilities)\n\t\t\tthis.ownAbilities = ownAbilities as Abilities<AS>;\n\t\t\n\t\tif (title !== undefined) {\n\t\t\tthis.title = title;\n\t\t\tthis.displayTitle = title || this._id;\n\t\t}\n\t\t\n\t\t\n\t\tif (ownInvolveIds || ownAbilities) {\n\t\t\tconst snapshot = [\n\t\t\t\tthis.ownInvolveIds.join(\",\"),\n\t\t\t\tJSON.stringify(this.ownAbilities)\n\t\t\t].join(\"\\n\");\n\t\t\t\n\t\t\tif (snapshot !== snapshots.get(this._id)) {\n\t\t\t\tsnapshots.set(this._id, snapshot);\n\t\t\t\t\n\t\t\t\tif (this.roles.users.isInited)\n\t\t\t\t\tthis.roles.updateDebounced();\n\t\t\t\t\n\t\t\t\tthis.roles.users.emit(\"roles-role-update\", this, next);\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\tdelete() {\n\t\t\n\t\tthis.roles.delete(this._id);\n\t\t\n\t\tsnapshots.delete(this._id);\n\t\t\n\t\tthis.roles.updateDebounced();\n\t\t\n\t}\n\t\n}\n", "import { InSiteCollectionSchema } from \"insite-db\";\nimport { regexps } from \"../lib\";\n\n\nexport const basisSchema: InSiteCollectionSchema = {\n\trequired: [\n\t\t\"_id\",\n\t\t\"involves\",\n\t\t\"abilities\",\n\t\t\"title\",\n\t\t\"description\",\n\t\t\"createdAt\"\n\t],\n\tproperties: {\n\t\t_id: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps.role.source,\n\t\t\tnot: { enum: [ \"root\" ] }\n\t\t},\n\t\tinvolves: {\n\t\t\tbsonType: \"array\",\n\t\t\tuniqueItems: true,\n\t\t\titems: {\n\t\t\t\tbsonType: \"string\",\n\t\t\t\tpattern: regexps.role.source,\n\t\t\t\tnot: { enum: [ \"root\" ] }\n\t\t\t},\n\t\t\tadditionalItems: false\n\t\t},\n\t\tabilities: {\n\t\t\tbsonType: \"object\"\n\t\t},\n\t\ttitle: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 256\n\t\t},\n\t\tdescription: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 10240\n\t\t},\n\t\tcreatedAt: {\n\t\t\tbsonType: \"number\"\n\t\t}\n\t},\n\tadditionalProperties: false\n};\n", "import crypto from \"node:crypto\";\nimport { deleteProps, random, removeAll } from \"@nesvet/n\";\nimport type { AbilitiesSchema } from \"insite-common\";\nimport { InSiteCollectionIndexes, InSiteWatchedCollection } from \"insite-db\";\nimport { User } from \"../users/User\";\nimport type { Users } from \"../users\";\nimport { basisSchema } from \"./schema\";\nimport { Session } from \"./Session\";\nimport { SessionDoc, SessionsOptions } from \"./types\";\n\n\nconst expireAfterSeconds = 3600 * 24 * 7;\n\nconst indexes: InSiteCollectionIndexes = [\n\t[ { user: 1 } ],\n\t[ { expiresAt: 1 }, { expireAfterSeconds } ]\n];\n\n\nexport class Sessions<AS extends AbilitiesSchema = AbilitiesSchema> extends Map<string, Session<AS>> {\n\tconstructor(users: Users<AS>, options: SessionsOptions = {}) {\n\t\tsuper();\n\t\t\n\t\tthis.users = users;\n\t\tthis.collections = users.collections;\n\t\t\n\t\tthis.initOptions = options;\n\t}\n\t\n\tusers;\n\tcollections;\n\t\n\tinitOptions?;\n\t\n\tcollection!: {\n\t\texpireAfterSeconds: number;\n\t} & InSiteWatchedCollection<SessionDoc>;\n\t\n\tisInited = false;\n\t\n\tuid() {\n\t\t\n\t\tlet _id;\n\t\tdo\n\t\t\t_id = `${crypto.randomBytes(random(8, 16)).toString(\"hex\")}$${crypto.randomBytes(random(8, 16)).toString(\"hex\")}`;\n\t\twhile (this.has(_id));\n\t\t\n\t\treturn _id;\n\t}\n\t\n\tload(sessionDoc: SessionDoc) {\n\t\tnew Session<AS>(this, sessionDoc);\n\t\t\n\t}\n\t\n\tinit? = async () => {\n\t\t\n\t\tconst {\n\t\t\tschema: customSchema,\n\t\t\tindexes: customIndexes\n\t\t} = this.initOptions!;\n\t\t\n\t\tif (customSchema) {\n\t\t\tif (customSchema.required)\n\t\t\t\tremoveAll(customSchema.required as string[], basisSchema.required as string[]);\n\t\t\tif (customSchema.properties)\n\t\t\t\tdeleteProps(customSchema, Object.keys(basisSchema.properties!));\n\t\t}\n\t\t\n\t\tconst jsonSchema = {\n\t\t\t...basisSchema,\n\t\t\t...customSchema,\n\t\t\trequired: [ ...basisSchema.required as string[], ...customSchema?.required as string[] ?? [] ],\n\t\t\tproperties: { ...basisSchema.properties, ...customSchema?.properties }\n\t\t};\n\t\t\n\t\tthis.collection = Object.assign(\n\t\t\tawait this.collections.ensure<SessionDoc>(\"sessions\", { jsonSchema }),\n\t\t\t{\n\t\t\t\texpireAfterSeconds\n\t\t\t}\n\t\t);\n\t\t\n\t\tthis.collection.ensureIndexes([ ...indexes, ...customIndexes ?? [] ]);\n\t\t\n\t\tawait this.collection.updateMany({ isOnline: true }, { $set: { isOnline: false } });\n\t\t\n\t\tfor (const sessionDoc of await this.collection.find().toArray())\n\t\t\tthis.load(sessionDoc);\n\t\t\n\t\tthis.collection.changeListeners.add(next => {\n\t\t\tswitch (next.operationType) {\n\t\t\t\tcase \"insert\":\n\t\t\t\t\tif (!this.has(next.documentKey._id))\n\t\t\t\t\t\tnew Session<AS>(this, next.fullDocument);\n\t\t\t\t\t\n\t\t\t\t\tthis.users.get(next.fullDocument.user)?.trimSessions();\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"replace\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.fullDocument);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"update\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.updateDescription.updatedFields!);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"delete\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.delete();\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\tthis.isInited = true;\n\t\t\n\t\tdelete this.initOptions;\n\t\tdelete this.init;\n\t\t\n\t};\n\t\n\tasync new(user: User<AS>, props: Partial<SessionDoc>) {\n\t\t\n\t\tconst ts = Date.now();\n\t\t\n\t\tconst sessionDoc: SessionDoc = {\n\t\t\tuserAgent: \"\",\n\t\t\tremoteAddress: \"127.0.0.1\",\n\t\t\tisOnline: true,\n\t\t\t...props,\n\t\t\t_id: this.uid(),\n\t\t\tuser: user._id,\n\t\t\tcreatedAt: ts,\n\t\t\tprolongedAt: ts,\n\t\t\texpiresAt: new Date(ts + (expireAfterSeconds * 1000))\n\t\t};\n\t\t\n\t\t/* new Session(\u2026) before await insertOne(\u2026) for avoid changeStream insert event to come earlier and create the session duplicate */\n\t\tconst session = new Session<AS>(this, sessionDoc);\n\t\t\n\t\tawait this.collection.insertOne(sessionDoc);\n\t\t\n\t\treturn session;\n\t}\n\t\n}\n", "import { InSiteCollectionSchema } from \"insite-db\";\nimport { regexps } from \"../lib\";\n\n\nexport const basisSchema: InSiteCollectionSchema = {\n\trequired: [\n\t\t\"_id\",\n\t\t\"user\",\n\t\t\"remoteAddress\",\n\t\t\"isOnline\",\n\t\t\"createdAt\",\n\t\t\"prolongedAt\",\n\t\t\"expiresAt\"\n\t],\n\tproperties: {\n\t\t_id: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps.sessionId.source\n\t\t},\n\t\tuser: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps._id.source\n\t\t},\n\t\tuserAgent: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 4096\n\t\t},\n\t\tremoteAddress: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps.ip.source\n\t\t},\n\t\tisOnline: {\n\t\t\tbsonType: \"bool\"\n\t\t},\n\t\tcreatedAt: {\n\t\t\tbsonType: \"number\"\n\t\t},\n\t\tprolongedAt: {\n\t\t\tbsonType: \"number\"\n\t\t},\n\t\texpiresAt: {\n\t\t\tbsonType: \"date\"\n\t\t}\n\t},\n\tadditionalProperties: false\n};\n", "import type { AbilitiesSchema } from \"insite-common\";\nimport type { User } from \"../users/User\";\nimport type { Sessions } from \"./Sessions\";\nimport type { SessionDoc } from \"./types\";\n\n\nexport class Session<AS extends AbilitiesSchema = AbilitiesSchema> {\n\tconstructor(sessions: Sessions<AS>, sessionDoc: SessionDoc) {\n\t\tconst user = sessions.users.get(sessionDoc.user);\n\t\t\n\t\tif (user) {\n\t\t\tthis.sessions = sessions;\n\t\t\t\n\t\t\tthis._id = sessionDoc._id;\n\t\t\tthis.sessions.set(this._id, this);\n\t\t\t\n\t\t\tthis.user = user;\n\t\t\tthis.user.sessions.add(this);\n\t\t\t\n\t\t\tthis.sessions.users.bySessionId.set(this._id, this.user);\n\t\t\t\n\t\t\tthis.update(sessionDoc);\n\t\t} else\n\t\t\tsessions.collection.deleteOne({ _id: sessionDoc._id });\n\t\t\n\t}\n\t\n\t_id!: string;\n\tuser!: User<AS>;\n\tisOnline = false;\n\t\n\tuserAgent!: string;\n\tremoteAddress!: string;\n\tcreatedAt!: number;\n\tprolongedAt!: number;\n\texpiresAt!: Date;\n\t\n\tprivate sessions!: Sessions<AS>;\n\t\n\tupdate({ _id, user, isOnline, ...restProps }: Partial<SessionDoc>) {\n\t\t\n\t\tif (isOnline !== undefined && this.isOnline !== isOnline) {\n\t\t\tthis.isOnline = isOnline;\n\t\t\t\n\t\t\tif (this.sessions.isInited && this.user.isOnline !== this.isOnline)\n\t\t\t\tthis.user.updateIsOnline();\n\t\t}\n\t\t\n\t\tObject.assign(this, restProps);\n\t\t\n\t}\n\t\n\tprolong({ _id, user, ...updates }: Partial<SessionDoc>) {\n\t\t\n\t\tconst ts = Date.now();\n\t\t\n\t\tupdates.prolongedAt = ts;\n\t\tupdates.expiresAt = new Date(ts + (this.sessions.collection.expireAfterSeconds * 1000));\n\t\t\n\t\tthis.update(updates);\n\t\t\n\t\treturn this.sessions.collection.updateOne({ _id: this._id }, { $set: updates });\n\t}\n\t\n\toffline() {\n\t\t\n\t\tconst updates = { isOnline: false };\n\t\t\n\t\tthis.update(updates);\n\t\t\n\t\treturn this.sessions.collection.updateOne({ _id: this._id }, { $set: updates });\n\t}\n\t\n\tdelete() {\n\t\t\n\t\tthis.sessions.delete(this._id);\n\t\tthis.user.sessions.delete(this);\n\t\tthis.sessions.users.bySessionId.delete(this._id);\n\t\t\n\t\tthis.sessions.users.emit(\"session-delete\", this);\n\t\t\n\t\tif (this.isOnline)\n\t\t\tthis.user.updateIsOnline();\n\t\t\n\t}\n\t\n}\n", "import { InSiteCollectionSchema } from \"insite-db\";\nimport { regexps } from \"../../lib\";\n\n\nexport const schema: InSiteCollectionSchema = {\n\trequired: [\n\t\t\"_id\",\n\t\t\"type\",\n\t\t\"size\",\n\t\t\"ts\",\n\t\t\"data\"\n\t],\n\tproperties: {\n\t\t_id: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps._id.source\n\t\t},\n\t\ttype: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 256\n\t\t},\n\t\tsize: {\n\t\t\tbsonType: \"number\"\n\t\t},\n\t\tts: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 10\n\t\t},\n\t\tdata: {\n\t\t\tbsonType: \"binData\"\n\t\t}\n\t},\n\tadditionalProperties: false\n};\n", "import type { AbilitiesSchema } from \"insite-common\";\nimport { InSiteWatchedCollection } from \"insite-db\";\nimport type { Users } from \"../Users\";\nimport { schema as jsonSchema } from \"./schema\";\nimport type { AvatarDoc } from \"./types\";\n// import { AvatarsOptions } from \"./types\";\n\n\nexport class Avatars<AS extends AbilitiesSchema = AbilitiesSchema> {\n\tconstructor(users: Users<AS>/* , options: AvatarsOptions = {} */) {\n\t\tthis.users = users;\n\t\tthis.collections = users.collections;\n\t\t\n\t}\n\t\n\tusers;\n\tcollections;\n\t\n\tcollection!: InSiteWatchedCollection<AvatarDoc>;\n\t\n\tinit? = async () => {\n\t\t\n\t\tthis.collection = await this.collections.ensure<AvatarDoc>(\"users.avatars\", { jsonSchema });\n\t\t\n\t\tdelete this.init;\n\t\t\n\t};\n\t\n}\n", "import { InSiteCollectionSchema } from \"insite-db\";\nimport { regexps } from \"../lib\";\n\n\nexport const basisSchema: InSiteCollectionSchema = {\n\trequired: [\n\t\t\"_id\",\n\t\t\"email\",\n\t\t\"password\",\n\t\t\"roles\",\n\t\t\"name\",\n\t\t\"org\",\n\t\t\"job\",\n\t\t\"createdAt\"\n\t],\n\tproperties: {\n\t\t_id: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps._id.source\n\t\t},\n\t\temail: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps.email.source\n\t\t},\n\t\tpassword: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps.argon2.source\n\t\t},\n\t\troles: {\n\t\t\tbsonType: \"array\",\n\t\t\tuniqueItems: true,\n\t\t\titems: {\n\t\t\t\tbsonType: \"string\",\n\t\t\t\tpattern: regexps.role.source\n\t\t\t},\n\t\t\tadditionalItems: false\n\t\t},\n\t\tname: {\n\t\t\tbsonType: \"object\",\n\t\t\trequired: [\n\t\t\t\t\"first\",\n\t\t\t\t\"middle\",\n\t\t\t\t\"last\"\n\t\t\t],\n\t\t\tproperties: {\n\t\t\t\tfirst: {\n\t\t\t\t\tbsonType: \"string\",\n\t\t\t\t\tmaxLength: 512\n\t\t\t\t},\n\t\t\t\tmiddle: {\n\t\t\t\t\tbsonType: \"string\",\n\t\t\t\t\tmaxLength: 512\n\t\t\t\t},\n\t\t\t\tlast: {\n\t\t\t\t\tbsonType: \"string\",\n\t\t\t\t\tmaxLength: 512\n\t\t\t\t}\n\t\t\t},\n\t\t\tadditionalProperties: false\n\t\t},\n\t\torg: {\n\t\t\toneOf: [\n\t\t\t\t{\n\t\t\t\t\tbsonType: \"string\",\n\t\t\t\t\tpattern: regexps._id.source\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbsonType: \"null\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tjob: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 512\n\t\t},\n\t\tavatar: {\n\t\t\toneOf: [\n\t\t\t\t{\n\t\t\t\t\tbsonType: \"string\",\n\t\t\t\t\tmaxLength: 10\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbsonType: \"null\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tcreatedAt: {\n\t\t\tbsonType: \"number\"\n\t\t}\n\t},\n\tadditionalProperties: false\n};\n", "import {\n\t_ids,\n\tdebounce,\n\tempty,\n\thasAny,\n\tremoveOne\n} from \"@nesvet/n\";\nimport type { Abilities, AbilitiesSchema } from \"insite-common\";\nimport type { GenericAbilities } from \"../abilities/types\";\nimport type { Org } from \"../orgs/Org\";\nimport type { Role } from \"../roles/Role\";\nimport type { Session } from \"../sessions/Session\";\nimport type { UserDoc } from \"./types\";\nimport type { Users } from \"./Users\";\n\n\nconst rolesSnapshots = new Map();\nconst permissionsSnapshots = new Map();\n\nconst staticUrl = process.env.INSITE_STATIC_URL ?? \"http://localhost:8080\";\n\n\nexport class User<AS extends AbilitiesSchema = AbilitiesSchema> {\n\tconstructor(users: Users<AS>, userDoc: UserDoc) {\n\t\tthis.users = users;\n\t\t\n\t\tthis._id = userDoc._id;\n\t\tusers.set(this._id, this);\n\t\t\n\t\tthis.update(userDoc);\n\t\t\n\t\tif (users.isInited)\n\t\t\tusers.emit(\"user-create\", this);\n\t\t\n\t}\n\t\n\t_id;\n\temail!: string;\n\tname = {\n\t\tfirst: \"\",\n\t\tmiddle: \"\",\n\t\tlast: \"\"\n\t};\n\t\n\tinitials = \"\";\n\tdisplayLabel = \"\";\n\torg!: Org<AS>;\n\tjob: string = \"\";\n\tavatar: null | string = null;\n\tavatarUrl: null | string = null;\n\t\n\tprivate users;\n\t\n\tisUser = true;\n\tisRoot?: boolean;\n\t\n\troles = new Set<Role<AS>>();\n\townRoles: Role<AS>[] = [];\n\townRoleIds: string[] = [];\n\tslaveRoles = new Set<Role<AS>>();\n\tslaveRoleIds: string[] = [];\n\tabilities: Abilities<AS> = {};\n\t\n\tslaveOrgs = new Set<Org<AS>>();\n\tslaveUsers = new Set<User<AS>>();\n\tslaves = new Set<Org<AS> | User<AS>>();\n\t\n\tslaveIds: string[] = [];\n\tpermissiveIds: string[] = [];\n\t\n\tsessions = new Set<Session<AS>>();\n\t\n\tisOnline = false;\n\t\n\tupdate({ _id, name, email, roles: ownRoleIds, org: orgId, avatar, ...restProps }: Partial<UserDoc>) {\n\t\t\n\t\tObject.assign(this, restProps);\n\t\t\n\t\tlet isEmailUpdated;\n\t\tif (email && this.email !== email) {\n\t\t\tthis.users.byEmail.delete(this.email);\n\t\t\tthis.email = email;\n\t\t\tthis.users.byEmail.set(email, this);\n\t\t\tisEmailUpdated = true;\n\t\t}\n\t\t\n\t\tlet isNameUpdated;\n\t\tlet isLastNameUpdated;\n\t\tif (name && (this.name.first !== name.first || this.name.middle !== name.middle || this.name.last !== name.last)) {\n\t\t\tisLastNameUpdated = this.name.last !== name.last;\n\t\t\tthis.name = {\n\t\t\t\tfirst: name.first ?? \"\",\n\t\t\t\tmiddle: name.middle ?? \"\",\n\t\t\t\tlast: name.last ?? \"\"\n\t\t\t};\n\t\t\tthis.initials = (((name.first?.[0] ?? \"\") + (name.last?.[0] ?? \"\")) || this.email[0]).toUpperCase();\n\t\t\tisNameUpdated = true;\n\t\t}\n\t\t\n\t\tif (isEmailUpdated || isNameUpdated)\n\t\t\tthis.displayLabel = `${this.name.first} ${this.name.last}`.trim() || this.name.middle || this.email;\n\t\t\n\t\tlet isRolesUpdated;\n\t\tif (ownRoleIds) {\n\t\t\tthis.ownRoleIds = ownRoleIds;\n\t\t\t\n\t\t\tconst snapshot = this.ownRoleIds.join(\",\");\n\t\t\t\n\t\t\tif (snapshot !== rolesSnapshots.get(this._id)) {\n\t\t\t\trolesSnapshots.set(this._id, snapshot);\n\t\t\t\tthis.updateRoles();\n\t\t\t\tisRolesUpdated = true;\n\t\t\t}\n\t\t}\n\t\t\n\t\tlet isOrgUpdated;\n\t\tif (orgId !== undefined && this.org?._id !== orgId) {\n\t\t\tthis.org?.users.delete(this);\n\t\t\tthis.org = orgId && this.users.orgs.get(orgId) || this.users.orgs.null;\n\t\t\tthis.org.users.add(this);\n\t\t\tisOrgUpdated = true;\n\t\t}\n\t\t\n\t\tif (avatar !== undefined && this.avatar !== avatar) {\n\t\t\tthis.avatar = avatar;\n\t\t\tthis.avatarUrl = avatar && `${staticUrl}/avatars/${this._id}-${avatar}.webp`;\n\t\t}\n\t\t\n\t\tif (isRolesUpdated || isOrgUpdated) {\n\t\t\tthis.updatePermissions();\n\t\t\t\n\t\t\tif (isLastNameUpdated)\n\t\t\t\tthis.users.isSortRequired = true;\n\t\t\t\n\t\t\tif (this.users.isInited)\n\t\t\t\tthis.users.updateDebounced();\n\t\t\t\n\t\t} else if (isLastNameUpdated)\n\t\t\tthis.users.sortDebounced();\n\t\t\n\t}\n\t\n\tupdateRoles() {\n\t\t\n\t\tif (this.users.isInited) {\n\t\t\tthis.ownRoles = [];\n\t\t\tthis.roles.clear();\n\t\t\tthis.slaveRoles.clear();\n\t\t\tempty(this.abilities);\n\t\t\t\n\t\t\tfor (const roleId of this.ownRoleIds) {\n\t\t\t\tconst role = this.users.roles.get(roleId);\n\t\t\t\tif (role) {\n\t\t\t\t\t\n\t\t\t\t\tthis.ownRoles.push(role);\n\t\t\t\t\tthis.roles.add(role);\n\t\t\t\t\tfor (const involvedRole of role.involves) {\n\t\t\t\t\t\tthis.roles.add(involvedRole);\n\t\t\t\t\t\tthis.slaveRoles.add(involvedRole);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tthis.slaveRoleIds = _ids(this.slaveRoles);\n\t\t\t\t\t\n\t\t\t\t\tthis.users.abilitiesMap.merge(this.abilities as GenericAbilities, role.abilities as GenericAbilities);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (this.roles.has(this.users.roles.root))\n\t\t\t\tthis.isRoot = true;\n\t\t\t\n\t\t\tthis.trimSessions();\n\t\t}\n\t\t\n\t}\n\t\n\tupdatePermissions() {\n\t\t\n\t\tif (this.users.isInited) {\n\t\t\tthis.slaveOrgs.clear();\n\t\t\tthis.slaveUsers.clear();\n\t\t\tthis.slaves.clear();\n\t\t\tconst slaveIds = new Set<string>();\n\t\t\t\n\t\t\tfor (const org of this.users.orgs.sorted)\n\t\t\t\tif ((org.ownerUsers.has(this) || this.isRoot) && !this.slaveOrgs.has(org)) {\n\t\t\t\t\tthis.slaveOrgs.add(org);\n\t\t\t\t\tthis.slaves.add(org);\n\t\t\t\t\tslaveIds.add(org._id);\n\t\t\t\t\tfor (const slaveOrg of org.slaveOrgs) {\n\t\t\t\t\t\tthis.slaveOrgs.add(slaveOrg);\n\t\t\t\t\t\tthis.slaves.add(slaveOrg);\n\t\t\t\t\t\tslaveIds.add(slaveOrg._id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\n\t\t\tfor (const org of new Set([ this.org, ...this.slaveOrgs, this.users.orgs.null ]))\n\t\t\t\tfor (const user of org.users)\n\t\t\t\t\tif (user !== this && (hasAny(this.slaveRoles, user.ownRoles) || !user.ownRoles.length)) {\n\t\t\t\t\t\tthis.slaveUsers.add(user);\n\t\t\t\t\t\tthis.slaves.add(user);\n\t\t\t\t\t\tslaveIds.add(user._id);\n\t\t\t\t\t}\n\t\t\t\n\t\t\tthis.slaveIds = [ ...slaveIds ];\n\t\t\t\n\t\t\tconst permissiveOrgIds = [];\n\t\t\tif (this.org._id) {\n\t\t\t\tpermissiveOrgIds.push(this.org._id);\n\t\t\t\tfor (const slaveOrg of this.org.slaveOrgs)\n\t\t\t\t\tif (!this.slaveOrgs.has(slaveOrg))\n\t\t\t\t\t\tpermissiveOrgIds.push(slaveOrg._id);\n\t\t\t}\n\t\t\t\n\t\t\tthis.permissiveIds = [ ...permissiveOrgIds, this._id, ...slaveIds ];\n\t\t\t\n\t\t\t\n\t\t\tconst snapshot = [\n\t\t\t\tthis.permissiveIds.join(\",\"),\n\t\t\t\tthis.ownRoleIds.join(\",\"),\n\t\t\t\tJSON.stringify(this.abilities),\n\t\t\t\tthis.slaveRoleIds.join(\",\")\n\t\t\t].join(\"\\n\");\n\t\t\t\n\t\t\tif (snapshot !== permissionsSnapshots.get(this._id)) {\n\t\t\t\tpermissionsSnapshots.set(this._id, snapshot);\n\t\t\t\t\n\t\t\t\tthis.users.emit(\"user-permissions-change\", this);\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\ttrimSessions() {\n\t\t\n\t\tconst sessionsLimit = this.abilities.login?.sessionsLimit ?? 0;\n\t\t\n\t\tif (this.sessions.size > sessionsLimit)\n\t\t\treturn this.users.sessions.collection.deleteMany({\n\t\t\t\t_id: {\n\t\t\t\t\t$in: _ids(\n\t\t\t\t\t\t[ ...this.sessions ]\n\t\t\t\t\t\t\t.sort((a, b) => a.expiresAt.valueOf() - b.expiresAt.valueOf())\n\t\t\t\t\t\t\t.slice(0, this.sessions.size - sessionsLimit)\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t});\n\t\t\n\t\treturn null;\n\t}\n\t\n\tupdateIsOnline = debounce(() => {\n\t\t\n\t\tlet isOnline = false;\n\t\t\n\t\tfor (const session of this.sessions)\n\t\t\tif (session.isOnline) {\n\t\t\t\tisOnline = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\n\t\tif (this.isOnline !== isOnline) {\n\t\t\tthis.isOnline = isOnline;\n\t\t\tthis.users.emit(\"user-is-online\", this);\n\t\t}\n\t\t\n\t}, 500);\n\t\n\tdelete() {\n\t\t\n\t\tthis.org.users.delete(this);\n\t\t\n\t\tthis.users.delete(this._id);\n\t\tthis.users.byEmail.delete(this.email);\n\t\tremoveOne(this.users.sorted, this);\n\t\t\n\t\trolesSnapshots.delete(this._id);\n\t\tpermissionsSnapshots.delete(this._id);\n\t\t\n\t\tthis.users.replace(this._id);\n\t\t\n\t\tthis.users.updateDebounced();\n\t\t\n\t}\n\t\n}\n"],
4
+ "sourcesContent": ["import * as argon2 from \"argon2\";\nimport EventEmitter from \"eventemitter3\";\nimport {\n\t_ids,\n\tdebounce,\n\tdeleteProps,\n\tremoveAll\n} from \"@nesvet/n\";\nimport type { AbilitiesSchema } from \"insite-common\";\nimport {\n\tInSiteCollectionIndexes,\n\tInSiteCollections,\n\tInSiteCollectionSchema,\n\tInSiteWatchedCollection,\n\tnewObjectIdString\n} from \"insite-db\";\nimport { AbilitiesMap } from \"../abilities\";\nimport { Orgs } from \"../orgs\";\nimport { Org } from \"../orgs/Org\";\nimport { Roles } from \"../roles\";\nimport { Sessions } from \"../sessions\";\nimport { Session } from \"../sessions/Session\";\nimport type { OrgsOptions } from \"../orgs/types\";\nimport type { RolesOptions } from \"../roles/types\";\nimport type { SessionDoc, SessionsOptions } from \"../sessions/types\";\nimport { Avatars/* , AvatarsOptions */ } from \"./avatars\";\nimport { basisSchema } from \"./schema\";\nimport { User } from \"./User\";\nimport type { UserDoc } from \"./types\";\n\n\nconst indexes: InSiteCollectionIndexes = [\n\t[ { email: 1 }, { unique: true } ],\n\t[ { org: 1 } ]\n];\n\n\nexport type Options<AS> = {\n\tabilities: AS;\n\tindexes?: InSiteCollectionIndexes;\n\tschema?: InSiteCollectionSchema;\n\tinitialRoot?: Partial<UserDoc>;\n\troles?: RolesOptions;\n\torgs?: OrgsOptions;\n\tsessions?: SessionsOptions;\n\t// avatars?: AvatarsOptions;\n};\n\n\nexport class Users<AS extends AbilitiesSchema = AbilitiesSchema> extends Map<string, User<AS>> {\n\tconstructor(collections: InSiteCollections, options: Options<AS>) {\n\t\tsuper();\n\t\t\n\t\tconst eventEmitter = new EventEmitter() as {\n\t\t\t_events: Record<string, object>;\n\t\t\t_eventsCount: number;\n\t\t} & EventEmitter;\n\t\tthis._events = eventEmitter._events;\n\t\tthis._eventsCount = eventEmitter._eventsCount;\n\t\tthis.emit = eventEmitter.emit;\n\t\tthis.on = eventEmitter.on;\n\t\tthis.once = eventEmitter.once;\n\t\tthis.addListener = eventEmitter.addListener;\n\t\tthis.off = eventEmitter.off;\n\t\tthis.removeListener = eventEmitter.removeListener;\n\t\t\n\t\tthis.collections = collections;\n\t\t\n\t\tthis.abilitiesMap = new AbilitiesMap<AS>(options.abilities);\n\t\t\n\t\tthis.initOptions = options;\n\t\t\n\t\tthis.initPromise = this.init!();\n\t\t\n\t}\n\t\n\t_events;\n\t_eventsCount;\n\temit;\n\ton;\n\tonce;\n\taddListener;\n\toff;\n\tremoveListener;\n\t\n\tprivate initOptions?;\n\t\n\tcollections;\n\tabilitiesMap;\n\t\n\tcollection!: InSiteWatchedCollection<UserDoc>;\n\troles!: Roles<AS>;\n\tsessions!: Sessions<AS>;\n\torgs!: Orgs<AS>;\n\tavatars!: Avatars<AS>;\n\t\n\tisInited = false;\n\t\n\tbyEmail = new Map();\n\tbySessionId = new Map();\n\tsorted: User<AS>[] = [];\n\t\n\tisSortRequired = false;\n\t\n\tload(userDoc: UserDoc) {\n\t\tnew User<AS>(this, userDoc);\n\t\t\n\t}\n\t\n\tsort() {\n\t\t\n\t\tthis.isSortRequired = false;\n\t\t\n\t\tthis.sorted = [ ...this.values() ].sort((a, b) => a.name.last > b.name.last ? 1 : a.name.last < b.name.last ? -1 : 0);\n\t\t\n\t}\n\t\n\tsortDebounced = debounce(() => this.sort(), 250);\n\t\n\tupdate(shouldUpdateRoles?: boolean) {\n\t\tif (shouldUpdateRoles)\n\t\t\tfor (const user of this.values())\n\t\t\t\tuser.updateRoles();\n\t\t\n\t\tfor (const user of this.values())\n\t\t\tuser.updatePermissions();\n\t\t\n\t\tif (this.isSortRequired)\n\t\t\tthis.sort();\n\t\t\n\t}\n\t\n\tupdateDebounced = debounce(() => this.update(), 250);\n\t\n\tpreinit? = async () => {\n\t\t\n\t\tconst {\n\t\t\tindexes: customIndexes,\n\t\t\tschema: customSchema,\n\t\t\tinitialRoot: initialRootProps\n\t\t\t// avatars: avatarsOptions\n\t\t} = this.initOptions!;\n\t\t\n\t\tif (customSchema) {\n\t\t\tif (customSchema.required)\n\t\t\t\tremoveAll(customSchema.required as string[], basisSchema.required as string[]);\n\t\t\tif (customSchema.properties)\n\t\t\t\tdeleteProps(customSchema, Object.keys(basisSchema.properties!));\n\t\t}\n\t\t\n\t\tconst jsonSchema = {\n\t\t\t...basisSchema,\n\t\t\t...customSchema,\n\t\t\trequired: [ ...basisSchema.required as string [], ...customSchema?.required as string[] ?? [] ],\n\t\t\tproperties: { ...basisSchema.properties, ...customSchema?.properties }\n\t\t};\n\t\t\n\t\tthis.collection = await this.collections.ensure<UserDoc>(\"users\", { jsonSchema });\n\t\t\n\t\tthis.collection.ensureIndexes([ ...indexes, ...customIndexes ?? [] ]);\n\t\t\n\t\tif (!await this.collection.countDocuments({ roles: \"root\" }))\n\t\t\tawait this.new({\n\t\t\t\temail: process.env.INSITE_ROOT_EMAIL ?? \"insite@root.email\",\n\t\t\t\tpassword: process.env.INSITE_ROOT_PASSWORD ?? \"inSiteRootPassword\",\n\t\t\t\troles: [ \"root\" ],\n\t\t\t\tname: { first: \"Root\" },\n\t\t\t\torg: null,\n\t\t\t\tjob: \"Root\",\n\t\t\t\t...initialRootProps && deleteProps(initialRootProps, [ \"roles\", \"org\" ])\n\t\t\t});\n\t\t\n\t\t\n\t\tfor (const userDoc of await this.collection.find().toArray())\n\t\t\tthis.load(userDoc);\n\t\t\n\t\tdelete this.preinit;\n\t\t\n\t};\n\t\n\tprivate initPromise;\n\t\n\tprivate init? = async () => {\n\t\t\n\t\tconst {\n\t\t\troles: rolesOptions,\n\t\t\torgs: orgsOptions,\n\t\t\tsessions: sessionsOptions\n\t\t// avatars: avatarsOptions\n\t\t} = this.initOptions!;\n\t\t\n\t\tthis.roles = new Roles<AS>(this, rolesOptions);\n\t\tthis.orgs = new Orgs<AS>(this, orgsOptions);\n\t\tthis.sessions = new Sessions<AS>(this, sessionsOptions);\n\t\tthis.avatars = new Avatars<AS>(this/* , avatarsOptions */);\n\t\t\n\t\tawait this.roles.init!();\n\t\tawait this.orgs.preinit!();\n\t\tawait this.preinit!();\n\t\tawait this.orgs.init!();\n\t\tawait this.avatars.init!();\n\t\t\n\t\tthis.isInited = true;\n\t\t\n\t\tthis.update(true);\n\t\t\n\t\tthis.collection.changeListeners.add(next => {\n\t\t\tswitch (next.operationType) {\n\t\t\t\tcase \"insert\":\n\t\t\t\t\tnew User<AS>(this, next.fullDocument);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"replace\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.fullDocument);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"update\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.updateDescription.updatedFields!);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"delete\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.delete();\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\tawait this.sessions.init!();\n\t\t\n\t\tdelete this.initOptions;\n\t\tdelete this.init;\n\t\t\n\t\treturn this;\n\t};\n\t\n\twhenReady() {\n\t\treturn this.initPromise;\n\t}\n\t\n\tasync new({ email, password, roles, name, org, job, ...restProps }: Omit<UserDoc, \"_id\" | \"createdAt\">) {\n\t\tif (this.byEmail.has(email))\n\t\t\tthrow new Error(\"User exists\");\n\t\t\n\t\tawait this.collection.insertOne({\n\t\t\t_id: newObjectIdString(),\n\t\t\temail,\n\t\t\tpassword: await argon2.hash(password),\n\t\t\troles: this.isInited ? this.roles.cleanUpIds(roles) : roles,\n\t\t\tname: {\n\t\t\t\tfirst: name.first ?? \"\",\n\t\t\t\tmiddle: name.middle ?? \"\",\n\t\t\t\tlast: name.last ?? \"\"\n\t\t\t},\n\t\t\torg: org ?? null,\n\t\t\tjob: job ?? \"\",\n\t\t\t...deleteProps(restProps, [ \"_id\" ]),\n\t\t\tcreatedAt: Date.now()\n\t\t});\n\t\t\n\t\treturn true;\n\t}\n\t\n\tasync changePassword(_id: string, newPassword: string) {\n\t\tif (!this.has(_id))\n\t\t\tthrow new Error(\"usernotfound\");\n\t\t\n\t\tif (!newPassword)\n\t\t\tthrow new Error(\"emptypasswordisnotallowed\");\n\t\t\n\t\tawait Promise.all([\n\t\t\tthis.collection.updateOne({ _id }, { $set: { password: await argon2.hash(newPassword) } }),\n\t\t\tthis.sessions.collection.deleteMany({ user: _id })\n\t\t]);\n\t\t\n\t}\n\t\n\tasync login(email: string, password: string, sessionProps: Partial<SessionDoc>) {\n\t\tconst user = this.byEmail.get(email);\n\t\t\n\t\tif (!user)\n\t\t\tthrow new Error(\"usernotfound\");\n\t\t\n\t\tif (!await argon2.verify(user.password, password))\n\t\t\tthrow new Error(\"incorrectpassword\");\n\t\t\n\t\tif (!user.abilities.login)\n\t\t\tthrow new Error(\"userisnotabletologin\");\n\t\t\n\t\treturn this.sessions.new(user, sessionProps);\n\t}\n\t\n\tlogout(session: Session<AS>) {\n\t\tsession.delete();\n\t\t\n\t\treturn this.sessions.collection.deleteOne({ _id: session._id });\n\t}\n\t\n\tprivate sortUsersAndOrgs(a: Org<AS> | User<AS>, b: Org<AS> | User<AS>) {\n\t\treturn (\n\t\t\t(a instanceof User && b instanceof User) ?\n\t\t\t\t(a.name.last && b.name.last) ?\n\t\t\t\t\ta.name.last > b.name.last ?\n\t\t\t\t\t\t1 :\n\t\t\t\t\t\ta.name.last < b.name.last ? -1 : 0 :\n\t\t\t\t\t(!a.name.last && !b.name.last) ?\n\t\t\t\t\t\ta.displayLabel > b.displayLabel ?\n\t\t\t\t\t\t\t1 :\n\t\t\t\t\t\t\ta.displayLabel < b.displayLabel ? -1 : 0 :\n\t\t\t\t\t\ta.name.last ? -1 : 1 :\n\t\t\t\t(a instanceof Org && b instanceof Org) ?\n\t\t\t\t\ta.title > b.title ?\n\t\t\t\t\t\t1 :\n\t\t\t\t\t\ta.title < b.title ? -1 : 0 :\n\t\t\t\t\ta instanceof Org ? -1 : 1\n\t\t);\n\t}\n\t\n\tsortIds(ids: string[]) {\n\t\treturn _ids((\n\t\t\tids\n\t\t\t\t.map(_id => this.get(_id) || this.orgs.get(_id))\n\t\t\t\t.filter(Boolean) as (Org<AS> | User<AS>)[]\n\t\t).sort(this.sortUsersAndOrgs));\n\t}\n\t\n\treplaceMap = new Map<string, string>();\n\t\n\treplaceHandlers = new Set<(fromId: string, toId: null | string) => Promise<void> | void>();\n\t\n\tasync replace(fromId: string) {\n\t\tconst toId = this.replaceMap.get(fromId) ?? null;\n\t\tif (toId)\n\t\t\tthis.replaceMap.delete(fromId);\n\t\t\n\t\tfor (const handler of this.replaceHandlers)\n\t\t\tawait handler(fromId, toId);\n\t\t\n\t}\n\t\n\t\n\tstatic init<IAS extends AbilitiesSchema>(collections: InSiteCollections, options: Options<IAS>) {\n\t\tconst users = new Users(collections, options);\n\t\t\n\t\treturn users.whenReady();\n\t}\n\t\n}\n", "import { empty, intersection } from \"@nesvet/n\";\nimport type { AbilitiesSchema, AbilityParamItemSchema, AbilitySchema } from \"insite-common\";\nimport type { User } from \"../users/User\";\nimport type {\n\tAbility,\n\tAbilityParam,\n\tAbilityParamItems,\n\tAbilityParamNumber,\n\tAbilityWithParams,\n\tGenericAbilities\n} from \"./types\";\n\n\nfunction isAbilityWithParams(value: Ability): value is AbilityWithParams {\n\treturn typeof value == \"object\";\n}\n\nfunction isAbilityParamNumber(value: AbilityParam): value is AbilityParamNumber {\n\treturn typeof value === \"number\";\n}\n\nfunction isAbilityParamItems(value: AbilityParam): value is AbilityParamItems {\n\treturn Array.isArray(value);\n}\n\n\nexport class AbilitiesMap<AS extends AbilitiesSchema = AbilitiesSchema> extends Map<string, AbilitySchema> {\n\tconstructor(schema: AbilitiesSchema) {\n\t\tsuper();\n\t\t\n\t\tthis.schema = schema;\n\t\t\n\t\tthis.parse(this.schema);\n\t\t\n\t}\n\t\n\tschema;\n\t\n\tprivate parse(list: AbilitiesSchema) {\n\t\tfor (const ability of list) {\n\t\t\tthis.set(ability._id, ability);\n\t\t\tif (ability.subAbilities)\n\t\t\t\tthis.parse(ability.subAbilities);\n\t\t}\n\t\t\n\t}\n\t\n\tmerge(target: GenericAbilities, source: GenericAbilities) {\n\t\tfor (const [ abilityId, ability ] of Object.entries(source)) {\n\t\t\tconst schema = this.get(abilityId);\n\t\t\tif (schema) {\n\t\t\t\tif (schema.isInheritable !== false && ability)\n\t\t\t\t\tif (!(abilityId in target))\n\t\t\t\t\t\ttarget[abilityId] = structuredClone(ability);\n\t\t\t\t\telse if (schema.params) {\n\t\t\t\t\t\tconst targetAbility = target[abilityId] as AbilityWithParams;\n\t\t\t\t\t\tconst sourceAbility = ability as AbilityWithParams;\n\t\t\t\t\t\tfor (const param of schema.params)\n\t\t\t\t\t\t\tif (param.isInheritable !== false && param._id in sourceAbility)\n\t\t\t\t\t\t\t\tif (!(param._id in targetAbility))\n\t\t\t\t\t\t\t\t\ttargetAbility[param._id] = structuredClone(sourceAbility[param._id]);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tif (param.type === \"number\") {\n\t\t\t\t\t\t\t\t\t\tif ((targetAbility[param._id] as AbilityParamNumber) < (sourceAbility[param._id] as AbilityParamNumber))\n\t\t\t\t\t\t\t\t\t\t\ttargetAbility[param._id] = sourceAbility[param._id];\n\t\t\t\t\t\t\t\t\t} else if (param.type === \"items\") {\n\t\t\t\t\t\t\t\t\t\tconst targetItems = targetAbility[param._id] as AbilityParamItems;\n\t\t\t\t\t\t\t\t\t\tfor (const itemId of sourceAbility[param._id] as AbilityParamItems)\n\t\t\t\t\t\t\t\t\t\t\tif (!targetItems.includes(itemId))\n\t\t\t\t\t\t\t\t\t\t\t\ttargetItems.push(itemId);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t} else\n\t\t\t\tdelete source[abilityId];\n\t\t}\n\t\t\n\t\treturn target;\n\t}\n\t\n\tgetMinimumOf(_id: string) {\n\t\tconst schema = this.get(_id);\n\t\tif (schema?.params) {\n\t\t\tconst ability: Ability = {};\n\t\t\tfor (const param of schema.params)\n\t\t\t\tif (param.type === \"number\")\n\t\t\t\t\tability[param._id] = param.min ?? 0;\n\t\t\t\telse if (param.type === \"items\")\n\t\t\t\t\tability[param._id] = [];\n\t\t\t\n\t\t\treturn ability;\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n\t\n\tgetMaximum() {\n\t\treturn [ ...this.values() ].reduce((abilities: GenericAbilities, schema: AbilitySchema) => {\n\t\t\tif (schema.params) {\n\t\t\t\tconst ability: Ability = {};\n\t\t\t\tfor (const param of schema.params)\n\t\t\t\t\tif (param.type === \"number\")\n\t\t\t\t\t\tability[param._id] = param.max ?? 0;\n\t\t\t\t\telse if (param.type === \"items\")\n\t\t\t\t\t\tability[param._id] = param.items.map(item => item._id);\n\t\t\t\t\n\t\t\t\tabilities[schema._id] = ability;\n\t\t\t} else\n\t\t\t\tabilities[schema._id as keyof typeof abilities] = true;\n\t\t\t\n\t\t\treturn abilities;\n\t\t}, {});\n\t}\n\t\n\tgetSchemeFor(user: User<AS>) {\n\t\treturn (function resolve(abilitiesSchema: AbilitySchema[]) {\n\t\t\tfor (let i = 0; i < abilitiesSchema.length; i++) {\n\t\t\t\tconst schema = abilitiesSchema[i];\n\t\t\t\tconst userAbility = user.abilities[schema._id as keyof typeof user.abilities];\n\t\t\t\tif (userAbility) {\n\t\t\t\t\tif (schema.params)\n\t\t\t\t\t\tfor (const param of schema.params) {\n\t\t\t\t\t\t\tconst userParam = (userAbility as AbilityWithParams)[param._id];\n\t\t\t\t\t\t\tif (param.type === \"number\") {\n\t\t\t\t\t\t\t\tif (\"max\" in param)\n\t\t\t\t\t\t\t\t\tparam.max = userParam as number;\n\t\t\t\t\t\t\t} else if (param.type === \"items\")\n\t\t\t\t\t\t\t\tfor (let j = 0; j < param.items.length; j++)\n\t\t\t\t\t\t\t\t\tif (!(userParam as AbilityParamItems).includes(param.items[j]._id))\n\t\t\t\t\t\t\t\t\t\t(param.items as AbilityParamItemSchema[]).splice(j--, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\tif (schema.subAbilities)\n\t\t\t\t\t\tresolve(schema.subAbilities as AbilitySchema[]);\n\t\t\t\t} else\n\t\t\t\t\tabilitiesSchema.splice(i--, 1);\n\t\t\t}\n\t\t\t\n\t\t\treturn abilitiesSchema;\n\t\t})(structuredClone(this.schema) as AbilitySchema[]);\n\t}\n\t\n\tadjust(abilities: GenericAbilities) {\n\t\tconst adjustedAbilities: Record<string, unknown> = {};\n\t\tlet isAdjusted = false;\n\t\t\n\t\tfor (const [ _id, ability ] of Object.entries(abilities) as [ string, Ability ][]) {\n\t\t\tconst abilitySchema = this.get(_id);\n\t\t\tif (abilitySchema)\n\t\t\t\tif (abilitySchema.params) {\n\t\t\t\t\tconst adjustedAbility: AbilityWithParams = {};\n\t\t\t\t\t\n\t\t\t\t\tif (isAbilityWithParams(ability)) {\n\t\t\t\t\t\tfor (const paramSchema of abilitySchema.params)\n\t\t\t\t\t\t\tif (paramSchema._id in ability) {\n\t\t\t\t\t\t\t\tlet paramValue = ability[paramSchema._id];\n\t\t\t\t\t\t\t\tif (paramSchema.type === \"number\") {\n\t\t\t\t\t\t\t\t\tif (!isAbilityParamNumber(paramValue))\n\t\t\t\t\t\t\t\t\t\tparamValue = (paramSchema.min ?? 0) as AbilityParamNumber;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tconst adjustedParamValue =\n\t\t\t\t\t\t\t\t\t\tadjustedAbility[paramSchema._id] =\n\t\t\t\t\t\t\t\t\t\t\tMath.max(Math.min(paramValue, paramSchema.max ?? Infinity), paramSchema.min ?? 0);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif (paramValue !== adjustedParamValue)\n\t\t\t\t\t\t\t\t\t\tisAdjusted = true;\n\t\t\t\t\t\t\t\t} else if (paramSchema.type === \"items\") {\n\t\t\t\t\t\t\t\t\tif (!isAbilityParamItems(paramValue))\n\t\t\t\t\t\t\t\t\t\tparamValue = [] as AbilityParamItems;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tconst adjustedParamValue =\n\t\t\t\t\t\t\t\t\t\tadjustedAbility[paramSchema._id] =\n\t\t\t\t\t\t\t\t\t\t\tintersection(paramSchema.items.map(item => item._id), paramValue);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif (paramValue.length !== adjustedParamValue.length || paramValue.some(paramId => !adjustedParamValue.includes(paramId)))\n\t\t\t\t\t\t\t\t\t\tisAdjusted = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (const paramSchema of abilitySchema.params)\n\t\t\t\t\t\t\tif (paramSchema.type === \"number\")\n\t\t\t\t\t\t\t\tadjustedAbility[paramSchema._id] = paramSchema.min ?? 0;\n\t\t\t\t\t\t\telse if (paramSchema.type === \"items\")\n\t\t\t\t\t\t\t\tadjustedAbility[paramSchema._id] = [];\n\t\t\t\t\t\t\n\t\t\t\t\t\tisAdjusted = true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tadjustedAbilities[_id] = adjustedAbility;\n\t\t\t\t} else {\n\t\t\t\t\tadjustedAbilities[_id] = true;\n\t\t\t\t\t\n\t\t\t\t\tif (ability !== true)\n\t\t\t\t\t\tisAdjusted = true;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tisAdjusted = true;\n\t\t}\n\t\t\n\t\tif (isAdjusted) {\n\t\t\tObject.assign(empty(abilities), adjustedAbilities);\n\t\t\t\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n}\n", "import {\n\tdebounce,\n\tdeleteProps,\n\tEmptyArray,\n\tEmptySet,\n\tremoveAll,\n\tsort\n} from \"@nesvet/n\";\nimport type { AbilitiesSchema } from \"insite-common\";\nimport { InSiteCollectionIndexes, InSiteWatchedCollection, newObjectIdString } from \"insite-db\";\nimport { Users } from \"../users\";\nimport { Org } from \"./Org\";\nimport { basisSchema } from \"./schema\";\nimport { OrgDoc, OrgsOptions } from \"./types\";\n\n\nconst indexes: InSiteCollectionIndexes = [\n\t[ { owners: 1 } ]\n];\n\nfunction preventDirectDelete() {\n\tthrow new Error(\"Direct usage of orgs collection.deleteOne or .deleteMany is forbidden. Use orgs.collectionDelete instead.\");\n}\n\n\nexport class Orgs<AS extends AbilitiesSchema = AbilitiesSchema> extends Map<string, Org<AS>> {\n\tconstructor(users: Users<AS>, options: OrgsOptions = {}) {\n\t\tsuper();\n\t\t\n\t\tthis.users = users;\n\t\tthis.collections = users.collections;\n\t\t\n\t\tthis.preinitOptions = options;\n\t\t\n\t}\n\t\n\tusers;\n\tcollections;\n\tpreinitOptions?;\n\t\n\tcollection!: {\n\t\t/** @deprecated Direct usage of roles collection.deleteOne is forbidden. Use orgs.collectionDelete instead. */\n\t\tdeleteOne: typeof preventDirectDelete;\n\t\t\n\t\t/** @deprecated Direct usage of roles collection.deleteMany is forbidden. Use orgs.collectionDelete instead. */\n\t\tdeleteMany: typeof preventDirectDelete;\n\t} & InSiteWatchedCollection<OrgDoc>;\n\t\n\tnull!: { _id: null } & Org<AS>;\n\t\n\tload(orgDoc: OrgDoc) {\n\t\tnew Org<AS>(this, orgDoc);\n\t\t\n\t}\n\t\n\tprivate resolve(org: Org<AS>, slaveOrgs: Org<AS>[]) {\n\t\tslaveOrgs = [ org, ...slaveOrgs ];\n\t\t\n\t\tfor (const ownerOrg of org.ownerOrgs) {\n\t\t\tthis.resolve(ownerOrg, slaveOrgs);\n\t\t\tfor (const slaveOrg of slaveOrgs)\n\t\t\t\townerOrg.slaveOrgs.add(slaveOrg);\n\t\t}\n\t\t\n\t}\n\t\n\tsorted: Org<AS>[] = [];\n\t\n\tupdate() {\n\t\t\n\t\tconst array = [ ...this.values() ];\n\t\tconst sorted = [];\n\t\t\n\t\tfor (const org of array) {\n\t\t\torg.ownerOrgs.clear();\n\t\t\torg.ownerUsers.clear();\n\t\t\torg.slaveOrgs.clear();\n\t\t\t\n\t\t\tfor (const ownerId of org.ownerIds) {\n\t\t\t\tconst ownerOrg = this.get(ownerId);\n\t\t\t\tif (ownerOrg)\n\t\t\t\t\torg.ownerOrgs.add(ownerOrg);\n\t\t\t\telse {\n\t\t\t\t\tconst ownerUser = this.users.get(ownerId);\n\t\t\t\t\tif (ownerUser)\n\t\t\t\t\t\torg.ownerUsers.add(ownerUser);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (!org.ownerOrgs.size && org._id)\n\t\t\t\tsorted.push(org);\n\t\t}\n\t\t\n\t\tfor (const org of array)\n\t\t\tif (!array.some(anotherOrg => anotherOrg.ownerOrgs.has(org)))\n\t\t\t\tthis.resolve(org, []);\n\t\t\n\t\tsorted.sort(this.sortOrgs);\n\t\tfor (const org of array)\n\t\t\tsort(org.slaveOrgs, this.sortOrgs);\n\t\t\n\t\tfor (let i = 0; i < sorted.length; i++) {\n\t\t\tconst org = sorted[i];\n\t\t\tfor (const slaveOrg of [ ...org.slaveOrgs ].reverse())\n\t\t\t\tif (slaveOrg.ownerOrgs.has(org)) {\n\t\t\t\t\tconst slaveOrgIndex = sorted.indexOf(slaveOrg);\n\t\t\t\t\tif (~slaveOrgIndex) {\n\t\t\t\t\t\tsorted.splice(slaveOrgIndex, 1);\n\t\t\t\t\t\ti--;\n\t\t\t\t\t}\n\t\t\t\t\tsorted.splice(i + 1, 0, slaveOrg);\n\t\t\t\t}\n\t\t}\n\t\tfor (let { length } = sorted, o = 0; o < length;)\n\t\t\tsorted[o]._o = o++;\n\t\t\n\t\tthis.sorted = sorted;\n\t\t\n\t\tthis.users.emit(\"orgs-update\");\n\t\t\n\t\tif (this.users.isInited) {\n\t\t\tthis.users.updateDebounced.clear();\n\t\t\tthis.users.update();\n\t\t}\n\t\t\n\t}\n\t\n\tprivate sortOrgs(a: Org<AS>, b: Org<AS>) {\n\t\treturn (\n\t\t\t(b.slaveOrgs.size - a.slaveOrgs.size) || (\n\t\t\t\ta.title > b.title ?\n\t\t\t\t\t1 :\n\t\t\t\t\ta.title < b.title ?\n\t\t\t\t\t\t-1 :\n\t\t\t\t\t\t0\n\t\t\t)\n\t\t);\n\t}\n\t\n\tupdateDebounced = debounce(this.update, 250);\n\t\n\tpreinit? = async () => {\n\t\t\n\t\tconst {\n\t\t\tschema: customSchema,\n\t\t\tindexes: customIndexes,\n\t\t\tnull: nullProps\n\t\t} = this.preinitOptions!;\n\t\t\n\t\tif (customSchema) {\n\t\t\tif (customSchema.required)\n\t\t\t\tremoveAll(customSchema.required as string [], basisSchema.required as string[]);\n\t\t\tif (customSchema.properties)\n\t\t\t\tdeleteProps(customSchema, Object.keys(basisSchema.properties!));\n\t\t}\n\t\t\n\t\tconst jsonSchema = {\n\t\t\t...basisSchema,\n\t\t\t...customSchema,\n\t\t\trequired: [ ...basisSchema.required as string[], ...customSchema?.required as string[] ?? [] ],\n\t\t\tproperties: { ...basisSchema.properties, ...customSchema?.properties }\n\t\t};\n\t\t\n\t\tthis.collection = Object.assign(\n\t\t\tawait this.collections.ensure<OrgDoc>(\"orgs\", { jsonSchema }),\n\t\t\t{\n\t\t\t\tdeleteOne: preventDirectDelete,\n\t\t\t\tdeleteMany: preventDirectDelete\n\t\t\t}\n\t\t);\n\t\t\n\t\tthis.collection.ensureIndexes([ ...indexes, ...customIndexes ?? [] ]);\n\t\t\n\t\tthis.null = Object.assign(\n\t\t\tnew Org<AS>(this, {\n\t\t\t\t...nullProps,\n\t\t\t\t_id: \"\",\n\t\t\t\ttitle: \"\",\n\t\t\t\tnote: \"\",\n\t\t\t\towners: [],\n\t\t\t\tcreatedAt: Date.now()\n\t\t\t}),\n\t\t\t{\n\t\t\t\t_id: null,\n\t\t\t\townerIds: new EmptyArray(),\n\t\t\t\townerOrgs: new EmptySet(),\n\t\t\t\townerUsers: new EmptySet(),\n\t\t\t\tslaveOrgs: new EmptySet()\n\t\t\t}\n\t\t);\n\t\t\n\t\tfor (const orgDoc of await this.collection.find().toArray())\n\t\t\tthis.load(orgDoc);\n\t\t\n\t\tdelete this.preinitOptions;\n\t\tdelete this.preinit;\n\t\t\n\t};\n\t\n\tinit? = async () => {\n\t\t\n\t\tawait this.update();\n\t\t\n\t\tthis.collection.changeListeners.add(next => {\n\t\t\tswitch (next.operationType) {\n\t\t\t\tcase \"insert\": {\n\t\t\t\t\tconst org = new Org<AS>(this, next.fullDocument);\n\t\t\t\t\tthis.users.emit(\"orgs-org-update\", org, next);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase \"replace\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.fullDocument, next);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"update\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.updateDescription.updatedFields!, next);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"delete\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.delete();\n\t\t\t\t\tthis.users.emit(\"orgs-org-update\", null, next);\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\tdelete this.init;\n\t\t\n\t};\n\t\n\tnew({ title, note, ...restProps }: Omit<OrgDoc, \"_id\" | \"createdAt\" | \"owners\">, ownerId: string) {\n\t\treturn this.collection.insertOne({\n\t\t\t_id: newObjectIdString(),\n\t\t\ttitle: title ?? \"\",\n\t\t\tnote: note ?? \"\",\n\t\t\towners: ownerId ? [ ownerId ] : [],\n\t\t\t...deleteProps(restProps, [ \"_id\", \"owners\" ]),\n\t\t\tcreatedAt: Date.now()\n\t\t});\n\t}\n\t\n\tcollectionDelete(org: Org<AS> | string) {\n\t\tconst _id = typeof org == \"string\" ? org : org._id;\n\t\t\n\t\treturn this.collection.bulkWrite([\n\t\t\t{ updateMany: { filter: { owners: _id }, update: { $pullAll: { owners: [ _id ] } } } },\n\t\t\t{ deleteOne: { filter: { _id } } }\n\t\t]);\n\t}\n\t\n\treplaceMap = new Map<string, string>();\n\t\n\treplaceHandlers = new Set<(fromId: string, toId: null | string) => Promise<void> | void>();\n\t\n\tasync replace(fromId: string) {\n\t\tconst toId = this.replaceMap.get(fromId) ?? null;\n\t\tif (toId)\n\t\t\tthis.replaceMap.delete(fromId);\n\t\t\n\t\tfor (const handler of this.replaceHandlers)\n\t\t\tawait handler(fromId, toId);\n\t\t\n\t}\n\t\n}\n", "import type { AbilitiesSchema } from \"insite-common\";\nimport type { ChangeStreamDocument } from \"insite-db\";\nimport { User } from \"../users/User\";\nimport type { Orgs } from \"./Orgs\";\nimport type { OrgDoc } from \"./types\";\n\nconst snapshots = new Map();\n\n\nexport class Org<AS extends AbilitiesSchema = AbilitiesSchema> {\n\tconstructor(orgs: Orgs<AS>, orgDoc: OrgDoc) {\n\t\tthis.orgs = orgs;\n\t\t\n\t\tthis._id = orgDoc._id;\n\t\torgs.set(this._id, this);\n\t\t\n\t\tthis.update(orgDoc);\n\t\t\n\t}\n\t\n\t_id;\n\ttitle = \"\";\n\tinitials = \"\";\n\tdisplayLabel = \"\";\n\t\n\t_o = 0;\n\t\n\torgs;\n\t\n\tisOrg = true;\n\t\n\townerOrgs = new Set<Org<AS>>();\n\townerUsers = new Set<User<AS>>();\n\t\n\tusers = new Set<User<AS>>();\n\t\n\tslaveOrgs = new Set<Org<AS>>();\n\t\n\townerIds: string[] = [];\n\t\n\tupdate({ _id, title, owners: ownerIds, ...restProps }: Partial<OrgDoc>, next?: ChangeStreamDocument<OrgDoc>) {\n\t\t\n\t\tObject.assign(this, restProps);\n\t\t\n\t\tif (title !== undefined) {\n\t\t\tthis.title = title;\n\t\t\tthis.initials = title?.[0]?.toUpperCase() ?? \"\";\n\t\t\tthis.displayLabel = title;\n\t\t}\n\t\t\n\t\tif (ownerIds) {\n\t\t\tthis.ownerIds = ownerIds;\n\t\t\t\n\t\t\t\n\t\t\tconst snapshot = this.ownerIds.join(\",\");\n\t\t\t\n\t\t\tif (snapshot !== snapshots.get(this._id)) {\n\t\t\t\tsnapshots.set(this._id, snapshot);\n\t\t\t\t\n\t\t\t\tif (this.orgs.users.isInited)\n\t\t\t\t\tthis.orgs.updateDebounced();\n\t\t\t\t\n\t\t\t\tthis.orgs.users.emit(\"orgs-org-update\", this, next);\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\tdelete() {\n\t\t\n\t\tthis.orgs.delete(this._id);\n\t\t\n\t\tsnapshots.delete(this._id);\n\t\t\n\t\tthis.orgs.replace(this._id);\n\t\t\n\t\tthis.orgs.updateDebounced();\n\t\t\n\t}\n\t\n}\n", "export const regexps = {\n\t_id: /^[\\dA-Fa-f]{24}$/,\n\temail: /^[^\\s@]{1,63}@[^\\s@]{1,63}\\.[^\\s@]{1,63}$/,\n\targon2: /^\\$argon2(?:i|d|id)\\$v=\\d+\\$m=\\d+,t=\\d+,p=\\d+(?:\\$[\\d+/A-Za-z]+){2}$/,\n\tsessionId: /^[\\dA-Fa-f]{16,32}\\$[\\dA-Fa-f]{16,32}$/,\n\trole: /^[\\d_a-z-]{1,64}$/,\n\tip: /^(?:\\d{1,3}\\.){3}\\d{1,3}$/\n};\n", "import { InSiteCollectionSchema } from \"insite-db\";\nimport { regexps } from \"../lib\";\n\n\nexport const basisSchema: InSiteCollectionSchema = {\n\trequired: [\n\t\t\"_id\",\n\t\t\"title\",\n\t\t\"note\",\n\t\t\"owners\",\n\t\t\"createdAt\"\n\t],\n\tproperties: {\n\t\t_id: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps._id.source\n\t\t},\n\t\ttitle: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 512\n\t\t},\n\t\tnote: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 131072\n\t\t},\n\t\towners: {\n\t\t\tbsonType: \"array\",\n\t\t\tuniqueItems: true,\n\t\t\titems: {\n\t\t\t\tbsonType: \"string\",\n\t\t\t\tpattern: regexps._id.source\n\t\t\t},\n\t\t\tadditionalItems: false\n\t\t},\n\t\tcreatedAt: {\n\t\t\tbsonType: \"number\"\n\t\t}\n\t},\n\tadditionalProperties: false\n};\n", "import {\n\tdebounce,\n\tdeleteProps,\n\tgetAll,\n\tintersection,\n\treAdd,\n\tremoveAll\n} from \"@nesvet/n\";\nimport type { AbilitiesSchema } from \"insite-common\";\nimport type { InSiteCollectionIndexes, InSiteWatchedCollection } from \"insite-db\";\nimport type { GenericAbilities } from \"../abilities/types\";\nimport type { Users } from \"../users\";\nimport { Role } from \"./Role\";\nimport { basisSchema } from \"./schema\";\nimport type { RoleDoc, RolesOptions } from \"./types\";\n\n\nconst indexes: InSiteCollectionIndexes = [\n\t[ { involves: 1 } ]\n];\n\nfunction preventDirectDelete() {\n\tthrow new Error(\"Direct usage of roles collection.deleteOne or .deleteMany is forbidden. Use roles.collectionDelete instead.\");\n}\n\n\nexport class Roles<AS extends AbilitiesSchema = AbilitiesSchema> extends Map<string, Role<AS>> {\n\tconstructor(users: Users<AS>, options: RolesOptions = {}) {\n\t\tsuper();\n\t\t\n\t\tconst {\n\t\t\troot: rootProps,\n\t\t\t...initOptions\n\t\t} = options;\n\t\t\n\t\tthis.users = users;\n\t\tthis.collections = users.collections;\n\t\tthis.abilitiesMap = users.abilitiesMap;\n\t\t\n\t\tthis.root = new Role<AS>(this, {\n\t\t\t...rootProps,\n\t\t\t_id: \"root\",\n\t\t\tinvolves: [],\n\t\t\tabilities: this.abilitiesMap.getMaximum(),\n\t\t\ttitle: \"Root\",\n\t\t\tdescription: \"Root\",\n\t\t\tcreatedAt: Date.now()\n\t\t});\n\t\t\n\t\tthis.initOptions = initOptions;\n\t\t\n\t}\n\t\n\tusers;\n\tcollections;\n\tcollection!: {\n\t\t/** @deprecated Direct usage of roles collection.deleteOne is forbidden. Use roles.collectionDelete instead. */\n\t\tdeleteOne: typeof preventDirectDelete;\n\t\t\n\t\t/** @deprecated Direct usage of roles collection.deleteMany is forbidden. Use roles.collectionDelete instead. */\n\t\tdeleteMany: typeof preventDirectDelete;\n\t} & InSiteWatchedCollection<RoleDoc>;\n\t\n\tabilitiesMap;\n\troot;\n\tinitOptions?;\n\t\n\tload(roleDoc: RoleDoc) {\n\t\tnew Role<AS>(this, roleDoc);\n\t\t\n\t}\n\t\n\tresolve(role: Role<AS>, involvedBy: Role<AS>[]) {\n\t\tinvolvedBy = [ role, ...involvedBy ];\n\t\t\n\t\tfor (const involvedRoleId of role.ownInvolveIds) {\n\t\t\tconst involvedRole = this.get(involvedRoleId);\n\t\t\tif (involvedRole) {\n\t\t\t\tfor (const involvedByRole of involvedBy) {\n\t\t\t\t\treAdd(involvedByRole.involves, involvedRole);\n\t\t\t\t\tthis.abilitiesMap.merge(involvedByRole.inheritedAbilities as GenericAbilities, involvedRole.abilities as GenericAbilities);\n\t\t\t\t}\n\t\t\t\tif (involvedRole !== role)\n\t\t\t\t\tthis.resolve(involvedRole, involvedBy);\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\tsorted: Role<AS>[] = [];\n\t\n\tprivate sortRoles(a: Role<AS>, b: Role<AS>) {\n\t\treturn (\n\t\t\t(b.involves.size - a.involves.size) || (\n\t\t\t\t(a.title && b.title) ?\n\t\t\t\t\ta.title > b.title ? 1 : a.title < b.title ? -1 : 0 :\n\t\t\t\t\ta.title ?\n\t\t\t\t\t\t-1 :\n\t\t\t\t\t\tb.title ?\n\t\t\t\t\t\t\t1 :\n\t\t\t\t\t\t\ta._id > b._id ?\n\t\t\t\t\t\t\t\t1 :\n\t\t\t\t\t\t\t\ta._id < b._id ?\n\t\t\t\t\t\t\t\t\t-1 :\n\t\t\t\t\t\t\t\t\t0\n\t\t\t\t\n\t\t\t)\n\t\t);\n\t}\n\t\n\tupdate() {\n\t\t\n\t\tconst array = [ ...this.values() ];\n\t\t\n\t\tthis.root.ownInvolveIds = [];\n\t\tfor (const role of array) {\n\t\t\tif (role !== this.root && !array.some(anotherRole => anotherRole.ownInvolveIds.includes(role._id)))\n\t\t\t\tthis.root.ownInvolveIds.push(role._id);\n\t\t\trole.involves.clear();\n\t\t\trole.abilities = structuredClone(role.ownAbilities);\n\t\t\trole.inheritedAbilities = {};\n\t\t}\n\t\t\n\t\tthis.root.involves.add(this.root);\n\t\tthis.resolve(this.root, []);\n\t\t\n\t\tfor (const role of array)\n\t\t\trole.ownInvolves = getAll(this, role.ownInvolveIds, true).sort(this.sortRoles).reverse();\n\t\t\n\t\tconst sorted = [ this.root ];\n\t\t\n\t\tfor (let i = 0; i < sorted.length; i++) {\n\t\t\tconst role = sorted[i];\n\t\t\tfor (const involvedRole of role.ownInvolves) {\n\t\t\t\tconst involvedRoleIndex = sorted.indexOf(involvedRole);\n\t\t\t\tif (~involvedRoleIndex) {\n\t\t\t\t\tsorted.splice(involvedRoleIndex, 1);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t\tsorted.splice(i + 1, 0, involvedRole);\n\t\t\t}\n\t\t}\n\t\t\n\t\tlet _o = 0;\n\t\tfor (const role of sorted) {\n\t\t\tthis.abilitiesMap.merge(role.abilities as GenericAbilities, role.inheritedAbilities as GenericAbilities);\n\t\t\trole._o = _o++;\n\t\t}\n\t\t\n\t\tthis.sorted = sorted;\n\t\t\n\t\tthis.users.emit(\"roles-update\");\n\t\t\n\t\tif (this.users.isInited) {\n\t\t\tthis.users.updateDebounced.clear();\n\t\t\tthis.users.update(true);\n\t\t}\n\t\t\n\t}\n\t\n\tupdateDebounced = debounce(this.update, 250);\n\t\n\tinit? = async () => {\n\t\t\n\t\tconst {\n\t\t\tschema: customSchema,\n\t\t\tindexes: customIndexes\n\t\t} = this.initOptions!;\n\t\t\n\t\tif (customSchema) {\n\t\t\tif (customSchema.required)\n\t\t\t\tremoveAll(customSchema.required as string[], basisSchema.required as string[]);\n\t\t\tif (customSchema.properties)\n\t\t\t\tdeleteProps(customSchema, Object.keys(basisSchema.properties!));\n\t\t}\n\t\t\n\t\tconst jsonSchema = {\n\t\t\t...basisSchema,\n\t\t\t...customSchema,\n\t\t\trequired: [ ...basisSchema.required as string[], ...customSchema?.required as string[] ?? [] ],\n\t\t\tproperties: { ...basisSchema.properties, ...customSchema?.properties }\n\t\t};\n\t\t\n\t\tthis.collection = Object.assign(\n\t\t\tawait this.collections.ensure<RoleDoc>(\"roles\", { jsonSchema }),\n\t\t\t{\n\t\t\t\tdeleteOne: preventDirectDelete,\n\t\t\t\tdeleteMany: preventDirectDelete\n\t\t\t}\n\t\t);\n\t\t\n\t\tthis.collection.ensureIndexes([ ...indexes, ...customIndexes ?? [] ]);\n\t\t\n\t\tfor (const roleDoc of await this.collection.find().toArray()) {\n\t\t\tif (this.abilitiesMap.adjust(roleDoc.abilities))\n\t\t\t\tawait this.collection.updateOne({ _id: roleDoc._id }, { $set: { abilities: roleDoc.abilities } });\n\t\t\t\n\t\t\tthis.load(roleDoc);\n\t\t}\n\t\t\n\t\tthis.update();\n\t\t\n\t\tthis.collection.changeListeners.add(next => {\n\t\t\tswitch (next.operationType) {\n\t\t\t\tcase \"insert\": {\n\t\t\t\t\tconst role = new Role<AS>(this, next.fullDocument);\n\t\t\t\t\tthis.users.emit(\"roles-role-update\", role, next);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase \"replace\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.fullDocument, next);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"update\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.updateDescription.updatedFields!, next);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"delete\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.delete();\n\t\t\t\t\tthis.users.emit(\"roles-role-update\", null, next);\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\tdelete this.initOptions;\n\t\tdelete this.init;\n\t\t\n\t};\n\t\n\tnew({ _id, involves, title, description, ...restProps }: Omit<RoleDoc, \"abilities\" | \"createdAt\">) {\n\t\treturn this.collection.insertOne({\n\t\t\t_id,\n\t\t\tinvolves: involves || [],\n\t\t\tabilities: {},\n\t\t\ttitle: title ?? \"\",\n\t\t\tdescription: description ?? \"\",\n\t\t\t...deleteProps(restProps, [ \"abilities\" ]),\n\t\t\tcreatedAt: Date.now()\n\t\t});\n\t}\n\t\n\tcollectionDelete(role: Role<AS> | string) {\n\t\tconst _id = typeof role == \"string\" ? role : role._id;\n\t\t\n\t\treturn this.collection.bulkWrite([\n\t\t\t{ updateMany: { filter: { involves: _id }, update: { $pullAll: { involves: [ _id ] } } } },\n\t\t\t{ deleteOne: { filter: { _id } } }\n\t\t]);\n\t}\n\t\n\tcleanUpIds(ids: string[]) {\n\t\tconst roles = intersection(this.sorted, getAll(this, ids, true));\n\t\t\n\t\tconst cleanedUpIds = [];\n\t\t\n\t\tfor (const role of roles)\n\t\t\tif (roles.every(anotherRole => anotherRole === role || !anotherRole.involves.has(role)))\n\t\t\t\tcleanedUpIds.push(role._id);\n\t\t\n\t\treturn cleanedUpIds;\n\t}\n\t\n}\n", "import type { Abilities, AbilitiesSchema } from \"insite-common\";\nimport type { ChangeStreamDocument } from \"insite-db\";\nimport { Roles } from \"./Roles\";\nimport { RoleDoc } from \"./types\";\n\nconst snapshots = new Map();\n\n\nexport class Role<AS extends AbilitiesSchema = AbilitiesSchema> {\n\tconstructor(roles: Roles<AS>, roleDoc: RoleDoc) {\n\t\tthis.roles = roles;\n\t\t\n\t\tthis._id = roleDoc._id;\n\t\troles.set(this._id, this);\n\t\t\n\t\tthis.update(roleDoc);\n\t\t\n\t}\n\t\n\tprivate roles;\n\t\n\t_id;\n\townInvolveIds!: string[];\n\townAbilities!: Abilities<AS>;\n\ttitle = \"\";\n\tdisplayTitle = \"\";\n\t_o = 0;\n\t\n\townInvolves: Role<AS>[] = [];\n\tinvolves = new Set<Role<AS>>();\n\tabilities: Abilities<AS> = {};\n\tinheritedAbilities: Abilities<AS> = {};\n\t\n\tupdate({ _id, involves: ownInvolveIds, abilities: ownAbilities, title, ...restProps }: Partial<RoleDoc>, next?: ChangeStreamDocument<RoleDoc>) {\n\t\t\n\t\tObject.assign(this, restProps);\n\t\t\n\t\tif (ownInvolveIds)\n\t\t\tthis.ownInvolveIds = ownInvolveIds;\n\t\t\n\t\tif (ownAbilities)\n\t\t\tthis.ownAbilities = ownAbilities as Abilities<AS>;\n\t\t\n\t\tif (title !== undefined) {\n\t\t\tthis.title = title;\n\t\t\tthis.displayTitle = title || this._id;\n\t\t}\n\t\t\n\t\t\n\t\tif (ownInvolveIds || ownAbilities) {\n\t\t\tconst snapshot = [\n\t\t\t\tthis.ownInvolveIds.join(\",\"),\n\t\t\t\tJSON.stringify(this.ownAbilities)\n\t\t\t].join(\"\\n\");\n\t\t\t\n\t\t\tif (snapshot !== snapshots.get(this._id)) {\n\t\t\t\tsnapshots.set(this._id, snapshot);\n\t\t\t\t\n\t\t\t\tif (this.roles.users.isInited)\n\t\t\t\t\tthis.roles.updateDebounced();\n\t\t\t\t\n\t\t\t\tthis.roles.users.emit(\"roles-role-update\", this, next);\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\tdelete() {\n\t\t\n\t\tthis.roles.delete(this._id);\n\t\t\n\t\tsnapshots.delete(this._id);\n\t\t\n\t\tthis.roles.updateDebounced();\n\t\t\n\t}\n\t\n}\n", "import { InSiteCollectionSchema } from \"insite-db\";\nimport { regexps } from \"../lib\";\n\n\nexport const basisSchema: InSiteCollectionSchema = {\n\trequired: [\n\t\t\"_id\",\n\t\t\"involves\",\n\t\t\"abilities\",\n\t\t\"title\",\n\t\t\"description\",\n\t\t\"createdAt\"\n\t],\n\tproperties: {\n\t\t_id: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps.role.source,\n\t\t\tnot: { enum: [ \"root\" ] }\n\t\t},\n\t\tinvolves: {\n\t\t\tbsonType: \"array\",\n\t\t\tuniqueItems: true,\n\t\t\titems: {\n\t\t\t\tbsonType: \"string\",\n\t\t\t\tpattern: regexps.role.source,\n\t\t\t\tnot: { enum: [ \"root\" ] }\n\t\t\t},\n\t\t\tadditionalItems: false\n\t\t},\n\t\tabilities: {\n\t\t\tbsonType: \"object\"\n\t\t},\n\t\ttitle: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 256\n\t\t},\n\t\tdescription: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 10240\n\t\t},\n\t\tcreatedAt: {\n\t\t\tbsonType: \"number\"\n\t\t}\n\t},\n\tadditionalProperties: false\n};\n", "import crypto from \"node:crypto\";\nimport { deleteProps, random, removeAll } from \"@nesvet/n\";\nimport type { AbilitiesSchema } from \"insite-common\";\nimport { InSiteCollectionIndexes, InSiteWatchedCollection } from \"insite-db\";\nimport { User } from \"../users/User\";\nimport type { Users } from \"../users\";\nimport { basisSchema } from \"./schema\";\nimport { Session } from \"./Session\";\nimport { SessionDoc, SessionsOptions } from \"./types\";\n\n\nconst expireAfterSeconds = 3600 * 24 * 7;\n\nconst indexes: InSiteCollectionIndexes = [\n\t[ { user: 1 } ],\n\t[ { expiresAt: 1 }, { expireAfterSeconds } ]\n];\n\n\nexport class Sessions<AS extends AbilitiesSchema = AbilitiesSchema> extends Map<string, Session<AS>> {\n\tconstructor(users: Users<AS>, options: SessionsOptions = {}) {\n\t\tsuper();\n\t\t\n\t\tthis.users = users;\n\t\tthis.collections = users.collections;\n\t\t\n\t\tthis.initOptions = options;\n\t}\n\t\n\tusers;\n\tcollections;\n\t\n\tinitOptions?;\n\t\n\tcollection!: {\n\t\texpireAfterSeconds: number;\n\t} & InSiteWatchedCollection<SessionDoc>;\n\t\n\tisInited = false;\n\t\n\tuid() {\n\t\t\n\t\tlet _id;\n\t\tdo\n\t\t\t_id = `${crypto.randomBytes(random(8, 16)).toString(\"hex\")}$${crypto.randomBytes(random(8, 16)).toString(\"hex\")}`;\n\t\twhile (this.has(_id));\n\t\t\n\t\treturn _id;\n\t}\n\t\n\tload(sessionDoc: SessionDoc) {\n\t\tnew Session<AS>(this, sessionDoc);\n\t\t\n\t}\n\t\n\tinit? = async () => {\n\t\t\n\t\tconst {\n\t\t\tschema: customSchema,\n\t\t\tindexes: customIndexes\n\t\t} = this.initOptions!;\n\t\t\n\t\tif (customSchema) {\n\t\t\tif (customSchema.required)\n\t\t\t\tremoveAll(customSchema.required as string[], basisSchema.required as string[]);\n\t\t\tif (customSchema.properties)\n\t\t\t\tdeleteProps(customSchema, Object.keys(basisSchema.properties!));\n\t\t}\n\t\t\n\t\tconst jsonSchema = {\n\t\t\t...basisSchema,\n\t\t\t...customSchema,\n\t\t\trequired: [ ...basisSchema.required as string[], ...customSchema?.required as string[] ?? [] ],\n\t\t\tproperties: { ...basisSchema.properties, ...customSchema?.properties }\n\t\t};\n\t\t\n\t\tthis.collection = Object.assign(\n\t\t\tawait this.collections.ensure<SessionDoc>(\"sessions\", { jsonSchema }),\n\t\t\t{\n\t\t\t\texpireAfterSeconds\n\t\t\t}\n\t\t);\n\t\t\n\t\tthis.collection.ensureIndexes([ ...indexes, ...customIndexes ?? [] ]);\n\t\t\n\t\tawait this.collection.updateMany({ isOnline: true }, { $set: { isOnline: false } });\n\t\t\n\t\tfor (const sessionDoc of await this.collection.find().toArray())\n\t\t\tthis.load(sessionDoc);\n\t\t\n\t\tthis.collection.changeListeners.add(next => {\n\t\t\tswitch (next.operationType) {\n\t\t\t\tcase \"insert\":\n\t\t\t\t\tif (!this.has(next.documentKey._id))\n\t\t\t\t\t\tnew Session<AS>(this, next.fullDocument);\n\t\t\t\t\t\n\t\t\t\t\tthis.users.get(next.fullDocument.user)?.trimSessions();\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"replace\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.fullDocument);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"update\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.update(next.updateDescription.updatedFields!);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"delete\":\n\t\t\t\t\tthis.get(next.documentKey._id)?.delete();\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\tthis.isInited = true;\n\t\t\n\t\tdelete this.initOptions;\n\t\tdelete this.init;\n\t\t\n\t};\n\t\n\tasync new(user: User<AS>, props: Partial<SessionDoc>) {\n\t\t\n\t\tconst ts = Date.now();\n\t\t\n\t\tconst sessionDoc: SessionDoc = {\n\t\t\tuserAgent: \"\",\n\t\t\tremoteAddress: \"127.0.0.1\",\n\t\t\tisOnline: true,\n\t\t\t...props,\n\t\t\t_id: this.uid(),\n\t\t\tuser: user._id,\n\t\t\tcreatedAt: ts,\n\t\t\tprolongedAt: ts,\n\t\t\texpiresAt: new Date(ts + (expireAfterSeconds * 1000))\n\t\t};\n\t\t\n\t\t/* new Session(\u2026) before await insertOne(\u2026) for avoid changeStream insert event to come earlier and create the session duplicate */\n\t\tconst session = new Session<AS>(this, sessionDoc);\n\t\t\n\t\tawait this.collection.insertOne(sessionDoc);\n\t\t\n\t\treturn session;\n\t}\n\t\n}\n", "import { InSiteCollectionSchema } from \"insite-db\";\nimport { regexps } from \"../lib\";\n\n\nexport const basisSchema: InSiteCollectionSchema = {\n\trequired: [\n\t\t\"_id\",\n\t\t\"user\",\n\t\t\"remoteAddress\",\n\t\t\"isOnline\",\n\t\t\"createdAt\",\n\t\t\"prolongedAt\",\n\t\t\"expiresAt\"\n\t],\n\tproperties: {\n\t\t_id: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps.sessionId.source\n\t\t},\n\t\tuser: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps._id.source\n\t\t},\n\t\tuserAgent: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 4096\n\t\t},\n\t\tremoteAddress: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps.ip.source\n\t\t},\n\t\tisOnline: {\n\t\t\tbsonType: \"bool\"\n\t\t},\n\t\tcreatedAt: {\n\t\t\tbsonType: \"number\"\n\t\t},\n\t\tprolongedAt: {\n\t\t\tbsonType: \"number\"\n\t\t},\n\t\texpiresAt: {\n\t\t\tbsonType: \"date\"\n\t\t}\n\t},\n\tadditionalProperties: false\n};\n", "import type { AbilitiesSchema } from \"insite-common\";\nimport type { User } from \"../users/User\";\nimport type { Sessions } from \"./Sessions\";\nimport type { SessionDoc } from \"./types\";\n\n\nexport class Session<AS extends AbilitiesSchema = AbilitiesSchema> {\n\tconstructor(sessions: Sessions<AS>, sessionDoc: SessionDoc) {\n\t\tconst user = sessions.users.get(sessionDoc.user);\n\t\t\n\t\tif (user) {\n\t\t\tthis.sessions = sessions;\n\t\t\t\n\t\t\tthis._id = sessionDoc._id;\n\t\t\tthis.sessions.set(this._id, this);\n\t\t\t\n\t\t\tthis.user = user;\n\t\t\tthis.user.sessions.add(this);\n\t\t\t\n\t\t\tthis.sessions.users.bySessionId.set(this._id, this.user);\n\t\t\t\n\t\t\tthis.update(sessionDoc);\n\t\t} else\n\t\t\tsessions.collection.deleteOne({ _id: sessionDoc._id });\n\t\t\n\t}\n\t\n\t_id!: string;\n\tuser!: User<AS>;\n\tisOnline = false;\n\t\n\tuserAgent!: string;\n\tremoteAddress!: string;\n\tcreatedAt!: number;\n\tprolongedAt!: number;\n\texpiresAt!: Date;\n\t\n\tprivate sessions!: Sessions<AS>;\n\t\n\tupdate({ _id, user, isOnline, ...restProps }: Partial<SessionDoc>) {\n\t\t\n\t\tif (isOnline !== undefined && this.isOnline !== isOnline) {\n\t\t\tthis.isOnline = isOnline;\n\t\t\t\n\t\t\tif (this.sessions.isInited && this.user.isOnline !== this.isOnline)\n\t\t\t\tthis.user.updateIsOnline();\n\t\t}\n\t\t\n\t\tObject.assign(this, restProps);\n\t\t\n\t}\n\t\n\tprolong({ _id, user, ...updates }: Partial<SessionDoc>) {\n\t\t\n\t\tconst ts = Date.now();\n\t\t\n\t\tupdates.prolongedAt = ts;\n\t\tupdates.expiresAt = new Date(ts + (this.sessions.collection.expireAfterSeconds * 1000));\n\t\t\n\t\tthis.update(updates);\n\t\t\n\t\treturn this.sessions.collection.updateOne({ _id: this._id }, { $set: updates });\n\t}\n\t\n\toffline() {\n\t\t\n\t\tconst updates = { isOnline: false };\n\t\t\n\t\tthis.update(updates);\n\t\t\n\t\treturn this.sessions.collection.updateOne({ _id: this._id }, { $set: updates });\n\t}\n\t\n\tdelete() {\n\t\t\n\t\tthis.sessions.delete(this._id);\n\t\tthis.user.sessions.delete(this);\n\t\tthis.sessions.users.bySessionId.delete(this._id);\n\t\t\n\t\tthis.sessions.users.emit(\"session-delete\", this);\n\t\t\n\t\tif (this.isOnline)\n\t\t\tthis.user.updateIsOnline();\n\t\t\n\t}\n\t\n}\n", "import { InSiteCollectionSchema } from \"insite-db\";\nimport { regexps } from \"../../lib\";\n\n\nexport const schema: InSiteCollectionSchema = {\n\trequired: [\n\t\t\"_id\",\n\t\t\"type\",\n\t\t\"size\",\n\t\t\"ts\",\n\t\t\"data\"\n\t],\n\tproperties: {\n\t\t_id: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps._id.source\n\t\t},\n\t\ttype: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 256\n\t\t},\n\t\tsize: {\n\t\t\tbsonType: \"number\"\n\t\t},\n\t\tts: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 10\n\t\t},\n\t\tdata: {\n\t\t\tbsonType: \"binData\"\n\t\t}\n\t},\n\tadditionalProperties: false\n};\n", "import type { AbilitiesSchema } from \"insite-common\";\nimport { InSiteWatchedCollection } from \"insite-db\";\nimport type { Users } from \"../Users\";\nimport { schema as jsonSchema } from \"./schema\";\nimport type { AvatarDoc } from \"./types\";\n// import { AvatarsOptions } from \"./types\";\n\n\nexport class Avatars<AS extends AbilitiesSchema = AbilitiesSchema> {\n\tconstructor(users: Users<AS>/* , options: AvatarsOptions = {} */) {\n\t\tthis.users = users;\n\t\tthis.collections = users.collections;\n\t\t\n\t}\n\t\n\tusers;\n\tcollections;\n\t\n\tcollection!: InSiteWatchedCollection<AvatarDoc>;\n\t\n\tinit? = async () => {\n\t\t\n\t\tthis.collection = await this.collections.ensure<AvatarDoc>(\"users.avatars\", { jsonSchema });\n\t\t\n\t\tdelete this.init;\n\t\t\n\t};\n\t\n}\n", "import { InSiteCollectionSchema } from \"insite-db\";\nimport { regexps } from \"../lib\";\n\n\nexport const basisSchema: InSiteCollectionSchema = {\n\trequired: [\n\t\t\"_id\",\n\t\t\"email\",\n\t\t\"password\",\n\t\t\"roles\",\n\t\t\"name\",\n\t\t\"org\",\n\t\t\"job\",\n\t\t\"createdAt\"\n\t],\n\tproperties: {\n\t\t_id: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps._id.source\n\t\t},\n\t\temail: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps.email.source\n\t\t},\n\t\tpassword: {\n\t\t\tbsonType: \"string\",\n\t\t\tpattern: regexps.argon2.source\n\t\t},\n\t\troles: {\n\t\t\tbsonType: \"array\",\n\t\t\tuniqueItems: true,\n\t\t\titems: {\n\t\t\t\tbsonType: \"string\",\n\t\t\t\tpattern: regexps.role.source\n\t\t\t},\n\t\t\tadditionalItems: false\n\t\t},\n\t\tname: {\n\t\t\tbsonType: \"object\",\n\t\t\trequired: [\n\t\t\t\t\"first\",\n\t\t\t\t\"middle\",\n\t\t\t\t\"last\"\n\t\t\t],\n\t\t\tproperties: {\n\t\t\t\tfirst: {\n\t\t\t\t\tbsonType: \"string\",\n\t\t\t\t\tmaxLength: 512\n\t\t\t\t},\n\t\t\t\tmiddle: {\n\t\t\t\t\tbsonType: \"string\",\n\t\t\t\t\tmaxLength: 512\n\t\t\t\t},\n\t\t\t\tlast: {\n\t\t\t\t\tbsonType: \"string\",\n\t\t\t\t\tmaxLength: 512\n\t\t\t\t}\n\t\t\t},\n\t\t\tadditionalProperties: false\n\t\t},\n\t\torg: {\n\t\t\toneOf: [\n\t\t\t\t{\n\t\t\t\t\tbsonType: \"string\",\n\t\t\t\t\tpattern: regexps._id.source\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbsonType: \"null\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tjob: {\n\t\t\tbsonType: \"string\",\n\t\t\tmaxLength: 512\n\t\t},\n\t\tavatar: {\n\t\t\toneOf: [\n\t\t\t\t{\n\t\t\t\t\tbsonType: \"string\",\n\t\t\t\t\tmaxLength: 10\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbsonType: \"null\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tcreatedAt: {\n\t\t\tbsonType: \"number\"\n\t\t}\n\t},\n\tadditionalProperties: false\n};\n", "import {\n\t_ids,\n\tdebounce,\n\tempty,\n\thasAny,\n\tremoveOne\n} from \"@nesvet/n\";\nimport type { Abilities, AbilitiesSchema } from \"insite-common\";\nimport type { GenericAbilities } from \"../abilities/types\";\nimport type { Org } from \"../orgs/Org\";\nimport type { Role } from \"../roles/Role\";\nimport type { Session } from \"../sessions/Session\";\nimport type { UserDoc } from \"./types\";\nimport type { Users } from \"./Users\";\n\n\nconst rolesSnapshots = new Map();\nconst permissionsSnapshots = new Map();\n\nconst staticUrl = process.env.INSITE_STATIC_URL ?? \"http://localhost:8080\";\n\n\nexport class User<AS extends AbilitiesSchema = AbilitiesSchema> {\n\tconstructor(users: Users<AS>, userDoc: UserDoc) {\n\t\tthis.users = users;\n\t\t\n\t\tthis._id = userDoc._id;\n\t\tusers.set(this._id, this);\n\t\t\n\t\tthis.update(userDoc);\n\t\t\n\t\tif (users.isInited)\n\t\t\tusers.emit(\"user-create\", this);\n\t\t\n\t}\n\t\n\t_id;\n\temail!: string;\n\tname = {\n\t\tfirst: \"\",\n\t\tmiddle: \"\",\n\t\tlast: \"\"\n\t};\n\t\n\tinitials = \"\";\n\tdisplayLabel = \"\";\n\torg!: Org<AS>;\n\tjob: string = \"\";\n\tavatar: null | string = null;\n\tavatarUrl: null | string = null;\n\t\n\tprivate users;\n\t\n\tisUser = true;\n\tisRoot?: boolean;\n\t\n\troles = new Set<Role<AS>>();\n\townRoles: Role<AS>[] = [];\n\townRoleIds: string[] = [];\n\tslaveRoles = new Set<Role<AS>>();\n\tslaveRoleIds: string[] = [];\n\tabilities: Abilities<AS> = {};\n\t\n\tslaveOrgs = new Set<Org<AS>>();\n\tslaveUsers = new Set<User<AS>>();\n\tslaves = new Set<Org<AS> | User<AS>>();\n\t\n\tslaveIds: string[] = [];\n\tpermissiveIds: string[] = [];\n\t\n\tsessions = new Set<Session<AS>>();\n\t\n\tisOnline = false;\n\t\n\tupdate({ _id, name, email, roles: ownRoleIds, org: orgId, avatar, ...restProps }: Partial<UserDoc>) {\n\t\t\n\t\tObject.assign(this, restProps);\n\t\t\n\t\tlet isEmailUpdated;\n\t\tif (email && this.email !== email) {\n\t\t\tthis.users.byEmail.delete(this.email);\n\t\t\tthis.email = email;\n\t\t\tthis.users.byEmail.set(email, this);\n\t\t\tisEmailUpdated = true;\n\t\t}\n\t\t\n\t\tlet isNameUpdated;\n\t\tlet isLastNameUpdated;\n\t\tif (name && (this.name.first !== name.first || this.name.middle !== name.middle || this.name.last !== name.last)) {\n\t\t\tisLastNameUpdated = this.name.last !== name.last;\n\t\t\tthis.name = {\n\t\t\t\tfirst: name.first ?? \"\",\n\t\t\t\tmiddle: name.middle ?? \"\",\n\t\t\t\tlast: name.last ?? \"\"\n\t\t\t};\n\t\t\tthis.initials = (((name.first?.[0] ?? \"\") + (name.last?.[0] ?? \"\")) || this.email[0]).toUpperCase();\n\t\t\tisNameUpdated = true;\n\t\t}\n\t\t\n\t\tif (isEmailUpdated || isNameUpdated)\n\t\t\tthis.displayLabel = `${this.name.first} ${this.name.last}`.trim() || this.name.middle || this.email;\n\t\t\n\t\tlet isRolesUpdated;\n\t\tif (ownRoleIds) {\n\t\t\tthis.ownRoleIds = ownRoleIds;\n\t\t\t\n\t\t\tconst snapshot = this.ownRoleIds.join(\",\");\n\t\t\t\n\t\t\tif (snapshot !== rolesSnapshots.get(this._id)) {\n\t\t\t\trolesSnapshots.set(this._id, snapshot);\n\t\t\t\tthis.updateRoles();\n\t\t\t\tisRolesUpdated = true;\n\t\t\t}\n\t\t}\n\t\t\n\t\tlet isOrgUpdated;\n\t\tif (orgId !== undefined && this.org?._id !== orgId) {\n\t\t\tthis.org?.users.delete(this);\n\t\t\tthis.org = orgId && this.users.orgs.get(orgId) || this.users.orgs.null;// eslint-disable-line @stylistic/no-mixed-operators\n\t\t\tthis.org.users.add(this);\n\t\t\tisOrgUpdated = true;\n\t\t}\n\t\t\n\t\tif (avatar !== undefined && this.avatar !== avatar) {\n\t\t\tthis.avatar = avatar;\n\t\t\tthis.avatarUrl = avatar && `${staticUrl}/avatars/${this._id}-${avatar}.webp`;\n\t\t}\n\t\t\n\t\tif (isRolesUpdated || isOrgUpdated) {\n\t\t\tthis.updatePermissions();\n\t\t\t\n\t\t\tif (isLastNameUpdated)\n\t\t\t\tthis.users.isSortRequired = true;\n\t\t\t\n\t\t\tif (this.users.isInited)\n\t\t\t\tthis.users.updateDebounced();\n\t\t\t\n\t\t} else if (isLastNameUpdated)\n\t\t\tthis.users.sortDebounced();\n\t\t\n\t}\n\t\n\tupdateRoles() {\n\t\t\n\t\tif (this.users.isInited) {\n\t\t\tthis.ownRoles = [];\n\t\t\tthis.roles.clear();\n\t\t\tthis.slaveRoles.clear();\n\t\t\tempty(this.abilities);\n\t\t\t\n\t\t\tfor (const roleId of this.ownRoleIds) {\n\t\t\t\tconst role = this.users.roles.get(roleId);\n\t\t\t\tif (role) {\n\t\t\t\t\t\n\t\t\t\t\tthis.ownRoles.push(role);\n\t\t\t\t\tthis.roles.add(role);\n\t\t\t\t\tfor (const involvedRole of role.involves) {\n\t\t\t\t\t\tthis.roles.add(involvedRole);\n\t\t\t\t\t\tthis.slaveRoles.add(involvedRole);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tthis.slaveRoleIds = _ids(this.slaveRoles);\n\t\t\t\t\t\n\t\t\t\t\tthis.users.abilitiesMap.merge(this.abilities as GenericAbilities, role.abilities as GenericAbilities);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (this.roles.has(this.users.roles.root))\n\t\t\t\tthis.isRoot = true;\n\t\t\t\n\t\t\tthis.trimSessions();\n\t\t}\n\t\t\n\t}\n\t\n\tupdatePermissions() {\n\t\t\n\t\tif (this.users.isInited) {\n\t\t\tthis.slaveOrgs.clear();\n\t\t\tthis.slaveUsers.clear();\n\t\t\tthis.slaves.clear();\n\t\t\tconst slaveIds = new Set<string>();\n\t\t\t\n\t\t\tfor (const org of this.users.orgs.sorted)\n\t\t\t\tif ((org.ownerUsers.has(this) || this.isRoot) && !this.slaveOrgs.has(org)) {\n\t\t\t\t\tthis.slaveOrgs.add(org);\n\t\t\t\t\tthis.slaves.add(org);\n\t\t\t\t\tslaveIds.add(org._id);\n\t\t\t\t\tfor (const slaveOrg of org.slaveOrgs) {\n\t\t\t\t\t\tthis.slaveOrgs.add(slaveOrg);\n\t\t\t\t\t\tthis.slaves.add(slaveOrg);\n\t\t\t\t\t\tslaveIds.add(slaveOrg._id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\n\t\t\tfor (const org of new Set([ this.org, ...this.slaveOrgs, this.users.orgs.null ]))\n\t\t\t\tfor (const user of org.users)\n\t\t\t\t\tif (user !== this && (hasAny(this.slaveRoles, user.ownRoles) || !user.ownRoles.length)) {\n\t\t\t\t\t\tthis.slaveUsers.add(user);\n\t\t\t\t\t\tthis.slaves.add(user);\n\t\t\t\t\t\tslaveIds.add(user._id);\n\t\t\t\t\t}\n\t\t\t\n\t\t\tthis.slaveIds = [ ...slaveIds ];\n\t\t\t\n\t\t\tconst permissiveOrgIds = [];\n\t\t\tif (this.org._id) {\n\t\t\t\tpermissiveOrgIds.push(this.org._id);\n\t\t\t\tfor (const slaveOrg of this.org.slaveOrgs)\n\t\t\t\t\tif (!this.slaveOrgs.has(slaveOrg))\n\t\t\t\t\t\tpermissiveOrgIds.push(slaveOrg._id);\n\t\t\t}\n\t\t\t\n\t\t\tthis.permissiveIds = [ ...permissiveOrgIds, this._id, ...slaveIds ];\n\t\t\t\n\t\t\t\n\t\t\tconst snapshot = [\n\t\t\t\tthis.permissiveIds.join(\",\"),\n\t\t\t\tthis.ownRoleIds.join(\",\"),\n\t\t\t\tJSON.stringify(this.abilities),\n\t\t\t\tthis.slaveRoleIds.join(\",\")\n\t\t\t].join(\"\\n\");\n\t\t\t\n\t\t\tif (snapshot !== permissionsSnapshots.get(this._id)) {\n\t\t\t\tpermissionsSnapshots.set(this._id, snapshot);\n\t\t\t\t\n\t\t\t\tthis.users.emit(\"user-permissions-change\", this);\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\ttrimSessions() {\n\t\t\n\t\tconst sessionsLimit = this.abilities.login?.sessionsLimit ?? 0;\n\t\t\n\t\tif (this.sessions.size > sessionsLimit)\n\t\t\treturn this.users.sessions.collection.deleteMany({\n\t\t\t\t_id: {\n\t\t\t\t\t$in: _ids(\n\t\t\t\t\t\t[ ...this.sessions ]\n\t\t\t\t\t\t\t.sort((a, b) => a.expiresAt.valueOf() - b.expiresAt.valueOf())\n\t\t\t\t\t\t\t.slice(0, this.sessions.size - sessionsLimit)\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t});\n\t\t\n\t\treturn null;\n\t}\n\t\n\tupdateIsOnline = debounce(() => {\n\t\t\n\t\tlet isOnline = false;\n\t\t\n\t\tfor (const session of this.sessions)\n\t\t\tif (session.isOnline) {\n\t\t\t\tisOnline = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\n\t\tif (this.isOnline !== isOnline) {\n\t\t\tthis.isOnline = isOnline;\n\t\t\tthis.users.emit(\"user-is-online\", this);\n\t\t}\n\t\t\n\t}, 500);\n\t\n\tdelete() {\n\t\t\n\t\tthis.org.users.delete(this);\n\t\t\n\t\tthis.users.delete(this._id);\n\t\tthis.users.byEmail.delete(this.email);\n\t\tremoveOne(this.users.sorted, this);\n\t\t\n\t\trolesSnapshots.delete(this._id);\n\t\tpermissionsSnapshots.delete(this._id);\n\t\t\n\t\tthis.users.replace(this._id);\n\t\t\n\t\tthis.users.updateDebounced();\n\t\t\n\t}\n\t\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["argon2", "EventEmitter", "_ids", "debounce", "deleteProps", "removeAll", "newObjectIdString", "empty", "intersection", "isAbilityWithParams", "value", "isAbilityParamNumber", "isAbilityParamItems", "AbilitiesMap", "schema", "list", "ability", "target", "source", "abilityId", "targetAbility", "sourceAbility", "param", "targetItems", "itemId", "_id", "abilities", "item", "user", "resolve", "abilitiesSchema", "userAbility", "userParam", "j", "adjustedAbilities", "isAdjusted", "abilitySchema", "adjustedAbility", "paramSchema", "paramValue", "adjustedParamValue", "paramId", "debounce", "deleteProps", "EmptyArray", "EmptySet", "removeAll", "sort", "newObjectIdString", "snapshots", "Org", "orgs", "orgDoc", "_id", "title", "ownerIds", "restProps", "next", "snapshot", "regexps", "basisSchema", "regexps", "indexes", "preventDirectDelete", "Orgs", "users", "options", "orgDoc", "Org", "org", "slaveOrgs", "ownerOrg", "slaveOrg", "array", "sorted", "ownerId", "ownerUser", "anotherOrg", "sort", "i", "slaveOrgIndex", "length", "o", "a", "b", "debounce", "customSchema", "customIndexes", "nullProps", "removeAll", "basisSchema", "deleteProps", "jsonSchema", "EmptyArray", "EmptySet", "next", "title", "note", "restProps", "newObjectIdString", "_id", "fromId", "toId", "handler", "debounce", "deleteProps", "getAll", "intersection", "reAdd", "removeAll", "snapshots", "Role", "roles", "roleDoc", "_id", "ownInvolveIds", "ownAbilities", "title", "restProps", "next", "snapshot", "basisSchema", "regexps", "indexes", "preventDirectDelete", "Roles", "users", "options", "rootProps", "initOptions", "Role", "roleDoc", "role", "involvedBy", "involvedRoleId", "involvedRole", "involvedByRole", "reAdd", "a", "b", "array", "anotherRole", "getAll", "sorted", "involvedRoleIndex", "_o", "debounce", "customSchema", "customIndexes", "removeAll", "basisSchema", "deleteProps", "jsonSchema", "next", "_id", "involves", "title", "description", "restProps", "ids", "roles", "intersection", "cleanedUpIds", "crypto", "deleteProps", "random", "removeAll", "basisSchema", "regexps", "Session", "sessions", "sessionDoc", "user", "_id", "isOnline", "restProps", "updates", "ts", "expireAfterSeconds", "indexes", "Sessions", "users", "options", "_id", "crypto", "random", "sessionDoc", "Session", "customSchema", "customIndexes", "removeAll", "basisSchema", "deleteProps", "jsonSchema", "next", "user", "props", "ts", "session", "schema", "regexps", "Avatars", "users", "schema", "basisSchema", "regexps", "_ids", "debounce", "empty", "hasAny", "removeOne", "rolesSnapshots", "permissionsSnapshots", "staticUrl", "User", "users", "userDoc", "_id", "name", "email", "ownRoleIds", "orgId", "avatar", "restProps", "isEmailUpdated", "isNameUpdated", "isLastNameUpdated", "isRolesUpdated", "snapshot", "isOrgUpdated", "roleId", "role", "involvedRole", "slaveIds", "org", "slaveOrg", "user", "permissiveOrgIds", "sessionsLimit", "a", "b", "isOnline", "session", "indexes", "Users", "_Users", "collections", "options", "eventEmitter", "EventEmitter", "AbilitiesMap", "userDoc", "User", "a", "b", "debounce", "shouldUpdateRoles", "user", "customIndexes", "customSchema", "initialRootProps", "removeAll", "basisSchema", "deleteProps", "jsonSchema", "rolesOptions", "orgsOptions", "sessionsOptions", "Roles", "Orgs", "Sessions", "Avatars", "next", "email", "password", "roles", "name", "org", "job", "restProps", "newObjectIdString", "_id", "newPassword", "sessionProps", "session", "Org", "ids", "_ids", "fromId", "toId", "handler"]
7
7
  }
@@ -8,6 +8,7 @@ export type SessionDoc = {
8
8
  createdAt: number;
9
9
  prolongedAt: number;
10
10
  expiresAt: Date;
11
+ [customProp: string]: unknown;
11
12
  };
12
13
  export type SessionsOptions = {
13
14
  schema?: InSiteCollectionSchema;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAG5E,MAAM,MAAM,UAAU,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC7B,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC,OAAO,CAAC,EAAE,uBAAuB,CAAC;CAClC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAG5E,MAAM,MAAM,UAAU,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC7B,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC,OAAO,CAAC,EAAE,uBAAuB,CAAC;CAClC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "insite-users-server",
3
- "version": "2.0.79",
3
+ "version": "2.0.80",
4
4
  "description": "inSite users server side",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",