Skip to content

Commit

Permalink
update auth
Browse files Browse the repository at this point in the history
  • Loading branch information
wermarter committed Feb 20, 2024
1 parent ab843a7 commit 8ecc87d
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 16 deletions.
30 changes: 18 additions & 12 deletions apps/hcdc-web-app/src/components/layout/AppDrawer/drawer-items.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ReactElement } from 'react'
import { To } from 'react-router-dom'
import { AuthSubject, PatientAction, SampleAction } from '@diut/hcdc'
import AccountBoxIcon from '@mui/icons-material/AccountBoxOutlined'
import HomeIcon from '@mui/icons-material/HomeOutlined'
import VaccinesIcon from '@mui/icons-material/VaccinesOutlined'
Expand All @@ -21,16 +20,7 @@ import PersonSearchIcon from '@mui/icons-material/PersonSearch'
import FileDownloadIcon from '@mui/icons-material/FileDownload'
import MapsHomeWorkIcon from '@mui/icons-material/MapsHomeWork'

export interface MenuItem {
icon: ReactElement
label: string
destination: To
}

export interface DrawerItem {
title: string
children: MenuItem[]
}
import { DrawerItem, authOneOf } from './utils'

export const drawerItems: DrawerItem[] = [
{
Expand All @@ -45,21 +35,34 @@ export const drawerItems: DrawerItem[] = [
icon: <AirlineSeatReclineNormalIcon />,
label: 'Nhập TT',
destination: 'info',
isAuthorized: authOneOf([
{ subject: AuthSubject.Sample, action: SampleAction.UpdateInfo },
]),
},
{
icon: <FaceRetouchingNaturalIcon />,
label: 'Xác nhận TT',
destination: 'info/confirm',
isAuthorized: authOneOf([
{ subject: AuthSubject.Sample, action: SampleAction.UpdateInfo },
]),
},
{
icon: <AppRegistrationIcon />,
label: 'Nhập KQ',
destination: 'result',
isAuthorized: authOneOf([
{ subject: AuthSubject.Sample, action: SampleAction.UpdateResult },
]),
},
{
icon: <PrintIcon />,
label: 'In KQ',
destination: 'result/print',
isAuthorized: authOneOf([
{ subject: AuthSubject.Sample, action: SampleAction.UpdateResult },
{ subject: AuthSubject.Sample, action: SampleAction.PrintResult },
]),
},
{
icon: <RuleIcon />,
Expand All @@ -70,6 +73,9 @@ export const drawerItems: DrawerItem[] = [
icon: <PersonSearchIcon />,
label: 'Tìm kiếm',
destination: 'patient/search',
isAuthorized: authOneOf([
{ subject: AuthSubject.Patient, action: PatientAction.Read },
]),
},
{
icon: <FileDownloadIcon />,
Expand Down
2 changes: 2 additions & 0 deletions apps/hcdc-web-app/src/components/layout/AppDrawer/hooks.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { checkPermission } from '@diut/hcdc'

import { useTypedSelector } from 'src/infra/redux'
import { drawerItems } from './drawer-items'
import { selectUserPermissions } from 'src/features/auth'

export function useDrawerItems() {
const userPermissions = useTypedSelector(selectUserPermissions)
Expand Down
36 changes: 36 additions & 0 deletions apps/hcdc-web-app/src/components/layout/AppDrawer/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { PermissionRule, isAuthorizedOneOf } from '@diut/hcdc'
import { ReactElement } from 'react'
import { To } from 'react-router-dom'

export interface MenuItem {
icon: ReactElement
label: string
destination: To
isAuthorized?: (
userPermissions: PermissionRule[],
branchId: string,
) => boolean
}

export interface DrawerItem {
title: string
children: MenuItem[]
}

export function authOneOf(
authDetails: Parameters<typeof isAuthorizedOneOf>[1],
) {
return (userPermissions: PermissionRule[], branchId: string) => {
if (branchId) {
return isAuthorizedOneOf(
userPermissions,
authDetails.map(({ filterObj: originalFilterObj, ...details }) => ({
...details,
filterObj: { ...(originalFilterObj ?? {}), branchId },
})),
)
}

return isAuthorizedOneOf(userPermissions, authDetails)
}
}
4 changes: 2 additions & 2 deletions apps/hcdc-web-app/src/features/auth/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import {
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import { toast } from 'react-toastify'
import { PermissionRule } from '@diut/hcdc'

import { authApi } from 'src/infra/api/access-service/auth'
import { RootState } from 'src/infra/redux'

interface AuthState {
id?: string
name?: string
accessToken?: string
permissions?: Permission[]
permissions?: PermissionRule[]
}

// Reset store state on user logout or token expiration
Expand Down
23 changes: 21 additions & 2 deletions libs/hcdc/src/auth/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import {
} from '@casl/ability'
import { $or, or } from '@ucast/mongo2js'

import { AuthAction } from './action'
import { AuthSubject, SubjectEntityMapping } from './subject'
import { AuthAction, AuthActionUnionType } from './action'
import {
AuthSubject,
AuthSubjectUnionType,
SubjectEntityMapping,
} from './subject'
import { AUTH_ACTION_ALL, AUTH_SUBJECT_ALL } from './constants'
import { PermissionRule } from '../entity'

Expand All @@ -29,3 +33,18 @@ export function checkPermission<TSubject extends keyof typeof AuthSubject>(

return ability.can(action, subject)
}

export function isAuthorizedOneOf(
userPermissions: PermissionRule[],
authDetails: {
subject: AuthSubjectUnionType
action: AuthActionUnionType
filterObj?: unknown
}[],
): boolean {
const ability = createAbility(userPermissions)

return authDetails.some(({ subject, action, filterObj }) =>
checkPermission(ability, subject, action, filterObj),
)
}

0 comments on commit 8ecc87d

Please sign in to comment.