Skip to content

Commit

Permalink
added page to manage user access (#137)
Browse files Browse the repository at this point in the history
* added page to manage user access

* addressed feedback

* removed ADMIN from manage user access dropdown

* removed unnecessary placeholder property

* fixed bugs after merge

* fixed errors

* fixed more errors

* addressed feedback

* Fix compatibility

---------

Co-authored-by: Alex Zhang <[email protected]>
Co-authored-by: Alex Zhang <[email protected]>
  • Loading branch information
3 people authored May 18, 2024
1 parent 1937b7e commit 824f846
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/components/profile/Preview/style.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
align-items: center;
display: flex;
flex-direction: column;

text-align: center;

.pfp {
Expand Down
34 changes: 34 additions & 0 deletions src/lib/api/AdminAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { config } from '@/lib';
import type { ModifyUserAccessLevelResponse, PrivateProfile } from '@/lib/types/apiResponses';
import axios from 'axios';

/**
* Update current user's access level
* @param token Authorization bearer token
* @param user Email of the user whose access is being updated
* @param accessType The user's updated access type
* @returns The updated user profile
*/
export const manageUserAccess = async (
token: string,
user: string,
accessType: string
): Promise<PrivateProfile[]> => {
const accessUpdates = [{ user: user, accessType: accessType }];

const requestUrl = `${config.api.baseUrl}${config.api.endpoints.admin.access}`;

const response = await axios.patch<ModifyUserAccessLevelResponse>(
requestUrl,
{ accessUpdates: accessUpdates },
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);

return response.data.updatedUsers;
};

export default manageUserAccess;
1 change: 1 addition & 0 deletions src/lib/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * as AdminAPI from './AdminAPI';
export * as AuthAPI from './AuthAPI';
export * as EventAPI from './EventAPI';
export * as FeedbackAPI from './FeedbackAPI';
Expand Down
2 changes: 2 additions & 0 deletions src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const config = {
attendance: '/admin/attendance',
bonus: '/admin/bonus',
emails: '/admin/email',
access: '/admin/access',
},
event: {
event: '/event',
Expand Down Expand Up @@ -106,6 +107,7 @@ const config = {
grantPastAttendance: '/admin/attendance',
awardMilestone: '/admin/milestone',
viewResumes: '/admin/resumes',
manageUserAccess: '/admin/access',
store: {
items: '/admin/store/items',
pickup: '/admin/store/pickup',
Expand Down
20 changes: 20 additions & 0 deletions src/lib/managers/AdminUserManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { AdminAPI } from '@/lib/api';
import { CookieService } from '@/lib/services';
import { APIHandlerProps } from '@/lib/types';
import { UserAccessUpdates } from '@/lib/types/apiRequests';
import { PrivateProfile } from '@/lib/types/apiResponses';
import { CookieType } from '@/lib/types/enums';

const manageUserAccess = async (data: UserAccessUpdates & APIHandlerProps<PrivateProfile[]>) => {
const { user, accessType, onSuccessCallback, onFailCallback } = data;

try {
const token = CookieService.getClientCookie(CookieType.ACCESS_TOKEN);
const updatedUsers = await AdminAPI.manageUserAccess(token, user, accessType);
onSuccessCallback?.(updatedUsers);
} catch (e: any) {
onFailCallback?.(e);
}
};

export default manageUserAccess;
84 changes: 84 additions & 0 deletions src/pages/admin/access/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import {
VerticalForm,
VerticalFormButton,
VerticalFormItem,
VerticalFormTitle,
} from '@/components/common';
import { showToast } from '@/lib';
import withAccessType from '@/lib/hoc/withAccessType';
import manageUserAccess from '@/lib/managers/AdminUserManager';
import { PermissionService, ValidationService } from '@/lib/services';
import { UserAccessUpdates } from '@/lib/types/apiRequests';
import { UserAccessType } from '@/lib/types/enums';
import { reportError } from '@/lib/utils';
import { GetServerSideProps } from 'next';
import { SubmitHandler, useForm } from 'react-hook-form';
import { AiOutlineMail } from 'react-icons/ai';
import { BsPerson } from 'react-icons/bs';

const ManageUserAccessPage = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<UserAccessUpdates>();

const onSubmit: SubmitHandler<UserAccessUpdates> = async ({ user, accessType }) => {
manageUserAccess({
user,
accessType,
onSuccessCallback: updatedUsers => {
showToast(`User access type updated for user ${updatedUsers[0]?.email}!`);
},
onFailCallback: error => {
reportError('Failed to update user access type', error);
},
});
};

return (
<VerticalForm onEnterPress={handleSubmit(onSubmit)}>
<VerticalFormTitle text="Manage User Access" />
<VerticalFormItem
icon={<AiOutlineMail />}
element="input"
name="user"
type="email"
placeholder="Email ([email protected])"
formRegister={register('user', {
validate: email => {
const validation = ValidationService.isValidEmail(email);
return validation.valid || validation.error;
},
})}
error={errors.user}
/>
<VerticalFormItem
icon={<BsPerson />}
element="select"
name="User Access"
options={Object.values(UserAccessType).filter(option => option !== 'ADMIN')}
formRegister={register('accessType')}
error={errors.user}
placeholder=""
/>
<VerticalFormButton
type="button"
display="button1"
text="Submit"
onClick={handleSubmit(onSubmit)}
/>
</VerticalForm>
);
};

export default ManageUserAccessPage;

const getServerSidePropsFunc: GetServerSideProps = async () => ({
props: {},
});

export const getServerSideProps = withAccessType(
getServerSidePropsFunc,
PermissionService.canViewAdminPage
);
5 changes: 4 additions & 1 deletion src/pages/admin/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ const AdminPage = ({ user: { accessType }, preview }: AdminProps) => {
}}
>
{PermissionService.canViewResumes.includes(accessType) ? (
<LinkButton href={config.admin.viewResumes}>View User Resumes</LinkButton>
<>
<LinkButton href={config.admin.viewResumes}>View User Resumes</LinkButton>
<LinkButton href={config.admin.manageUserAccess}>Manage User Access</LinkButton>
</>
) : (
'Restricted Access'
)}
Expand Down

0 comments on commit 824f846

Please sign in to comment.