Socket io implementation
This commit is contained in:
@@ -8,6 +8,7 @@ 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
|
||||||
|
from fastapi_socketio import SocketManager
|
||||||
|
|
||||||
ON_DOCKER = len(sys.argv) > 1 and sys.argv[1] == "DOCKER"
|
ON_DOCKER = len(sys.argv) > 1 and sys.argv[1] == "DOCKER"
|
||||||
DEBUG = len(sys.argv) > 1 and sys.argv[1] == "DEBUG"
|
DEBUG = len(sys.argv) > 1 and sys.argv[1] == "DEBUG"
|
||||||
@@ -30,14 +31,22 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/login", auto_error=False)
|
|||||||
crypto = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
crypto = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||||
|
|
||||||
app = FastAPI(debug=DEBUG, redoc_url=None)
|
app = FastAPI(debug=DEBUG, redoc_url=None)
|
||||||
|
sio = SocketManager(app, "/sock", socketio_path="")
|
||||||
|
|
||||||
def APP_STATUS(): return "init" if conf.get("password") is None else "run"
|
def APP_STATUS(): return "init" if conf.get("password") is None else "run"
|
||||||
def JWT_SECRET(): return conf.get("secret")
|
def JWT_SECRET(): return conf.get("secret")
|
||||||
|
|
||||||
|
async def refresh_frontend():
|
||||||
|
await sio.emit("update","Refresh")
|
||||||
|
|
||||||
|
@sio.on("update")
|
||||||
|
async def updater(): pass
|
||||||
|
|
||||||
@app.on_event("startup")
|
@app.on_event("startup")
|
||||||
async def startup_event():
|
async def startup_event():
|
||||||
db.init()
|
db.init()
|
||||||
await firewall.init()
|
await firewall.init(refresh_frontend)
|
||||||
|
await refresh_frontend()
|
||||||
if not JWT_SECRET(): conf.put("secret", secrets.token_hex(32))
|
if not JWT_SECRET(): conf.put("secret", secrets.token_hex(32))
|
||||||
|
|
||||||
@app.on_event("shutdown")
|
@app.on_event("shutdown")
|
||||||
@@ -117,6 +126,7 @@ async def change_password(form: PasswordChangeForm, auth: bool = Depends(is_logg
|
|||||||
|
|
||||||
hash_psw = crypto.hash(form.password)
|
hash_psw = crypto.hash(form.password)
|
||||||
conf.put("password",hash_psw)
|
conf.put("password",hash_psw)
|
||||||
|
await refresh_frontend()
|
||||||
return {"status":"ok", "access_token": create_access_token({"logged_in": True})}
|
return {"status":"ok", "access_token": create_access_token({"logged_in": True})}
|
||||||
|
|
||||||
|
|
||||||
@@ -128,6 +138,7 @@ async def set_password(form: PasswordForm):
|
|||||||
return {"status":"Cannot insert an empty password!"}
|
return {"status":"Cannot insert an empty password!"}
|
||||||
hash_psw = crypto.hash(form.password)
|
hash_psw = crypto.hash(form.password)
|
||||||
conf.put("password",hash_psw)
|
conf.put("password",hash_psw)
|
||||||
|
await refresh_frontend()
|
||||||
return {"status":"ok", "access_token": create_access_token({"logged_in": True})}
|
return {"status":"ok", "access_token": create_access_token({"logged_in": True})}
|
||||||
|
|
||||||
class GeneralStatModel(BaseModel):
|
class GeneralStatModel(BaseModel):
|
||||||
@@ -189,12 +200,14 @@ class StatusMessageModel(BaseModel):
|
|||||||
async def service_stop(service_port: int, auth: bool = Depends(is_loggined)):
|
async def service_stop(service_port: int, auth: bool = Depends(is_loggined)):
|
||||||
"""Request the stop of a specific service"""
|
"""Request the stop of a specific service"""
|
||||||
await firewall.get(service_port).next(STATUS.STOP)
|
await firewall.get(service_port).next(STATUS.STOP)
|
||||||
|
await refresh_frontend()
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
|
|
||||||
@app.get('/api/service/{service_port}/start', response_model=StatusMessageModel)
|
@app.get('/api/service/{service_port}/start', response_model=StatusMessageModel)
|
||||||
async def service_start(service_port: int, auth: bool = Depends(is_loggined)):
|
async def service_start(service_port: int, auth: bool = Depends(is_loggined)):
|
||||||
"""Request the start of a specific service"""
|
"""Request the start of a specific service"""
|
||||||
await firewall.get(service_port).next(STATUS.ACTIVE)
|
await firewall.get(service_port).next(STATUS.ACTIVE)
|
||||||
|
await refresh_frontend()
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
|
|
||||||
@app.get('/api/service/{service_port}/delete', response_model=StatusMessageModel)
|
@app.get('/api/service/{service_port}/delete', response_model=StatusMessageModel)
|
||||||
@@ -203,6 +216,7 @@ async def service_delete(service_port: int, auth: bool = Depends(is_loggined)):
|
|||||||
db.query('DELETE FROM services WHERE port = ?;', service_port)
|
db.query('DELETE FROM services WHERE port = ?;', service_port)
|
||||||
db.query('DELETE FROM regexes WHERE service_port = ?;', service_port)
|
db.query('DELETE FROM regexes WHERE service_port = ?;', service_port)
|
||||||
await firewall.remove(service_port)
|
await firewall.remove(service_port)
|
||||||
|
await refresh_frontend()
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
|
|
||||||
class RenameForm(BaseModel):
|
class RenameForm(BaseModel):
|
||||||
@@ -213,6 +227,7 @@ async def service_rename(service_port: int, form: RenameForm, auth: bool = Depen
|
|||||||
"""Request to change the name of a specific service"""
|
"""Request to change the name of a specific service"""
|
||||||
if not form.name: return {'status': 'The name cannot be empty!'}
|
if not form.name: return {'status': 'The name cannot be empty!'}
|
||||||
db.query('UPDATE services SET name=? WHERE port = ?;', form.name, service_port)
|
db.query('UPDATE services SET name=? WHERE port = ?;', form.name, service_port)
|
||||||
|
await refresh_frontend()
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
|
|
||||||
class RegexModel(BaseModel):
|
class RegexModel(BaseModel):
|
||||||
@@ -254,6 +269,7 @@ async def regex_delete(regex_id: int, auth: bool = Depends(is_loggined)):
|
|||||||
if len(res) != 0:
|
if len(res) != 0:
|
||||||
db.query('DELETE FROM regexes WHERE regex_id = ?;', regex_id)
|
db.query('DELETE FROM regexes WHERE regex_id = ?;', regex_id)
|
||||||
await firewall.get(res[0]["service_port"]).update_filters()
|
await firewall.get(res[0]["service_port"]).update_filters()
|
||||||
|
await refresh_frontend()
|
||||||
|
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
|
|
||||||
@@ -264,6 +280,7 @@ async def regex_enable(regex_id: int, auth: bool = Depends(is_loggined)):
|
|||||||
if len(res) != 0:
|
if len(res) != 0:
|
||||||
db.query('UPDATE regexes SET active=1 WHERE regex_id = ?;', regex_id)
|
db.query('UPDATE regexes SET active=1 WHERE regex_id = ?;', regex_id)
|
||||||
await firewall.get(res[0]["service_port"]).update_filters()
|
await firewall.get(res[0]["service_port"]).update_filters()
|
||||||
|
await refresh_frontend()
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
|
|
||||||
@app.get('/api/regex/{regex_id}/disable', response_model=StatusMessageModel)
|
@app.get('/api/regex/{regex_id}/disable', response_model=StatusMessageModel)
|
||||||
@@ -273,6 +290,7 @@ async def regex_disable(regex_id: int, auth: bool = Depends(is_loggined)):
|
|||||||
if len(res) != 0:
|
if len(res) != 0:
|
||||||
db.query('UPDATE regexes SET active=0 WHERE regex_id = ?;', regex_id)
|
db.query('UPDATE regexes SET active=0 WHERE regex_id = ?;', regex_id)
|
||||||
await firewall.get(res[0]["service_port"]).update_filters()
|
await firewall.get(res[0]["service_port"]).update_filters()
|
||||||
|
await refresh_frontend()
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
|
|
||||||
class RegexAddForm(BaseModel):
|
class RegexAddForm(BaseModel):
|
||||||
@@ -297,6 +315,7 @@ async def add_new_regex(form: RegexAddForm, auth: bool = Depends(is_loggined)):
|
|||||||
return {'status': 'An identical regex already exists'}
|
return {'status': 'An identical regex already exists'}
|
||||||
|
|
||||||
await firewall.get(form.service_port).update_filters()
|
await firewall.get(form.service_port).update_filters()
|
||||||
|
await refresh_frontend()
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
|
|
||||||
class ServiceAddForm(BaseModel):
|
class ServiceAddForm(BaseModel):
|
||||||
@@ -312,6 +331,7 @@ async def add_new_service(form: ServiceAddForm, auth: bool = Depends(is_loggined
|
|||||||
except sqlite3.IntegrityError:
|
except sqlite3.IntegrityError:
|
||||||
return {'status': 'Name or/and ports of the service has been already assigned to another service'}
|
return {'status': 'Name or/and ports of the service has been already assigned to another service'}
|
||||||
await firewall.reload()
|
await firewall.reload()
|
||||||
|
await refresh_frontend()
|
||||||
|
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ passlib[bcrypt]
|
|||||||
python-jose[cryptography]
|
python-jose[cryptography]
|
||||||
NetfilterQueue
|
NetfilterQueue
|
||||||
scapy
|
scapy
|
||||||
python-pcre
|
python-pcre
|
||||||
|
fastapi-socketio
|
||||||
@@ -177,9 +177,9 @@ class ProxyManager:
|
|||||||
self.lock = asyncio.Lock()
|
self.lock = asyncio.Lock()
|
||||||
self.updater_task = None
|
self.updater_task = None
|
||||||
|
|
||||||
def init_updater(self):
|
def init_updater(self, callback = None):
|
||||||
if not self.updater_task:
|
if not self.updater_task:
|
||||||
self.updater_task = asyncio.create_task(self._stats_updater())
|
self.updater_task = asyncio.create_task(self._stats_updater(callback))
|
||||||
|
|
||||||
def close_updater(self):
|
def close_updater(self):
|
||||||
if self.updater_task: self.updater_task.cancel()
|
if self.updater_task: self.updater_task.cancel()
|
||||||
@@ -196,11 +196,11 @@ class ProxyManager:
|
|||||||
await self.proxy_table[port].next(STATUS.STOP)
|
await self.proxy_table[port].next(STATUS.STOP)
|
||||||
del self.proxy_table[port]
|
del self.proxy_table[port]
|
||||||
|
|
||||||
async def init(self):
|
async def init(self, callback = None):
|
||||||
|
self.init_updater(callback)
|
||||||
await self.reload()
|
await self.reload()
|
||||||
|
|
||||||
async def reload(self):
|
async def reload(self):
|
||||||
self.init_updater()
|
|
||||||
async with self.lock:
|
async with self.lock:
|
||||||
for srv in self.db.query('SELECT port, status FROM services;'):
|
for srv in self.db.query('SELECT port, status FROM services;'):
|
||||||
srv_port, req_status = srv["port"], srv["status"]
|
srv_port, req_status = srv["port"], srv["status"]
|
||||||
@@ -210,7 +210,7 @@ class ProxyManager:
|
|||||||
self.proxy_table[srv_port] = ServiceManager(srv_port,self.db)
|
self.proxy_table[srv_port] = ServiceManager(srv_port,self.db)
|
||||||
await self.proxy_table[srv_port].next(req_status)
|
await self.proxy_table[srv_port].next(req_status)
|
||||||
|
|
||||||
async def _stats_updater(self):
|
async def _stats_updater(self, callback):
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@@ -218,7 +218,10 @@ class ProxyManager:
|
|||||||
self.proxy_table[key].update_stats()
|
self.proxy_table[key].update_stats()
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
await asyncio.sleep(1)
|
if callback:
|
||||||
|
if asyncio.iscoroutinefunction(callback): await callback()
|
||||||
|
else: callback()
|
||||||
|
await asyncio.sleep(5)
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
self.updater_task = None
|
self.updater_task = None
|
||||||
return
|
return
|
||||||
|
|||||||
135
frontend/package-lock.json
generated
135
frontend/package-lock.json
generated
@@ -29,6 +29,7 @@
|
|||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"sass": "^1.52.3",
|
"sass": "^1.52.3",
|
||||||
|
"socket.io-client": "^4.5.1",
|
||||||
"typescript": "^4.7.3",
|
"typescript": "^4.7.3",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
}
|
}
|
||||||
@@ -3164,6 +3165,11 @@
|
|||||||
"@sinonjs/commons": "^1.7.0"
|
"@sinonjs/commons": "^1.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@socket.io/component-emitter": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||||
|
},
|
||||||
"node_modules/@surma/rollup-plugin-off-main-thread": {
|
"node_modules/@surma/rollup-plugin-off-main-thread": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
||||||
@@ -6403,6 +6409,46 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/engine.io-client": {
|
||||||
|
"version": "6.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz",
|
||||||
|
"integrity": "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1",
|
||||||
|
"engine.io-parser": "~5.0.3",
|
||||||
|
"ws": "~8.2.3",
|
||||||
|
"xmlhttprequest-ssl": "~2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/engine.io-client/node_modules/ws": {
|
||||||
|
"version": "8.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
|
||||||
|
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": "^5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/engine.io-parser": {
|
||||||
|
"version": "5.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
|
||||||
|
"integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
"node_modules/enhanced-resolve": {
|
||||||
"version": "5.9.3",
|
"version": "5.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
|
||||||
@@ -13217,6 +13263,32 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/socket.io-client": {
|
||||||
|
"version": "4.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz",
|
||||||
|
"integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.2",
|
||||||
|
"engine.io-client": "~6.2.1",
|
||||||
|
"socket.io-parser": "~4.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/socket.io-parser": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/sockjs": {
|
"node_modules/sockjs": {
|
||||||
"version": "0.3.24",
|
"version": "0.3.24",
|
||||||
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
|
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
|
||||||
@@ -15144,6 +15216,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
|
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/xmlhttprequest-ssl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xtend": {
|
"node_modules/xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
@@ -17365,6 +17445,11 @@
|
|||||||
"@sinonjs/commons": "^1.7.0"
|
"@sinonjs/commons": "^1.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@socket.io/component-emitter": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||||
|
},
|
||||||
"@surma/rollup-plugin-off-main-thread": {
|
"@surma/rollup-plugin-off-main-thread": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
||||||
@@ -19740,6 +19825,31 @@
|
|||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
|
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
|
||||||
},
|
},
|
||||||
|
"engine.io-client": {
|
||||||
|
"version": "6.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz",
|
||||||
|
"integrity": "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==",
|
||||||
|
"requires": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1",
|
||||||
|
"engine.io-parser": "~5.0.3",
|
||||||
|
"ws": "~8.2.3",
|
||||||
|
"xmlhttprequest-ssl": "~2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ws": {
|
||||||
|
"version": "8.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
|
||||||
|
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
|
||||||
|
"requires": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine.io-parser": {
|
||||||
|
"version": "5.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
|
||||||
|
"integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg=="
|
||||||
|
},
|
||||||
"enhanced-resolve": {
|
"enhanced-resolve": {
|
||||||
"version": "5.9.3",
|
"version": "5.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
|
||||||
@@ -24538,6 +24648,26 @@
|
|||||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||||
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="
|
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="
|
||||||
},
|
},
|
||||||
|
"socket.io-client": {
|
||||||
|
"version": "4.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz",
|
||||||
|
"integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==",
|
||||||
|
"requires": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.2",
|
||||||
|
"engine.io-client": "~6.2.1",
|
||||||
|
"socket.io-parser": "~4.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"socket.io-parser": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
|
||||||
|
"requires": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"sockjs": {
|
"sockjs": {
|
||||||
"version": "0.3.24",
|
"version": "0.3.24",
|
||||||
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
|
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
|
||||||
@@ -26008,6 +26138,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
|
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
|
||||||
},
|
},
|
||||||
|
"xmlhttprequest-ssl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A=="
|
||||||
|
},
|
||||||
"xtend": {
|
"xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"sass": "^1.52.3",
|
"sass": "^1.52.3",
|
||||||
|
"socket.io-client": "^4.5.1",
|
||||||
"typescript": "^4.7.3",
|
"typescript": "^4.7.3",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,9 +5,12 @@ import { ImCross } from 'react-icons/im';
|
|||||||
import { Navigate, Outlet, Route, Routes } from 'react-router-dom';
|
import { Navigate, Outlet, Route, Routes } from 'react-router-dom';
|
||||||
import MainLayout from './components/MainLayout';
|
import MainLayout from './components/MainLayout';
|
||||||
import { PasswordSend, ServerStatusResponse } from './js/models';
|
import { PasswordSend, ServerStatusResponse } from './js/models';
|
||||||
import { fireUpdateRequest, getstatus, login, setpassword } from './js/utils';
|
import { errorNotify, fireUpdateRequest, getstatus, login, setpassword } from './js/utils';
|
||||||
import HomePage from './pages/HomePage';
|
import HomePage from './pages/HomePage';
|
||||||
import ServiceDetails from './pages/ServiceDetails';
|
import ServiceDetails from './pages/ServiceDetails';
|
||||||
|
import io from 'socket.io-client';
|
||||||
|
|
||||||
|
const socket = io({transports: ["websocket", "polling"], path:"/sock" });
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
@@ -29,11 +32,19 @@ function App() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(getStatus,[])
|
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
const updater = setInterval(fireUpdateRequest,2000)
|
getStatus()
|
||||||
return () => clearInterval(updater)
|
socket.on("update", () => {
|
||||||
|
fireUpdateRequest()
|
||||||
|
})
|
||||||
|
socket.on("connect_error", (err) => {
|
||||||
|
errorNotify("Socket.Io connection failed! ",`Error message: [${err.message}]`)
|
||||||
|
getStatus()
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
socket.off("update")
|
||||||
|
socket.off("connect_error")
|
||||||
|
}
|
||||||
},[])
|
},[])
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Button, Group, Space, TextInput, Notification, Switch, NativeSelect, Mo
|
|||||||
import { useForm } from '@mantine/hooks';
|
import { useForm } from '@mantine/hooks';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { RegexAddForm } from '../js/models';
|
import { RegexAddForm } from '../js/models';
|
||||||
import { addregex, b64decode, b64encode, fireUpdateRequest, okNotify } from '../js/utils';
|
import { addregex, b64decode, b64encode, okNotify } from '../js/utils';
|
||||||
import { ImCross } from "react-icons/im"
|
import { ImCross } from "react-icons/im"
|
||||||
import FilterTypeSelector from './FilterTypeSelector';
|
import FilterTypeSelector from './FilterTypeSelector';
|
||||||
|
|
||||||
@@ -58,7 +58,6 @@ function AddNewRegex({ opened, onClose, service }:{ opened:boolean, onClose:()=>
|
|||||||
if (!res){
|
if (!res){
|
||||||
setSubmitLoading(false)
|
setSubmitLoading(false)
|
||||||
close();
|
close();
|
||||||
fireUpdateRequest();
|
|
||||||
okNotify(`Regex ${b64decode(request.regex)} has been added`, `Successfully added ${request.is_case_sensitive?"case sensitive":"case insensitive"} ${request.is_blacklist?"blacklist":"whitelist"} regex to ${request.service_port} service`)
|
okNotify(`Regex ${b64decode(request.regex)} has been added`, `Successfully added ${request.is_case_sensitive?"case sensitive":"case insensitive"} ${request.is_blacklist?"blacklist":"whitelist"} regex to ${request.service_port} service`)
|
||||||
}else if (res.toLowerCase() === "invalid regex"){
|
}else if (res.toLowerCase() === "invalid regex"){
|
||||||
setSubmitLoading(false)
|
setSubmitLoading(false)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Button, Group, NumberInput, Space, TextInput, Notification, Modal, Switch } 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 { addservice, fireUpdateRequest, okNotify, startservice } from '../js/utils';
|
import { addservice, okNotify, startservice } from '../js/utils';
|
||||||
import { ImCross } from "react-icons/im"
|
import { ImCross } from "react-icons/im"
|
||||||
|
|
||||||
type ServiceAddForm = {
|
type ServiceAddForm = {
|
||||||
@@ -39,7 +39,6 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void })
|
|||||||
if (res.status === "ok"){
|
if (res.status === "ok"){
|
||||||
setSubmitLoading(false)
|
setSubmitLoading(false)
|
||||||
close();
|
close();
|
||||||
fireUpdateRequest();
|
|
||||||
if (autostart) startservice(port)
|
if (autostart) startservice(port)
|
||||||
okNotify(`Service ${name} has been added`, `Successfully added service with port ${port}`)
|
okNotify(`Service ${name} has been added`, `Successfully added service with port ${port}`)
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Grid, Text, Title, Badge, Space, ActionIcon, Tooltip } from '@mantine/core';
|
import { Grid, Text, Title, Badge, Space, ActionIcon, Tooltip } from '@mantine/core';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { RegexFilter } from '../../js/models';
|
import { RegexFilter } from '../../js/models';
|
||||||
import { activateregex, b64decode, deactivateregex, deleteregex, errorNotify, fireUpdateRequest, okNotify } from '../../js/utils';
|
import { activateregex, b64decode, deactivateregex, deleteregex, errorNotify, okNotify } from '../../js/utils';
|
||||||
import style from "./index.module.scss";
|
import style from "./index.module.scss";
|
||||||
import { BsTrashFill } from "react-icons/bs"
|
import { BsTrashFill } from "react-icons/bs"
|
||||||
import YesNoModal from '../YesNoModal';
|
import YesNoModal from '../YesNoModal';
|
||||||
@@ -25,7 +25,6 @@ function RegexView({ regexInfo }:{ regexInfo:RegexFilter }) {
|
|||||||
deleteregex(regexInfo.id).then(res => {
|
deleteregex(regexInfo.id).then(res => {
|
||||||
if(!res){
|
if(!res){
|
||||||
okNotify(`Regex ${regex_expr} deleted successfully!`,`Regex '${regex_expr}' ID:${regexInfo.id} has been deleted!`)
|
okNotify(`Regex ${regex_expr} deleted successfully!`,`Regex '${regex_expr}' ID:${regexInfo.id} has been deleted!`)
|
||||||
fireUpdateRequest()
|
|
||||||
}else{
|
}else{
|
||||||
errorNotify(`Regex ${regex_expr} deleation failed!`,`Error: ${res}`)
|
errorNotify(`Regex ${regex_expr} deleation failed!`,`Error: ${res}`)
|
||||||
}
|
}
|
||||||
@@ -37,7 +36,6 @@ function RegexView({ regexInfo }:{ regexInfo:RegexFilter }) {
|
|||||||
(regexInfo.active?deactivateregex:activateregex)(regexInfo.id).then(res => {
|
(regexInfo.active?deactivateregex:activateregex)(regexInfo.id).then(res => {
|
||||||
if(!res){
|
if(!res){
|
||||||
okNotify(`Regex ${regex_expr} ${regexInfo.active?"deactivated":"activated"} successfully!`,`Regex '${regex_expr}' ID:${regexInfo.id} has been ${regexInfo.active?"deactivated":"activated"}!`)
|
okNotify(`Regex ${regex_expr} ${regexInfo.active?"deactivated":"activated"} successfully!`,`Regex '${regex_expr}' ID:${regexInfo.id} has been ${regexInfo.active?"deactivated":"activated"}!`)
|
||||||
fireUpdateRequest()
|
|
||||||
}else{
|
}else{
|
||||||
errorNotify(`Regex ${regex_expr} ${regexInfo.active?"deactivation":"activation"} failed!`,`Error: ${res}`)
|
errorNotify(`Regex ${regex_expr} ${regexInfo.active?"deactivation":"activation"} failed!`,`Error: ${res}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Button, Group, Space, TextInput, Notification, Modal } from '@mantine/core';
|
import { Button, Group, Space, TextInput, Notification, Modal } from '@mantine/core';
|
||||||
import { useForm } from '@mantine/hooks';
|
import { useForm } from '@mantine/hooks';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { fireUpdateRequest, okNotify, renameservice } from '../../js/utils';
|
import { okNotify, renameservice } from '../../js/utils';
|
||||||
import { ImCross } from "react-icons/im"
|
import { ImCross } from "react-icons/im"
|
||||||
import { Service } from '../../js/models';
|
import { Service } from '../../js/models';
|
||||||
|
|
||||||
@@ -29,7 +29,6 @@ function RenameForm({ opened, onClose, service }:{ opened:boolean, onClose:()=>v
|
|||||||
if (!res){
|
if (!res){
|
||||||
setSubmitLoading(false)
|
setSubmitLoading(false)
|
||||||
close();
|
close();
|
||||||
fireUpdateRequest();
|
|
||||||
okNotify(`Service ${service.name} has been renamed in ${ name }`, `Successfully renamed service on port ${service.port}`)
|
okNotify(`Service ${service.name} has been renamed in ${ name }`, `Successfully renamed service on port ${service.port}`)
|
||||||
}else{
|
}else{
|
||||||
setSubmitLoading(false)
|
setSubmitLoading(false)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Service } from '../../js/models';
|
|||||||
import { MdOutlineArrowForwardIos } from "react-icons/md"
|
import { MdOutlineArrowForwardIos } from "react-icons/md"
|
||||||
import style from "./index.module.scss";
|
import style from "./index.module.scss";
|
||||||
import YesNoModal from '../YesNoModal';
|
import YesNoModal from '../YesNoModal';
|
||||||
import { deleteservice, errorNotify, fireUpdateRequest, okNotify, startservice, stopservice } from '../../js/utils';
|
import { deleteservice, errorNotify, okNotify, startservice, stopservice } from '../../js/utils';
|
||||||
import { BsTrashFill } from 'react-icons/bs';
|
import { BsTrashFill } from 'react-icons/bs';
|
||||||
import { BiRename } from 'react-icons/bi'
|
import { BiRename } from 'react-icons/bi'
|
||||||
import RenameForm from './RenameForm';
|
import RenameForm from './RenameForm';
|
||||||
@@ -28,7 +28,6 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
|
|||||||
await stopservice(service.port).then(res => {
|
await stopservice(service.port).then(res => {
|
||||||
if(!res){
|
if(!res){
|
||||||
okNotify(`Service ${service.name} stopped successfully!`,`The service on ${service.port} has been stopped!`)
|
okNotify(`Service ${service.name} stopped successfully!`,`The service on ${service.port} has been stopped!`)
|
||||||
fireUpdateRequest();
|
|
||||||
}else{
|
}else{
|
||||||
errorNotify(`An error as occurred during the stopping of the service ${service.port}`,`Error: ${res}`)
|
errorNotify(`An error as occurred during the stopping of the service ${service.port}`,`Error: ${res}`)
|
||||||
}
|
}
|
||||||
@@ -43,7 +42,6 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
|
|||||||
await startservice(service.port).then(res => {
|
await startservice(service.port).then(res => {
|
||||||
if(!res){
|
if(!res){
|
||||||
okNotify(`Service ${service.name} started successfully!`,`The service on ${service.port} has been started!`)
|
okNotify(`Service ${service.name} started successfully!`,`The service on ${service.port} has been started!`)
|
||||||
fireUpdateRequest();
|
|
||||||
}else{
|
}else{
|
||||||
errorNotify(`An error as occurred during the starting of the service ${service.port}`,`Error: ${res}`)
|
errorNotify(`An error as occurred during the starting of the service ${service.port}`,`Error: ${res}`)
|
||||||
}
|
}
|
||||||
@@ -57,7 +55,6 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
|
|||||||
deleteservice(service.port).then(res => {
|
deleteservice(service.port).then(res => {
|
||||||
if (!res){
|
if (!res){
|
||||||
okNotify("Service delete complete!",`The service ${service.name} has been deleted!`)
|
okNotify("Service delete complete!",`The service ${service.name} has been deleted!`)
|
||||||
fireUpdateRequest();
|
|
||||||
}else
|
}else
|
||||||
errorNotify("An error occurred while deleting a service",`Error: ${res}`)
|
errorNotify("An error occurred while deleting a service",`Error: ${res}`)
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
|
|||||||
Reference in New Issue
Block a user