-import React, { createContext, useState, useContext, useEffect } from 'react';
+import React, { createContext, useContext, useEffect, useState } from 'react';
import { VPNService } from '../../services';
-import { CreateVPNClientDialog, ConfirmRevoke } from '../index';
+import { ConfirmRevoke, CreateVPNClientDialog, VPNStatusDialog } from '../index';
const VPNContext = createContext( undefined );
const [availableClients, setAvailableClients] = useState( [] );
const [message, setMessage] = useState( '' );
const [createOpen, setCreateOpen] = useState( false );
+ const [statusOpen, setStatusOpen] = useState( false );
+ const [serverStatus, setServerStatus] = useState( {} );
+
+ const fetchServerStatus = async () => {
+ await VPNService.getServerStatus()
+ .then( res => setServerStatus( res ) )
+ .catch( err => setMessage( err ) );
+ };
const fetchClients = async () => {
await VPNService.fetchClients()
useEffect( () => {
fetchClients().catch( e => setMessage( e ) );
fetchAvailableClients().catch( e => setMessage( e ) );
+ fetchServerStatus().catch( e => setMessage( e ) );
const interval = setInterval( () => {
fetchClients().catch( e => setMessage( e ) );
fetchAvailableClients().catch( e => setMessage( e ) );
+ fetchServerStatus().catch( e => setMessage( e ) );
}, 10000 * 120 );
return () => clearInterval( interval );
createOpen,
setCreateOpen,
handleCreateClientSubmit,
- handleRevokeClientSubmit
+ handleRevokeClientSubmit,
+ statusOpen,
+ setStatusOpen,
+ serverStatus,
+ setServerStatus
};
return <VPNContext.Provider value={ value }>
- {revokeOpen && <ConfirmRevoke open={revokeOpen} onClose={() => setRevokeOpen(false)} onConfirm={handleRevokeClientSubmit}/>}
- {createOpen && <CreateVPNClientDialog open={createOpen} onClose={() => setCreateOpen(false)} onCreate={handleCreateClientSubmit}/>}
+ { revokeOpen && <ConfirmRevoke open={ revokeOpen }
+ onClose={ () => setRevokeOpen( false ) }
+ onConfirm={ handleRevokeClientSubmit }/> }
+ { createOpen && <CreateVPNClientDialog open={ createOpen }
+ onClose={ () => setCreateOpen( false ) }
+ onCreate={ handleCreateClientSubmit }/> }
+ { statusOpen && <VPNStatusDialog open={ statusOpen }
+ onClose={ () => setStatusOpen( false ) }
+ status={ serverStatus }/> }
{ children }</VPNContext.Provider>;
};
--- /dev/null
+import { Dialog, DialogTitle, DialogContent, DialogActions, Button} from '@mui/material';
+
+export default function VPNStatusDialog( { open, onClose, status } ) {
+ return (
+ <Dialog open={ open } onClose={ onClose } >
+ <DialogTitle>VPN Status</DialogTitle>
+ <DialogContent>{ status }</DialogContent>
+ <DialogActions>
+ <Button onClick={ onClose }>OK</Button>
+ </DialogActions>
+ </Dialog>
+ );
+};
\ No newline at end of file
import ConfirmRevoke from './VPN/ConfirmRevoke';
import CreateVPNClientDialog from './VPN/CreateVPNClientDialog';
+import VPNStatusDialog from './VPN/VPNStatusDialog';
+export * from './VPN/VPNContext';
-export { ConfirmRevoke, CreateVPNClientDialog };
\ No newline at end of file
+export { ConfirmRevoke, CreateVPNClientDialog, VPNStatusDialog };
\ No newline at end of file
import { Route, Routes } from 'react-router-dom';
import { Login, NotFound, Dashboard, Git, VPN, Docker } from './views';
-import { VPNProvider } from './components/VPN/VPNContext';
+import { VPNProvider } from './components/';
export default function AppRoutes() {
return (
<Routes>
- <Route path="/" element={<Dashboard />} />
- <Route path="/login" element={<Login />} />
- <Route path="/git" element={<Git />} />
- <Route path="/vpn" element={ <VPNProvider><VPN/></VPNProvider>} />
- <Route path="/docker" element={<Docker />} />
- <Route path="*" element={<NotFound />} />
+ <Route path="/" element={ <Dashboard /> } />
+ <Route path="/login" element={ <Login /> } />
+ <Route path="/git" element={ <Git /> } />
+ <Route path="/vpn" element={ <VPNProvider><VPN/></VPNProvider> } />
+ <Route path="/docker" element={ <Docker /> } />
+ <Route path="*" element={ <NotFound /> } />
</Routes>
);
};
create: `${base}create-client/`,
delete: `${base}revoke-client/`,
index: `${base}clients/`,
- availableClients: `${base}available-clients/`
+ availableClients: `${base}available-clients/`,
+ getStatus: `${base}status/`,
+ disconnect: `${base}disconnect/`,
+ restart: `${base}restart/`
};
export default VPNConfig;
\ No newline at end of file
fetchClients = () => {
return new Promise( async ( resolve ) => {
try {
- const response = await axios.get(`${base_url}${VPNConfig.index}`);
- resolve(response.data.clients);
+ const response = await axios.get( `${ base_url }${ VPNConfig.index }` );
+ resolve( response.data.clients );
} catch (error) {
- resolve(`Error: ${error.response?.data?.error || 'Failed to fetch clients'}`);
+ resolve( `Error: ${ error.response?.data?.error || 'Failed to fetch clients' }` );
}
- });
+ } );
};
fetchAvailableClients = () => {
return new Promise( async ( resolve ) => {
try {
- const response = await axios.get(`${base_url}${VPNConfig.availableClients}`);
- resolve(response.data.clients);
+ const response = await axios.get( `${ base_url }${ VPNConfig.availableClients }` );
+ resolve( response.data.clients );
} catch (error) {
- resolve(`Error: ${error.response?.data?.error || 'Failed to fetch available clients'}`);
+ resolve( `Error: ${ error.response?.data?.error || 'Failed to fetch available clients' }` );
}
- });
+ } );
};
createClient = ( data, fetchClients ) => {
return new Promise( async ( resolve ) => {
const { clientName, useStaticIp, staticIp } = data;
try {
- const response = await axios.post(`${base_url}${VPNConfig.create}`, {
+ const response = await axios.post( `${ base_url }${ VPNConfig.create }`, {
clientName,
- staticIp: useStaticIp ? staticIp : undefined,
- });
+ staticIp:useStaticIp ? staticIp : undefined,
+ } );
fetchClients();
if (response.data.ovpn) {
- const element = document.createElement('a');
- const file = new Blob([response.data.ovpn], { type: 'text/plain' });
- element.href = URL.createObjectURL(file);
- element.download = `${clientName}.ovpn`;
- document.body.appendChild(element);
+ const element = document.createElement( 'a' );
+ const file = new Blob( [response.data.ovpn], { type:'text/plain' } );
+ element.href = URL.createObjectURL( file );
+ element.download = `${ clientName }.ovpn`;
+ document.body.appendChild( element );
element.click();
- document.body.removeChild(element);
+ document.body.removeChild( element );
}
- resolve(response.data.message);
+ resolve( response.data.message );
} catch (error) {
- resolve(`Error: ${error.response?.data?.error || 'Failed to create client'}`);
+ resolve( `Error: ${ error.response?.data?.error || 'Failed to create client' }` );
}
- })
+ } );
};
revokeClient = ( data, fetchClients ) => {
return new Promise( async ( resolve ) => {
const { revokeClientName } = data;
try {
- const response = await axios.put(`${base_url}${VPNConfig.delete}`, {
- clientName: revokeClientName,
- });
+ const response = await axios.put( `${ base_url }${ VPNConfig.delete }`, {
+ clientName:revokeClientName,
+ } );
fetchClients();
- resolve(response.data.message);
+ resolve( response.data.message );
} catch (error) {
- resolve(`Error: ${error.response?.data?.error || 'Failed to revoke client'}`);
+ resolve( `Error: ${ error.response?.data?.error || 'Failed to revoke client' }` );
}
- });
+ } );
+ };
+
+ getServerStatus = () => {
+ return new Promise( async ( resolve ) => {
+ try {
+ const response = await axios.get( `${ base_url }${ VPNConfig.getStatus }` );
+ resolve( response.data );
+ } catch (error) {
+ resolve( `Error: ${ error.response?.data?.error || 'Failed to fetch server status' }` );
+ }
+ } );
+ };
+
+ disconnect = () => {
+ return new Promise( async ( resolve ) => {
+ try {
+ const response = await axios.put( `${ base_url }${ VPNConfig.disconnect }` );
+ resolve( response.data.message );
+ } catch (error) {
+ resolve( `Error: ${ error.response?.data?.error || 'Failed to disconnect' }` );
+ }
+ } );
+ };
+
+ restart = () => {
+ return new Promise( async ( resolve ) => {
+ try {
+ const response = await axios.put( `${ base_url }${ VPNConfig.restart }` );
+ resolve( response.data.message );
+ } catch (error) {
+ resolve( `Error: ${ error.response?.data?.error || 'Failed to restart' }` );
+ }
+ } );
};
}
import { Container, Typography, Button, Grid } from '@mui/material';
import { MaterialReactTable, useMaterialReactTable } from 'material-react-table';
-import { useVPN } from '../../components/VPN/VPNContext';
+import { useVPN } from '../../components';
const VPN = () => {
const { setRevokeOpen,
clients,
availableClients,
message,
- setCreateOpen } = useVPN();
+ setCreateOpen,
+ setStatusOpen } = useVPN();
const clientTable = useMaterialReactTable( {
columns: [
{ accessorKey: 'name', header: 'Name' },
data: availableClients,
renderTopToolbarCustomActions: () => (
<>
- <Button variant="contained"
- color="primary"
+ <Button variant='contained'
+ color='primary'
+ size='small'
onClick={ () => setCreateOpen( true ) }>
Create Client
</Button>
+ <Button variant='contained'
+ color='warning'
+ size='small'
+ onClick={ () => setStatusOpen( true ) }>
+ Show VPN Status
+ </Button>
</>
)
});