Update VNC page

This commit is contained in:
Eric Wang
2022-07-21 15:00:58 -05:00
parent 7852d9cd12
commit 5bb35bbf4a
8 changed files with 507 additions and 27327 deletions

View File

@@ -34,15 +34,19 @@ class SecurityController extends ApplicationApiController
public function getVncCredentials(Server $server)
{
$data = $this->vncService->setServer($server)->getSessionCredentials();
$data = $this->vncService->setServer($server)->getTemporaryVncCredentials();
if (!$data)
{
if (!$data) {
throw new ServiceUnavailableHttpException();
}
return array_merge($this->removeExtraDataProperty($data), ['endpoint' => $this->vncService->setServer($server)->getSessionEndpoint()]);
return array_merge([
'node_id' => $server->node->cluster,
'vmid' => $server->vmid,
'token' => $data,
'endpoint' => 'https://' . $server->node->hostname . ':' . $server->node->port . '/novnc/novnc.html',
]);
}
}
}

View File

@@ -12,9 +12,9 @@ use Webmozart\Assert\Assert;
*/
abstract class ProxmoxService
{
protected $server;
protected Server $server;
protected $node;
protected Node $node;
/**

View File

@@ -5,29 +5,11 @@ namespace App\Services\Servers;
use App\Services\ProxmoxService;
use Carbon\Carbon;
use Illuminate\Support\Str;
use Proxmox\PVE;
class VNCService extends ProxmoxService
{
public function createRole()
{
$vnc_role = [
"roleid" => "VNC",
"privs" => "VM.Console"
];
return $this->proxmox()->access()->roles()->post($vnc_role);
}
public function createUser()
{
$user = [
"enable" => "1",
"userid" => "test",
"email" => "",
"password" => ""
];
return $this->proxmox()->access()->users()->post($user);
}
// deprecated
public function getSessionCredentials()
{
return $this->instance()->vncproxy()->post();
@@ -36,10 +18,10 @@ class VNCService extends ProxmoxService
public function getSessionEndpoint()
{
return $this->instance()->getPve()->getApiURL() . $this->instance()->vncwebsocket()->getWebsocketEndpoint();
return $this->instance()->getPve()->getApiURL();
}
public function temp()
public function getTemporaryVncCredentials()
{
$expirationDate = Carbon::now();
$expirationDate->addDay();
@@ -64,11 +46,21 @@ class VNCService extends ProxmoxService
$this->mainInstance()->access()->roles()->post($role);
$this->mainInstance()->access()->acl()->put([
'path' => '/vms/' . '100',
'path' => '/vms/' . $this->server->vmid,
'users' => $user['userid'],
'roles' => $role['roleid']
]);
$node = $this->server->node;
/* $userFaker = new PVE(...[
$node->hostname,
,
$node->password,
intval($node->port),
$node->auth_type,
]); */
$token = $this->mainInstance()->access()->users()->userId($user['userid'])->token()->tokenId('convoy-vnc')->post(['userid' => $user['userid']]);
return $token['data']['full-tokenid'] .'='. $token['data']['value'];

View File

@@ -16,7 +16,7 @@ return new class extends Migration
Schema::create('nodes', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('cluster')->default("proxmox");
$table->string('cluster')->default('proxmox');
$table->string('hostname');
$table->string('username');
$table->string('password');

27709
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -39,7 +39,6 @@
"deepmerge-ts": "^4.2.1",
"easy-peasy": "^5.0.4",
"react-chartjs-2": "^4.2.0",
"react-vnc": "^0.5.1",
"ts-essentials": "^9.1.2"
}
}

View File

@@ -1,5 +1,7 @@
import axios from 'axios'
/*
// deprecated
export interface VncCredentials {
upid: string
port: string
@@ -7,6 +9,13 @@ export interface VncCredentials {
user: string
ticket: string
endpoint: string
} */
export interface VncCredentials {
node_id: string
vmid: number
token: string
endpoint: string
}
export default (serverId: number) => {

View File

@@ -7,36 +7,43 @@ import Main from '@/components/Main'
import ServerNav from '@/components/servers/ServerNav'
import PasswordConfigSettings from '@/pages/servers/security/modules/PasswordConfigSettings'
import { SettingsContext } from '@/pages/servers/settings/Index'
import { CheckCircleIcon, CheckIcon } from '@heroicons/react/outline'
import { Head } from '@inertiajs/inertia-react'
import { Loader } from '@mantine/core'
import { Button, Loader } from '@mantine/core'
import { useEffect, useMemo, useState } from 'react'
import { VncScreen } from 'react-vnc'
interface Props extends DefaultProps {
server: Server
}
const Index = ({ auth, server }: Props) => {
const [credentials, setCredentials] = useState<VncCredentials | undefined>()
const [processing, setProcessing] = useState(true)
const [credentials, setCredentials] = useState<VncCredentials>()
useEffect(() => {
const main = async () => {
const { data } = await getCredentials(server.id)
setCredentials(data)
console.log(data.endpoint)
setProcessing(false)
}
main()
}, [])
const endpoint = useMemo(( ) => {
if (!credentials) return ''
const launchPopup = () => {
if (!credentials) return
const link = credentials.endpoint.replace(/^http/, 'ws').replace(/^https/, 'wss').slice(0, -1)
const url = `${link}?port=${encodeURIComponent(credentials.port)}&vncticket=${encodeURIComponent(credentials.ticket)}`
return url
}, [credentials])
window.open(
`${credentials.endpoint}?novnc=1&token=${encodeURIComponent(
credentials.token
)}&console=qemu&virtualization=qemu&node=${encodeURIComponent(
credentials.node_id
)}&vmid=${credentials.vmid}`,
'Server Terminal | Convoy',
'width=800,height=600,resizable=yes,scrollbars=yes'
)
}
return (
<Authenticated
@@ -48,21 +55,23 @@ const Index = ({ auth, server }: Props) => {
<Main>
<h3 className='h3-deemphasized'>NoVNC Terminal</h3>
{credentials && <VncScreen
url={endpoint}
scaleViewport
background="#000000"
style={{
width: '75vw',
height: '75vh',
}}
/>}
{!credentials && <div className='grid place-items-center w-full h-[30vh]'>
<div className='flex flex-col items-center space-y-3'>
<div className='grid place-items-center w-full h-[30vh]'>
<div className='flex flex-col items-center space-y-3'>
{!processing && (
<>
<CheckCircleIcon className='text-green-600 w-14 h-14' />
<h3 className='h3-deemphasized'>Session Authorized</h3>
<Button onClick={launchPopup}>Launch noVNC in popup</Button>
</>
)}
{processing && (
<>
<Loader />
<h3 className='h3-deemphasized'>Connecting</h3>
</div>
</div>}
</>
)}
</div>
</div>
</Main>
</Authenticated>
)