Skip to content

Commit db4e6e1

Browse files
authored
uberf-8544: improve memdb account handling (#7047)
Signed-off-by: Alexey Zinoviev <alexey.zinoviev@xored.com>
1 parent 3b52779 commit db4e6e1

File tree

3 files changed

+96
-15
lines changed

3 files changed

+96
-15
lines changed

packages/core/src/__tests__/memdb.test.ts

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
SearchResult
3030
} from '../storage'
3131
import { Tx } from '../tx'
32-
import { genMinModel, test, TestMixin } from './minmodel'
32+
import { createDoc, deleteDoc, genMinModel, test, TestMixin, updateDoc } from './minmodel'
3333

3434
const txes = genMinModel()
3535

@@ -59,17 +59,17 @@ class ClientModel extends ModelDb implements Client {
5959
async close (): Promise<void> {}
6060
}
6161

62-
async function createModel (): Promise<{ model: ClientModel, hierarchy: Hierarchy, txDb: TxDb }> {
62+
async function createModel (modelTxes: Tx[] = txes): Promise<{ model: ClientModel, hierarchy: Hierarchy, txDb: TxDb }> {
6363
const hierarchy = new Hierarchy()
64-
for (const tx of txes) {
64+
for (const tx of modelTxes) {
6565
hierarchy.tx(tx)
6666
}
6767
const model = new ClientModel(hierarchy)
68-
for (const tx of txes) {
68+
for (const tx of modelTxes) {
6969
await model.tx(tx)
7070
}
7171
const txDb = new TxDb(hierarchy)
72-
for (const tx of txes) await txDb.tx(tx)
72+
for (const tx of modelTxes) await txDb.tx(tx)
7373
return { model, hierarchy, txDb }
7474
}
7575

@@ -78,7 +78,7 @@ describe('memdb', () => {
7878
const { txDb } = await createModel()
7979

8080
const result = await txDb.findAll(core.class.Tx, {})
81-
expect(result.length).toBe(txes.filter((tx) => tx._class === core.class.TxCreateDoc).length)
81+
expect(result.length).toBe(txes.length)
8282
})
8383

8484
it('should create space', async () => {
@@ -396,4 +396,41 @@ describe('memdb', () => {
396396
expect(e).toEqual(new Error('createDoc cannot be used for objects inherited from AttachedDoc'))
397397
}
398398
})
399+
400+
it('has correct accounts', async () => {
401+
const modTxes = [...txes]
402+
403+
modTxes.push(
404+
createDoc(core.class.Account, {
405+
email: 'system_admin',
406+
role: AccountRole.Owner
407+
})
408+
)
409+
410+
const system1Account = createDoc(core.class.Account, {
411+
email: 'system1',
412+
role: AccountRole.Maintainer
413+
})
414+
modTxes.push(system1Account)
415+
416+
const user1Account = createDoc(core.class.Account, {
417+
email: 'user1',
418+
role: AccountRole.User
419+
})
420+
modTxes.push(user1Account)
421+
422+
modTxes.push(updateDoc(core.class.Account, core.space.Model, system1Account.objectId, { email: 'user1' }))
423+
424+
modTxes.push(deleteDoc(core.class.Account, core.space.Model, user1Account.objectId))
425+
426+
const { model } = await createModel(modTxes)
427+
428+
expect(model.getAccountByEmail('system_admin')).not.toBeUndefined()
429+
expect(model.getAccountByEmail('system_admin')?.role).toBe(AccountRole.Owner)
430+
431+
expect(model.getAccountByEmail('system1')).toBeUndefined()
432+
433+
expect(model.getAccountByEmail('user1')).not.toBeUndefined()
434+
expect(model.getAccountByEmail('user1')?.role).toBe(AccountRole.Maintainer)
435+
})
399436
})

packages/core/src/__tests__/minmodel.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515

1616
import type { IntlString, Plugin } from '@hcengineering/platform'
1717
import { plugin } from '@hcengineering/platform'
18-
import type { Arr, Class, Data, Doc, Interface, Mixin, Obj, Ref } from '../classes'
18+
import type { Arr, Class, Data, Doc, Interface, Mixin, Obj, Ref, Space } from '../classes'
1919
import { AttachedDoc, ClassifierKind, DOMAIN_MODEL } from '../classes'
2020
import core from '../component'
21-
import type { TxCUD, TxCreateDoc } from '../tx'
21+
import type { DocumentUpdate, TxCUD, TxCreateDoc, TxRemoveDoc, TxUpdateDoc } from '../tx'
2222
import { DOMAIN_TX, TxFactory } from '../tx'
2323

2424
const txFactory = new TxFactory(core.account.System)
@@ -31,10 +31,23 @@ function createInterface (_interface: Ref<Interface<Doc>>, attributes: Data<Inte
3131
return txFactory.createTxCreateDoc(core.class.Interface, core.space.Model, attributes, _interface)
3232
}
3333

34-
export function createDoc<T extends Doc> (_class: Ref<Class<T>>, attributes: Data<T>): TxCreateDoc<Doc> {
34+
export function createDoc<T extends Doc> (_class: Ref<Class<T>>, attributes: Data<T>): TxCreateDoc<T> {
3535
return txFactory.createTxCreateDoc(_class, core.space.Model, attributes)
3636
}
3737

38+
export function updateDoc<T extends Doc> (
39+
_class: Ref<Class<T>>,
40+
space: Ref<Space>,
41+
objectId: Ref<T>,
42+
operations: DocumentUpdate<T>
43+
): TxUpdateDoc<Doc> {
44+
return txFactory.createTxUpdateDoc(_class, space, objectId, operations)
45+
}
46+
47+
export function deleteDoc<T extends Doc> (_class: Ref<Class<T>>, space: Ref<Space>, objectId: Ref<T>): TxRemoveDoc<Doc> {
48+
return txFactory.createTxRemoveDoc(_class, space, objectId)
49+
}
50+
3851
export interface TestMixin extends Doc {
3952
arr: Arr<string>
4053
}

packages/core/src/memdb.ts

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export abstract class MemDb extends TxProcessor implements Storage {
3232
private readonly objectById = new Map<Ref<Doc>, Doc>()
3333

3434
private readonly accountByPersonId = new Map<Ref<Doc>, Account[]>()
35-
private readonly accountByEmail = new Map<string, Account>()
35+
private readonly accountByEmail = new Map<string, [string, Account][]>()
3636

3737
constructor (protected readonly hierarchy: Hierarchy) {
3838
super()
@@ -83,7 +83,14 @@ export abstract class MemDb extends TxProcessor implements Storage {
8383
}
8484

8585
getAccountByEmail (email: Account['email']): Account | undefined {
86-
return this.accountByEmail.get(email)
86+
const accounts = this.accountByEmail.get(email)
87+
if (accounts === undefined || accounts.length === 0) {
88+
return undefined
89+
}
90+
91+
if (accounts.length > 0) {
92+
return accounts[accounts.length - 1][1]
93+
}
8794
}
8895

8996
findObject<T extends Doc>(_id: Ref<T>): T | undefined {
@@ -225,21 +232,44 @@ export abstract class MemDb extends TxProcessor implements Storage {
225232
)
226233
}
227234

235+
addAccount (account: Account): void {
236+
if (!this.accountByEmail.has(account.email)) {
237+
this.accountByEmail.set(account.email, [])
238+
}
239+
240+
this.accountByEmail.get(account.email)?.push([account._id, account])
241+
}
242+
228243
addDoc (doc: Doc): void {
229244
this.hierarchy.getAncestors(doc._class).forEach((_class) => {
230245
const arr = this.getObjectsByClass(_class)
231246
arr.set(doc._id, doc)
232247
})
233248
if (this.hierarchy.isDerived(doc._class, core.class.Account)) {
234249
const account = doc as Account
235-
this.accountByEmail.set(account.email, account)
250+
251+
this.addAccount(account)
252+
236253
if (account.person !== undefined) {
237254
this.accountByPersonId.set(account.person, [...(this.accountByPersonId.get(account.person) ?? []), account])
238255
}
239256
}
240257
this.objectById.set(doc._id, doc)
241258
}
242259

260+
delAccount (account: Account): void {
261+
const accounts = this.accountByEmail.get(account.email)
262+
if (accounts !== undefined) {
263+
const newAccounts = accounts.filter((it) => it[0] !== account._id)
264+
265+
if (newAccounts.length === 0) {
266+
this.accountByEmail.delete(account.email)
267+
} else {
268+
this.accountByEmail.set(account.email, newAccounts)
269+
}
270+
}
271+
}
272+
243273
delDoc (_id: Ref<Doc>): void {
244274
const doc = this.objectById.get(_id)
245275
if (doc === undefined) {
@@ -251,7 +281,8 @@ export abstract class MemDb extends TxProcessor implements Storage {
251281
})
252282
if (this.hierarchy.isDerived(doc._class, core.class.Account)) {
253283
const account = doc as Account
254-
this.accountByEmail.delete(account.email)
284+
this.delAccount(account)
285+
255286
if (account.person !== undefined) {
256287
const acc = this.accountByPersonId.get(account.person) ?? []
257288
this.accountByPersonId.set(
@@ -280,8 +311,8 @@ export abstract class MemDb extends TxProcessor implements Storage {
280311
}
281312
} else if (newEmail !== undefined) {
282313
const account = doc as Account
283-
this.accountByEmail.delete(account.email)
284-
this.accountByEmail.set(newEmail, account)
314+
this.delAccount(account)
315+
this.addAccount({ ...account, email: newEmail })
285316
}
286317
}
287318
}

0 commit comments

Comments
 (0)