Create permission service, create public access and sharing management actions
[arvados-workbench2.git] / src / store / sharing-dialog / sharing-dialog-actions.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { dialogActions } from "~/store/dialog/dialog-actions";
6 import { withDialog } from "~/store/dialog/with-dialog";
7 import { SHARING_DIALOG_NAME, SharingPublicAccessFormData, SHARING_PUBLIC_ACCESS_FORM_NAME, SHARING_INVITATION_FORM_NAME, SharingManagementFormData, SharingInvitationFormData } from './sharing-dialog-types';
8 import { Dispatch } from 'redux';
9 import { ServiceRepository } from "~/services/services";
10 import { FilterBuilder } from '~/services/api/filter-builder';
11 import { initialize, getFormValues, isDirty, reset } from 'redux-form';
12 import { SHARING_MANAGEMENT_FORM_NAME } from '~/store/sharing-dialog/sharing-dialog-types';
13 import { RootState } from '~/store/store';
14 import { getDialog } from '~/store/dialog/dialog-reducer';
15 import { PermissionLevel } from '../../models/permission';
16 import { getPublicGroupUuid } from "~/store/workflow-panel/workflow-panel-actions";
17
18 export const openSharingDialog = (resourceUuid: string) =>
19     async (dispatch: Dispatch, getState: () => RootState, { permissionService }: ServiceRepository) => {
20
21         dispatch(dialogActions.OPEN_DIALOG({ id: SHARING_DIALOG_NAME, data: resourceUuid }));
22
23         const state = getState();
24         const { items } = await permissionService.listResourcePermissions(resourceUuid);
25
26         const managementFormData: SharingManagementFormData = {
27             permissions: items
28                 .filter(item =>
29                     item.tailUuid !== getPublicGroupUuid(state))
30                 .map(({ tailUuid, name }) => ({
31                     email: tailUuid,
32                     permissions: name as PermissionLevel,
33                 }))
34         };
35
36         dispatch(initialize(SHARING_MANAGEMENT_FORM_NAME, managementFormData));
37
38         const [publicPermission] = items.filter(item => item.tailUuid === getPublicGroupUuid(state));
39         if (publicPermission) {
40             const publicAccessFormData: SharingPublicAccessFormData = {
41                 enabled: publicPermission.name !== PermissionLevel.NONE,
42                 permissions: publicPermission.name as PermissionLevel,
43             };
44
45             dispatch(initialize(SHARING_PUBLIC_ACCESS_FORM_NAME, publicAccessFormData));
46         } else {
47             dispatch(reset(SHARING_PUBLIC_ACCESS_FORM_NAME));
48         }
49     };
50
51 export const closeSharingDialog = () =>
52     dialogActions.CLOSE_DIALOG({ id: SHARING_DIALOG_NAME });
53
54 export const connectSharingDialog = withDialog(SHARING_DIALOG_NAME);
55
56 export const saveSharingDialogChanges = async (dispatch: Dispatch) => {
57     dispatch<any>(savePublicPermissionChanges);
58     dispatch<any>(sendInvitations);
59 };
60
61 const savePublicPermissionChanges = async (dispatch: Dispatch, getState: () => RootState, { permissionService }: ServiceRepository) => {
62     const state = getState();
63     const { user } = state.auth;
64     const dialog = getDialog<string>(state.dialog, SHARING_DIALOG_NAME);
65     if (dialog && user) {
66         const publicAccess = getFormValues(SHARING_PUBLIC_ACCESS_FORM_NAME)(state) as SharingPublicAccessFormData;
67
68         const filters = new FilterBuilder()
69             .addEqual('headUuid', dialog.data)
70             .getFilters();
71
72         const { items } = await permissionService.list({ filters });
73
74         const [publicPermission] = items.filter(item => item.tailUuid === getPublicGroupUuid(state));
75
76         if (publicPermission) {
77
78             await permissionService.update(publicPermission.uuid, {
79                 name: publicAccess.enabled ? publicAccess.permissions : PermissionLevel.NONE
80             });
81
82         } else {
83
84             await permissionService.create({
85                 ownerUuid: user.uuid,
86                 headUuid: dialog.data,
87                 tailUuid: getPublicGroupUuid(state),
88                 name: publicAccess.enabled ? publicAccess.permissions : PermissionLevel.NONE
89             });
90         }
91     }
92 };
93
94 const sendInvitations = async (dispatch: Dispatch, getState: () => RootState, { permissionService }: ServiceRepository) => {
95     const state = getState();
96     const { user } = state.auth;
97     const dialog = getDialog<string>(state.dialog, SHARING_DIALOG_NAME);
98     if (dialog && user) {
99
100         const invitations = getFormValues(SHARING_INVITATION_FORM_NAME)(state) as SharingInvitationFormData;
101
102         const promises = invitations.invitedPeople
103             .map(person => ({
104                 ownerUuid: user.uuid,
105                 headUuid: dialog.data,
106                 tailUuid: person.uuid,
107                 name: invitations.permissions
108             }))
109             .map(data => permissionService.create(data));
110
111         await Promise.all(promises);
112     }
113 };
114
115 export const hasChanges = (state: RootState) =>
116     isDirty(SHARING_PUBLIC_ACCESS_FORM_NAME)(state) ||
117     isDirty(SHARING_MANAGEMENT_FORM_NAME)(state) ||
118     isDirty(SHARING_INVITATION_FORM_NAME)(state);