Skip to content

Commit

Permalink
Merge pull request #186 from CSCfi/CSCFC4EMSCR-491_Implement-MSCR-cop…
Browse files Browse the repository at this point in the history
…y-in-UI-continues

CSCFC4EMSCR-491 Implement MSCR copy in UI continues
  • Loading branch information
konolak authored Jun 20, 2024
2 parents 6153e17 + ecd7bdd commit 79519e3
Show file tree
Hide file tree
Showing 16 changed files with 265 additions and 162 deletions.
1 change: 1 addition & 0 deletions mscr-ui/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"finish-editing": "Finish editing",
"invalidate-crosswalk": "Invalidate crosswalk",
"invalidate-schema": "Invalidate schema",
"mscr-copy": "Make MSCR copy",
"publish-crosswalk": "Publish crosswalk",
"publish-schema": "Publish schema",
"revision": "Add new revision"
Expand Down
1 change: 1 addition & 0 deletions mscr-ui/public/locales/fi/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"finish-editing": "",
"invalidate-crosswalk": "",
"invalidate-schema": "",
"mscr-copy": "",
"publish-crosswalk": "",
"publish-schema": "",
"revision": ""
Expand Down
1 change: 1 addition & 0 deletions mscr-ui/public/locales/sv/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"finish-editing": "",
"invalidate-crosswalk": "",
"invalidate-schema": "",
"mscr-copy": "",
"publish-crosswalk": "",
"publish-schema": "",
"revision": ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { CrosswalkWithVersionInfo } from '@app/common/interfaces/crosswalk.inter
import { SchemaWithVersionInfo } from '@app/common/interfaces/schema.interface';
import { ActionMenuWrapper } from '@app/common/components/schema-and-crosswalk-actionmenu/schema-and-crosswalk-actionmenu.styles';
import FormModal, { ModalType } from '@app/modules/form';
import { Format } from '@app/common/interfaces/format.interface';
import { Format, formatsAvailableForMscrCopy } from '@app/common/interfaces/format.interface';

interface SchemaAndCrosswalkActionmenuProps {
type: ActionMenuTypes;
Expand Down Expand Up @@ -55,6 +55,7 @@ export default function SchemaAndCrosswalkActionMenu({
const [isDeleteConfirmModalOpen, setDeleteConfirmModalOpen] = useState(false);
const [isRemoveConfirmModalOpen, setRemoveConfirmModalOpen] = useState(false);
const [isRevisionModalOpen, setRevisionModalOpen] = useState(false);
const [isMscrCopyModalOpen, setMscrCopyModalOpen] = useState(false);
const [isCrosswalkPublished, setCrosswalkPublished] =
React.useState<boolean>(false);
const [isLatestVersion, setIsLatestVersion] = useState(false);
Expand Down Expand Up @@ -202,6 +203,10 @@ export default function SchemaAndCrosswalkActionMenu({
}
}, [metadata.revisions, metadata.pid]);

if (type == ActionMenuTypes.NoEditPermission) {
return renderStubMenu();
}

return (
<>
<ActionMenuWrapper>
Expand Down Expand Up @@ -293,6 +298,18 @@ export default function SchemaAndCrosswalkActionMenu({
>
{t('actionmenu.revision')}
</ActionMenuItem>
<ActionMenuItem
className={
formatsAvailableForMscrCopy.includes(metadata.format) &&
(type === ActionMenuTypes.Schema ||
type === ActionMenuTypes.SchemaMetadata)
? ''
: 'd-none'
}
onClick={() => setMscrCopyModalOpen(true)}
>
{t('actionmenu.mscr-copy')}
</ActionMenuItem>
</ActionMenu>
</ActionMenuWrapper>
<ConfirmModal
Expand Down Expand Up @@ -406,6 +423,34 @@ export default function SchemaAndCrosswalkActionMenu({
setVisible={setRevisionModalOpen}
initialData={metadata}
/>
<FormModal
modalType={ModalType.McsrCopy}
contentType={Type.Schema}
visible={isMscrCopyModalOpen}
setVisible={setMscrCopyModalOpen}
initialData={metadata}
/>
</>
);

function renderStubMenu() {
return (
<>
<ActionMenuWrapper>
<ActionMenu buttonText={t('action.actions')}>
<ActionMenuItem onClick={() => setMscrCopyModalOpen(true)}>
{t('actionmenu.mscr-copy')}
</ActionMenuItem>
</ActionMenu>
</ActionMenuWrapper>
<FormModal
modalType={ModalType.McsrCopy}
contentType={Type.Schema}
visible={isMscrCopyModalOpen}
setVisible={setMscrCopyModalOpen}
initialData={metadata}
/>
</>
);
}
}
11 changes: 11 additions & 0 deletions mscr-ui/src/common/components/schema/schema.slice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ export const schemaApi = createApi({
},
})
}),
putSchemaMscrCopy: builder.mutation<Schema, { pid: string; data: Partial<Metadata> }>({
query: ({pid, data }) => ({
url: `/schema?action=mscrCopyOf&target=${pid}`,
method: 'PUT',
data: data,
headers: {
'content-Type': 'application/json;',
},
}),
}),
patchSchema: builder.mutation<
Metadata,
{
Expand Down Expand Up @@ -141,6 +151,7 @@ export const {
useGetSchemasQuery,
usePutSchemaFullMutation,
usePutSchemaRevisionMutation,
usePutSchemaMscrCopyMutation,
usePatchSchemaMutation,
util: { getRunningQueriesThunk },
} = schemaApi;
Expand Down
8 changes: 8 additions & 0 deletions mscr-ui/src/common/interfaces/format.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ export const formatsAvailableForSchemaRegistration: Format[] = [
Format.Shacl
];

export const formatsAvailableForMscrCopy: Format[] = [
Format.Csv,
Format.Jsonschema,
Format.Mscr,
Format.Shacl,
Format.Xsd
];

export const fileExtensionsAvailableForCrosswalkRegistrationAttachments: FileExtensions[] =
[FileExtensions.Csv, FileExtensions.Xslt, FileExtensions.Pdf];

Expand Down
1 change: 1 addition & 0 deletions mscr-ui/src/common/interfaces/search.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export enum ActionMenuTypes {
CrosswalkVersionInfo = 'CROSSWALK_VERSIONINFO',
Schema = 'SCHEMA',
SchemaMetadata = 'SCHEMA_METADATA',
NoEditPermission = 'NO_EDIT_PERMISSION',
}

export interface ResultInfo {
Expand Down
145 changes: 45 additions & 100 deletions mscr-ui/src/common/utils/has-permission.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,36 @@ import {
import { User } from 'yti-common-ui/interfaces/user.interface';
import { Roles } from '../interfaces/format.interface';

// Need to specify the acctions permitted for each type of user
// Need to specify the actions permitted for each type of user
const actions = [
'CREATE_SCHEMA',
'EDIT_SCHEMA',
'EDIT_SCHEMA_METADATA',
'EDIT_SCHEMA_FILES',
'DELETE_SCHEMA',
'CREATE_CROSSWALK',
'EDIT_CROSSWALK_MAPPINGS',
'EDIT_CROSSWALK_METADATA',
'EDIT_CROSSWALK_FILES',
'DELETE_CROSSWALK',
// 'CREATE_SCHEMA',
// 'EDIT_SCHEMA',
// 'EDIT_SCHEMA_METADATA',
// 'EDIT_SCHEMA_FILES',
// 'DELETE_SCHEMA',
// 'CREATE_CROSSWALK',
// 'EDIT_CROSSWALK_MAPPINGS',
// 'EDIT_CROSSWALK_METADATA',
// 'EDIT_CROSSWALK_FILES',
// 'DELETE_CROSSWALK',
'EDIT_CONTENT',
'MAKE_MSCR_COPY',
] as const;

export type Actions = typeof actions[number];
export type Action = typeof actions[number];

export interface hasPermissionProps {
actions: Actions | Actions[];
targetOrganization?: string;
action: Action;
owner?: string[];
}

export interface checkPermissionProps {
user: User;
actions: Actions[];
targetOrganizations?: string[];
action: Action;
owner?: string[];
}

export default function HasPermission({
actions,
targetOrganization,
owner,
}: hasPermissionProps) {
export default function HasPermission({ action, owner }: hasPermissionProps) {
const { data: authenticatedUser } = useGetAuthenticatedUserQuery();
const dispatch = useStoreDispatch();
const user = useSelector(selectLogin());
Expand All @@ -66,99 +62,48 @@ export default function HasPermission({
return false;
}

//No Target Organization
if (!targetOrganization) {
if (owner && owner.length) {
//Editing Step as already has owner
return checkEditPermission({
user,
actions: Array.isArray(actions) ? actions : [actions],
owner,
});
}
if (!owner || owner.length == 0) {
return checkPermission({
user,
actions: Array.isArray(actions) ? actions : [actions],
action,
});
}

//If there is target organization
if (owner && owner.length) {
//Editing Step as already has owner
return checkEditPermission({
user,
actions: Array.isArray(actions) ? actions : [actions],
targetOrganizations: [targetOrganization],
owner,
});
}
return checkPermission({
//Content Creation
user,
actions: Array.isArray(actions) ? actions : [actions],
targetOrganizations: [targetOrganization],
action,
owner,
});
}

export function checkPermission({
user,
actions,
targetOrganizations,
}: checkPermissionProps) {

const rolesInOrganizations = Object.keys(user.organizationsInRole);

const rolesInTargetOrganizations =
targetOrganizations &&
targetOrganizations
?.flatMap((org) => user.rolesInOrganizations[org])
.filter((t) => t);

// Return true if user is superuser
if (user.superuser) {
return true;
}

// Return true if target organization is undefined and user has admin role
if (rolesInOrganizations.includes(Roles.admin) && !targetOrganizations) {
return true;
}

// console.log(rolesInTargetOrganizations);
// Return true if user has data model editor role in target organization
if (
rolesInTargetOrganizations?.includes(Roles.dataModelEditor)||rolesInTargetOrganizations?.includes(Roles.admin)
) {
export function checkPermission({ user, action, owner }: checkPermissionProps) {
if (action == 'MAKE_MSCR_COPY') {
return true;
}


return false;
}

export function checkEditPermission({
user,
owner
}: checkPermissionProps) {
if (owner?.includes(user.id)) {
//user is the owner, Check for personal Contents
return true;
} else {
//Gruop Content

if (owner && user.organizationsInRole[Roles.admin]&& user.organizationsInRole[Roles.admin].includes(owner[0])) {
// User has admin right for this group
return true;
}

if (
owner &&user.organizationsInRole[Roles.dataModelEditor]&&
user.organizationsInRole[Roles.dataModelEditor].includes(owner[0])
) {
} else if (action == 'EDIT_CONTENT') {
if (owner?.includes(user.id)) {
//user is the owner, Check for personal Contents
return true;
} else {
//Group Content
if (
owner &&
user.organizationsInRole[Roles.admin] &&
user.organizationsInRole[Roles.admin].includes(owner[0])
) {
// User has admin right for this group
return true;
}

if (
owner &&
user.organizationsInRole[Roles.dataModelEditor] &&
user.organizationsInRole[Roles.dataModelEditor].includes(owner[0])
) {
// User has data model editor right for this group
return true;
}
}
}


return false;
}
20 changes: 12 additions & 8 deletions mscr-ui/src/modules/crosswalk-editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export default function CrosswalkEditor({
} = useGetCrosswalkWithRevisionsQuery(crosswalkId);

const hasEditRights = HasPermission({
actions: ['EDIT_CROSSWALK_MAPPINGS'],
action: 'EDIT_CONTENT',
owner: getCrosswalkData?.owner,
});

Expand Down Expand Up @@ -723,13 +723,17 @@ export default function CrosswalkEditor({
</Grid>
<Grid item xs={6} className="d-flex justify-content-end">
<div className="mt-3 me-2">
<SchemaAndCrosswalkActionMenu
buttonCallbackFunction={performCallbackFromActionMenu}
metadata={getCrosswalkData}
isMappingsEditModeActive={isEditModeActive}
refetchMetadata={refetchCrosswalkData}
type={ActionMenuTypes.CrosswalkVersionInfo}
></SchemaAndCrosswalkActionMenu>
{hasEditRights && (
<SchemaAndCrosswalkActionMenu
buttonCallbackFunction={
performCallbackFromActionMenu
}
metadata={getCrosswalkData}
isMappingsEditModeActive={isEditModeActive}
refetchMetadata={refetchCrosswalkData}
type={ActionMenuTypes.CrosswalkVersionInfo}
/>
)}
</div>
</Grid>
<Grid item xs={12}>
Expand Down
Loading

0 comments on commit 79519e3

Please sign in to comment.