Skip to content

Commit

Permalink
feat: sample-type and instrument
Browse files Browse the repository at this point in the history
  • Loading branch information
wermarter committed Jan 25, 2024
1 parent 09090dc commit 7414579
Show file tree
Hide file tree
Showing 65 changed files with 1,215 additions and 170 deletions.
4 changes: 4 additions & 0 deletions apps/hcdc-access-service/src/domain/auth/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { AuthSubject, AuthSubjectUnionType } from './subject'
import {
BioProductAction,
BranchAction,
InstrumentAction,
RoleAction,
SampleTypeAction,
TestCategoryAction,
UserAction,
} from '../entity'
Expand All @@ -16,6 +18,8 @@ export const AuthAction = {
Branch: stringEnumValues(BranchAction),
Role: stringEnumValues(RoleAction),
User: stringEnumValues(UserAction),
Instrument: stringEnumValues(InstrumentAction),
SampleType: stringEnumValues(SampleTypeAction),
} satisfies Record<keyof typeof AuthSubject, string[]>

export const AuthActionValues = [
Expand Down
14 changes: 13 additions & 1 deletion apps/hcdc-access-service/src/domain/auth/subject.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { RecordTypes } from '@casl/mongoose'

import { BioProduct, Branch, Role, TestCategory, User } from '../entity'
import {
BioProduct,
Branch,
Instrument,
Role,
SampleType,
TestCategory,
User,
} from '../entity'
import { AUTH_SUBJECT_ALL } from './constants'

// key-value must be identical for working with '@casl/mongoose'.accessibleBy()
Expand All @@ -10,6 +18,8 @@ export const AuthSubject = {
Branch: 'Branch',
Role: 'Role',
User: 'User',
Instrument: 'Instrument',
SampleType: 'SampleType',
} satisfies Record<keyof RecordTypes, keyof RecordTypes>

export type AuthSubjectUnionType = keyof typeof AuthSubject
Expand All @@ -25,4 +35,6 @@ export type SubjectEntityMapping = {
Branch: Branch
Role: Role
User: User
Instrument: Instrument
SampleType: SampleType
}
2 changes: 2 additions & 0 deletions apps/hcdc-access-service/src/domain/entity/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export * from './base-entity'

export * from './bio-product'
export * from './instrument'
export * from './sample-type'
export * from './test-category'
export * from './role'
export * from './user'
Expand Down
14 changes: 14 additions & 0 deletions apps/hcdc-access-service/src/domain/entity/instrument/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import '@casl/mongoose'

export enum InstrumentAction {
Create = 'Create',
Read = 'Read',
Update = 'Update',
Delete = 'Delete',
}

declare module '@casl/mongoose' {
interface RecordTypes {
Instrument: true
}
}
10 changes: 10 additions & 0 deletions apps/hcdc-access-service/src/domain/entity/instrument/entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { BaseEntity } from '../base-entity'
import { Branch } from '../branch'

export type Instrument = BaseEntity & {
displayIndex: number
name: string

branchId: string
branch?: Branch | null
}
17 changes: 17 additions & 0 deletions apps/hcdc-access-service/src/domain/entity/instrument/example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { exampleMongoObjectId } from '@diut/nest-core'

import { EntityDataExample } from '../base-entity'
import { Instrument } from './entity'

export const exampleInstrument = {
displayIndex: {
example: 1,
},
name: {
example: 'máy xét nghiệm A',
},
branchId: exampleMongoObjectId,
branch: {
required: false,
},
} satisfies EntityDataExample<Instrument>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './entity'
export * from './example'
export * from './auth'
14 changes: 14 additions & 0 deletions apps/hcdc-access-service/src/domain/entity/sample-type/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import '@casl/mongoose'

export enum SampleTypeAction {
Create = 'Create',
Read = 'Read',
Update = 'Update',
Delete = 'Delete',
}

declare module '@casl/mongoose' {
interface RecordTypes {
SampleType: true
}
}
10 changes: 10 additions & 0 deletions apps/hcdc-access-service/src/domain/entity/sample-type/entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { BaseEntity } from '../base-entity'
import { Branch } from '../branch'

export type SampleType = BaseEntity & {
displayIndex: number
name: string

branchId: string
branch?: Branch | null
}
17 changes: 17 additions & 0 deletions apps/hcdc-access-service/src/domain/entity/sample-type/example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { exampleMongoObjectId } from '@diut/nest-core'

import { EntityDataExample } from '../base-entity'
import { SampleType } from './entity'

export const exampleSampleType = {
displayIndex: {
example: 1,
},
name: {
example: 'máu',
},
branchId: exampleMongoObjectId,
branch: {
required: false,
},
} satisfies EntityDataExample<SampleType>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './entity'
export * from './example'
export * from './auth'
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export * from './test-category'
export * from './user'
export * from './branch'
export * from './role'
export * from './instrument'
export * from './sample-type'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Instrument } from 'src/domain/entity'
import { IRepository } from './interface'

export const InstrumentRepositoryToken = Symbol('InstrumentRepository')

export interface IInstrumentRepository extends IRepository<Instrument> {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { SampleType } from 'src/domain/entity'
import { IRepository } from './interface'

export const SampleTypeRepositoryToken = Symbol('SampleTypeRepository')

export interface ISampleTypeRepository extends IRepository<SampleType> {}
18 changes: 18 additions & 0 deletions apps/hcdc-access-service/src/domain/use-case/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,24 @@ export * from './bio-product/assert-exists'
export * from './bio-product/validate'
export * from './bio-product/authorize-populates'

export * from './instrument/create'
export * from './instrument/find-one'
export * from './instrument/update'
export * from './instrument/delete'
export * from './instrument/search'
export * from './instrument/assert-exists'
export * from './instrument/validate'
export * from './instrument/authorize-populates'

export * from './sample-type/create'
export * from './sample-type/find-one'
export * from './sample-type/update'
export * from './sample-type/delete'
export * from './sample-type/search'
export * from './sample-type/assert-exists'
export * from './sample-type/validate'
export * from './sample-type/authorize-populates'

export * from './test-category/create'
export * from './test-category/find-one'
export * from './test-category/update'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Inject, Injectable } from '@nestjs/common'

import { Instrument } from 'src/domain/entity'
import { EEntityNotFound } from 'src/domain/exception'
import {
InstrumentRepositoryToken,
EntityFindOneOptions,
IInstrumentRepository,
} from 'src/domain/interface'

@Injectable()
export class InstrumentAssertExistsUseCase {
constructor(
@Inject(InstrumentRepositoryToken)
private readonly instrumentRepository: IInstrumentRepository,
) {}

async execute(input: EntityFindOneOptions<Instrument>['filter']) {
const rv = await this.instrumentRepository.findOne({ filter: input })

if (rv === null) {
throw new EEntityNotFound(`Instrument ${JSON.stringify(input)}`)
}

return rv
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Inject, Injectable } from '@nestjs/common'

import { AuthSubject, authorizePopulates } from 'src/domain/auth'
import { BranchAction, Instrument } from 'src/domain/entity'
import { EEntityPopulatePathUnknown } from 'src/domain/exception'
import {
AuthContextToken,
EntityFindOneOptions,
IAuthContext,
} from 'src/domain/interface'

@Injectable()
export class InstrumentAuthorizePopulatesUseCase {
constructor(
@Inject(AuthContextToken)
private readonly authContext: IAuthContext,
) {}
execute(input: EntityFindOneOptions<Instrument>['populates']) {
const { ability } = this.authContext.getData()

return authorizePopulates(ability, input, (path) => {
switch (path) {
case 'branch':
return { subject: AuthSubject.Branch, action: BranchAction.Read }
default:
throw new EEntityPopulatePathUnknown(path)
}
})
}
}
37 changes: 37 additions & 0 deletions apps/hcdc-access-service/src/domain/use-case/instrument/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Inject, Injectable } from '@nestjs/common'

import {
AuthContextToken,
InstrumentRepositoryToken,
IAuthContext,
IInstrumentRepository,
} from 'src/domain/interface'
import { Instrument, InstrumentAction, EntityData } from 'src/domain/entity'
import { AuthSubject, assertPermission } from 'src/domain/auth'
import { InstrumentValidateUseCase } from './validate'

@Injectable()
export class InstrumentCreateUseCase {
constructor(
@Inject(AuthContextToken)
private readonly authContext: IAuthContext,
@Inject(InstrumentRepositoryToken)
private readonly instrumentRepository: IInstrumentRepository,
private readonly instrumentValidateUseCase: InstrumentValidateUseCase,
) {}

async execute(input: EntityData<Instrument>) {
const { ability } = this.authContext.getData()
assertPermission(
ability,
AuthSubject.Instrument,
InstrumentAction.Create,
input,
)
await this.instrumentValidateUseCase.execute(input)

const entity = await this.instrumentRepository.create(input)

return entity
}
}
39 changes: 39 additions & 0 deletions apps/hcdc-access-service/src/domain/use-case/instrument/delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Inject, Injectable } from '@nestjs/common'

import { InstrumentAction } from 'src/domain/entity'
import { AuthSubject, assertPermission } from 'src/domain/auth'
import {
AuthContextToken,
InstrumentRepositoryToken,
IAuthContext,
IInstrumentRepository,
} from 'src/domain/interface'
import { InstrumentAssertExistsUseCase } from './assert-exists'

@Injectable()
export class InstrumentDeleteUseCase {
constructor(
@Inject(AuthContextToken)
private readonly authContext: IAuthContext,
@Inject(InstrumentRepositoryToken)
private readonly instrumentRepository: IInstrumentRepository,
private readonly instrumentAssertExistsUseCase: InstrumentAssertExistsUseCase,
) {}

async execute(input: { id: string }) {
const entity = await this.instrumentAssertExistsUseCase.execute({
_id: input.id,
})
const { ability } = this.authContext.getData()
assertPermission(
ability,
AuthSubject.Instrument,
InstrumentAction.Delete,
entity,
)

await this.instrumentRepository.deleteById(input.id)

return entity
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Inject, Injectable } from '@nestjs/common'

import { Instrument, InstrumentAction } from 'src/domain/entity'
import { AuthSubject, assertPermission } from 'src/domain/auth'
import {
AuthContextToken,
InstrumentRepositoryToken,
EntityFindOneOptions,
IAuthContext,
IInstrumentRepository,
} from 'src/domain/interface'
import { InstrumentAuthorizePopulatesUseCase } from './authorize-populates'

@Injectable()
export class InstrumentFindOneUseCase {
constructor(
@Inject(InstrumentRepositoryToken)
private readonly instrumentRepository: IInstrumentRepository,
@Inject(AuthContextToken)
private readonly authContext: IAuthContext,
private readonly instrumentAuthorizePopulatesUseCase: InstrumentAuthorizePopulatesUseCase,
) {}

async execute(input: EntityFindOneOptions<Instrument>) {
input.populates = this.instrumentAuthorizePopulatesUseCase.execute(
input.populates,
)
const entity = await this.instrumentRepository.findOne(input)
const { ability } = this.authContext.getData()
assertPermission(
ability,
AuthSubject.Instrument,
InstrumentAction.Read,
entity,
)

return entity
}
}
Loading

0 comments on commit 7414579

Please sign in to comment.