Skip to content

Commit

Permalink
Merge pull request #96 from c4dt/playwright
Browse files Browse the repository at this point in the history
Action Buttons that manipulate a form are only visible to the owner
  • Loading branch information
PascalinDe authored Feb 7, 2024
2 parents baa48d9 + 2a4116e commit 0d353b8
Show file tree
Hide file tree
Showing 16 changed files with 163 additions and 63 deletions.
6 changes: 6 additions & 0 deletions web/frontend/src/components/modal/RedirectToModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type RedirectToModalProps = {
children: string;
buttonRightText: string;
navigateDestination?: To | number;
needsReload?: boolean;
};

const RedirectToModal: FC<RedirectToModalProps> = ({
Expand All @@ -18,12 +19,17 @@ const RedirectToModal: FC<RedirectToModalProps> = ({
children,
buttonRightText,
navigateDestination,
needsReload = false,
}) => {
const navigate = useNavigate();

const closeModal = () => {
if (navigateDestination) {
navigate(navigateDestination as To);
if (needsReload) {
// reload the page to update the locally cached permissions
window.location.reload();
}
}
setShowModal(false);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { OngoingAction, Status } from 'types/form';
import ActionButton from './ActionButton';
const SUBJECT_ELECTION = 'election';
const ACTION_CREATE = 'create';
const CancelButton = ({ status, handleCancel, ongoingAction }) => {
const authCtx = useContext(AuthContext);
import { isManager } from './utils';

const CancelButton = ({ status, handleCancel, ongoingAction, formID }) => {
const { authorization, isLogged } = useContext(AuthContext);
const { t } = useTranslation();

return (
authCtx.isAllowed(SUBJECT_ELECTION, ACTION_CREATE) &&
isManager(formID, authorization, isLogged) &&
status === Status.Open && (
<ActionButton
handleClick={handleCancel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { OngoingAction, Status } from 'types/form';
import ActionButton from './ActionButton';
import { isManager } from './utils';

const SUBJECT_ELECTION = 'election';
const ACTION_CREATE = 'create';
const CloseButton = ({ status, handleClose, ongoingAction }) => {
const authCtx = useContext(AuthContext);
const CloseButton = ({ status, handleClose, ongoingAction, formID }) => {
const { authorization, isLogged } = useContext(AuthContext);
const { t } = useTranslation();

return (
authCtx.isAllowed(SUBJECT_ELECTION, ACTION_CREATE) &&
isManager(formID, authorization, isLogged) &&
status === Status.Open && (
<ActionButton
handleClick={handleClose}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { OngoingAction, Status } from 'types/form';
import ActionButton from './ActionButton';
import { isManager } from './utils';

const SUBJECT_ELECTION = 'election';
const ACTION_CREATE = 'create';
const CombineButton = ({ status, handleCombine, ongoingAction }) => {
const authCtx = useContext(AuthContext);
const CombineButton = ({ status, handleCombine, ongoingAction, formID }) => {
const { t } = useTranslation();
const { authorization, isLogged } = useContext(AuthContext);

return (
authCtx.isAllowed(SUBJECT_ELECTION, ACTION_CREATE) &&
isManager(formID, authorization, isLogged) &&
status === Status.PubSharesSubmitted && (
<ActionButton
handleClick={handleCombine}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { OngoingAction, Status } from 'types/form';
import ActionButton from './ActionButton';
import { isManager } from './utils';

const SUBJECT_ELECTION = 'election';
const ACTION_CREATE = 'create';
const DecryptButton = ({ status, handleDecrypt, ongoingAction }) => {
const authCtx = useContext(AuthContext);
const DecryptButton = ({ status, handleDecrypt, ongoingAction, formID }) => {
const { authorization, isLogged } = useContext(AuthContext);
const { t } = useTranslation();

return (
authCtx.isAllowed(SUBJECT_ELECTION, ACTION_CREATE) &&
isManager(formID, authorization, isLogged) &&
status === Status.ShuffledBallots && (
<ActionButton
handleClick={handleDecrypt}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ import { TrashIcon } from '@heroicons/react/outline';
import { AuthContext } from 'index';
import { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { isManager } from './utils';

const SUBJECT_ELECTION = 'election';
const ACTION_CREATE = 'create';

const DeleteButton = ({ handleDelete }) => {
const authCtx = useContext(AuthContext);
const DeleteButton = ({ handleDelete, formID }) => {
const { t } = useTranslation();
const { authorization, isLogged } = useContext(AuthContext);

return (
authCtx.isAllowed(SUBJECT_ELECTION, ACTION_CREATE) && (
isManager(formID, authorization, isLogged) && (
<button onClick={handleDelete}>
<div className="whitespace-nowrap inline-flex items-center justify-center px-4 py-1 mr-2 border border-gray-300 text-sm rounded-full font-medium text-gray-700 hover:text-red-500">
<TrashIcon className="-ml-1 mr-2 h-5 w-5" aria-hidden="true" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { OngoingAction, Status } from 'types/form';
import ActionButton from './ActionButton';
const SUBJECT_ELECTION = 'election';
const ACTION_CREATE = 'create';
const InitializeButton = ({ status, handleInitialize, ongoingAction }) => {
const authCtx = useContext(AuthContext);
import { isManager } from './utils';

const InitializeButton = ({ status, handleInitialize, ongoingAction, formID }) => {
const { authorization, isLogged } = useContext(AuthContext);
const { t } = useTranslation();

return (
authCtx.isAllowed(SUBJECT_ELECTION, ACTION_CREATE) &&
isManager(formID, authorization, isLogged) &&
status === Status.Initial && (
<ActionButton
handleClick={handleInitialize}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { OngoingAction, Status } from 'types/form';
import ActionButton from './ActionButton';
import { isManager } from './utils';

const SUBJECT_ELECTION = 'election';
const ACTION_CREATE = 'create';
const OpenButton = ({ status, handleOpen, ongoingAction }) => {
const authCtx = useContext(AuthContext);
const OpenButton = ({ status, handleOpen, ongoingAction, formID }) => {
const { t } = useTranslation();
const { authorization, isLogged } = useContext(AuthContext);

return (
authCtx.isAllowed(SUBJECT_ELECTION, ACTION_CREATE) &&
isManager(formID, authorization, isLogged) &&
status === Status.Setup && (
<ActionButton
handleClick={handleOpen}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { OngoingAction, Status } from 'types/form';
import ActionButton from './ActionButton';
import { isManager } from './utils';

const SUBJECT_ELECTION = 'election';
const ACTION_CREATE = 'create';
const SetupButton = ({ status, handleSetup, ongoingAction }) => {
const authCtx = useContext(AuthContext);
const SetupButton = ({ status, handleSetup, ongoingAction, formID }) => {
const { t } = useTranslation();
const { authorization, isLogged } = useContext(AuthContext);

return (
authCtx.isAllowed(SUBJECT_ELECTION, ACTION_CREATE) &&
isManager(formID, authorization, isLogged) &&
status === Status.Initialized && (
<ActionButton
handleClick={handleSetup}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { OngoingAction, Status } from 'types/form';
import ActionButton from './ActionButton';
import { isManager } from './utils';

const SUBJECT_ELECTION = 'election';
const ACTION_CREATE = 'create';
const ShuffleButton = ({ status, handleShuffle, ongoingAction }) => {
const authCtx = useContext(AuthContext);
const ShuffleButton = ({ status, handleShuffle, ongoingAction, formID }) => {
const { t } = useTranslation();
const { authorization, isLogged } = useContext(AuthContext);

return (
authCtx.isAllowed(SUBJECT_ELECTION, ACTION_CREATE) &&
isManager(formID, authorization, isLogged) &&
status === Status.Closed && (
<ActionButton
handleClick={handleShuffle}
Expand Down
3 changes: 2 additions & 1 deletion web/frontend/src/pages/form/components/FormForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,8 @@ const FormForm: FC<FormFormProps> = () => {
setShowModal={setShowModal}
title={t('notification')}
buttonRightText={t('close')}
navigateDestination={navigateDestination}>
navigateDestination={navigateDestination}
needsReload={true}>
{textModal}
</RedirectToModal>

Expand Down
44 changes: 32 additions & 12 deletions web/frontend/src/pages/form/components/utils/useChangeAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -488,36 +488,53 @@ const useChangeAction = (
status={status}
handleInitialize={handleInitialize}
ongoingAction={ongoingAction}
formID={formID}
/>
<DeleteButton handleDelete={handleDelete} />
<DeleteButton handleDelete={handleDelete} formID={formID} />
</>
);
case Status.Initialized:
return (
<>
<SetupButton status={status} handleSetup={handleSetup} ongoingAction={ongoingAction} />
<DeleteButton handleDelete={handleDelete} />
<SetupButton
status={status}
handleSetup={handleSetup}
ongoingAction={ongoingAction}
formID={formID}
/>
<DeleteButton handleDelete={handleDelete} formID={formID} />
</>
);
case Status.Setup:
return (
<>
<OpenButton status={status} handleOpen={handleOpen} ongoingAction={ongoingAction} />
<DeleteButton handleDelete={handleDelete} />
<OpenButton
status={status}
handleOpen={handleOpen}
ongoingAction={ongoingAction}
formID={formID}
/>
<DeleteButton handleDelete={handleDelete} formID={formID} />
<AddVotersButton handleAddVoters={handleAddVoters} formID={formID} />
</>
);
case Status.Open:
return (
<>
<CloseButton status={status} handleClose={handleClose} ongoingAction={ongoingAction} />
<CloseButton
status={status}
handleClose={handleClose}
ongoingAction={ongoingAction}
formID={formID}
/>
<CancelButton
status={status}
handleCancel={handleCancel}
ongoingAction={ongoingAction}
formID={formID}
/>
<VoteButton status={status} formID={formID} />
<DeleteButton handleDelete={handleDelete} />
<DeleteButton handleDelete={handleDelete} formID={formID} />
<AddVotersButton handleAddVoters={handleAddVoters} formID={formID} />
</>
);
Expand All @@ -528,8 +545,9 @@ const useChangeAction = (
status={status}
handleShuffle={handleShuffle}
ongoingAction={ongoingAction}
formID={formID}
/>
<DeleteButton handleDelete={handleDelete} />
<DeleteButton handleDelete={handleDelete} formID={formID} />
</>
);
case Status.ShuffledBallots:
Expand All @@ -539,8 +557,9 @@ const useChangeAction = (
status={status}
handleDecrypt={handleDecrypt}
ongoingAction={ongoingAction}
formID={formID}
/>
<DeleteButton handleDelete={handleDelete} />
<DeleteButton handleDelete={handleDelete} formID={formID} />
</>
);
case Status.PubSharesSubmitted:
Expand All @@ -550,21 +569,22 @@ const useChangeAction = (
status={status}
handleCombine={handleCombine}
ongoingAction={ongoingAction}
formID={formID}
/>
<DeleteButton handleDelete={handleDelete} />
<DeleteButton handleDelete={handleDelete} formID={formID} />
</>
);
case Status.ResultAvailable:
return (
<>
<ResultButton status={status} formID={formID} />
<DeleteButton handleDelete={handleDelete} />
<DeleteButton handleDelete={handleDelete} formID={formID} />
</>
);
default:
return (
<>
<DeleteButton handleDelete={handleDelete} />
<DeleteButton handleDelete={handleDelete} formID={formID} />
</>
);
}
Expand Down
2 changes: 1 addition & 1 deletion web/frontend/tests/formIndex.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { default as i18n } from 'i18next';
import { assertHasFooter, assertHasNavBar, initI18n, logIn, setUp, translate } from './shared';
import { SCIPER_ADMIN, SCIPER_USER, mockPersonalInfo } from './mocks/api';
import { mockForms } from './mocks/evoting';
import Forms from './json/formList.json';
import Forms from './json/formIndex.json';
import User from './json/api/personal_info/789012.json';
import Admin from './json/api/personal_info/123456.json';

Expand Down
Loading

0 comments on commit 0d353b8

Please sign in to comment.