Skip to content

Commit

Permalink
update schema
Browse files Browse the repository at this point in the history
  • Loading branch information
wermarter committed Jan 24, 2024
1 parent 3673b57 commit 5773b72
Show file tree
Hide file tree
Showing 42 changed files with 245 additions and 76 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('indexing collections...')
6 changes: 5 additions & 1 deletion apps/hcdc-access-service/src/domain/auth/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
TestCategoryAction,
UserAction,
} from '../entity'
import { AUTH_ACTION_ALL } from './constants'

export const AuthAction = {
BioProduct: stringEnumValues(BioProductAction),
Expand All @@ -17,7 +18,10 @@ export const AuthAction = {
User: stringEnumValues(UserAction),
} satisfies Record<keyof typeof AuthSubject, string[]>

export const AuthActionValues = [...new Set(Object.values(AuthAction).flat())]
export const AuthActionValues = [
...new Set(Object.values(AuthAction).flat()),
AUTH_ACTION_ALL,
]

export type AuthActionUnionType =
(typeof AuthAction)[AuthSubjectUnionType][number]
2 changes: 2 additions & 0 deletions apps/hcdc-access-service/src/domain/auth/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const AUTH_SUBJECT_ALL = 'all'
export const AUTH_ACTION_ALL = 'manage'
1 change: 1 addition & 0 deletions apps/hcdc-access-service/src/domain/auth/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './action'
export * from './subject'
export * from './utils'
export * from './constants'
8 changes: 5 additions & 3 deletions apps/hcdc-access-service/src/domain/auth/subject.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { RecordTypes } from '@casl/mongoose'

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

// key-value must be identical for working with '@casl/mongoose'.accessibleBy()
export const AuthSubject = {
Expand All @@ -13,9 +14,10 @@ export const AuthSubject = {

export type AuthSubjectUnionType = keyof typeof AuthSubject

export const AuthSubjectValues = Object.keys(
AuthSubject,
) as AuthSubjectUnionType[]
export const AuthSubjectValues = [
...Object.keys(AuthSubject),
AUTH_SUBJECT_ALL,
] as AuthSubjectUnionType[]

export type SubjectEntityMapping = {
BioProduct: BioProduct
Expand Down
9 changes: 5 additions & 4 deletions apps/hcdc-access-service/src/domain/auth/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { MongoAbility, subject as assignSubject } from '@casl/ability'
import { AuthAction } from './action'
import { AuthSubject, SubjectEntityMapping } from './subject'
import { EAuthzPermissionDenied } from 'src/domain/exception'
import { AUTH_ACTION_ALL, AUTH_SUBJECT_ALL } from './constants'

export function checkPermission<TSubject extends keyof typeof AuthSubject>(
ability: MongoAbility,
subject: TSubject,
action: (typeof AuthAction)[TSubject][number],
subject: TSubject | typeof AUTH_SUBJECT_ALL,
action: (typeof AuthAction)[TSubject][number] | typeof AUTH_ACTION_ALL,
object?: Partial<SubjectEntityMapping[TSubject]> | null,
) {
if (object != undefined) {
Expand All @@ -19,8 +20,8 @@ export function checkPermission<TSubject extends keyof typeof AuthSubject>(

export function assertPermission<TSubject extends keyof typeof AuthSubject>(
ability: MongoAbility,
subject: TSubject,
action: (typeof AuthAction)[TSubject][number],
subject: TSubject | typeof AUTH_SUBJECT_ALL,
action: (typeof AuthAction)[TSubject][number] | typeof AUTH_ACTION_ALL,
object?: Partial<SubjectEntityMapping[TSubject]> | null,
) {
if (!checkPermission(ability, subject, action, object)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { BaseEntity } from '../base-entity'
import { Branch } from '../branch'

export type BioProduct = BaseEntity & {
index: number
displayIndex: number
name: string

branchId: string
branch?: Branch | null
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { exampleMongoObjectId } from '@diut/nest-core'

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

export const exampleBioProduct = {
index: {
displayIndex: {
example: 1,
},
name: {
example: 'CHIV Advia centaur',
},
branchId: exampleMongoObjectId,
branch: {
required: false,
},
} satisfies EntityDataExample<BioProduct>
7 changes: 4 additions & 3 deletions apps/hcdc-access-service/src/domain/entity/branch/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ export enum BranchType {
export const BranchTypeValues = stringEnumValues(BranchType)

export type Branch = BaseEntity & {
index: number
displayIndex: number
name: string

address: string

type: BranchType

sampleOriginIds: string[]
sampleOrigins?: (Omit<Branch, 'sampleOrigins'> | null)[]
}
9 changes: 8 additions & 1 deletion apps/hcdc-access-service/src/domain/entity/branch/example.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { exampleMongoObjectIds } from '@diut/nest-core'

import { EntityDataExample } from '../base-entity'
import { Branch, BranchType } from './entity'

export const exampleBranch = {
index: {
displayIndex: {
example: 1,
},
name: {
Expand All @@ -14,4 +16,9 @@ export const exampleBranch = {
type: {
enum: BranchType,
},
sampleOriginIds: exampleMongoObjectIds,
sampleOrigins: {
required: false,
isArray: true,
},
} satisfies EntityDataExample<Branch>
8 changes: 3 additions & 5 deletions apps/hcdc-access-service/src/domain/entity/role/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ import { Branch } from '../branch'
import { PermissionRule } from '../permission-rule'

export type Role = BaseEntity & {
index: number
displayIndex: number
name: string

description: string

permissions: PermissionRule[]

branchIds: string[]
branches?: (Branch | null)[]
branchId: string
branch?: Branch | null
}
9 changes: 4 additions & 5 deletions apps/hcdc-access-service/src/domain/entity/role/example.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { exampleMongoObjectIds } from '@diut/nest-core'
import { exampleMongoObjectId } from '@diut/nest-core'

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

export const exampleRole = {
index: {
displayIndex: {
example: 1,
},
name: {
Expand All @@ -16,9 +16,8 @@ export const exampleRole = {
permissions: {
isArray: true,
},
branchIds: exampleMongoObjectIds,
branches: {
branchId: exampleMongoObjectId,
branch: {
required: false,
isArray: true,
},
} satisfies EntityDataExample<Role>
1 change: 0 additions & 1 deletion apps/hcdc-access-service/src/domain/entity/user/auth.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import '@casl/mongoose'

export enum UserAction {
Manage = 'Manage',
Create = 'Create',
Read = 'Read',
Update = 'Update',
Expand Down
2 changes: 0 additions & 2 deletions apps/hcdc-access-service/src/domain/entity/user/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ import { Role } from '../role'
export type User = BaseEntity & {
username: string
passwordHash: string

name: string
phoneNumber: string

inlinePermissions: PermissionRule[]

branchIds: string[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class EAuthnPayloadUserNotFound extends EAuthn {
DomainErrorCode.AUTHN_PAYLOAD_USER_NOT_FOUND,
'user not found, HttpPublicRoute is applied where it should not be?',
undefined,
HttpStatus.BAD_REQUEST,
HttpStatus.UNAUTHORIZED,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import { DomainErrorCode } from '@diut/hcdc-common'
import { EAuthz } from './base'

export class EAuthzPermissionDenied extends EAuthz {
constructor(reason: string) {
constructor(
reason: string,
private readonly debug?: unknown,
) {
super(
DomainErrorCode.AUTHZ_PERMISSION_DENIED,
`permission denied: ${reason}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,19 @@ export class AuthPopulateContextUseCase {
filter: { _id: input.userId },
populates: [{ path: 'roles', fields: ['permissions'] as (keyof Role)[] }],
})

if (!user) {
throw new EAuthnPayloadUserNotFound()
}

const rolesPermissions: PermissionRule[] = []
user.roles?.forEach((role) => {
if (role != null) {
if (role !== null) {
rolesPermissions.push(...role.permissions)
}
})
const { inlinePermissions } = user

const permissionTemplate = buildJSONTemplate([
...rolesPermissions,
...inlinePermissions,
...user.inlinePermissions,
])
const permissions = permissionTemplate({ user }) as PermissionRule[]
const ability = createMongoAbility(permissions)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from 'src/domain/interface'
import { BioProduct, BioProductAction, EntityData } from 'src/domain/entity'
import { AuthSubject, assertPermission } from 'src/domain/auth'
import { BioProductValidateUseCase } from './validate'

@Injectable()
export class BioProductCreateUseCase {
Expand All @@ -16,6 +17,7 @@ export class BioProductCreateUseCase {
private readonly authContext: IAuthContext,
@Inject(BioProductRepositoryToken)
private readonly bioProductRepository: IBioProductRepository,
private readonly bioProductValidateUseCase: BioProductValidateUseCase,
) {}

async execute(input: EntityData<BioProduct>) {
Expand All @@ -26,6 +28,7 @@ export class BioProductCreateUseCase {
BioProductAction.Create,
input,
)
await this.bioProductValidateUseCase.execute(input)

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
IBioProductRepository,
} from 'src/domain/interface'
import { BioProductAssertExistsUseCase } from './assert-exists'
import { BioProductValidateUseCase } from './validate'

@Injectable()
export class BioProductUpdateUseCase {
Expand All @@ -18,6 +19,7 @@ export class BioProductUpdateUseCase {
@Inject(AuthContextToken)
private readonly authContext: IAuthContext,
private readonly bioProductAssertExistsUseCase: BioProductAssertExistsUseCase,
private readonly bioProductValidateUseCase: BioProductValidateUseCase,
) {}

async execute(...input: Parameters<IBioProductRepository['update']>) {
Expand All @@ -29,6 +31,7 @@ export class BioProductUpdateUseCase {
BioProductAction.Update,
entity,
)
await this.bioProductValidateUseCase.execute(input[1])

return this.bioProductRepository.update(...input)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Injectable } from '@nestjs/common'

import { BioProduct, EntityData } from 'src/domain/entity'
import { BranchAssertExistsUseCase } from '../branch/assert-exists'

@Injectable()
export class BioProductValidateUseCase {
constructor(
private readonly branchAssertExistsUseCase: BranchAssertExistsUseCase,
) {}

async execute(input: Partial<Pick<EntityData<BioProduct>, 'branchId'>>) {
const { branchId } = input

if (branchId !== undefined) {
await this.branchAssertExistsUseCase.execute({ _id: branchId })
}
}
}
3 changes: 3 additions & 0 deletions apps/hcdc-access-service/src/domain/use-case/branch/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from 'src/domain/interface'
import { Branch, BranchAction, EntityData } from 'src/domain/entity'
import { AuthSubject, assertPermission } from 'src/domain/auth'
import { BranchValidateUseCase } from './validate'

@Injectable()
export class BranchCreateUseCase {
Expand All @@ -16,11 +17,13 @@ export class BranchCreateUseCase {
private readonly authContext: IAuthContext,
@Inject(BranchRepositoryToken)
private readonly branchRepository: IBranchRepository,
private readonly branchValidateUseCase: BranchValidateUseCase,
) {}

async execute(input: EntityData<Branch>) {
const { ability } = this.authContext.getData()
assertPermission(ability, AuthSubject.Branch, BranchAction.Create, input)
await this.branchValidateUseCase.execute(input)

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

Expand Down
3 changes: 3 additions & 0 deletions apps/hcdc-access-service/src/domain/use-case/branch/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
IBranchRepository,
} from 'src/domain/interface'
import { BranchAssertExistsUseCase } from './assert-exists'
import { BranchValidateUseCase } from './validate'

@Injectable()
export class BranchUpdateUseCase {
Expand All @@ -18,12 +19,14 @@ export class BranchUpdateUseCase {
@Inject(AuthContextToken)
private readonly authContext: IAuthContext,
private readonly branchAssertExistsUseCase: BranchAssertExistsUseCase,
private readonly branchValidateUseCase: BranchValidateUseCase,
) {}

async execute(...input: Parameters<IBranchRepository['update']>) {
const entity = await this.branchAssertExistsUseCase.execute(input[0])
const { ability } = this.authContext.getData()
assertPermission(ability, AuthSubject.Branch, BranchAction.Update, entity)
await this.branchValidateUseCase.execute(input[1])

return this.branchRepository.update(...input)
}
Expand Down
21 changes: 21 additions & 0 deletions apps/hcdc-access-service/src/domain/use-case/branch/validate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Injectable } from '@nestjs/common'

import { Branch, EntityData } from 'src/domain/entity'
import { BranchAssertExistsUseCase } from './assert-exists'

@Injectable()
export class BranchValidateUseCase {
constructor(
private readonly branchAssertExistsUseCase: BranchAssertExistsUseCase,
) {}

async execute(input: Partial<Pick<EntityData<Branch>, 'sampleOriginIds'>>) {
const { sampleOriginIds } = input

if (sampleOriginIds) {
for (const branchId of sampleOriginIds) {
await this.branchAssertExistsUseCase.execute({ _id: branchId })
}
}
}
}
Loading

0 comments on commit 5773b72

Please sign in to comment.