From a064652fcfa8dabd27717b8f90165585c8cad927 Mon Sep 17 00:00:00 2001 From: DomySh Date: Wed, 29 Jun 2022 23:40:39 +0200 Subject: [PATCH] Added autorun and random id service generation --- backend/app.py | 10 +++++--- backend/utils.py | 11 +++++--- frontend/src/components/AddNewService.tsx | 31 +++++++++++++++-------- frontend/src/js/models.ts | 4 +++ frontend/src/js/utils.tsx | 5 ++-- 5 files changed, 40 insertions(+), 21 deletions(-) diff --git a/backend/app.py b/backend/app.py index e673214..e769838 100644 --- a/backend/app.py +++ b/backend/app.py @@ -3,7 +3,7 @@ import sqlite3, uvicorn, sys, secrets, re, os, asyncio, httpx, urllib, websocket from fastapi import FastAPI, HTTPException, WebSocket, Depends from pydantic import BaseModel, BaseSettings 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 jose import JWTError, jwt from passlib.context import CryptContext @@ -22,6 +22,7 @@ class Settings(BaseSettings): JWT_ALGORITHM: str = "HS256" REACT_BUILD_DIR: str = "../frontend/build/" if not ON_DOCKER else "frontend/" REACT_HTML_PATH: str = os.path.join(REACT_BUILD_DIR,"index.html") + VERSION = "2.0.0" settings = Settings() @@ -73,7 +74,8 @@ async def is_loggined(auth: bool = Depends(check_login)): async def get_status(auth: bool = Depends(check_login)): return { "status": APP_STATUS(), - "loggined": auth + "loggined": auth, + "version": settings.VERSION } class PasswordForm(BaseModel): @@ -247,7 +249,7 @@ class ServiceAddForm(BaseModel): @app.post('/api/services/add') 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: 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') @@ -255,7 +257,7 @@ async def post_services_add(form: ServiceAddForm, auth: bool = Depends(is_loggin except sqlite3.IntegrityError: 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): httpc = httpx.AsyncClient() diff --git a/backend/utils.py b/backend/utils.py index aeb57d3..d24d952 100755 --- a/backend/utils.py +++ b/backend/utils.py @@ -1,3 +1,4 @@ +import secrets import threading from proxy import Filter, Proxy import random, string, os, sqlite3, socket, asyncio @@ -260,10 +261,12 @@ def check_port_is_open(port): except Exception: return False -def from_name_get_id(name): - serv_id = name.strip().replace(" ","-") - serv_id = "".join([c for c in serv_id if c in (string.ascii_uppercase + string.ascii_lowercase + string.digits + "-")]) - return serv_id.lower() +def gen_service_id(db): + while True: + res = secrets.token_hex(8) + if len(db.query('SELECT 1 FROM services WHERE service_id = ?;', res)) == 0: + break + return res def gen_internal_port(db): while True: diff --git a/frontend/src/components/AddNewService.tsx b/frontend/src/components/AddNewService.tsx index 3a3eb6e..23f9682 100755 --- a/frontend/src/components/AddNewService.tsx +++ b/frontend/src/components/AddNewService.tsx @@ -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 React, { useState } from 'react'; -import { ServiceAddForm } from '../js/models'; -import { addservice, fireUpdateRequest, okNotify } from '../js/utils'; +import { addservice, fireUpdateRequest, okNotify, startservice } from '../js/utils'; import { ImCross } from "react-icons/im" +type ServiceAddForm = { + name:string, + port:number, + autostart: boolean +} + function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void }) { const form = useForm({ initialValues: { name:"", port:1, + autostart: true }, validationRules:{ name: (value) => value !== ""?true:false, @@ -26,18 +32,19 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void }) const [submitLoading, setSubmitLoading] = useState(false) const [error, setError] = useState(null) - - const submitRequest = (values:ServiceAddForm) =>{ + + const submitRequest = ({ name, port, autostart }:ServiceAddForm) =>{ setSubmitLoading(true) - addservice(values).then( res => { - if (!res){ + addservice({ name, port }).then( res => { + if (res.status === "ok"){ setSubmitLoading(false) close(); 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{ setSubmitLoading(false) - setError("Invalid request! [ "+res+" ]") + setError("Invalid request! [ "+res.status+" ]") } }).catch( err => { setSubmitLoading(false) @@ -63,9 +70,13 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void }) {...form.getInputProps('port')} /> - + + diff --git a/frontend/src/js/models.ts b/frontend/src/js/models.ts index 9dff5b2..1fdff8f 100755 --- a/frontend/src/js/models.ts +++ b/frontend/src/js/models.ts @@ -22,6 +22,10 @@ export type ServiceAddForm = { export type ServerResponse = { status:string } +export type ServerResponseWithID = { + status:string, + id:string +} export type ServerResponseToken = { status:string, diff --git a/frontend/src/js/utils.tsx b/frontend/src/js/utils.tsx index 1b703e1..901adeb 100755 --- a/frontend/src/js/utils.tsx +++ b/frontend/src/js/utils.tsx @@ -1,7 +1,7 @@ import { showNotification } from "@mantine/notifications"; import { ImCross } from "react-icons/im"; 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 @@ -119,8 +119,7 @@ export async function regenport(service_id:string){ } export async function addservice(data:ServiceAddForm) { - const { status } = await postapi("services/add",data) as ServerResponse; - return status === "ok"?undefined:status + return await postapi("services/add",data) as ServerResponseWithID; } export async function deleteservice(service_id:string) {