Add permissions handling to the console; remove kill permission (wrapped in with stop)
This commit is contained in:
parent
79095b526c
commit
171b21e7ee
5 changed files with 42 additions and 28 deletions
|
@ -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';
|
||||
|
|
|
@ -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.',
|
||||
],
|
||||
],
|
||||
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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 () => {
|
|||
{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>
|
||||
|
|
|
@ -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' |
|
||||
|
|
Loading…
Reference in a new issue