Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
wermarter committed Jan 21, 2024
1 parent aa79429 commit 2885be1
Show file tree
Hide file tree
Showing 83 changed files with 960 additions and 377 deletions.
12 changes: 7 additions & 5 deletions apps/hcdc-access-service/src/domain/entity/auth/action.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { stringEnumValues } from '@diut/common'

import { AuthSubject, AuthSubjectUnionType } from './subject'
import { BioProductAction } from '../bio-product'
import { TestCategoryAction } from '../test-category'
import { BranchAction } from '../branch'
import { RoleAction } from '../role'

// NOTE: beware of circular dependency
import { BioProductAction } from '../bio-product/auth'
import { TestCategoryAction } from '../test-category/auth'
import { BranchAction } from '../branch/auth'
import { RoleAction } from '../role/auth'

export const AuthAction = {
BioProduct: stringEnumValues(BioProductAction),
Expand All @@ -13,7 +15,7 @@ export const AuthAction = {
Role: stringEnumValues(RoleAction),
} satisfies Record<keyof typeof AuthSubject, string[]>

export const AuthActions = Object.values(AuthAction).flat()
export const AuthActionValues = Object.values(AuthAction).flat()

export type AuthActionUnionType =
(typeof AuthAction)[AuthSubjectUnionType][number]
25 changes: 25 additions & 0 deletions apps/hcdc-access-service/src/domain/entity/auth/example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { exampleMongoObjectId } from '@diut/nest-core'

import { EntityDataExample } from '../base-entity'
import { AuthActionValues } from './action'
import { PermissionRule } from './entity'
import { AuthSubjectValues } from './subject'

export const examplePermissionRule = {
subject: {
example: AuthSubjectValues[0],
enum: AuthSubjectValues,
},
action: {
example: AuthActionValues[0],
enum: AuthActionValues,
},
inverted: {
example: false,
default: false,
required: false,
},
conditions: {
example: { _id: { $eq: exampleMongoObjectId.example } },
},
} satisfies EntityDataExample<PermissionRule>
1 change: 1 addition & 0 deletions apps/hcdc-access-service/src/domain/entity/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './action'
export * from './subject'
export * from './utils'
export * from './entity'
export * from './example'
4 changes: 3 additions & 1 deletion apps/hcdc-access-service/src/domain/entity/auth/subject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ export const AuthSubject = {

export type AuthSubjectUnionType = keyof typeof AuthSubject

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

export type SubjectEntityMapping = {
BioProduct: BioProduct
Expand Down
2 changes: 1 addition & 1 deletion apps/hcdc-access-service/src/domain/entity/auth/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function assertPermission<TSubject extends keyof typeof AuthSubject>(
) {
if (!checkPermission(ability, subject, action, object)) {
logger.warn(
`assertPermission failed:\n ${JSON.stringify(
`assertPermission failed: ${JSON.stringify(
{
ability,
subject,
Expand Down
72 changes: 66 additions & 6 deletions apps/hcdc-access-service/src/domain/entity/base-entity.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,78 @@
import { exampleMongoObjectId } from '@diut/nest-core'
import { ApiPropertyOptions } from '@nestjs/swagger'
import { omit } from 'lodash'

export type BaseEntity = {
_id: string

createdAt: Date
updatedAt: Date
}

export type EntityData<TEntity extends BaseEntity> = Omit<
TEntity,
export const exampleBaseEntity = {
_id: exampleMongoObjectId,
createdAt: {
format: 'date-time',
example: '2022-08-20T16:00:00.000Z',
},
updatedAt: {
format: 'date-time',
example: '2022-08-20T16:00:00.000Z',
},
} satisfies EntityExample<BaseEntity>

export const baseEntityKeys: (keyof BaseEntity)[] = [
'_id',
'createdAt',
'updatedAt',
]

export type EntityData<TEntity> = Omit<TEntity, keyof BaseEntity>

export type EntityExample<TEntity> = {
[key in keyof Required<EntityData<TEntity>>]: Omit<
ApiPropertyOptions,
'example' | 'examples'
> & {
example?: EntityData<TEntity>[key]
examples?: EntityData<TEntity>[key][]
}
}

export type EntityDataExample<TEntity> = Omit<
EntityExample<TEntity>,
keyof BaseEntity
>

export type EntityExample<TEntity extends BaseEntity> = {
[key in keyof EntityData<TEntity>]: {
example: EntityData<TEntity>[key]
description: string
export function omitBaseEntityKeys<TEntity>(
example: EntityExample<TEntity>,
): EntityDataExample<TEntity> {
return omit(example, ...baseEntityKeys)
}

export function populateEntityDataExample<TEntity>(
exampleData: EntityDataExample<TEntity>,
): EntityExample<TEntity> {
return {
...exampleBaseEntity,
...exampleData,
} as EntityExample<TEntity>
}

export function extractExampleEntity<TEntity>(
exampleData: EntityDataExample<TEntity>,
includeBaseEntityKeys = true,
) {
let example: object = populateEntityDataExample(exampleData)
if (!includeBaseEntityKeys) {
example = omitBaseEntityKeys(example)
}

const rv: object = {}

Object.keys(example).forEach((key) => {
rv[key] = example[key].example
})

return rv as TEntity
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { EntityExample } from '../base-entity'
import { EntityDataExample } from '../base-entity'
import { BioProduct } from './entity'

export const exampleBioProduct: EntityExample<BioProduct> = {
export const exampleBioProduct = {
index: {
example: 1,
description: 'index',
},
name: {
example: 'CHIV Advia centaur',
description: 'name',
},
}
} satisfies EntityDataExample<BioProduct>
11 changes: 11 additions & 0 deletions apps/hcdc-access-service/src/domain/entity/branch/entity.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import { stringEnumValues } from '@diut/common'

import { BaseEntity } from '../base-entity'

export enum BranchType {
Internal = 'Internal',
External = 'External',
}

export const BranchTypeValues = stringEnumValues(BranchType)

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

address: string

type: BranchType
}
17 changes: 8 additions & 9 deletions apps/hcdc-access-service/src/domain/entity/branch/example.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { exampleMongoObjectIds } from '@diut/nest-core'
import { EntityExample } from '../base-entity'
import { Branch } from './entity'
import { EntityDataExample } from '../base-entity'
import { Branch, BranchType } from './entity'

export const exampleBranch: EntityExample<Branch> = {
export const exampleBranch = {
index: {
example: 1,
description: 'index',
},
name: {
example: 'HCDC Ba tháng hai',
description: 'tên chi nhánh',
},
address: {
example: 'Ba tháng hai',
description: 'địa chỉ chi nhánh',
example: 'đường 3/2',
},
}
type: {
enum: BranchType,
},
} satisfies EntityDataExample<Branch>
18 changes: 8 additions & 10 deletions apps/hcdc-access-service/src/domain/entity/role/example.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import { exampleMongoObjectIds } from '@diut/nest-core'

import { EntityExample } from '../base-entity'
import { EntityDataExample, extractExampleEntity } from '../base-entity'
import { Role } from './entity'
import { examplePermissionRule } from '../auth'
import { exampleBranch } from '../branch'

export const exampleRole: EntityExample<Role> = {
export const exampleRole = {
index: {
example: 1,
description: 'index',
},
name: {
example: 'Admin',
description: 'tên phân quyền',
},
description: {
example: 'phân quyền cao nhất',
description: 'mô tả',
},
policy: {
example: [],
description: 'policy',
example: [extractExampleEntity(examplePermissionRule, false)],
},
branchIds: exampleMongoObjectIds,
branches: {
example: [],
description: 'các chi nhánh khả dụng cho phân quyền này',
example: [extractExampleEntity(exampleBranch)],
required: false,
},
}
} satisfies EntityDataExample<Role>
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import { EntityExample } from '../base-entity'
import { EntityDataExample } from '../base-entity'
import { TestCategory } from './entity'

export const exampleTestCategory: EntityExample<TestCategory> = {
export const exampleTestCategory = {
index: {
example: 1,
description: 'thứ tự in trong kết quả',
},
name: {
example: 'XN Huyết học - Đông máu',
description: 'name',
},
reportIndex: {
example: 1,
description: 'thứ tự in trong báo cáo',
},
}
} satisfies EntityDataExample<TestCategory>
15 changes: 8 additions & 7 deletions apps/hcdc-access-service/src/domain/entity/user/example.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import { exampleMongoObjectIds } from '@diut/nest-core'

import { EntityExample } from '../base-entity'
import { EntityDataExample, extractExampleEntity } from '../base-entity'
import { User } from './entity'
import { exampleBranch } from '../branch'

export const exampleUser: EntityExample<User> = {
export const exampleUser = {
username: {
example: 'levana',
description: 'username',
},
name: {
example: 'Lê Văn A',
description: 'name',
},
phoneNumber: {
example: '1234567890',
description: 'phoneNumber',
},
passwordHash: {
example: 'hashed_password',
description: 'passwordHash',
},
branchIds: exampleMongoObjectIds,
}
branches: {
example: [extractExampleEntity(exampleBranch)],
isArray: true,
},
} satisfies EntityDataExample<User>
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class EAuthnCookieAccessTokenNotFound extends EAuthn {
constructor() {
super(
DomainErrorCode.AUTHN_COOKIE_ACCESS_TOKEN_NOT_FOUND,
'Access token cookie not found',
'access token cookie not found',
undefined,
HttpStatus.UNAUTHORIZED,
)
Expand Down
2 changes: 1 addition & 1 deletion apps/hcdc-access-service/src/domain/exception/authn/jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class EAuthnJwtInvalidToken extends EAuthn {
constructor() {
super(
DomainErrorCode.AUTHN_JWT_INVALID_TOKEN,
'Invalid JWT token',
'invalid JWT token',
undefined,
HttpStatus.UNAUTHORIZED,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class EAuthnPayloadNotFound extends EAuthn {
constructor() {
super(
DomainErrorCode.AUTHN_PAYLOAD_NOT_FOUND,
'Auth payload not found',
'auth payload not found',
undefined,
HttpStatus.BAD_REQUEST,
)
Expand All @@ -18,7 +18,7 @@ export class EAuthnPayloadUserNotFound extends EAuthn {
constructor() {
super(
DomainErrorCode.AUTHN_PAYLOAD_USER_NOT_FOUND,
'User not found, HttpPublicRoute is used where it should not be?',
'user not found, HttpPublicRoute is applied where it should not be?',
undefined,
HttpStatus.BAD_REQUEST,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class EAuthzAuthenticationRequired extends EAuthz {
constructor() {
super(
DomainErrorCode.AUTHZ_AUTHENTICATION_REQUIRED,
'Authentication required',
'authentication required',
undefined,
HttpStatus.UNAUTHORIZED,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { DomainErrorCode } from '@diut/hcdc-common'
import { EAuthz } from './base'

export class EAuthzPermissionDenied extends EAuthz {
constructor(message?: string) {
constructor(reason: string) {
super(
DomainErrorCode.AUTHZ_PERMISSION_DENIED,
`Permission denied${message?.length! > 0 ? `: ${message}` : ''}`,
`permission denied: ${reason}`,
undefined,
HttpStatus.FORBIDDEN,
)
Expand Down
4 changes: 2 additions & 2 deletions apps/hcdc-access-service/src/domain/exception/entity/crud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { DomainErrorCode } from '@diut/hcdc-common'
import { EEntity } from './base'

export class EEntityNotFound extends EEntity {
constructor(entity: unknown) {
constructor(reason: string) {
super(
DomainErrorCode.ENTITY_NOT_FOUND,
`Cannot find entity: ${JSON.stringify(entity)}`,
`entity not found: ${reason}`,
undefined,
HttpStatus.NOT_FOUND,
)
Expand Down
1 change: 1 addition & 0 deletions apps/hcdc-access-service/src/domain/exception/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './authn'
export * from './authz'
export * from './entity'
export * from './service'
export * from './request'
Loading

0 comments on commit 2885be1

Please sign in to comment.