[ARVADOS-WORKBENCH2] updated: 2.3.0-149-gb178ea37
Git user
git at public.arvados.org
Tue Feb 8 16:43:48 UTC 2022
Summary of changes:
cypress/integration/virtual-machine-admin.spec.js | 100 +++++++++++++++++++--
.../virtual-machines/virtual-machines-actions.ts | 53 ++++++++---
.../virtual-machines-dialog/add-login-dialog.tsx | 14 +--
.../virtual-machine-admin-panel.tsx | 10 ++-
4 files changed, 148 insertions(+), 29 deletions(-)
via b178ea37c7a247a6399ecf1112d5f8c8aae12136 (commit)
from c2a580be1484629e557b967524473a75b2d02274 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit b178ea37c7a247a6399ecf1112d5f8c8aae12136
Author: Stephen Smith <stephen at curii.com>
Date: Tue Feb 8 11:43:05 2022 -0500
18284: Add update vm login dialog, remove default group, update tests
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>
diff --git a/cypress/integration/virtual-machine-admin.spec.js b/cypress/integration/virtual-machine-admin.spec.js
index d057ce49..73804b20 100644
--- a/cypress/integration/virtual-machine-admin.spec.js
+++ b/cypress/integration/virtual-machine-admin.spec.js
@@ -41,10 +41,10 @@ describe('Virtual machine login manage tests', function() {
cy.get('button[title="Add Login Permission"]').click();
});
cy.get('[data-cy=form-dialog]')
- .should('contain', 'Add login permissions')
+ .should('contain', 'Add login permission')
.within(() => {
cy.get('label')
- .contains('Search for users')
+ .contains('Search for user')
.parent()
.within(() => {
cy.get('input').type('VMAdmin');
@@ -52,13 +52,13 @@ describe('Virtual machine login manage tests', function() {
});
cy.get('[role=tooltip]').click();
cy.get('[data-cy=form-dialog]')
- .should('contain', 'Add login permissions')
+ .should('contain', 'Add login permission')
.within(() => {
cy.get('label')
.contains('Add groups')
.parent()
.within(() => {
- cy.get('input').type('sudo{enter}');
+ cy.get('input').type('docker sudo{enter}');
})
});
cy.get('[data-cy=form-dialog]').within(() => {
@@ -79,10 +79,10 @@ describe('Virtual machine login manage tests', function() {
cy.get('button[title="Add Login Permission"]').click();
});
cy.get('[data-cy=form-dialog]')
- .should('contain', 'Add login permissions')
+ .should('contain', 'Add login permission')
.within(() => {
cy.get('label')
- .contains('Search for users')
+ .contains('Search for user')
.parent()
.within(() => {
cy.get('input').type('VMActive user');
@@ -118,12 +118,100 @@ describe('Virtual machine login manage tests', function() {
cy.get('header button[title="Account Management"]').click();
cy.get('#account-menu').contains('Virtual Machines').click();
+ cy.get('[data-cy=vm-user-table]')
+ .contains(vmHost)
+ .parents('tr')
+ .within(() => {
+ cy.get('td').contains('user');
+ cy.get('td').should('not.contain', 'docker');
+ cy.get('td').should('not.contain', 'sudo');
+ cy.get('td').contains('ssh user@' + vmHost);
+ });
+
+ // Edit login permissions
+ cy.loginAs(adminUser);
+ cy.get('header button[title="Admin Panel"]').click();
+ cy.get('#admin-menu').contains('Virtual Machines').click();
+
+ cy.get('[data-cy=vm-admin-table]')
+ .contains('admin'); // Wait for page to finish
+
+ cy.get('[data-cy=vm-admin-table]')
+ .contains(vmHost)
+ .parents('tr')
+ .contains('admin')
+ .click();
+
+ cy.get('[data-cy=form-dialog]')
+ .should('contain', 'Update login permission')
+ .within(() => {
+ cy.get('label')
+ .contains('Add groups')
+ .parent()
+ .as('groupInput');
+ });
+
+ cy.get('@groupInput').within(() => {
+ cy.get('div[role=button]').contains('sudo').parent().find('svg').click();
+ cy.get('div[role=button]').contains('docker').parent().find('svg').click();
+ });
+
+ cy.get('[data-cy=form-dialog]').within(() => {
+ cy.get('[data-cy=form-submit-btn]').click();
+ });
+
+ cy.get('[data-cy=vm-admin-table]')
+ .contains('user'); // Wait for page to finish
+
+ cy.get('[data-cy=vm-admin-table]')
+ .contains(vmHost)
+ .parents('tr')
+ .contains('user')
+ .click();
+
+ cy.get('[data-cy=form-dialog]')
+ .should('contain', 'Update login permission')
+ .within(() => {
+ cy.get('label')
+ .contains('Add groups')
+ .parent()
+ .within(() => {
+ cy.get('input').type('docker{enter}');
+ })
+ });
+
+ cy.get('[data-cy=form-dialog]').within(() => {
+ cy.get('[data-cy=form-submit-btn]').click();
+ });
+
+ // Verify new login permissions
+ // Check admin's vm page for login
+ cy.get('header button[title="Account Management"]').click();
+ cy.get('#account-menu').contains('Virtual Machines').click();
+
+ cy.get('[data-cy=vm-user-table]')
+ .contains(vmHost)
+ .parents('tr')
+ .within(() => {
+ cy.get('td').contains('admin');
+ cy.get('td').should('not.contain', 'docker');
+ cy.get('td').should('not.contain', 'sudo');
+ cy.get('td').contains('ssh admin@' + vmHost);
+ });
+
+ // Verify new login permissions
+ // Check activeUser's vm page for login
+ cy.loginAs(activeUser);
+ cy.get('header button[title="Account Management"]').click();
+ cy.get('#account-menu').contains('Virtual Machines').click();
+
cy.get('[data-cy=vm-user-table]')
.contains(vmHost)
.parents('tr')
.within(() => {
cy.get('td').contains('user');
cy.get('td').contains('docker');
+ cy.get('td').should('not.contain', 'sudo');
cy.get('td').contains('ssh user@' + vmHost);
});
diff --git a/src/store/virtual-machines/virtual-machines-actions.ts b/src/store/virtual-machines/virtual-machines-actions.ts
index 08654a44..e2cf6fd4 100644
--- a/src/store/virtual-machines/virtual-machines-actions.ts
+++ b/src/store/virtual-machines/virtual-machines-actions.ts
@@ -18,6 +18,7 @@ import { PermissionLevel } from "models/permission";
import { deleteResources, updateResources } from 'store/resources/resources-actions';
import { Participant } from "views-components/sharing-dialog/participant-select";
import { initialize, reset } from "redux-form";
+import { getUserDisplayName } from "models/user";
export const virtualMachinesActions = unionize({
SET_REQUESTED_DATE: ofType<string>(),
@@ -35,6 +36,7 @@ export const VIRTUAL_MACHINE_ADD_LOGIN_DIALOG = 'virtualMachineAddLoginDialog';
export const VIRTUAL_MACHINE_ADD_LOGIN_FORM = 'virtualMachineAddLoginForm';
export const VIRTUAL_MACHINE_REMOVE_LOGIN_DIALOG = 'virtualMachineRemoveLoginDialog';
+export const VIRTUAL_MACHINE_UPDATE_LOGIN_UUID_FIELD = 'uuid';
export const VIRTUAL_MACHINE_ADD_LOGIN_VM_FIELD = 'vmUuid';
export const VIRTUAL_MACHINE_ADD_LOGIN_USER_FIELD = 'user';
export const VIRTUAL_MACHINE_ADD_LOGIN_GROUPS_FIELD = 'groups';
@@ -111,42 +113,67 @@ export const loadVirtualMachinesUserData = () =>
dispatch(virtualMachinesActions.SET_LINKS(links));
};
-export const openAddVirtualMachineLoginDialog = (uuid: string) =>
+export const openAddVirtualMachineLoginDialog = (vmUuid: string) =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
- dispatch(initialize(VIRTUAL_MACHINE_ADD_LOGIN_FORM, {[VIRTUAL_MACHINE_ADD_LOGIN_VM_FIELD]: uuid, [VIRTUAL_MACHINE_ADD_LOGIN_GROUPS_FIELD]: ['docker']}));
+ dispatch(initialize(VIRTUAL_MACHINE_ADD_LOGIN_FORM, {[VIRTUAL_MACHINE_ADD_LOGIN_VM_FIELD]: vmUuid, [VIRTUAL_MACHINE_ADD_LOGIN_GROUPS_FIELD]: []}));
dispatch(dialogActions.OPEN_DIALOG( {id: VIRTUAL_MACHINE_ADD_LOGIN_DIALOG, data: {}} ));
}
+export const openEditVirtualMachineLoginDialog = (permissionUuid: string) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const login = await services.permissionService.get(permissionUuid);
+ const user = await services.userService.get(login.tailUuid);
+ dispatch(initialize(VIRTUAL_MACHINE_ADD_LOGIN_FORM, {
+ [VIRTUAL_MACHINE_UPDATE_LOGIN_UUID_FIELD]: permissionUuid,
+ [VIRTUAL_MACHINE_ADD_LOGIN_USER_FIELD]: {name: getUserDisplayName(user, true), uuid: login.tailUuid},
+ [VIRTUAL_MACHINE_ADD_LOGIN_GROUPS_FIELD]: login.properties.groups,
+ }));
+ dispatch(dialogActions.OPEN_DIALOG( {id: VIRTUAL_MACHINE_ADD_LOGIN_DIALOG, data: {updating: true}} ));
+ }
+
export interface AddLoginFormData {
+ [VIRTUAL_MACHINE_UPDATE_LOGIN_UUID_FIELD]: string;
[VIRTUAL_MACHINE_ADD_LOGIN_VM_FIELD]: string;
[VIRTUAL_MACHINE_ADD_LOGIN_USER_FIELD]: Participant;
[VIRTUAL_MACHINE_ADD_LOGIN_GROUPS_FIELD]: string[];
}
-export const addVirtualMachineLogin = ({vmUuid, user, groups}: AddLoginFormData) =>
+export const addUpdateVirtualMachineLogin = ({uuid, vmUuid, user, groups}: AddLoginFormData) =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
try {
// Get user
const userResource = await services.userService.get(user.uuid);
- const permission = await services.permissionService.create({
+ if (uuid) {
+ const permission = await services.permissionService.update(uuid, {
+ tailUuid: userResource.uuid,
+ name: PermissionLevel.CAN_LOGIN,
+ properties: {
+ username: userResource.username,
+ groups,
+ }
+ });
+ dispatch(updateResources([permission]));
+ } else {
+ const permission = await services.permissionService.create({
headUuid: vmUuid,
- tailUuid: userResource.uuid,
- name: PermissionLevel.CAN_LOGIN,
- properties: {
- username: userResource.username,
- groups,
- }
- });
- dispatch(updateResources([permission]));
+ tailUuid: userResource.uuid,
+ name: PermissionLevel.CAN_LOGIN,
+ properties: {
+ username: userResource.username,
+ groups,
+ }
+ });
+ dispatch(updateResources([permission]));
+ }
dispatch(reset(VIRTUAL_MACHINE_ADD_LOGIN_FORM));
dispatch(dialogActions.CLOSE_DIALOG({ id: VIRTUAL_MACHINE_ADD_LOGIN_DIALOG }));
dispatch<any>(loadVirtualMachinesAdminData());
dispatch(snackbarActions.OPEN_SNACKBAR({
- message: `Permissions updated`,
+ message: `Permission updated`,
kind: SnackbarKind.SUCCESS
}));
} catch (e) {
diff --git a/src/views-components/virtual-machines-dialog/add-login-dialog.tsx b/src/views-components/virtual-machines-dialog/add-login-dialog.tsx
index 8d543406..bfc04716 100644
--- a/src/views-components/virtual-machines-dialog/add-login-dialog.tsx
+++ b/src/views-components/virtual-machines-dialog/add-login-dialog.tsx
@@ -7,7 +7,7 @@ import { compose } from "redux";
import { reduxForm, InjectedFormProps, WrappedFieldProps, Field } from 'redux-form';
import { withDialog, WithDialogProps } from "store/dialog/with-dialog";
import { FormDialog } from 'components/form-dialog/form-dialog';
-import { VIRTUAL_MACHINE_ADD_LOGIN_DIALOG, VIRTUAL_MACHINE_ADD_LOGIN_FORM, addVirtualMachineLogin, AddLoginFormData, VIRTUAL_MACHINE_ADD_LOGIN_USER_FIELD, VIRTUAL_MACHINE_ADD_LOGIN_GROUPS_FIELD } from 'store/virtual-machines/virtual-machines-actions';
+import { VIRTUAL_MACHINE_ADD_LOGIN_DIALOG, VIRTUAL_MACHINE_ADD_LOGIN_FORM, addUpdateVirtualMachineLogin, AddLoginFormData, VIRTUAL_MACHINE_ADD_LOGIN_USER_FIELD, VIRTUAL_MACHINE_ADD_LOGIN_GROUPS_FIELD } from 'store/virtual-machines/virtual-machines-actions';
import { ParticipantSelect } from 'views-components/sharing-dialog/participant-select';
import { GroupArrayInput } from 'views-components/virtual-machines-dialog/group-array-input';
@@ -16,27 +16,27 @@ export const VirtualMachineAddLoginDialog = compose(
reduxForm<AddLoginFormData>({
form: VIRTUAL_MACHINE_ADD_LOGIN_FORM,
onSubmit: (data, dispatch) => {
- dispatch(addVirtualMachineLogin(data));
+ dispatch(addUpdateVirtualMachineLogin(data));
}
})
)(
(props: CreateGroupDialogComponentProps) =>
<FormDialog
- dialogTitle='Add login permissions'
+ dialogTitle={props.data.updating ? "Update login permission" : "Add login permission"}
formFields={AddLoginFormFields}
- submitLabel='Add'
+ submitLabel={props.data.updating ? "Update" : "Add"}
{...props}
/>
);
-type CreateGroupDialogComponentProps = WithDialogProps<{}> & InjectedFormProps<AddLoginFormData>;
+type CreateGroupDialogComponentProps = WithDialogProps<{updating: boolean}> & InjectedFormProps<AddLoginFormData>;
const AddLoginFormFields = () =>
<>
<UserField />
<GroupArrayInput
name={VIRTUAL_MACHINE_ADD_LOGIN_GROUPS_FIELD}
- input={{id:"Add groups to VM login", disabled:false}}
+ input={{id:"Add groups to VM login (eg: docker, sudo)", disabled:false}}
required={false}
/>
</>;
@@ -50,7 +50,7 @@ const UserField = () =>
const UserSelect = ({ input, meta }: WrappedFieldProps) =>
<ParticipantSelect
onlyPeople
- label='Search for users to grant login permission'
+ label='Search for user to grant login permission'
items={input.value ? [input.value] : []}
onSelect={input.onChange}
onDelete={() => (input.onChange(''))} />;
diff --git a/src/views/virtual-machine-panel/virtual-machine-admin-panel.tsx b/src/views/virtual-machine-panel/virtual-machine-admin-panel.tsx
index bfa6be26..468ef35a 100644
--- a/src/views/virtual-machine-panel/virtual-machine-admin-panel.tsx
+++ b/src/views/virtual-machine-panel/virtual-machine-admin-panel.tsx
@@ -8,7 +8,7 @@ import { Grid, Card, Chip, CardContent, TableBody, TableCell, TableHead, TableRo
import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
import { ArvadosTheme } from 'common/custom-theme';
import { compose, Dispatch } from 'redux';
-import { loadVirtualMachinesAdminData, openAddVirtualMachineLoginDialog, openRemoveVirtualMachineLoginDialog } from 'store/virtual-machines/virtual-machines-actions';
+import { loadVirtualMachinesAdminData, openAddVirtualMachineLoginDialog, openRemoveVirtualMachineLoginDialog, openEditVirtualMachineLoginDialog } from 'store/virtual-machines/virtual-machines-actions';
import { RootState } from 'store/store';
import { ListResults } from 'services/common-service/common-service';
import { MoreOptionsIcon, AddUserIcon } from 'components/icon/icon';
@@ -40,7 +40,7 @@ const mapStateToProps = (state: RootState) => {
};
};
-const mapDispatchToProps = (dispatch: Dispatch): Pick<VirtualMachinesPanelActionProps, 'loadVirtualMachinesData' | 'onOptionsMenuOpen' | 'onAddLogin' | 'onDeleteLogin'> => ({
+const mapDispatchToProps = (dispatch: Dispatch): Pick<VirtualMachinesPanelActionProps, 'loadVirtualMachinesData' | 'onOptionsMenuOpen' | 'onAddLogin' | 'onDeleteLogin' | 'onLoginEdit'> => ({
loadVirtualMachinesData: () => dispatch<any>(loadVirtualMachinesAdminData()),
onOptionsMenuOpen: (event, virtualMachine) => {
dispatch<any>(openVirtualMachinesContextMenu(event, virtualMachine));
@@ -51,6 +51,9 @@ const mapDispatchToProps = (dispatch: Dispatch): Pick<VirtualMachinesPanelAction
onDeleteLogin: (uuid: string) => {
dispatch<any>(openRemoveVirtualMachineLoginDialog(uuid));
},
+ onLoginEdit: (uuid: string) => {
+ dispatch<any>(openEditVirtualMachineLoginDialog(uuid));
+ },
});
interface VirtualMachinesPanelDataProps {
@@ -65,6 +68,7 @@ interface VirtualMachinesPanelActionProps {
onOptionsMenuOpen: (event: React.MouseEvent<HTMLElement>, virtualMachine: VirtualMachinesResource) => void;
onAddLogin: (uuid: string) => void;
onDeleteLogin: (uuid: string) => void;
+ onLoginEdit: (uuid: string) => void;
}
type VirtualMachineProps = VirtualMachinesPanelActionProps & VirtualMachinesPanelDataProps & WithStyles<CssRules>;
@@ -117,7 +121,7 @@ const virtualMachinesTable = (props: VirtualMachineProps) =>
<Grid container spacing={8} className={props.classes.chipsRoot}>
{props.links.items.filter((link) => (link.headUuid === machine.uuid)).map((permission, i) => (
<Grid item key={i}>
- <Chip label={<VirtualMachineLogin linkUuid={permission.uuid} />} onDelete={event => props.onDeleteLogin(permission.uuid)} />
+ <Chip label={<VirtualMachineLogin linkUuid={permission.uuid} />} onDelete={event => props.onDeleteLogin(permission.uuid)} onClick={event => props.onLoginEdit(permission.uuid)} />
</Grid>
))}
</Grid>
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list