Skip to content

Commit

Permalink
Issue #PS-1157 feat: Implemented Role based access for TL and Facilit…
Browse files Browse the repository at this point in the history
…ator on all pages in app
  • Loading branch information
Rushikesh-Sonawane99 committed Jul 8, 2024
1 parent 7752d5e commit 169249e
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 34 deletions.
17 changes: 14 additions & 3 deletions app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,18 @@ export const dropoutReasons = [
];

export const accessControl: { [key: string]: Role[] } = {
viewDashboard: [Role.TEACHER, Role.TEAM_LEADER],
viewAttendance: [Role.TEACHER, Role.TEAM_LEADER],
createLearner: [Role.TEACHER, Role.TEAM_LEADER],
accessDashboard: [Role.TEACHER, Role.TEAM_LEADER],
accessAttendanceHistory: [Role.TEACHER, Role.TEAM_LEADER],
accessAttendanceOverview: [Role.TEACHER, Role.TEAM_LEADER],
accessProfile: [Role.TEACHER, Role.TEAM_LEADER],
accessLearnerProfile: [Role.TEACHER, Role.TEAM_LEADER],
accessLearnerAttendanceHistory: [Role.TEACHER, Role.TEAM_LEADER],
showTeachingCenter : [Role.TEAM_LEADER],
showBlockLevelCohort : [Role.TEAM_LEADER],
showTeacherCohorts: [Role.TEACHER],
showBlockLevelData: [Role.TEAM_LEADER],
showCreateCenterButton: [Role.TEAM_LEADER],
showBlockLevelCenterData: [Role.TEAM_LEADER],
showTeacherLevelCenterData: [Role.TEACHER],
};

8 changes: 7 additions & 1 deletion src/components/MenuDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import { useTheme } from '@mui/material/styles';
import { useTranslation } from 'next-i18next';
import PeopleOutlineOutlinedIcon from '@mui/icons-material/PeopleOutlineOutlined';
import EditNoteIcon from '@mui/icons-material/EditNote';
import { Role } from '@/utils/app.constant';
import useStore from '@/store/store';
import { accessGranted } from '@/utils/Helper';
import { accessControl } from '../../app.config';
interface DrawerProps {
toggleDrawer: (open: boolean) => () => void;
open: boolean;
Expand All @@ -33,6 +37,8 @@ const MenuDrawer: React.FC<DrawerProps> = ({
const [isTeamLeader, setIsTeamLeader] = useState(false);
const { t } = useTranslation();
const router = useRouter();
const store = useStore();
const userRole = store.userRole;

useEffect(() => setIsOpen(open), [open]);

Expand Down Expand Up @@ -206,7 +212,7 @@ const MenuDrawer: React.FC<DrawerProps> = ({
router.push(`/centers`); // Check route
}}
>
{isTeamLeader
{accessGranted('showTeachingCenter', accessControl, userRole)
? t('DASHBOARD.TEACHING_CENTERS')
: t('DASHBOARD.MY_TEACHING_CENTERS')}
</Button>
Expand Down
5 changes: 4 additions & 1 deletion src/pages/attendance-history.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ import { logEvent } from '@/utils/googleAnalytics';
import { showToastMessage } from '@/components/Toastify';
import { Status } from '@/utils/app.constant';
import CohortSelectionSection from '@/components/CohortSelectionSection';
import withAccessControl from '@/utils/hoc/withAccessControl';
import { accessControl } from '../../app.config';

interface user {
memberStatus: string;
Expand Down Expand Up @@ -829,4 +831,5 @@ export async function getStaticProps({ locale }: any) {
};
}

export default UserAttendanceHistory;
// export default UserAttendanceHistory;
export default withAccessControl('accessAttendanceHistory', accessControl)(UserAttendanceHistory);
7 changes: 5 additions & 2 deletions src/pages/attendance-overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import SortingModal from '@/components/SortingModal';
import StudentsStatsList from '@/components/LearnerAttendanceStatsListView';
import UpDownButton from '@/components/UpDownButton';
import { getMyCohortMemberList } from '@/services/MyClassDetailsService';
import { lowLearnerAttendanceLimit } from './../../app.config';
import { accessControl, lowLearnerAttendanceLimit } from './../../app.config';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { usePathname } from 'next/navigation';
import { useRouter } from 'next/router';
Expand All @@ -51,6 +51,7 @@ import { useTranslation } from 'next-i18next';
import { logEvent } from '@/utils/googleAnalytics';
import { showToastMessage } from '@/components/Toastify';
import CohortSelectionSection from '@/components/CohortSelectionSection';
import withAccessControl from '@/utils/hoc/withAccessControl';

interface AttendanceOverviewProps {
// buttonText: string;
Expand Down Expand Up @@ -798,4 +799,6 @@ export async function getStaticProps({ locale }: any) {
};
}

export default AttendanceOverview;
// export default AttendanceOverview;
export default withAccessControl('accessAttendanceOverview', accessControl)(AttendanceOverview);

22 changes: 14 additions & 8 deletions src/pages/centers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,19 @@ import ManageUser from '@/components/ManageUser';
import { setTimeout } from 'timers';
import SmartDisplayOutlinedIcon from '@mui/icons-material/SmartDisplayOutlined';
import CreateCenterModal from '@/components/center/CreateCenterModal';
import { toPascalCase } from '@/utils/Helper';
import { accessGranted, toPascalCase } from '@/utils/Helper';
import { Role } from '@/utils/app.constant';
import useStore from '@/store/store';
import { accessControl } from '../../../app.config';

const TeachingCenters = () => {
const [loading, setLoading] = React.useState(false);
const { t } = useTranslation();
const theme = useTheme<any>();
const router = useRouter();
const store = useStore();
const userRole = store.userRole;

const [cohortsData, setCohortsData] = React.useState<Array<cohort>>([]);
const [value, setValue] = React.useState(1);
const [blockData, setBlockData] =
Expand Down Expand Up @@ -71,7 +77,7 @@ const TeachingCenters = () => {
try {
if (typeof window !== 'undefined' && window.localStorage) {
const userId = localStorage.getItem('userId');
if (userId && isTeamLeader) {
if (userId && accessGranted('showBlockLevelCohort', accessControl, userRole)) {
const response = await getCohortList(userId, {
customField: 'true',
});
Expand Down Expand Up @@ -107,7 +113,7 @@ const TeachingCenters = () => {
setCenterData(centerData);
});
}
if (userId && !isTeamLeader) {
if (userId && accessGranted('showTeacherCohorts', accessControl, userRole)) {
const response = await getCohortList(userId);
const cohortData = response.map((block: any) => {
const cohortName = block.cohortName;
Expand Down Expand Up @@ -136,7 +142,7 @@ const TeachingCenters = () => {
<Header />
{loading && <Loader showBackdrop={true} loadingText={t('LOADING')} />}
<Box sx={{ padding: '0 18px' }}>
{isTeamLeader ? (
{accessGranted('showBlockLevelData', accessControl, userRole) ? (
<>
{blockData?.length !== 0 &&
blockData?.map((block: any) => (
Expand Down Expand Up @@ -166,7 +172,7 @@ const TeachingCenters = () => {
{t('DASHBOARD.MY_TEACHING_CENTERS')}
</Box>
)}
{isTeamLeader && (
{accessGranted('showBlockLevelData', accessControl, userRole) && (
<Box sx={{ width: '100%' }}>
<Tabs
value={value}
Expand Down Expand Up @@ -257,7 +263,7 @@ const TeachingCenters = () => {
</FormControl>
</Box>
</Grid>
{isTeamLeader && (
{accessGranted('showCreateCenterButton', accessControl, userRole) && (
<Box mt={'18px'} px={'18px'}>
<Button
sx={{
Expand Down Expand Up @@ -290,7 +296,7 @@ const TeachingCenters = () => {
sx={{ borderRadius: '16px', mt: 2 }}
padding={'10px 16px 2px'}
>
{isTeamLeader && centerData && (
{accessGranted('showBlockLevelCenterData', accessControl, userRole) && centerData && (
<>
{/* Regular Centers */}
{centerData.some(
Expand Down Expand Up @@ -458,7 +464,7 @@ const TeachingCenters = () => {
</>
)}

{!isTeamLeader &&
{accessGranted('showTeacherLevelCenterData', accessControl, userRole) &&
cohortsData &&
cohortsData?.map((cohort: any) => {
return (
Expand Down
13 changes: 7 additions & 6 deletions src/pages/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { calculatePercentage } from '@/utils/attendanceStats';
import calendar from '../assets/images/calendar.svg';
import { getMyCohortMemberList } from '@/services/MyClassDetailsService';
import { logEvent } from '@/utils/googleAnalytics';
import { lowLearnerAttendanceLimit } from './../../app.config';
import { accessControl, lowLearnerAttendanceLimit } from './../../app.config';
import { modifyAttendanceLimit } from '../../app.config';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { showToastMessage } from '@/components/Toastify';
Expand All @@ -46,10 +46,13 @@ import { useRouter } from 'next/navigation';
import { useTheme } from '@mui/material/styles';
import { useTranslation } from 'next-i18next';
import CohortSelectionSection from '@/components/CohortSelectionSection';
// import withAccessControl from '@/utils/hoc/withAccessControl';
// import useStore from '@/store/store';


import withAccessControl from '@/utils/hoc/withAccessControl';
// import { Role } from '@/utils/app.constant';
// import { accessControl } from '../../app.config';

// import useStore from '@/store/store';
// const store = useStore();
// const userRole: string = store.userRole;

Expand Down Expand Up @@ -950,6 +953,4 @@ export async function getStaticProps({ locale }: any) {
};
}

export default Dashboard;

// export default withAccessControl(Role.TEACHER, accessControl)(Dashboard);
export default withAccessControl('accessDashboard', accessControl)(Dashboard);
5 changes: 4 additions & 1 deletion src/pages/learner-attendance-history.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { useTranslation } from 'next-i18next';
import { useRouter } from 'next/router';
import { logEvent } from '@/utils/googleAnalytics';
import { showToastMessage } from '@/components/Toastify';
import withAccessControl from '@/utils/hoc/withAccessControl';
import { accessControl } from '../../app.config';

type LearnerAttendanceData = {
[date: string]: {
Expand Down Expand Up @@ -250,4 +252,5 @@ export async function getStaticProps({ locale }: any) {
},
};
}
export default LearnerAttendanceHistory;

export default withAccessControl('accessLearnerAttendanceHistory', accessControl)(LearnerAttendanceHistory);
4 changes: 3 additions & 1 deletion src/pages/learner/[userId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { showToastMessage } from '@/components/Toastify';
import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next';
import withAccessControl from '@/utils/hoc/withAccessControl';
import { accessControl } from '../../../app.config';

// import { UserData, updateCustomField } from '../utils/Interfaces';

Expand Down Expand Up @@ -1628,4 +1630,4 @@ export const getStaticPaths: GetStaticPaths<{ slug: string }> = async () => {
};
};

export default LearnerProfile;
export default withAccessControl('accessLearnerProfile', accessControl)(LearnerProfile);
4 changes: 3 additions & 1 deletion src/pages/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import { useTranslation } from 'next-i18next';
import userPicture from '@/assets/images/imageOne.jpg';
import user_placeholder from '../assets/images/user_placeholder.png';
import { useProfileInfo } from '@/services/queries';
import withAccessControl from '@/utils/hoc/withAccessControl';
import { accessControl } from '../../app.config';

interface FieldOption {
name: string;
Expand Down Expand Up @@ -1148,4 +1150,4 @@ export async function getStaticProps({ locale }: any) {
};
}

export default TeacherProfile;
export default withAccessControl('accessProfile', accessControl)(TeacherProfile);
10 changes: 9 additions & 1 deletion src/utils/Helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import FingerprintJS from 'fingerprintjs2';
import { Status } from './app.constant';
import { Role, Status } from './app.constant';

export const ATTENDANCE_ENUM = {
PRESENT: 'present',
Expand Down Expand Up @@ -255,3 +255,11 @@ export const sortClassesMissed = (data: any[], order: string) => {
}
);
};


export const accessGranted = (action: string, accessControl: { [key: string]: Role[] }, currentRole: Role): boolean => {
if (accessControl[action]?.includes(currentRole)) {
return true;
}
return false;
};
17 changes: 8 additions & 9 deletions src/utils/hoc/withAccessControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@ import { useEffect } from 'react';
import useStore from '@/store/store';
import { Role } from '../app.constant';

const withAccessControl = (requiredRole: Role, accessControl: any) => (Component: React.ComponentType<any>) => {
const withAccessControl = (action: string, accessControl: { [key: string]: Role[] }) => (Component: React.ComponentType<any>) => {
return (props: any) => {
debugger;
const store = useStore();
const userRole = store.userRole;
const userRole = store.userRole;
const router = useRouter();

useEffect(() => {
if (!userRole || !accessControl[requiredRole]?.includes(userRole)) {
router.replace('/unauthorized'); // Redirect to an unauthorized page
if (!userRole || !accessControl[action]?.includes(userRole)) {
router.replace('/unauthorized');
}
}, [userRole, requiredRole, router]);
}, [userRole, action, router]);

if (!userRole || !accessControl[requiredRole]?.includes(userRole)) {
return null; // or a loading spinner
if (!userRole || !accessControl[action]?.includes(userRole)) {
return null;
}

return <Component {...props} />;
Expand Down

0 comments on commit 169249e

Please sign in to comment.