[arvados-workbench2] created: 2.6.3-87-g017ab19b
git repository hosting
git at public.arvados.org
Tue Aug 22 18:29:28 UTC 2023
at 017ab19b42969ed662d11291d399294c8f231a4e (commit)
commit 017ab19b42969ed662d11291d399294c8f231a4e
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Tue Aug 22 14:16:29 2023 -0400
20829: Migrate to canWrite and canManage for permission checks
Replace use of writableBy with canWrite and canManage, and remove
writableBy from workbench 2 entirely.
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/src/models/group.ts b/src/models/group.ts
index df4ea6aa..0932b3c9 100644
--- a/src/models/group.ts
+++ b/src/models/group.ts
@@ -15,7 +15,6 @@ export interface GroupResource extends TrashableResource, ResourceWithProperties
name: string;
groupClass: GroupClass | null;
description: string;
- writableBy: string[];
ensure_unique_name: boolean;
canWrite: boolean;
canManage: boolean;
@@ -49,7 +48,6 @@ export const selectedFieldsOfGroup = [
"group_class",
"description",
"properties",
- "writable_by",
"can_write",
"can_manage",
"trash_at",
diff --git a/src/models/test-utils.ts b/src/models/test-utils.ts
index a2a980bf..74667a91 100644
--- a/src/models/test-utils.ts
+++ b/src/models/test-utils.ts
@@ -23,7 +23,6 @@ export const mockGroupResource = (data: Partial<GroupResource> = {}): GroupResou
properties: "",
trashAt: "",
uuid: "",
- writableBy: [],
ensure_unique_name: true,
canWrite: false,
canManage: false,
diff --git a/src/models/user.ts b/src/models/user.ts
index 87a2e8c1..0df6eac2 100644
--- a/src/models/user.ts
+++ b/src/models/user.ts
@@ -24,6 +24,8 @@ export interface User {
prefs: UserPrefs;
isAdmin: boolean;
isActive: boolean;
+ canWrite: boolean;
+ canManage: boolean;
}
export const getUserFullname = (user: User) => {
@@ -62,5 +64,4 @@ export const getUserClusterID = (user: User): string | undefined => {
export interface UserResource extends Resource, User {
kind: ResourceKind.USER;
defaultOwnerUuid: string;
- writableBy: string[];
}
diff --git a/src/services/auth-service/auth-service.ts b/src/services/auth-service/auth-service.ts
index b530e4cd..79a6b7e1 100644
--- a/src/services/auth-service/auth-service.ts
+++ b/src/services/auth-service/auth-service.ts
@@ -35,6 +35,8 @@ export interface UserDetailsResponse {
is_active: boolean;
username: string;
prefs: UserPrefs;
+ can_write: boolean;
+ can_manage: boolean;
}
export class AuthService {
@@ -146,6 +148,8 @@ export class AuthService {
isAdmin: resp.data.is_admin,
isActive: resp.data.is_active,
username: resp.data.username,
+ canWrite: resp.data.can_write,
+ canManage: resp.data.can_manage,
prefs
};
})
diff --git a/src/services/user-service/user-service.ts b/src/services/user-service/user-service.ts
index 8581b267..75131f92 100644
--- a/src/services/user-service/user-service.ts
+++ b/src/services/user-service/user-service.ts
@@ -12,8 +12,7 @@ export class UserService extends CommonResourceService<UserResource> {
constructor(serverApi: AxiosInstance, actions: ApiActions, readOnlyFields: string[] = []) {
super(serverApi, "users", actions, readOnlyFields.concat([
'fullName',
- 'isInvited',
- 'writableBy',
+ 'isInvited'
]));
}
diff --git a/src/store/advanced-tab/advanced-tab.tsx b/src/store/advanced-tab/advanced-tab.tsx
index 63337117..fedd5518 100644
--- a/src/store/advanced-tab/advanced-tab.tsx
+++ b/src/store/advanced-tab/advanced-tab.tsx
@@ -468,7 +468,7 @@ const collectionApiResponse = (apiResponse: CollectionResource): JSX.Element =>
const groupRequestApiResponse = (apiResponse: ProjectResource): JSX.Element => {
const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name,
- description, groupClass, trashAt, isTrashed, deleteAt, properties, writableBy,
+ description, groupClass, trashAt, isTrashed, deleteAt, properties,
canWrite, canManage } = apiResponse;
const response = `
"uuid": "${uuid}",
@@ -485,8 +485,7 @@ const groupRequestApiResponse = (apiResponse: ProjectResource): JSX.Element => {
"delete_at": ${stringify(deleteAt)},
"properties": ${stringifyObject(properties)},
"can_write": ${stringify(canWrite)},
-"can_manage": ${stringify(canManage)},
-"writable_by": ${stringifyObject(writableBy)}`;
+"can_manage": ${stringify(canManage)}`;
return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
};
diff --git a/src/store/context-menu/context-menu-actions.test.ts b/src/store/context-menu/context-menu-actions.test.ts
index d9e87b1a..623c4508 100644
--- a/src/store/context-menu/context-menu-actions.test.ts
+++ b/src/store/context-menu/context-menu-actions.test.ts
@@ -107,13 +107,13 @@ describe('context-menu-actions', () => {
[projectUuid]: {
uuid: projectUuid,
ownerUuid: isEditable ? userUuid : otherUserUuid,
- writableBy: isEditable ? [userUuid] : [otherUserUuid],
+ canWrite: isEditable,
groupClass: GroupClass.PROJECT,
},
[filterGroupUuid]: {
uuid: filterGroupUuid,
ownerUuid: isEditable ? userUuid : otherUserUuid,
- writableBy: isEditable ? [userUuid] : [otherUserUuid],
+ canWrite: isEditable,
groupClass: GroupClass.FILTER,
},
[linkUuid]: {
diff --git a/src/store/resources/resources.test.ts b/src/store/resources/resources.test.ts
index 300e21d1..503e19a2 100644
--- a/src/store/resources/resources.test.ts
+++ b/src/store/resources/resources.test.ts
@@ -27,7 +27,7 @@ describe('resources', () => {
modifiedAt: 'string',
href: 'string',
kind: ResourceKind.PROJECT,
- writableBy: [groupFixtures.user_uuid],
+ canWrite: true,
etag: 'string',
},
[groupFixtures.editable_collection_resource_uuid]: {
@@ -50,7 +50,7 @@ describe('resources', () => {
modifiedAt: 'string',
href: 'string',
kind: ResourceKind.PROJECT,
- writableBy: [groupFixtures.unknown_user_resource_uuid],
+ canWrite: false,
etag: 'string',
},
[groupFixtures.not_editable_collection_resource_uuid]: {
@@ -137,4 +137,4 @@ describe('resources', () => {
expect(result!.isEditable).toBeFalsy();
});
});
-});
\ No newline at end of file
+});
diff --git a/src/store/resources/resources.ts b/src/store/resources/resources.ts
index 6f7acada..a063db97 100644
--- a/src/store/resources/resources.ts
+++ b/src/store/resources/resources.ts
@@ -9,26 +9,6 @@ import { GroupResource } from "models/group";
export type ResourcesState = { [key: string]: Resource };
-const getResourceWritableBy = (state: ResourcesState, id: string, userUuid: string): string[] => {
- if (!id) {
- return [];
- }
-
- if (id === userUuid) {
- return [userUuid];
- }
-
- const resource = (state[id] as ProjectResource);
-
- if (!resource) {
- return [];
- }
-
- const { writableBy } = resource;
-
- return writableBy || getResourceWritableBy(state, resource.ownerUuid, userUuid);
-};
-
export const getResourceWithEditableStatus = <T extends EditableResource & GroupResource>(id: string, userUuid?: string) =>
(state: ResourcesState): T | undefined => {
if (state[id] === undefined) { return; }
@@ -36,7 +16,7 @@ export const getResourceWithEditableStatus = <T extends EditableResource & Group
const resource = JSON.parse(JSON.stringify(state[id] as T));
if (resource) {
- resource.isEditable = userUuid ? getResourceWritableBy(state, id, userUuid).indexOf(userUuid) > -1 : false;
+ resource.isEditable = resource.canWrite;
}
return resource;
diff --git a/src/store/run-process-panel/run-process-panel-actions.ts b/src/store/run-process-panel/run-process-panel-actions.ts
index 58796295..67a89e4c 100644
--- a/src/store/run-process-panel/run-process-panel-actions.ts
+++ b/src/store/run-process-panel/run-process-panel-actions.ts
@@ -104,7 +104,7 @@ export const setWorkflow = (workflow: WorkflowResource, isWorkflowChanged = true
let owner = getResource<ProjectResource | UserResource>(getState().runProcessPanel.processOwnerUuid)(getState().resources);
const userUuid = getUserUuid(getState());
- if (!owner || !userUuid || owner.writableBy.indexOf(userUuid) === -1) {
+ if (!owner || !owner.canWrite) {
owner = undefined;
}
diff --git a/src/store/tree-picker/tree-picker-actions.ts b/src/store/tree-picker/tree-picker-actions.ts
index ad657f14..72d1cb65 100644
--- a/src/store/tree-picker/tree-picker-actions.ts
+++ b/src/store/tree-picker/tree-picker-actions.ts
@@ -390,7 +390,7 @@ export const loadFavoritesProject = (params: LoadFavoritesProjectParams,
id: 'Favorites',
pickerId,
data: items.filter((item) => {
- if (options.showOnlyWritable && (item as GroupResource).writableBy && (item as GroupResource).writableBy.indexOf(uuid) === -1) {
+ if (options.showOnlyWritable && !(item as GroupResource).canWrite) {
return false;
}
diff --git a/src/store/workflow-panel/workflow-panel-actions.ts b/src/store/workflow-panel/workflow-panel-actions.ts
index eab16882..2c44fae4 100644
--- a/src/store/workflow-panel/workflow-panel-actions.ts
+++ b/src/store/workflow-panel/workflow-panel-actions.ts
@@ -65,7 +65,7 @@ export const openRunProcess = (workflowUuid: string, ownerUuid?: string, name?:
// Must be writable.
const userUuid = getUserUuid(getState());
owner = getResource<ProjectResource | UserResource>(ownerUuid)(getState().resources);
- if (!owner || !userUuid || owner.writableBy.indexOf(userUuid) === -1) {
+ if (!owner || !owner.canWrite) {
owner = undefined;
}
}
diff --git a/src/views-components/data-explorer/renderers.tsx b/src/views-components/data-explorer/renderers.tsx
index d274157c..25130407 100644
--- a/src/views-components/data-explorer/renderers.tsx
+++ b/src/views-components/data-explorer/renderers.tsx
@@ -91,7 +91,7 @@ const renderName = (dispatch: Dispatch, item: GroupContentsResource) => {
};
-const FrozenProject = (props: {item: ProjectResource}) => {
+const FrozenProject = (props: { item: ProjectResource }) => {
const [fullUsername, setFullusername] = React.useState<any>(null);
const getFullName = React.useCallback(() => {
if (props.item.frozenByUuid) {
@@ -102,7 +102,7 @@ const FrozenProject = (props: {item: ProjectResource}) => {
if (props.item.frozenByUuid) {
return <Tooltip onOpen={getFullName} enterDelay={500} title={<span>Project was frozen by {fullUsername}</span>}>
- <FreezeIcon style={{ fontSize: "inherit" }}/>
+ <FreezeIcon style={{ fontSize: "inherit" }} />
</Tooltip>;
} else {
return null;
@@ -115,7 +115,7 @@ export const ResourceName = connect(
return resource;
})((resource: GroupContentsResource & DispatchProp<any>) => renderName(resource.dispatch, resource));
-
+
const renderIcon = (item: GroupContentsResource) => {
switch (item.kind) {
case ResourceKind.PROJECT:
@@ -230,12 +230,12 @@ export const UserResourceFullName = connect(
const renderUuid = (item: { uuid: string }) =>
<Typography data-cy="uuid" noWrap>
{item.uuid}
- {(item.uuid && <CopyToClipboardSnackbar value={item.uuid} />) || '-' }
+ {(item.uuid && <CopyToClipboardSnackbar value={item.uuid} />) || '-'}
</Typography>;
const renderUuidCopyIcon = (item: { uuid: string }) =>
<Typography data-cy="uuid" noWrap>
- {(item.uuid && <CopyToClipboardSnackbar value={item.uuid} />) || '-' }
+ {(item.uuid && <CopyToClipboardSnackbar value={item.uuid} />) || '-'}
</Typography>;
export const ResourceUuid = connect((state: RootState, props: { uuid: string }) => (
@@ -617,11 +617,8 @@ export const ResourceLinkTailPermissionLevel = connect(
const getResourceLinkCanManage = (state: RootState, link: LinkResource) => {
const headResource = getResource<Resource>(link.headUuid)(state.resources);
- // const tailResource = getResource<Resource>(link.tailUuid)(state.resources);
- const userUuid = getUserUuid(state);
-
if (headResource && headResource.kind === ResourceKind.GROUP) {
- return userUuid ? (headResource as GroupResource).writableBy?.includes(userUuid) : false;
+ return (headResource as GroupResource).canManage;
} else {
// true for now
return true;
@@ -687,12 +684,12 @@ const renderUuidLinkWithCopyIcon = (dispatch: Dispatch, item: ProcessResource, c
const selectedColumnUuid = item[column]
return <Grid container alignItems="center" wrap="nowrap" >
<Grid item>
- {selectedColumnUuid ?
- <Typography color="primary" style={{ width: 'auto', cursor: 'pointer' }} noWrap
+ {selectedColumnUuid ?
+ <Typography color="primary" style={{ width: 'auto', cursor: 'pointer' }} noWrap
onClick={() => dispatch<any>(navigateTo(selectedColumnUuid))}>
- {selectedColumnUuid}
- </Typography>
- : '-' }
+ {selectedColumnUuid}
+ </Typography>
+ : '-'}
</Grid>
<Grid item>
{selectedColumnUuid && renderUuidCopyIcon({ uuid: selectedColumnUuid })}
@@ -716,20 +713,20 @@ export const ResourceParentProcess = connect(
(state: RootState, props: { uuid: string }) => {
const process = getProcess(props.uuid)(state.resources)
return { parentProcess: process?.containerRequest?.requestingContainerUuid || '' };
- })((props: { parentProcess: string }) => renderUuid({uuid: props.parentProcess}));
+ })((props: { parentProcess: string }) => renderUuid({ uuid: props.parentProcess }));
export const ResourceModifiedByUserUuid = connect(
(state: RootState, props: { uuid: string }) => {
const process = getProcess(props.uuid)(state.resources)
return { userUuid: process?.containerRequest?.modifiedByUserUuid || '' };
- })((props: { userUuid: string }) => renderUuid({uuid: props.userUuid}));
+ })((props: { userUuid: string }) => renderUuid({ uuid: props.userUuid }));
- export const ResourceCreatedAtDate = connect(
+export const ResourceCreatedAtDate = connect(
(state: RootState, props: { uuid: string }) => {
const resource = getResource<GroupContentsResource>(props.uuid)(state.resources);
return { date: resource ? resource.createdAt : '' };
})((props: { date: string }) => renderDate(props.date));
-
+
export const ResourceLastModifiedDate = connect(
(state: RootState, props: { uuid: string }) => {
const resource = getResource<GroupContentsResource>(props.uuid)(state.resources);
@@ -787,39 +784,39 @@ export const ResourceUUID = connect(
(state: RootState, props: { uuid: string }) => {
const resource = getResource<CollectionResource>(props.uuid)(state.resources);
return { uuid: resource ? resource.uuid : '' };
- })((props: { uuid: string }) => renderUuid({uuid: props.uuid}));
+ })((props: { uuid: string }) => renderUuid({ uuid: props.uuid }));
-const renderVersion = (version: number) =>{
+const renderVersion = (version: number) => {
return <Typography>{version ?? '-'}</Typography>
}
export const ResourceVersion = connect(
(state: RootState, props: { uuid: string }) => {
const resource = getResource<CollectionResource>(props.uuid)(state.resources);
- return { version: resource ? resource.version: '' };
+ return { version: resource ? resource.version : '' };
})((props: { version: number }) => renderVersion(props.version));
-
-const renderPortableDataHash = (portableDataHash:string | null) =>
+
+const renderPortableDataHash = (portableDataHash: string | null) =>
<Typography noWrap>
{portableDataHash ? <>{portableDataHash}
- <CopyToClipboardSnackbar value={portableDataHash} /></> : '-' }
+ <CopyToClipboardSnackbar value={portableDataHash} /></> : '-'}
</Typography>
-
+
export const ResourcePortableDataHash = connect(
(state: RootState, props: { uuid: string }) => {
const resource = getResource<CollectionResource>(props.uuid)(state.resources);
- return { portableDataHash: resource ? resource.portableDataHash : '' };
+ return { portableDataHash: resource ? resource.portableDataHash : '' };
})((props: { portableDataHash: string }) => renderPortableDataHash(props.portableDataHash));
-const renderFileCount = (fileCount: number) =>{
+const renderFileCount = (fileCount: number) => {
return <Typography>{fileCount ?? '-'}</Typography>
}
export const ResourceFileCount = connect(
(state: RootState, props: { uuid: string }) => {
const resource = getResource<CollectionResource>(props.uuid)(state.resources);
- return { fileCount: resource ? resource.fileCount: '' };
+ return { fileCount: resource ? resource.fileCount : '' };
})((props: { fileCount: number }) => renderFileCount(props.fileCount));
const userFromID =
@@ -968,12 +965,12 @@ export const CollectionStatus = connect((state: RootState, props: { uuid: string
export const CollectionName = connect((state: RootState, props: { uuid: string, className?: string }) => {
return {
- collection: getResource<CollectionResource>(props.uuid)(state.resources),
- uuid: props.uuid,
- className: props.className,
- };
+ collection: getResource<CollectionResource>(props.uuid)(state.resources),
+ uuid: props.uuid,
+ className: props.className,
+ };
})((props: { collection: CollectionResource, uuid: string, className?: string }) =>
- <Typography className={props.className}>{props.collection?.name || props.uuid}</Typography>
+ <Typography className={props.className}>{props.collection?.name || props.uuid}</Typography>
);
export const ProcessStatus = compose(
@@ -994,7 +991,7 @@ export const ProcessStatus = compose(
}}
/>
: <Typography>-</Typography>
- );
+ );
export const ProcessStartDate = connect(
(state: RootState, props: { uuid: string }) => {
diff --git a/src/views-components/side-panel-button/side-panel-button.tsx b/src/views-components/side-panel-button/side-panel-button.tsx
index 78744415..6acbb161 100644
--- a/src/views-components/side-panel-button/side-panel-button.tsx
+++ b/src/views-components/side-panel-button/side-panel-button.tsx
@@ -89,8 +89,7 @@ export const SidePanelButton = withStyles(styles)(
enabled = true;
} else if (matchProjectRoute(location ? location.pathname : '')) {
const currentProject = getResource<ProjectResource>(currentItemId)(resources);
- if (currentProject && currentProject.writableBy &&
- currentProject.writableBy.indexOf(currentUserUUID || '') >= 0 &&
+ if (currentProject && currentProject.canWrite &&
!currentProject.frozenByUuid &&
!isProjectTrashed(currentProject, resources) &&
currentProject.groupClass !== GroupClass.FILTER) {
diff --git a/src/views/collection-panel/collection-panel.tsx b/src/views/collection-panel/collection-panel.tsx
index 79cf07bf..8cf19c03 100644
--- a/src/views/collection-panel/collection-panel.tsx
+++ b/src/views/collection-panel/collection-panel.tsx
@@ -150,8 +150,8 @@ export const CollectionPanel = withStyles(styles)(connect(
isWritable = true;
} else {
const itemOwner = getResource<GroupResource | UserResource>(item.ownerUuid)(state.resources);
- if (itemOwner && itemOwner.writableBy) {
- isWritable = itemOwner.writableBy.indexOf(currentUserUUID || '') >= 0;
+ if (itemOwner) {
+ isWritable = itemOwner.canWrite;
}
}
}
@@ -351,7 +351,7 @@ export const CollectionDetailsAttributes = (props: CollectionDetailsProps) => {
{/*
NOTE: The property list should be kept at the bottom, because it spans
the entire available width, without regards of the twoCol prop.
- */}
+ */}
<Grid item xs={12} md={12}>
<DetailsAttribute classLabel={classes.label} classValue={classes.value}
label='Properties' />
diff --git a/src/views/group-details-panel/group-details-panel.tsx b/src/views/group-details-panel/group-details-panel.tsx
index 798a7b67..fdbc204e 100644
--- a/src/views/group-details-panel/group-details-panel.tsx
+++ b/src/views/group-details-panel/group-details-panel.tsx
@@ -136,8 +136,8 @@ const mapStateToProps = (state: RootState) => {
return {
resources: state.resources,
groupCanManage: userUuid && !isBuiltinGroup(group?.uuid || '')
- ? group?.writableBy?.includes(userUuid)
- : false,
+ ? group?.canManage
+ : false,
};
};
@@ -158,7 +158,7 @@ export const GroupDetailsPanel = withStyles(styles)(connect(
)(
class GroupDetailsPanel extends React.Component<GroupDetailsPanelProps & WithStyles<CssRules>> {
state = {
- value: 0,
+ value: 0,
};
componentDidMount() {
@@ -169,56 +169,56 @@ export const GroupDetailsPanel = withStyles(styles)(connect(
const { value } = this.state;
return (
<Paper className={this.props.classes.root}>
- <Tabs value={value} onChange={this.handleChange} variant="fullWidth">
- <Tab data-cy="group-details-members-tab" label="MEMBERS" />
- <Tab data-cy="group-details-permissions-tab" label="PERMISSIONS" />
- </Tabs>
- <div className={this.props.classes.content}>
- {value === 0 &&
- <DataExplorer
- id={GROUP_DETAILS_MEMBERS_PANEL_ID}
- data-cy="group-members-data-explorer"
- onRowClick={noop}
- onRowDoubleClick={noop}
- onContextMenu={noop}
- contextMenuColumn={false}
- defaultViewIcon={UserPanelIcon}
- defaultViewMessages={[MEMBERS_DEFAULT_MESSAGE]}
- hideColumnSelector
- hideSearchInput
- actions={
+ <Tabs value={value} onChange={this.handleChange} variant="fullWidth">
+ <Tab data-cy="group-details-members-tab" label="MEMBERS" />
+ <Tab data-cy="group-details-permissions-tab" label="PERMISSIONS" />
+ </Tabs>
+ <div className={this.props.classes.content}>
+ {value === 0 &&
+ <DataExplorer
+ id={GROUP_DETAILS_MEMBERS_PANEL_ID}
+ data-cy="group-members-data-explorer"
+ onRowClick={noop}
+ onRowDoubleClick={noop}
+ onContextMenu={noop}
+ contextMenuColumn={false}
+ defaultViewIcon={UserPanelIcon}
+ defaultViewMessages={[MEMBERS_DEFAULT_MESSAGE]}
+ hideColumnSelector
+ hideSearchInput
+ actions={
this.props.groupCanManage &&
<Grid container justify='flex-end'>
<Button
- data-cy="group-member-add"
- variant="contained"
- color="primary"
- onClick={this.props.onAddUser}>
- <AddIcon /> Add user
+ data-cy="group-member-add"
+ variant="contained"
+ color="primary"
+ onClick={this.props.onAddUser}>
+ <AddIcon /> Add user
</Button>
</Grid>
- }
- paperProps={{
- elevation: 0,
- }} />
- }
- {value === 1 &&
- <DataExplorer
- id={GROUP_DETAILS_PERMISSIONS_PANEL_ID}
- data-cy="group-permissions-data-explorer"
- onRowClick={noop}
- onRowDoubleClick={noop}
- onContextMenu={noop}
- contextMenuColumn={false}
- defaultViewIcon={KeyIcon}
- defaultViewMessages={[PERMISSIONS_DEFAULT_MESSAGE]}
- hideColumnSelector
- hideSearchInput
- paperProps={{
- elevation: 0,
- }} />
- }
- </div>
+ }
+ paperProps={{
+ elevation: 0,
+ }} />
+ }
+ {value === 1 &&
+ <DataExplorer
+ id={GROUP_DETAILS_PERMISSIONS_PANEL_ID}
+ data-cy="group-permissions-data-explorer"
+ onRowClick={noop}
+ onRowDoubleClick={noop}
+ onContextMenu={noop}
+ contextMenuColumn={false}
+ defaultViewIcon={KeyIcon}
+ defaultViewMessages={[PERMISSIONS_DEFAULT_MESSAGE]}
+ hideColumnSelector
+ hideSearchInput
+ paperProps={{
+ elevation: 0,
+ }} />
+ }
+ </div>
</Paper>
);
}
diff --git a/src/views/run-process-panel/inputs/project-input.tsx b/src/views/run-process-panel/inputs/project-input.tsx
index 688af4aa..d91a6b84 100644
--- a/src/views/run-process-panel/inputs/project-input.tsx
+++ b/src/views/run-process-panel/inputs/project-input.tsx
@@ -99,7 +99,7 @@ export const ProjectInputComponent = connect(mapStateToProps)(
}
}
- invalid = () => (!this.state.project || this.state.project.writableBy.indexOf(this.props.userUuid) === -1);
+ invalid = () => (!this.state.project || !this.state.project.canWrite);
renderInput() {
return <GenericInput
commit c48418079ce922e7f0710b552a5f13280dd1e4b5
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Tue Aug 22 13:19:22 2023 -0400
20829: Add canWrite and canManage to group and API response dialog
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/src/models/group.ts b/src/models/group.ts
index 109f3857..df4ea6aa 100644
--- a/src/models/group.ts
+++ b/src/models/group.ts
@@ -17,6 +17,8 @@ export interface GroupResource extends TrashableResource, ResourceWithProperties
description: string;
writableBy: string[];
ensure_unique_name: boolean;
+ canWrite: boolean;
+ canManage: boolean;
}
export enum GroupClass {
diff --git a/src/models/project.ts b/src/models/project.ts
index 04dae4d2..8dd2e716 100644
--- a/src/models/project.ts
+++ b/src/models/project.ts
@@ -5,8 +5,7 @@
import { GroupClass, GroupResource } from "./group";
export interface ProjectResource extends GroupResource {
- frozenByUuid: null|string;
- canManage: boolean;
+ frozenByUuid: null | string;
groupClass: GroupClass.PROJECT | GroupClass.FILTER | GroupClass.ROLE;
}
diff --git a/src/models/test-utils.ts b/src/models/test-utils.ts
index 1e1041a1..a2a980bf 100644
--- a/src/models/test-utils.ts
+++ b/src/models/test-utils.ts
@@ -25,6 +25,8 @@ export const mockGroupResource = (data: Partial<GroupResource> = {}): GroupResou
uuid: "",
writableBy: [],
ensure_unique_name: true,
+ canWrite: false,
+ canManage: false,
...data
});
diff --git a/src/store/advanced-tab/advanced-tab.tsx b/src/store/advanced-tab/advanced-tab.tsx
index a495e89c..63337117 100644
--- a/src/store/advanced-tab/advanced-tab.tsx
+++ b/src/store/advanced-tab/advanced-tab.tsx
@@ -467,7 +467,9 @@ const collectionApiResponse = (apiResponse: CollectionResource): JSX.Element =>
};
const groupRequestApiResponse = (apiResponse: ProjectResource): JSX.Element => {
- const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name, description, groupClass, trashAt, isTrashed, deleteAt, properties, writableBy } = apiResponse;
+ const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name,
+ description, groupClass, trashAt, isTrashed, deleteAt, properties, writableBy,
+ canWrite, canManage } = apiResponse;
const response = `
"uuid": "${uuid}",
"owner_uuid": "${ownerUuid}",
@@ -482,6 +484,8 @@ const groupRequestApiResponse = (apiResponse: ProjectResource): JSX.Element => {
"is_trashed": ${stringify(isTrashed)},
"delete_at": ${stringify(deleteAt)},
"properties": ${stringifyObject(properties)},
+"can_write": ${stringify(canWrite)},
+"can_manage": ${stringify(canManage)},
"writable_by": ${stringifyObject(writableBy)}`;
return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list