Add permissions handling to the console; remove kill permission (wrapped in with stop)

This commit is contained in:
Dane Everitt 2020-03-29 22:12:50 -07:00
parent 79095b526c
commit 171b21e7ee
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
5 changed files with 42 additions and 28 deletions

View file

@ -18,11 +18,10 @@ class SendPowerRequest extends ClientApiRequest
case 'start':
return Permission::ACTION_CONTROL_START;
case 'stop':
case 'kill':
return Permission::ACTION_CONTROL_STOP;
case 'restart':
return Permission::ACTION_CONTROL_RESTART;
case 'kill':
return Permission::ACTION_CONTROL_KILL;
}
return '__invalid';

View file

@ -20,7 +20,6 @@ class Permission extends Validable
const ACTION_CONTROL_START = 'control.start';
const ACTION_CONTROL_STOP = 'control.stop';
const ACTION_CONTROL_RESTART = 'control.restart';
const ACTION_CONTROL_KILL = 'control.kill';
const ACTION_DATABASE_READ = 'database.read';
const ACTION_DATABASE_CREATE = 'database.create';
@ -111,7 +110,6 @@ class Permission extends Validable
'start' => 'Allows a user to start the server if it is stopped.',
'stop' => 'Allows a user to stop a server if it is running.',
'restart' => 'Allows a user to perform a server restart. This allows them to start the server if it is offline, but not put the server in a completely stopped state.',
'kill' => 'Allows a user to terminate a server process.',
],
],

View file

@ -4,6 +4,9 @@ import * as TerminalFit from 'xterm/lib/addons/fit/fit';
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import { ServerContext } from '@/state/server';
import styled from 'styled-components';
import Can from '@/components/elements/Can';
import { usePermissions } from '@/plugins/usePermissions';
import classNames from 'classnames';
const theme = {
background: 'transparent',
@ -52,6 +55,7 @@ export default () => {
const useRef = useCallback(node => setTerminalElement(node), []);
const terminal = useMemo(() => new Terminal({ ...terminalProps }), []);
const { connected, instance } = ServerContext.useStoreState(state => state.socket);
const [ canSendCommands ] = usePermissions([ 'control.console']);
const handleConsoleOutput = (line: string, prelude = false) => terminal.writeln(
(prelude ? TERMINAL_PRELUDE : '') + line.replace(/(?:\r\n|\r|\n)$/im, '') + '\u001b[0m',
@ -121,7 +125,9 @@ export default () => {
<div className={'text-xs font-mono relative'}>
<SpinnerOverlay visible={!connected} size={'large'}/>
<div
className={'rounded-t p-2 bg-black w-full'}
className={classNames('rounded-t p-2 bg-black w-full', {
'rounded-b': !canSendCommands,
})}
style={{
minHeight: '16rem',
maxHeight: '32rem',
@ -129,6 +135,7 @@ export default () => {
>
<TerminalDiv id={'terminal'} ref={useRef}/>
</div>
{canSendCommands &&
<div className={'rounded-b bg-neutral-900 text-neutral-100 flex'}>
<div className={'flex-no-shrink p-2 font-bold'}>$</div>
<div className={'w-full'}>
@ -140,6 +147,7 @@ export default () => {
/>
</div>
</div>
}
</div>
);
};

View file

@ -9,6 +9,7 @@ import { faMicrochip } from '@fortawesome/free-solid-svg-icons/faMicrochip';
import { bytesToHuman } from '@/helpers';
import SuspenseSpinner from '@/components/elements/SuspenseSpinner';
import TitledGreyBox from '@/components/elements/TitledGreyBox';
import Can from '@/components/elements/Can';
type PowerAction = 'start' | 'stop' | 'restart' | 'kill';
@ -109,28 +110,36 @@ export default () => {
&nbsp;{cpu.toFixed(2)} %
</p>
</TitledGreyBox>
<div className={'grey-box justify-center'}>
<button
className={'btn btn-secondary btn-xs mr-2'}
disabled={status !== 'offline'}
onClick={e => {
e.preventDefault();
sendPowerCommand('start');
}}
>
Start
</button>
<button
className={'btn btn-secondary btn-xs mr-2'}
onClick={e => {
e.preventDefault();
sendPowerCommand('restart');
}}
>
Restart
</button>
<StopOrKillButton onPress={action => sendPowerCommand(action)}/>
</div>
<Can action={[ 'control.start', 'control.stop', 'control.restart' ]} matchAny={true}>
<div className={'grey-box justify-center'}>
<Can action={'control.start'}>
<button
className={'btn btn-secondary btn-xs mr-2'}
disabled={status !== 'offline'}
onClick={e => {
e.preventDefault();
sendPowerCommand('start');
}}
>
Start
</button>
</Can>
<Can action={'control.restart'}>
<button
className={'btn btn-secondary btn-xs mr-2'}
onClick={e => {
e.preventDefault();
sendPowerCommand('restart');
}}
>
Restart
</button>
</Can>
<Can action={'control.stop'}>
<StopOrKillButton onPress={action => sendPowerCommand(action)}/>
</Can>
</div>
</Can>
</div>
<div className={'flex-1 mx-4 mr-4'}>
<SuspenseSpinner>

View file

@ -2,7 +2,7 @@ import { action, Action } from 'easy-peasy';
export type SubuserPermission =
'websocket.*' |
'control.console' | 'control.start' | 'control.stop' | 'control.restart' | 'control.kill' |
'control.console' | 'control.start' | 'control.stop' | 'control.restart' |
'user.create' | 'user.read' | 'user.update' | 'user.delete' |
'file.create' | 'file.read' | 'file.update' | 'file.delete' | 'file.archive' | 'file.sftp' |
'allocation.read' | 'allocation.update' |