[ARVADOS-WORKBENCH2] created: 2.4.0-42-gf35d7197
Git user
git at public.arvados.org
Mon Apr 25 21:53:09 UTC 2022
at f35d7197b88370eac78d26d55bf7157b523536df (commit)
commit f35d7197b88370eac78d26d55bf7157b523536df
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date: Mon Apr 25 18:52:35 2022 -0300
16115: pre-vacations WIP commit.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>
diff --git a/src/services/api-client-authorization-service/api-client-authorization-service.ts b/src/services/api-client-authorization-service/api-client-authorization-service.ts
index 012fdb15..7c985dbb 100644
--- a/src/services/api-client-authorization-service/api-client-authorization-service.ts
+++ b/src/services/api-client-authorization-service/api-client-authorization-service.ts
@@ -33,11 +33,11 @@ export class ApiClientAuthorizationService extends CommonService<ApiClientAuthor
}
return this.list({
filters: new FilterBuilder()
- .addEqual("scopes", JSON.stringify([
+ .addEqual("scopes", [
`GET /arvados/v1/collections/${uuid}`,
`GET /arvados/v1/collections/${uuid}/`,
- "GET /arvados/v1/keep_services/accessible",
- ])).getFilters()
+ "GET /arvados/v1/keep_services/accessible"
+ ]).getFilters()
});
}
}
\ No newline at end of file
diff --git a/src/services/api/filter-builder.ts b/src/services/api/filter-builder.ts
index d1a4fd08..4809e7a8 100644
--- a/src/services/api/filter-builder.ts
+++ b/src/services/api/filter-builder.ts
@@ -9,7 +9,7 @@ export function joinFilters(...filters: string[]) {
export class FilterBuilder {
constructor(private filters = "") { }
- public addEqual(field: string, value?: string | boolean | null, resourcePrefix?: string) {
+ public addEqual(field: string, value?: string | string[] | boolean | null, resourcePrefix?: string) {
return this.addCondition(field, "=", value, "", "", resourcePrefix);
}
diff --git a/src/store/sharing-dialog/sharing-dialog-actions.ts b/src/store/sharing-dialog/sharing-dialog-actions.ts
index 4c0b8825..91703d5c 100644
--- a/src/store/sharing-dialog/sharing-dialog-actions.ts
+++ b/src/store/sharing-dialog/sharing-dialog-actions.ts
@@ -19,7 +19,9 @@ import { differenceWith } from "lodash";
import { withProgress } from "store/progress-indicator/with-progress";
import { progressIndicatorActions } from 'store/progress-indicator/progress-indicator-actions';
import { snackbarActions, SnackbarKind } from "../snackbar/snackbar-actions";
-import { extractUuidKind, ResourceKind } from "models/resource";
+import { extractUuidKind, extractUuidObjectType, ResourceKind, ResourceObjectType } from "models/resource";
+import { ApiClientAuthorizationService } from "services/api-client-authorization-service/api-client-authorization-service";
+import { resourcesActions } from "store/resources/resources-actions";
export const openSharingDialog = (resourceUuid: string, refresh?: () => void) =>
(dispatch: Dispatch) => {
@@ -41,6 +43,7 @@ export const saveSharingDialogChanges = async (dispatch: Dispatch, getState: ()
await dispatch<any>(sendInvitations);
dispatch(reset(SHARING_INVITATION_FORM_NAME));
await dispatch<any>(loadSharingDialog);
+ dispatch(progressIndicatorActions.STOP_WORKING(SHARING_DIALOG_NAME));
const dialog = getDialog<SharingDialogData>(getState().dialog, SHARING_DIALOG_NAME);
if (dialog && dialog.data.refresh) {
@@ -57,31 +60,40 @@ export const sendSharingInvitations = async (dispatch: Dispatch, getState: () =>
kind: SnackbarKind.SUCCESS,
}));
dispatch(progressIndicatorActions.STOP_WORKING(SHARING_DIALOG_NAME));
-
+
const dialog = getDialog<SharingDialogData>(getState().dialog, SHARING_DIALOG_NAME);
if (dialog && dialog.data.refresh) {
dialog.data.refresh();
}
};
-interface SharingDialogData {
+export interface SharingDialogData {
resourceUuid: string;
refresh: () => void;
}
-const loadSharingDialog = async (dispatch: Dispatch, getState: () => RootState, { permissionService }: ServiceRepository) => {
+const loadSharingDialog = async (dispatch: Dispatch, getState: () => RootState, { permissionService, apiClientAuthorizationService }: ServiceRepository) => {
const dialog = getDialog<SharingDialogData>(getState().dialog, SHARING_DIALOG_NAME);
if (dialog) {
dispatch(progressIndicatorActions.START_WORKING(SHARING_DIALOG_NAME));
try {
- const { items } = await permissionService.listResourcePermissions(dialog.data.resourceUuid);
+ const resourceUuid = dialog.data.resourceUuid;
+ const { items } = await permissionService.listResourcePermissions(resourceUuid);
dispatch<any>(initializePublicAccessForm(items));
await dispatch<any>(initializeManagementForm(items));
- dispatch(progressIndicatorActions.STOP_WORKING(SHARING_DIALOG_NAME));
+ // For collections, we need to load the public sharing tokens
+ if (extractUuidObjectType(resourceUuid) === ResourceObjectType.COLLECTION) {
+ const sharingTokens = await apiClientAuthorizationService.listCollectionSharingTokens(resourceUuid);
+ dispatch(resourcesActions.SET_RESOURCES([sharingTokens.items]));
+ }
} catch (e) {
- dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'You do not have access to share this item', hideDuration: 2000, kind: SnackbarKind.ERROR }));
+ dispatch(snackbarActions.OPEN_SNACKBAR({
+ message: 'You do not have access to share this item',
+ hideDuration: 2000,
+ kind: SnackbarKind.ERROR }));
dispatch(dialogActions.CLOSE_DIALOG({ id: SHARING_DIALOG_NAME }));
+ } finally {
dispatch(progressIndicatorActions.STOP_WORKING(SHARING_DIALOG_NAME));
}
}
@@ -108,8 +120,8 @@ const initializeManagementForm = (permissionLinks: PermissionResource[]) =>
};
const managementPermissions = permissionLinks
- .filter(item =>
- item.tailUuid !== getPublicGroupUuid(getState()))
+ // .filter(item =>
+ // item.tailUuid !== getPublicGroupUuid(getState()))
.map(({ tailUuid, name, uuid }) => ({
email: getEmail(tailUuid),
permissions: name as PermissionLevel,
@@ -178,19 +190,14 @@ const saveManagementChanges = async (_: Dispatch, getState: () => RootState, { p
const { user } = state.auth;
const dialog = getDialog<string>(state.dialog, SHARING_DIALOG_NAME);
if (dialog && user) {
-
const { initialPermissions, permissions } = getSharingMangementFormData(state);
const { visibility } = getSharingPublicAccessFormData(state);
-
if (visibility === VisibilityLevel.PRIVATE) {
-
for (const permission of initialPermissions) {
await permissionService.delete(permission.permissionUuid);
}
-
} else {
-
const cancelledPermissions = differenceWith(
initialPermissions,
permissions,
@@ -204,7 +211,6 @@ const saveManagementChanges = async (_: Dispatch, getState: () => RootState, { p
for (const permission of permissions) {
await permissionService.update(permission.permissionUuid, { name: permission.permissions });
}
-
}
}
};
diff --git a/src/views-components/sharing-dialog/advanced-view-switch.tsx b/src/views-components/sharing-dialog/advanced-view-switch.tsx
index 969128be..37517fd6 100644
--- a/src/views-components/sharing-dialog/advanced-view-switch.tsx
+++ b/src/views-components/sharing-dialog/advanced-view-switch.tsx
@@ -22,4 +22,3 @@ export const connectAdvancedViewSwitch = (Component: React.ComponentType<Advance
return <Component {...this.state} {...this} />;
}
};
-
\ No newline at end of file
diff --git a/src/views-components/sharing-dialog/sharing-dialog-component.tsx b/src/views-components/sharing-dialog/sharing-dialog-component.tsx
index be15cce6..2610e40b 100644
--- a/src/views-components/sharing-dialog/sharing-dialog-component.tsx
+++ b/src/views-components/sharing-dialog/sharing-dialog-component.tsx
@@ -3,26 +3,47 @@
// SPDX-License-Identifier: AGPL-3.0
import React from 'react';
-import { Dialog, DialogTitle, Button, Grid, DialogContent, CircularProgress, Paper } from '@material-ui/core';
+import {
+ Dialog,
+ DialogTitle,
+ Button,
+ Grid,
+ DialogContent,
+ CircularProgress,
+ Paper,
+ Tabs,
+ Tab
+} from '@material-ui/core';
+import {
+ StyleRulesCallback,
+ WithStyles,
+ withStyles
+} from '@material-ui/core/styles';
import { DialogActions } from 'components/dialog-actions/dialog-actions';
-import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
-
+import { SharingDialogContent } from './sharing-dialog-content';
+import { SharingURLsContent } from './sharing-urls';
+import { extractUuidObjectType, ResourceObjectType } from 'models/resource';
export interface SharingDialogDataProps {
open: boolean;
loading: boolean;
saveEnabled: boolean;
- advancedEnabled: boolean;
- children: React.ReactNode;
+ // advancedEnabled: boolean;
+ // children: React.ReactNode;
+ sharedResourceUuid: string;
}
export interface SharingDialogActionProps {
onClose: () => void;
onExited: () => void;
onSave: () => void;
- onAdvanced: () => void;
+ // onAdvanced: () => void;
+ // onTabChange?: (event: React.ChangeEvent<{}>, value: number) => void;
}
export default (props: SharingDialogDataProps & SharingDialogActionProps) => {
- const { children, open, loading, advancedEnabled, saveEnabled, onAdvanced, onClose, onExited, onSave } = props;
+ const { open, loading, saveEnabled, sharedResourceUuid,
+ onClose, onExited, onSave } = props;
+ const showSharingURLTab = extractUuidObjectType(sharedResourceUuid) === ResourceObjectType.COLLECTION
+ const [tabNr, setTabNr] = React.useState<number>(0);
return <Dialog
{...{ open, onClose, onExited }}
className="sharing-dialog"
@@ -32,13 +53,20 @@ export default (props: SharingDialogDataProps & SharingDialogActionProps) => {
disableEscapeKeyDown>
<DialogTitle>
Sharing settings
- </DialogTitle>
+ </DialogTitle>
+ { showSharingURLTab &&
+ <Tabs value={tabNr} onChange={(_, tb) => setTabNr(tb)}>
+ <Tab label="With users/groups" />
+ <Tab label="Sharing URLs" />
+ </Tabs>
+ }
<DialogContent>
- {children}
+ { tabNr === 0 && <SharingDialogContent /> }
+ { tabNr === 1 && <SharingURLsContent uuid={sharedResourceUuid} />}
</DialogContent>
<DialogActions>
<Grid container spacing={8}>
- {advancedEnabled &&
+ {/* {props.advancedEnabled && !tabNr &&
<Grid item>
<Button
color='primary'
@@ -46,7 +74,7 @@ export default (props: SharingDialogDataProps & SharingDialogActionProps) => {
Advanced
</Button>
</Grid>
- }
+ } */}
<Grid item xs />
<Grid item>
<Button onClick={onClose}>
diff --git a/src/views-components/sharing-dialog/sharing-dialog-content.tsx b/src/views-components/sharing-dialog/sharing-dialog-content.tsx
index 15df2245..c9a5929f 100644
--- a/src/views-components/sharing-dialog/sharing-dialog-content.tsx
+++ b/src/views-components/sharing-dialog/sharing-dialog-content.tsx
@@ -3,25 +3,21 @@
// SPDX-License-Identifier: AGPL-3.0
import React from 'react';
-import { Grid, Typography } from '@material-ui/core';
+import { Grid } from '@material-ui/core';
import { SharingInvitationForm } from './sharing-invitation-form';
import { SharingManagementForm } from './sharing-management-form';
import { SharingPublicAccessForm } from './sharing-public-access-form';
-export const SharingDialogContent = (props: { advancedViewOpen: boolean }) =>
+export const SharingDialogContent = () =>
<Grid container direction='column' spacing={24}>
- {props.advancedViewOpen &&
- <>
- <Grid item>
- <Typography variant='subtitle1'>
- Who can access
- </Typography>
- <SharingPublicAccessForm />
- <SharingManagementForm />
- </Grid>
- </>
- }
+ <Grid item>
+ {/* <Typography variant='subtitle1'>
+ Who can access
+ </Typography> */}
+ {/* <SharingPublicAccessForm /> */}
+ <SharingManagementForm />
+ </Grid>
<Grid item>
<SharingInvitationForm />
</Grid>
diff --git a/src/views-components/sharing-dialog/sharing-dialog.tsx b/src/views-components/sharing-dialog/sharing-dialog.tsx
index fe3b8396..feddc206 100644
--- a/src/views-components/sharing-dialog/sharing-dialog.tsx
+++ b/src/views-components/sharing-dialog/sharing-dialog.tsx
@@ -2,50 +2,66 @@
//
// SPDX-License-Identifier: AGPL-3.0
+import React from 'react';
import { compose, Dispatch } from 'redux';
import { connect } from 'react-redux';
-
-import React from 'react';
-import { connectSharingDialog, saveSharingDialogChanges, connectSharingDialogProgress, sendSharingInvitations } from 'store/sharing-dialog/sharing-dialog-actions';
-import { WithDialogProps } from 'store/dialog/with-dialog';
import { RootState } from 'store/store';
-
-import SharingDialogComponent, { SharingDialogDataProps, SharingDialogActionProps } from './sharing-dialog-component';
+import {
+ connectSharingDialog,
+ saveSharingDialogChanges,
+ connectSharingDialogProgress,
+ sendSharingInvitations,
+ SharingDialogData
+} from 'store/sharing-dialog/sharing-dialog-actions';
+import { WithDialogProps } from 'store/dialog/with-dialog';
+import SharingDialogComponent, {
+ SharingDialogDataProps,
+ SharingDialogActionProps
+} from './sharing-dialog-component';
import { SharingDialogContent } from './sharing-dialog-content';
-import { connectAdvancedViewSwitch, AdvancedViewSwitchInjectedProps } from './advanced-view-switch';
-import { hasChanges } from 'store/sharing-dialog/sharing-dialog-types';
+import {
+ connectAdvancedViewSwitch,
+ AdvancedViewSwitchInjectedProps
+} from './advanced-view-switch';
+import { hasChanges, SHARING_DIALOG_NAME } from 'store/sharing-dialog/sharing-dialog-types';
import { WithProgressStateProps } from 'store/progress-indicator/with-progress';
+import { getDialog } from 'store/dialog/dialog-reducer';
+import { extractUuidObjectType, ResourceObjectType } from 'models/resource';
-type Props = WithDialogProps<string> & AdvancedViewSwitchInjectedProps & WithProgressStateProps;
+type Props = WithDialogProps<string> & WithProgressStateProps;
-const mapStateToProps = (state: RootState, { advancedViewOpen, working, ...props }: Props): SharingDialogDataProps => ({
+const mapStateToProps = (state: RootState, { working, ...props }: Props): SharingDialogDataProps => {
+ const dialog = getDialog<SharingDialogData>(state.dialog, SHARING_DIALOG_NAME);
+ return ({
...props,
saveEnabled: hasChanges(state),
loading: working,
- advancedEnabled: !advancedViewOpen,
- children: <SharingDialogContent {...{ advancedViewOpen }} />,
-});
+ // advancedEnabled: !advancedViewOpen,
+ // children: <SharingDialogContent />,
+ sharedResourceUuid: dialog?.data.resourceUuid || '',
+ })
+};
-const mapDispatchToProps = (dispatch: Dispatch, { toggleAdvancedView, advancedViewOpen, ...props }: Props): SharingDialogActionProps => ({
+const mapDispatchToProps = (dispatch: Dispatch, { ...props }: Props): SharingDialogActionProps => ({
...props,
onClose: props.closeDialog,
onExited: () => {
- if (advancedViewOpen) {
- toggleAdvancedView();
- }
+ // if (advancedViewOpen) {
+ // toggleAdvancedView();
+ // }
},
onSave: () => {
- if (advancedViewOpen) {
+ // if (advancedViewOpen) {
dispatch<any>(saveSharingDialogChanges);
- } else {
- dispatch<any>(sendSharingInvitations);
- }
+ // } else {
+ // dispatch<any>(sendSharingInvitations);
+ // }
},
- onAdvanced: toggleAdvancedView,
+ // onAdvanced: toggleAdvancedView,
});
export const SharingDialog = compose(
- connectAdvancedViewSwitch,
+ // connectAdvancedViewSwitch,
connectSharingDialog,
connectSharingDialogProgress,
connect(mapStateToProps, mapDispatchToProps)
diff --git a/src/views-components/sharing-dialog/sharing-urls-component.tsx b/src/views-components/sharing-dialog/sharing-urls-component.tsx
new file mode 100644
index 00000000..0d54fa8c
--- /dev/null
+++ b/src/views-components/sharing-dialog/sharing-urls-component.tsx
@@ -0,0 +1,33 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from 'react';
+import {
+ Grid,
+ Typography
+} from '@material-ui/core';
+import { ApiClientAuthorization } from 'models/api-client-authorization';
+
+export interface SharingURLsComponentDataProps {
+ sharingTokens: ApiClientAuthorization[];
+ sharingURLsPrefix: string;
+}
+
+export interface SharingURLsComponentActionProps {
+ onCreateSharingToken: (colUuid: string) => void;
+ onDeleteSharingToken: (uuid: string) => void;
+}
+
+type SharingURLsComponentProps = SharingURLsComponentDataProps & SharingURLsComponentActionProps;
+
+export const SharingURLsComponent = (props: SharingURLsComponentProps ) =>
+ <Grid container direction='column' spacing={24}>
+ {props.sharingTokens.map(token => (
+ <Grid item key={token.uuid}>
+ <Typography>
+ Sharing URLsss
+ </Typography>
+ </Grid>
+ ))}
+ </Grid>
diff --git a/src/views-components/sharing-dialog/sharing-urls.tsx b/src/views-components/sharing-dialog/sharing-urls.tsx
new file mode 100644
index 00000000..86051fb3
--- /dev/null
+++ b/src/views-components/sharing-dialog/sharing-urls.tsx
@@ -0,0 +1,44 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from 'react';
+import { RootState } from 'store/store';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { ApiClientAuthorization } from 'models/api-client-authorization';
+import { filterResources } from 'store/resources/resources';
+import { ResourceKind } from 'models/resource';
+import {
+ SharingURLsComponent,
+ SharingURLsComponentActionProps,
+ SharingURLsComponentDataProps
+} from './sharing-urls-component';
+
+const mapStateToProps =
+ (state: RootState, ownProps: { uuid: string }): SharingURLsComponentDataProps => {
+ const sharingTokens = filterResources(
+ (resource: ApiClientAuthorization) =>
+ resource.kind === ResourceKind.API_CLIENT_AUTHORIZATION &&
+ resource.scopes.includes(`GET /arvados/v1/collections/${ownProps.uuid}`) &&
+ resource.scopes.includes(`GET /arvados/v1/collections/${ownProps.uuid}/`) &&
+ resource.scopes.includes('GET /arvados/v1/keep_services/accessible')
+ )(state.resources) as ApiClientAuthorization[];
+ const sharingURLsPrefix = state.auth.config.keepWebServiceUrl;
+ return {
+ sharingTokens,
+ sharingURLsPrefix,
+ }
+ }
+
+const mapDispatchToProps = (dispatch: Dispatch): SharingURLsComponentActionProps => ({
+ onCreateSharingToken(colUuid: string) {
+ // dispatch(createSharingToken(colUuid));
+ },
+ onDeleteSharingToken(uuid: string) {
+ // dispatch(deleteSharingToken(uuid));
+ }
+})
+
+export const SharingURLsContent = connect(mapStateToProps, mapDispatchToProps)(SharingURLsComponent)
+
commit 042f8362da7b7e835d2451169eecafc5ea4d258d
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date: Thu Apr 21 15:03:09 2022 -0300
16115: Removes unused import.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>
diff --git a/src/services/api-client-authorization-service/api-client-authorization-service.test.ts b/src/services/api-client-authorization-service/api-client-authorization-service.test.ts
index cc1942cf..31fa046e 100644
--- a/src/services/api-client-authorization-service/api-client-authorization-service.test.ts
+++ b/src/services/api-client-authorization-service/api-client-authorization-service.test.ts
@@ -3,7 +3,6 @@
// SPDX-License-Identifier: AGPL-3.0
import axios, { AxiosInstance } from "axios";
-// import MockAdapter from 'axios-mock-adapter';
import { ApiClientAuthorizationService } from "./api-client-authorization-service";
@@ -12,7 +11,6 @@ describe('ApiClientAuthorizationService', () => {
let serverApi: AxiosInstance;
let actions;
-
beforeEach(() => {
serverApi = axios.create();
actions = {
commit 7baacecfced2112da01ae9b9709109d63f4dfcc3
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date: Mon Apr 18 16:43:39 2022 -0300
16115: Adds sharing token management methods to ACA service, with tests.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>
diff --git a/src/services/api-client-authorization-service/api-client-authorization-service.test.ts b/src/services/api-client-authorization-service/api-client-authorization-service.test.ts
new file mode 100644
index 00000000..cc1942cf
--- /dev/null
+++ b/src/services/api-client-authorization-service/api-client-authorization-service.test.ts
@@ -0,0 +1,70 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import axios, { AxiosInstance } from "axios";
+// import MockAdapter from 'axios-mock-adapter';
+import { ApiClientAuthorizationService } from "./api-client-authorization-service";
+
+
+describe('ApiClientAuthorizationService', () => {
+ let apiClientAuthorizationService: ApiClientAuthorizationService;
+ let serverApi: AxiosInstance;
+ let actions;
+
+
+ beforeEach(() => {
+ serverApi = axios.create();
+ actions = {
+ progressFn: jest.fn(),
+ } as any;
+ apiClientAuthorizationService = new ApiClientAuthorizationService(serverApi, actions);
+ });
+
+ describe('createCollectionSharingToken', () => {
+ it('should return error on invalid collection uuid', () => {
+ expect(() => apiClientAuthorizationService.createCollectionSharingToken("foo")).toThrowError("UUID foo is not a collection");
+ });
+
+ it('should make a create request with proper scopes', async () => {
+ serverApi.post = jest.fn(() => Promise.resolve(
+ { data: { uuid: 'zzzzz-4zz18-0123456789abcde' } }
+ ));
+ const uuid = 'zzzzz-4zz18-0123456789abcde'
+ await apiClientAuthorizationService.createCollectionSharingToken(uuid);
+ expect(serverApi.post).toHaveBeenCalledWith(
+ '/api_client_authorizations', {
+ scopes: [
+ `GET /arvados/v1/collections/${uuid}`,
+ `GET /arvados/v1/collections/${uuid}/`,
+ `GET /arvados/v1/keep_services/accessible`,
+ ]
+ }
+ );
+ });
+ });
+
+ describe('listCollectionSharingToken', () => {
+ it('should return error on invalid collection uuid', () => {
+ expect(() => apiClientAuthorizationService.listCollectionSharingTokens("foo")).toThrowError("UUID foo is not a collection");
+ });
+
+ it('should make a list request with proper scopes', async () => {
+ serverApi.get = jest.fn(() => Promise.resolve(
+ { data: { items: [{}] } }
+ ));
+ const uuid = 'zzzzz-4zz18-0123456789abcde'
+ await apiClientAuthorizationService.listCollectionSharingTokens(uuid);
+ expect(serverApi.get).toHaveBeenCalledWith(
+ `/api_client_authorizations`, {params: {
+ filters: '[["scopes","=","' + JSON.stringify([
+ `GET /arvados/v1/collections/${uuid}`,
+ `GET /arvados/v1/collections/${uuid}/`,
+ `GET /arvados/v1/keep_services/accessible`,
+ ]) + '"]]',
+ select: undefined,
+ }}
+ );
+ });
+ });
+});
\ No newline at end of file
diff --git a/src/services/api-client-authorization-service/api-client-authorization-service.ts b/src/services/api-client-authorization-service/api-client-authorization-service.ts
index 386c9747..012fdb15 100644
--- a/src/services/api-client-authorization-service/api-client-authorization-service.ts
+++ b/src/services/api-client-authorization-service/api-client-authorization-service.ts
@@ -5,10 +5,39 @@
import { AxiosInstance } from "axios";
import { ApiActions } from 'services/api/api-actions';
import { ApiClientAuthorization } from 'models/api-client-authorization';
-import { CommonService } from 'services/common-service/common-service';
+import { CommonService, ListResults } from 'services/common-service/common-service';
+import { extractUuidObjectType, ResourceObjectType } from "models/resource";
+import { FilterBuilder } from "services/api/filter-builder";
export class ApiClientAuthorizationService extends CommonService<ApiClientAuthorization> {
constructor(serverApi: AxiosInstance, actions: ApiActions) {
super(serverApi, "api_client_authorizations", actions);
}
-}
\ No newline at end of file
+
+ createCollectionSharingToken(uuid: string): Promise<ApiClientAuthorization> {
+ if (extractUuidObjectType(uuid) !== ResourceObjectType.COLLECTION) {
+ throw new Error(`UUID ${uuid} is not a collection`);
+ }
+ return this.create({
+ scopes: [
+ `GET /arvados/v1/collections/${uuid}`,
+ `GET /arvados/v1/collections/${uuid}/`,
+ `GET /arvados/v1/keep_services/accessible`,
+ ]
+ });
+ }
+
+ listCollectionSharingTokens(uuid: string): Promise<ListResults<ApiClientAuthorization>> {
+ if (extractUuidObjectType(uuid) !== ResourceObjectType.COLLECTION) {
+ throw new Error(`UUID ${uuid} is not a collection`);
+ }
+ return this.list({
+ filters: new FilterBuilder()
+ .addEqual("scopes", JSON.stringify([
+ `GET /arvados/v1/collections/${uuid}`,
+ `GET /arvados/v1/collections/${uuid}/`,
+ "GET /arvados/v1/keep_services/accessible",
+ ])).getFilters()
+ });
+ }
+}
\ No newline at end of file
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list