mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-13 19:58:09 +00:00
uberf-8544: improve memdb account handling (#7047)
Signed-off-by: Alexey Zinoviev <alexey.zinoviev@xored.com>
This commit is contained in:
parent
3b52779876
commit
db4e6e1945
@ -29,7 +29,7 @@ import {
|
||||
SearchResult
|
||||
} from '../storage'
|
||||
import { Tx } from '../tx'
|
||||
import { genMinModel, test, TestMixin } from './minmodel'
|
||||
import { createDoc, deleteDoc, genMinModel, test, TestMixin, updateDoc } from './minmodel'
|
||||
|
||||
const txes = genMinModel()
|
||||
|
||||
@ -59,17 +59,17 @@ class ClientModel extends ModelDb implements Client {
|
||||
async close (): Promise<void> {}
|
||||
}
|
||||
|
||||
async function createModel (): Promise<{ model: ClientModel, hierarchy: Hierarchy, txDb: TxDb }> {
|
||||
async function createModel (modelTxes: Tx[] = txes): Promise<{ model: ClientModel, hierarchy: Hierarchy, txDb: TxDb }> {
|
||||
const hierarchy = new Hierarchy()
|
||||
for (const tx of txes) {
|
||||
for (const tx of modelTxes) {
|
||||
hierarchy.tx(tx)
|
||||
}
|
||||
const model = new ClientModel(hierarchy)
|
||||
for (const tx of txes) {
|
||||
for (const tx of modelTxes) {
|
||||
await model.tx(tx)
|
||||
}
|
||||
const txDb = new TxDb(hierarchy)
|
||||
for (const tx of txes) await txDb.tx(tx)
|
||||
for (const tx of modelTxes) await txDb.tx(tx)
|
||||
return { model, hierarchy, txDb }
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ describe('memdb', () => {
|
||||
const { txDb } = await createModel()
|
||||
|
||||
const result = await txDb.findAll(core.class.Tx, {})
|
||||
expect(result.length).toBe(txes.filter((tx) => tx._class === core.class.TxCreateDoc).length)
|
||||
expect(result.length).toBe(txes.length)
|
||||
})
|
||||
|
||||
it('should create space', async () => {
|
||||
@ -396,4 +396,41 @@ describe('memdb', () => {
|
||||
expect(e).toEqual(new Error('createDoc cannot be used for objects inherited from AttachedDoc'))
|
||||
}
|
||||
})
|
||||
|
||||
it('has correct accounts', async () => {
|
||||
const modTxes = [...txes]
|
||||
|
||||
modTxes.push(
|
||||
createDoc(core.class.Account, {
|
||||
email: 'system_admin',
|
||||
role: AccountRole.Owner
|
||||
})
|
||||
)
|
||||
|
||||
const system1Account = createDoc(core.class.Account, {
|
||||
email: 'system1',
|
||||
role: AccountRole.Maintainer
|
||||
})
|
||||
modTxes.push(system1Account)
|
||||
|
||||
const user1Account = createDoc(core.class.Account, {
|
||||
email: 'user1',
|
||||
role: AccountRole.User
|
||||
})
|
||||
modTxes.push(user1Account)
|
||||
|
||||
modTxes.push(updateDoc(core.class.Account, core.space.Model, system1Account.objectId, { email: 'user1' }))
|
||||
|
||||
modTxes.push(deleteDoc(core.class.Account, core.space.Model, user1Account.objectId))
|
||||
|
||||
const { model } = await createModel(modTxes)
|
||||
|
||||
expect(model.getAccountByEmail('system_admin')).not.toBeUndefined()
|
||||
expect(model.getAccountByEmail('system_admin')?.role).toBe(AccountRole.Owner)
|
||||
|
||||
expect(model.getAccountByEmail('system1')).toBeUndefined()
|
||||
|
||||
expect(model.getAccountByEmail('user1')).not.toBeUndefined()
|
||||
expect(model.getAccountByEmail('user1')?.role).toBe(AccountRole.Maintainer)
|
||||
})
|
||||
})
|
||||
|
@ -15,10 +15,10 @@
|
||||
|
||||
import type { IntlString, Plugin } from '@hcengineering/platform'
|
||||
import { plugin } from '@hcengineering/platform'
|
||||
import type { Arr, Class, Data, Doc, Interface, Mixin, Obj, Ref } from '../classes'
|
||||
import type { Arr, Class, Data, Doc, Interface, Mixin, Obj, Ref, Space } from '../classes'
|
||||
import { AttachedDoc, ClassifierKind, DOMAIN_MODEL } from '../classes'
|
||||
import core from '../component'
|
||||
import type { TxCUD, TxCreateDoc } from '../tx'
|
||||
import type { DocumentUpdate, TxCUD, TxCreateDoc, TxRemoveDoc, TxUpdateDoc } from '../tx'
|
||||
import { DOMAIN_TX, TxFactory } from '../tx'
|
||||
|
||||
const txFactory = new TxFactory(core.account.System)
|
||||
@ -31,10 +31,23 @@ function createInterface (_interface: Ref<Interface<Doc>>, attributes: Data<Inte
|
||||
return txFactory.createTxCreateDoc(core.class.Interface, core.space.Model, attributes, _interface)
|
||||
}
|
||||
|
||||
export function createDoc<T extends Doc> (_class: Ref<Class<T>>, attributes: Data<T>): TxCreateDoc<Doc> {
|
||||
export function createDoc<T extends Doc> (_class: Ref<Class<T>>, attributes: Data<T>): TxCreateDoc<T> {
|
||||
return txFactory.createTxCreateDoc(_class, core.space.Model, attributes)
|
||||
}
|
||||
|
||||
export function updateDoc<T extends Doc> (
|
||||
_class: Ref<Class<T>>,
|
||||
space: Ref<Space>,
|
||||
objectId: Ref<T>,
|
||||
operations: DocumentUpdate<T>
|
||||
): TxUpdateDoc<Doc> {
|
||||
return txFactory.createTxUpdateDoc(_class, space, objectId, operations)
|
||||
}
|
||||
|
||||
export function deleteDoc<T extends Doc> (_class: Ref<Class<T>>, space: Ref<Space>, objectId: Ref<T>): TxRemoveDoc<Doc> {
|
||||
return txFactory.createTxRemoveDoc(_class, space, objectId)
|
||||
}
|
||||
|
||||
export interface TestMixin extends Doc {
|
||||
arr: Arr<string>
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ export abstract class MemDb extends TxProcessor implements Storage {
|
||||
private readonly objectById = new Map<Ref<Doc>, Doc>()
|
||||
|
||||
private readonly accountByPersonId = new Map<Ref<Doc>, Account[]>()
|
||||
private readonly accountByEmail = new Map<string, Account>()
|
||||
private readonly accountByEmail = new Map<string, [string, Account][]>()
|
||||
|
||||
constructor (protected readonly hierarchy: Hierarchy) {
|
||||
super()
|
||||
@ -83,7 +83,14 @@ export abstract class MemDb extends TxProcessor implements Storage {
|
||||
}
|
||||
|
||||
getAccountByEmail (email: Account['email']): Account | undefined {
|
||||
return this.accountByEmail.get(email)
|
||||
const accounts = this.accountByEmail.get(email)
|
||||
if (accounts === undefined || accounts.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
if (accounts.length > 0) {
|
||||
return accounts[accounts.length - 1][1]
|
||||
}
|
||||
}
|
||||
|
||||
findObject<T extends Doc>(_id: Ref<T>): T | undefined {
|
||||
@ -225,6 +232,14 @@ export abstract class MemDb extends TxProcessor implements Storage {
|
||||
)
|
||||
}
|
||||
|
||||
addAccount (account: Account): void {
|
||||
if (!this.accountByEmail.has(account.email)) {
|
||||
this.accountByEmail.set(account.email, [])
|
||||
}
|
||||
|
||||
this.accountByEmail.get(account.email)?.push([account._id, account])
|
||||
}
|
||||
|
||||
addDoc (doc: Doc): void {
|
||||
this.hierarchy.getAncestors(doc._class).forEach((_class) => {
|
||||
const arr = this.getObjectsByClass(_class)
|
||||
@ -232,7 +247,9 @@ export abstract class MemDb extends TxProcessor implements Storage {
|
||||
})
|
||||
if (this.hierarchy.isDerived(doc._class, core.class.Account)) {
|
||||
const account = doc as Account
|
||||
this.accountByEmail.set(account.email, account)
|
||||
|
||||
this.addAccount(account)
|
||||
|
||||
if (account.person !== undefined) {
|
||||
this.accountByPersonId.set(account.person, [...(this.accountByPersonId.get(account.person) ?? []), account])
|
||||
}
|
||||
@ -240,6 +257,19 @@ export abstract class MemDb extends TxProcessor implements Storage {
|
||||
this.objectById.set(doc._id, doc)
|
||||
}
|
||||
|
||||
delAccount (account: Account): void {
|
||||
const accounts = this.accountByEmail.get(account.email)
|
||||
if (accounts !== undefined) {
|
||||
const newAccounts = accounts.filter((it) => it[0] !== account._id)
|
||||
|
||||
if (newAccounts.length === 0) {
|
||||
this.accountByEmail.delete(account.email)
|
||||
} else {
|
||||
this.accountByEmail.set(account.email, newAccounts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delDoc (_id: Ref<Doc>): void {
|
||||
const doc = this.objectById.get(_id)
|
||||
if (doc === undefined) {
|
||||
@ -251,7 +281,8 @@ export abstract class MemDb extends TxProcessor implements Storage {
|
||||
})
|
||||
if (this.hierarchy.isDerived(doc._class, core.class.Account)) {
|
||||
const account = doc as Account
|
||||
this.accountByEmail.delete(account.email)
|
||||
this.delAccount(account)
|
||||
|
||||
if (account.person !== undefined) {
|
||||
const acc = this.accountByPersonId.get(account.person) ?? []
|
||||
this.accountByPersonId.set(
|
||||
@ -280,8 +311,8 @@ export abstract class MemDb extends TxProcessor implements Storage {
|
||||
}
|
||||
} else if (newEmail !== undefined) {
|
||||
const account = doc as Account
|
||||
this.accountByEmail.delete(account.email)
|
||||
this.accountByEmail.set(newEmail, account)
|
||||
this.delAccount(account)
|
||||
this.addAccount({ ...account, email: newEmail })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user