mirror of
https://github.com/ConvoyPanel/panel.git
synced 2026-06-08 19:02:28 +08:00
Update VNC page
This commit is contained in:
@@ -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',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ use Webmozart\Assert\Assert;
|
||||
*/
|
||||
abstract class ProxmoxService
|
||||
{
|
||||
protected $server;
|
||||
protected Server $server;
|
||||
|
||||
protected $node;
|
||||
protected Node $node;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -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'];
|
||||
|
||||
@@ -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
27709
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user