Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix permissions for users #1054

Merged
merged 3 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion client/cypress/e2e/data.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ describe('Data page - user', () => {
});

it('not admin user should not be able to upload data source', () => {
cy.intercept('/api/v1/users/me', { fixture: 'profiles/no-permissions' });
cy.intercept('/api/v1/users/me', { fixture: 'profiles/no-permissions' }).as('user-profile');
cy.wait('@user-profile');
cy.get('[data-testid="upload-data-source-btn"]').should('be.disabled');
});
});
2 changes: 1 addition & 1 deletion client/src/containers/analysis-sidebar/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const ScenariosComponent: React.FC<{ scrollref?: MutableRefObject<HTMLDivElement
const { scenarioId = ACTUAL_DATA.id } = query;
const { hasPermission } = usePermissions();

const canCreateScenario = hasPermission(Permission.CAN_CREATE_SCENARIO, false);
const canCreateScenario = hasPermission(Permission.CAN_CREATE_SCENARIO);

const { sort, searchTerm } = useAppSelector(scenarios);
const dispatch = useAppDispatch();
Expand Down
6 changes: 3 additions & 3 deletions client/src/containers/scenarios/form/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ const ScenarioForm: React.FC<React.PropsWithChildren<ScenarioFormProps>> = ({
criteriaMode: 'all',
});

const { hasPermission } = usePermissions(scenario?.user?.id);
const { hasPermission } = usePermissions();
// If scenario exists, check if the user can edit,
// else, check if the user can create a scenario
const canSave =
(scenario?.id
? hasPermission(Permission.CAN_EDIT_SCENARIO)
: hasPermission(Permission.CAN_CREATE_SCENARIO, false)) && isValid;
? hasPermission(Permission.CAN_EDIT_SCENARIO, scenario.user?.id)
: hasPermission(Permission.CAN_CREATE_SCENARIO)) && isValid;

return (
<form
Expand Down
4 changes: 2 additions & 2 deletions client/src/containers/scenarios/item/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ const ScenarioItem = ({ scenario, isSelected }: ScenariosItemProps) => {
[updatedAt],
);

const { hasPermission } = usePermissions(scenario?.user?.id);
const canEdit = hasPermission(Permission.CAN_EDIT_SCENARIO);
const { hasPermission } = usePermissions();
const canEdit = hasPermission(Permission.CAN_EDIT_SCENARIO, scenario.user?.id);

return (
<div data-testid={`scenario-item-${scenario.id || 'null'}`}>
Expand Down
64 changes: 39 additions & 25 deletions client/src/containers/scenarios/table/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@ import ScenarioMakePublic from '../scenario-items/make-public';
import ScenarioActions from '../scenario-items/actions';

import Table from 'components/table';
import { usePermissions } from 'hooks/permissions';
import { Permission } from 'hooks/permissions/enums';

import type { ScenarioTableProps } from '../types';

export const ScenarioTable = ({
data,
className,
canDeleteScenario,
canEditScenario,
onDelete,
}: ScenarioTableProps) => {
export const ScenarioTable = ({ data, className, onDelete }: ScenarioTableProps) => {
const { hasPermission } = usePermissions();

return (
<div className={classNames('w-full h-full', className)}>
<Table
Expand All @@ -42,35 +40,51 @@ export const ScenarioTable = ({
{
id: 'ss',
header: 'Growth Rates',
cell: ({ row }) => <ScenarioGrowthRate display="list" />,
cell: () => <ScenarioGrowthRate display="list" />,
},
{
id: 'ssss',
header: 'Access',
cell: ({ row }) => (
<ScenarioMakePublic
id={row.original.id}
display="list"
isPublic={row.original.isPublic}
canEditScenario={canEditScenario}
/>
),
cell: ({ row }) => {
const canEditScenario = hasPermission(
Permission.CAN_EDIT_SCENARIO,
row.original?.user.id,
);
return (
<ScenarioMakePublic
id={row.original.id}
display="list"
isPublic={row.original.isPublic}
canEditScenario={canEditScenario}
/>
);
},
},
{
id: 'actions',
header: '',
align: 'right',
size: 260,
isSticky: 'right',
cell: ({ row }) => (
<ScenarioActions
canDeleteScenario={canDeleteScenario}
canEditScenario={canEditScenario}
scenarioId={row.original.id}
display="list"
setDeleteVisibility={() => onDelete(row.original.id)}
/>
),
cell: ({ row }) => {
const canDeleteScenario = hasPermission(
Permission.CAN_DELETE_SCENARIO,
row.original?.user.id,
);
const canEditScenario = hasPermission(
Permission.CAN_EDIT_SCENARIO,
row.original?.user.id,
);
return (
<ScenarioActions
canDeleteScenario={canDeleteScenario}
canEditScenario={canEditScenario}
scenarioId={row.original.id}
display="list"
setDeleteVisibility={() => onDelete(row.original.id)}
/>
);
},
},
]}
/>
Expand Down
2 changes: 0 additions & 2 deletions client/src/containers/scenarios/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ export type ScenarioInterventionProps = {
export type ScenarioTableProps = {
data: Scenario[];
className?: string;
canEditScenario: boolean;
canDeleteScenario: boolean;
onDelete: (id: string) => void;
};

Expand Down
6 changes: 3 additions & 3 deletions client/src/hooks/permissions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useProfile } from 'hooks/profile';

import type { Permission } from './enums';

export function usePermissions(creatorId?: string) {
export function usePermissions() {
const { data, isLoading } = useProfile();

const roles: RoleName[] = [];
Expand All @@ -27,11 +27,11 @@ export function usePermissions(creatorId?: string) {
* Function to determine if a user is allowed to perform an action.
* For CREATE actions add param needsCreatorPermission=false, so it will not check the 'creatorId'
*/
const hasPermission = (permissionName: Permission, needsCreatorPermission = true) => {
const hasPermission = (permissionName: Permission, creatorId?: string) => {
// The user has permission
let permission = permissions?.includes(permissionName);
// The user is creator of the entity and has permission (for delete and update actions)
if (needsCreatorPermission) {
if (!!creatorId) {
permission = permission && creatorId === data?.id;
}
// Admin always has permission
Expand Down
39 changes: 21 additions & 18 deletions client/src/pages/data/scenarios/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ const ScenariosAdminPage: React.FC = () => {
}, [deleteScenario, scenatioToDelete]);

const { hasPermission } = usePermissions();
const canCreateScenario = hasPermission(Permission.CAN_CREATE_SCENARIO, false);
const canDeleteScenario = hasPermission(Permission.CAN_DELETE_SCENARIO);
const canEditScenario = hasPermission(Permission.CAN_EDIT_SCENARIO);
const canCreateScenario = hasPermission(Permission.CAN_CREATE_SCENARIO);
const handleSort = useCallback(
({ value }: Option<string>) => {
router.replace(
Expand Down Expand Up @@ -222,23 +220,28 @@ const ScenariosAdminPage: React.FC = () => {
(currentDisplay === 'grid' ? (
<div className={displayClasses[currentDisplay]}>
{!isLoading &&
data?.map((scenarioData) => (
<ScenarioCard
key={`scenario-card-${scenarioData.id}`}
data={scenarioData}
canEditScenario={canEditScenario}
canDeleteScenario={canDeleteScenario}
onDelete={onDeleteScenario}
/>
))}
data?.map((scenarioData) => {
const canDeleteScenario = hasPermission(
Permission.CAN_DELETE_SCENARIO,
scenarioData.user?.id,
);
const canEditScenario = hasPermission(
Permission.CAN_EDIT_SCENARIO,
scenarioData.user?.id,
);
return (
<ScenarioCard
key={`scenario-card-${scenarioData.id}`}
data={scenarioData}
onDelete={onDeleteScenario}
canDeleteScenario={canDeleteScenario}
canEditScenario={canEditScenario}
/>
);
})}
</div>
) : (
<ScenarioTable
data={data}
canEditScenario={canEditScenario}
canDeleteScenario={canDeleteScenario}
onDelete={onDeleteScenario}
/>
<ScenarioTable data={data} onDelete={onDeleteScenario} />
))}
</div>
<DeleteDialog
Expand Down