Added autorun and random id service generation
This commit is contained in:
@@ -3,7 +3,7 @@ import sqlite3, uvicorn, sys, secrets, re, os, asyncio, httpx, urllib, websocket
|
|||||||
from fastapi import FastAPI, HTTPException, WebSocket, Depends
|
from fastapi import FastAPI, HTTPException, WebSocket, Depends
|
||||||
from pydantic import BaseModel, BaseSettings
|
from pydantic import BaseModel, BaseSettings
|
||||||
from fastapi.responses import FileResponse, StreamingResponse
|
from fastapi.responses import FileResponse, StreamingResponse
|
||||||
from utils import SQLite, KeyValueStorage, gen_internal_port, ProxyManager, from_name_get_id, STATUS
|
from utils import *
|
||||||
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
||||||
from jose import JWTError, jwt
|
from jose import JWTError, jwt
|
||||||
from passlib.context import CryptContext
|
from passlib.context import CryptContext
|
||||||
@@ -22,6 +22,7 @@ class Settings(BaseSettings):
|
|||||||
JWT_ALGORITHM: str = "HS256"
|
JWT_ALGORITHM: str = "HS256"
|
||||||
REACT_BUILD_DIR: str = "../frontend/build/" if not ON_DOCKER else "frontend/"
|
REACT_BUILD_DIR: str = "../frontend/build/" if not ON_DOCKER else "frontend/"
|
||||||
REACT_HTML_PATH: str = os.path.join(REACT_BUILD_DIR,"index.html")
|
REACT_HTML_PATH: str = os.path.join(REACT_BUILD_DIR,"index.html")
|
||||||
|
VERSION = "2.0.0"
|
||||||
|
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
@@ -73,7 +74,8 @@ async def is_loggined(auth: bool = Depends(check_login)):
|
|||||||
async def get_status(auth: bool = Depends(check_login)):
|
async def get_status(auth: bool = Depends(check_login)):
|
||||||
return {
|
return {
|
||||||
"status": APP_STATUS(),
|
"status": APP_STATUS(),
|
||||||
"loggined": auth
|
"loggined": auth,
|
||||||
|
"version": settings.VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
class PasswordForm(BaseModel):
|
class PasswordForm(BaseModel):
|
||||||
@@ -247,7 +249,7 @@ class ServiceAddForm(BaseModel):
|
|||||||
|
|
||||||
@app.post('/api/services/add')
|
@app.post('/api/services/add')
|
||||||
async def post_services_add(form: ServiceAddForm, auth: bool = Depends(is_loggined)):
|
async def post_services_add(form: ServiceAddForm, auth: bool = Depends(is_loggined)):
|
||||||
serv_id = from_name_get_id(form.name)
|
serv_id = gen_service_id(db)
|
||||||
try:
|
try:
|
||||||
db.query("INSERT INTO services (name, service_id, internal_port, public_port, status) VALUES (?, ?, ?, ?, ?)",
|
db.query("INSERT INTO services (name, service_id, internal_port, public_port, status) VALUES (?, ?, ?, ?, ?)",
|
||||||
form.name, serv_id, gen_internal_port(db), form.port, 'stop')
|
form.name, serv_id, gen_internal_port(db), form.port, 'stop')
|
||||||
@@ -255,7 +257,7 @@ async def post_services_add(form: ServiceAddForm, auth: bool = Depends(is_loggin
|
|||||||
except sqlite3.IntegrityError:
|
except sqlite3.IntegrityError:
|
||||||
return {'status': 'Name or/and port of the service has been already assigned to another service'}
|
return {'status': 'Name or/and port of the service has been already assigned to another service'}
|
||||||
|
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok', "id": serv_id }
|
||||||
|
|
||||||
async def frontend_debug_proxy(path):
|
async def frontend_debug_proxy(path):
|
||||||
httpc = httpx.AsyncClient()
|
httpc = httpx.AsyncClient()
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import secrets
|
||||||
import threading
|
import threading
|
||||||
from proxy import Filter, Proxy
|
from proxy import Filter, Proxy
|
||||||
import random, string, os, sqlite3, socket, asyncio
|
import random, string, os, sqlite3, socket, asyncio
|
||||||
@@ -260,10 +261,12 @@ def check_port_is_open(port):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def from_name_get_id(name):
|
def gen_service_id(db):
|
||||||
serv_id = name.strip().replace(" ","-")
|
while True:
|
||||||
serv_id = "".join([c for c in serv_id if c in (string.ascii_uppercase + string.ascii_lowercase + string.digits + "-")])
|
res = secrets.token_hex(8)
|
||||||
return serv_id.lower()
|
if len(db.query('SELECT 1 FROM services WHERE service_id = ?;', res)) == 0:
|
||||||
|
break
|
||||||
|
return res
|
||||||
|
|
||||||
def gen_internal_port(db):
|
def gen_internal_port(db):
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
import { Button, Group, NumberInput, Space, TextInput, Notification, Modal } from '@mantine/core';
|
import { Button, Group, NumberInput, Space, TextInput, Notification, Modal, Switch } from '@mantine/core';
|
||||||
import { useForm } from '@mantine/hooks';
|
import { useForm } from '@mantine/hooks';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { ServiceAddForm } from '../js/models';
|
import { addservice, fireUpdateRequest, okNotify, startservice } from '../js/utils';
|
||||||
import { addservice, fireUpdateRequest, okNotify } from '../js/utils';
|
|
||||||
import { ImCross } from "react-icons/im"
|
import { ImCross } from "react-icons/im"
|
||||||
|
|
||||||
|
type ServiceAddForm = {
|
||||||
|
name:string,
|
||||||
|
port:number,
|
||||||
|
autostart: boolean
|
||||||
|
}
|
||||||
|
|
||||||
function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void }) {
|
function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void }) {
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
name:"",
|
name:"",
|
||||||
port:1,
|
port:1,
|
||||||
|
autostart: true
|
||||||
},
|
},
|
||||||
validationRules:{
|
validationRules:{
|
||||||
name: (value) => value !== ""?true:false,
|
name: (value) => value !== ""?true:false,
|
||||||
@@ -27,17 +33,18 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void })
|
|||||||
const [submitLoading, setSubmitLoading] = useState(false)
|
const [submitLoading, setSubmitLoading] = useState(false)
|
||||||
const [error, setError] = useState<string|null>(null)
|
const [error, setError] = useState<string|null>(null)
|
||||||
|
|
||||||
const submitRequest = (values:ServiceAddForm) =>{
|
const submitRequest = ({ name, port, autostart }:ServiceAddForm) =>{
|
||||||
setSubmitLoading(true)
|
setSubmitLoading(true)
|
||||||
addservice(values).then( res => {
|
addservice({ name, port }).then( res => {
|
||||||
if (!res){
|
if (res.status === "ok"){
|
||||||
setSubmitLoading(false)
|
setSubmitLoading(false)
|
||||||
close();
|
close();
|
||||||
fireUpdateRequest();
|
fireUpdateRequest();
|
||||||
okNotify(`Service ${values.name} has been added`, `Successfully added ${values.name} with port ${values.port}`)
|
if (autostart) startservice(res.id)
|
||||||
|
okNotify(`Service ${name} has been added`, `Successfully added ${res.id} with port ${port}`)
|
||||||
}else{
|
}else{
|
||||||
setSubmitLoading(false)
|
setSubmitLoading(false)
|
||||||
setError("Invalid request! [ "+res+" ]")
|
setError("Invalid request! [ "+res.status+" ]")
|
||||||
}
|
}
|
||||||
}).catch( err => {
|
}).catch( err => {
|
||||||
setSubmitLoading(false)
|
setSubmitLoading(false)
|
||||||
@@ -63,9 +70,13 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void })
|
|||||||
{...form.getInputProps('port')}
|
{...form.getInputProps('port')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
<Space h="md" />
|
<Space h="md" />
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
label="Auto-Start Service"
|
||||||
|
{...form.getInputProps('autostart', { type: 'checkbox' })}
|
||||||
|
/>
|
||||||
|
|
||||||
<Group position="right" mt="md">
|
<Group position="right" mt="md">
|
||||||
<Button loading={submitLoading} type="submit">Add Service</Button>
|
<Button loading={submitLoading} type="submit">Add Service</Button>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ export type ServiceAddForm = {
|
|||||||
export type ServerResponse = {
|
export type ServerResponse = {
|
||||||
status:string
|
status:string
|
||||||
}
|
}
|
||||||
|
export type ServerResponseWithID = {
|
||||||
|
status:string,
|
||||||
|
id:string
|
||||||
|
}
|
||||||
|
|
||||||
export type ServerResponseToken = {
|
export type ServerResponseToken = {
|
||||||
status:string,
|
status:string,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { showNotification } from "@mantine/notifications";
|
import { showNotification } from "@mantine/notifications";
|
||||||
import { ImCross } from "react-icons/im";
|
import { ImCross } from "react-icons/im";
|
||||||
import { TiTick } from "react-icons/ti"
|
import { TiTick } from "react-icons/ti"
|
||||||
import { GeneralStats, Service, ServiceAddForm, ServerResponse, RegexFilter, RegexAddForm, ServerStatusResponse, PasswordSend, ChangePassword, LoginResponse, ServerResponseToken } from "./models";
|
import { GeneralStats, Service, ServiceAddForm, ServerResponse, RegexFilter, RegexAddForm, ServerStatusResponse, PasswordSend, ChangePassword, LoginResponse, ServerResponseToken, ServerResponseWithID } from "./models";
|
||||||
|
|
||||||
var Buffer = require('buffer').Buffer
|
var Buffer = require('buffer').Buffer
|
||||||
|
|
||||||
@@ -119,8 +119,7 @@ export async function regenport(service_id:string){
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function addservice(data:ServiceAddForm) {
|
export async function addservice(data:ServiceAddForm) {
|
||||||
const { status } = await postapi("services/add",data) as ServerResponse;
|
return await postapi("services/add",data) as ServerResponseWithID;
|
||||||
return status === "ok"?undefined:status
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteservice(service_id:string) {
|
export async function deleteservice(service_id:string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user