1
0
mirror of https://github.com/AR2000AR/openComputers_codes.git synced 2025-09-08 06:31:14 +02:00

[icable_server] massive refactoring of python module

This commit is contained in:
2023-08-11 16:15:37 +02:00
parent 32958139be
commit cd236541d9
7 changed files with 67 additions and 90 deletions

View File

@@ -13,6 +13,7 @@ from pathlib import Path
from signal import SIGINT, SIGTERM, signal
from string import Template
from urllib.parse import parse_qs
import pathlib
import models.database
import models.firewall
@@ -23,7 +24,10 @@ from icable.firewall import *
from icable.packet import *
from icable.protocol import *
db = models.database.DatabaseHandler('icable.db')
dataPath = pathlib.Path(pathlib.Path.home(),'.local','share','icable')
dataPath.mkdir(parents=True,exist_ok=True)
db = models.database.DatabaseHandler(pathlib.Path(dataPath,'icable.db'))
users = models.user.Users(db)
webSessions = models.web.WebSessions(db)
networks = models.network.Networks(db)
@@ -340,7 +344,7 @@ class WebInterface(BaseHTTPRequestHandler):
user_networks.sort()
for network in user_networks:
dl_button = ""
if(self.user.get_network_permission(network)==1 or models.user.User.SubnetworkPermission.OWNER in self.user.subnetwork_permission):
if(self.user.get_network_permission(network)==1 or models.user.SubnetworkPermission.OWNER in self.user.subnetwork_permission):
dl_button = f"""<form action='/network' method='post'>
<input class='ip-cell' type='submit' value='Delete'>
<input class='ip-cell' type='hidden' name='cmd' value='delete'>
@@ -357,7 +361,7 @@ class WebInterface(BaseHTTPRequestHandler):
#region firewall
mapping['firewallDefault']=firewalls[self.user.subnetid].action.name
FIREWALL_ALLOWED = models.user.User.SubnetworkPermission.FIREWALL|models.user.User.SubnetworkPermission.OWNER
FIREWALL_ALLOWED = models.user.SubnetworkPermission.FIREWALL|models.user.SubnetworkPermission.OWNER
mapping['firewallRuleList']=""
for rule in firewalls[self.user.subnetid].rules:

View File

@@ -1,4 +1,5 @@
from . import database
from sqlite3 import Cursor
__all__ = ["user","network","firewall","web","database"]
@@ -6,4 +7,4 @@ class Model():
"""Abstract class for data model calss"""
def __init__(self,database:database.DatabaseHandler):
self._database = database
self._database = database

View File

@@ -2,16 +2,12 @@ import threading
import pathlib
import sqlite3
class DatabaseHandler():
class DatabaseHandler(sqlite3.Connection):
def __init__(self,dbPath:str):
self._semaphore = threading.BoundedSemaphore()
dataPath = pathlib.Path(pathlib.Path.home(),'.local','share','icable')
dataPath.mkdir(parents=True,exist_ok=True)
self._database = sqlite3.connect(pathlib.Path(dataPath,dbPath),check_same_thread=False,detect_types=sqlite3.PARSE_DECLTYPES)
def __init__(self,*args,**kwargs):
super().__init__(*args,check_same_thread=False,detect_types=sqlite3.PARSE_DECLTYPES,**kwargs)
#self._database.row_factory = Row
self._cursor = self._database.cursor()
self._cursor.executescript("""
self.executescript("""
BEGIN;
CREATE TABLE IF NOT EXISTS "users" (
login TEXT PRIMARY KEY CHECK(typeof("login") = 'text'),
@@ -46,28 +42,9 @@ class DatabaseHandler():
END;
COMMIT;
PRAGMA foreign_keys=ON;""")
def execute(self,*args,**kwargs):
return self._cursor.execute(*args,**kwargs)
def fetchone(self,*args,**kwargs):
return self._cursor.fetchone(*args,**kwargs)
def fetchall(self,*args,**kwargs):
return self._cursor.fetchall(*args,**kwargs)
def fetchmany(self,*args,**kwargs):
return self._cursor.fetchmany(*args,**kwargs)
def commit(self,*args,**kwargs):
return self.database.commit()
@property
def semaphore(self)->threading.BoundedSemaphore:
return self._semaphore
@property
def database(self):
return self._database
def __del__(self):
self._cursor.execute("PRAGMA optimize;")
self.database.commit()
self._cursor.close()
self.database.close()
self.rollback()
self.execute("PRAGMA optimize;")
self.commit()
self.close()

View File

@@ -4,13 +4,12 @@ from icable.firewall import Firewall
class Firewalls(Model):
def __getitem__(self,key:int):
self._database.execute("SELECT pickle FROM firewall WHERE subnetid = ?",(key,))
res=self._database.fetchone()
cursor=self._database.execute("SELECT pickle FROM firewall WHERE subnetid = ?",(key,))
res=cursor.fetchone()
if(not res):
return Firewall()
return res[0]
def __setitem__(self,key:int,firewall:Firewall):
with self._database.semaphore:
self._database.execute("INSERT OR REPLACE INTO firewall VALUES(?,?)",(key,firewall))
self._database.commit()
self._database.execute("INSERT OR REPLACE INTO firewall VALUES(?,?)",(key,firewall))
self._database.commit()

View File

@@ -30,37 +30,35 @@ class Network():
class Networks(Model):
def getNetworkById(self,id:int):
self._database.execute("SELECT subnetid,network,nmask FROM networks WHERE id = ?",(id,))
res = self._database.fetchone()
cursor=self._database.execute("SELECT subnetid,network,nmask FROM networks WHERE id = ?",(id,))
res = cursor.fetchone()
if(not res):
return False
return Network(id,res[0],ipaddress.ip_network((res[1],ipaddress.ip_address(res[2]).compressed)))
def getNetworksInSubnet(self,subnetid:int):
self._database.execute("SELECT id,subnetid,network,nmask FROM networks WHERE subnetid = ?",(subnetid,))
res = self._database.fetchall()
cursor=self._database.execute("SELECT id,subnetid,network,nmask FROM networks WHERE subnetid = ?",(subnetid,))
res = cursor.fetchall()
if(not res):
return list[Network]()
return [Network(net[0],subnetid,ipaddress.ip_network(net[2],ipaddress.ip_address(net[3]).compressed))for net in res]
def getAllNetworks(self):
self._database.execute("SELECT id,subnetid,network,nmask FROM networks")
res = self._database.fetchall()
cursor=self._database.execute("SELECT id,subnetid,network,nmask FROM networks")
res = cursor.fetchall()
if(not res):
return list[Network]()
return [Network(net[0],net[1],ipaddress.ip_network((net[2],ipaddress.ip_address(net[3]).compressed)))for net in res]
def createNetwork(self,subnetwork:int,network:ipaddress.IPv4Network) :
with self._database.semaphore:
self._database.execute("INSERT INTO networks(subnetid,network,nmask) VALUES(?,?,?)",(subnetwork,int(network.network_address),int(network.netmask)))
self._database.commit()
self._database.execute("SELECT id from networks WHERE subnetid = ? AND network = ? and nmask = ?",(subnetwork,int(network.network_address),int(network.netmask)))
res = self._database.fetchone()
self._database.execute("INSERT INTO networks(subnetid,network,nmask) VALUES(?,?,?)",(subnetwork,int(network.network_address),int(network.netmask)))
self._database.commit()
cursor=self._database.execute("SELECT id from networks WHERE subnetid = ? AND network = ? and nmask = ?",(subnetwork,int(network.network_address),int(network.netmask)))
res = cursor.fetchone()
nt = self.getNetworkById(res[0])
assert(isinstance(nt,Network))
return nt
def deleteNetwork(self,network:Network):
with self._database.semaphore:
self._database.execute("DELETE FROM networks WHERE id = ?",(network.id,))
self._database.commit()
self._database.execute("DELETE FROM networks WHERE id = ?",(network.id,))
self._database.commit()

View File

@@ -20,12 +20,11 @@ class User(Model):
@property
def password(self)->str:
self._database.execute("SELECT password FROM users WHERE login = ?",(self.login,))
return self._database.fetchone()[0]
cursor=self._database.execute("SELECT password FROM users WHERE login = ?",(self.login,))
return cursor.fetchone()[0]
@password.setter
def password(self,value:str):
with self._database.semaphore:
self._database.execute("UPDATE users SET password = ? WHERE login = ?",(self.hashpassword(value),self.login))
self._database.commit()
@@ -72,12 +71,11 @@ class User(Model):
@property
def subnetid(self):
self._database.execute("SELECT subnetid FROM users WHERE login = ?",(self.login,))
return self._database.fetchone()[0]
cursor=self._database.execute("SELECT subnetid FROM users WHERE login = ?",(self.login,))
return cursor.fetchone()[0]
@subnetid.setter
def subnetid(self,value):
with self._database.semaphore:
self._database.execute("UPDATE users SET subnetid = ? WHERE login = ?",(value,self.login))
self._database.commit()
@@ -87,9 +85,9 @@ class User(Model):
@property
def networks(self)->list[Network]:
self._database.execute("""SELECT id from networks WHERE id IN
cursor=self._database.execute("""SELECT id from networks WHERE id IN
(SELECT networkid FROM networkUsers WHERE userid = ? OR subnetid = ?);""",(self.login,self.subnetid))
networks = self._database.fetchall()
networks = cursor.fetchall()
networksDB = Networks(self._database)
return [networksDB.getNetworkById(res[0]) for res in networks]
@@ -98,8 +96,8 @@ class User(Model):
self._database.commit()
def get_network_permission(self,net:Network)->int:
self._database.execute("SELECT permissions FROM networkUsers WHERE userid = ? AND networkid = ?",(self.login,net.id))
perm = self._database.fetchone()
cursor=self._database.execute("SELECT permissions FROM networkUsers WHERE userid = ? AND networkid = ?",(self.login,net.id))
perm = cursor.fetchone()
if(not perm):
return 0
else:
@@ -107,28 +105,32 @@ class User(Model):
@property
def subnetwork_permission(self)->SubnetworkPermission:
self._database.execute("SELECT subnetperm FROM users WHERE login = ?",(self.login,))
res = self._database.fetchone()
cursor=self._database.execute("SELECT subnetperm FROM users WHERE login = ?",(self.login,))
res = cursor.fetchone()
assert(res)
return SubnetworkPermission(res[0])
class Users():
class Users(Model):
def __init__(self,database_handler:DatabaseHandler):
self._database = database_handler
self._database.execute("SELECT * FROM users LIMIT 1")
if(self._database.fetchone()==None):
super().__init__(database_handler)
self.initUsers()
def initUsers(self):
cursor=self._database.execute("SELECT * FROM users LIMIT 1")
if(cursor.fetchone()==None):
self.createUser('admin','admin')
def getUserFromLogin(self,login:str):
self._database.execute("SELECT * FROM users WHERE login = ?",(login,))
if(self._database.fetchone()):
cursor=self._database.execute("SELECT * FROM users WHERE login = ?",(login,))
if(cursor.fetchone()):
return User(self._database,login)
else:
return False
def get_users_in_subnet(self,subnetid:int):
self._database.execute("SELECT login FROM users WHERE subnetid = ?",(subnetid,))
return [self.getUserFromLogin(res[0]) for res in self._database.fetchall()]
cursor=self._database.execute("SELECT login FROM users WHERE subnetid = ?",(subnetid,))
return [self.getUserFromLogin(res[0]) for res in cursor.fetchall()]
def createUser(self,login:str,password:str,subnetid=None):
if(self.getUserFromLogin(login)):
@@ -139,15 +141,13 @@ class Users():
subnetid = random.getrandbits(32)
subnetperm |= SubnetworkPermission.OWNER
#TODO : make sure subnetid is uniq
with self._database.semaphore:
self._database.execute("INSERT INTO users VALUES(?,?,?,?)",(login,User.hashpassword(password),subnetid,int(subnetperm)))
self._database.commit()
cursor=self._database.execute("INSERT INTO users VALUES(?,?,?,?)",(login,User.hashpassword(password),subnetid,int(subnetperm)))
self._database.commit()
return self.getUserFromLogin(login)
def deleteUser(self,user:User):
subnetwork = user.subnetid
with self._database.semaphore:
self._database.execute("DELETE FROM users WHERE login = ?",(user.login,))
if(not self._database.execute("SELECT * FROM users WHERE subnetid = ?",(subnetwork,)).fetchall()):
self._database.execute("DELETE FROM networks WHERE subnetid = ?",(subnetwork,))
self._database.commit()
self._database.execute("DELETE FROM users WHERE login = ?",(user.login,))
if(not self._database.execute("SELECT * FROM users WHERE subnetid = ?",(subnetwork,)).fetchall()):
self._database.execute("DELETE FROM networks WHERE subnetid = ?",(subnetwork,))
self._database.commit()

View File

@@ -6,8 +6,8 @@ class WebSessions(Model):
def getSession(self,sid:int):
"""Return the user the session belong to or False"""
self._database.execute("SELECT sid,login FROM sessions WHERE sid = ?",(sid,))
res = self._database.fetchone()
cursor=self._database.execute("SELECT sid,login FROM sessions WHERE sid = ?",(sid,))
res = cursor.fetchone()
if(res):
return Users(self._database).getUserFromLogin(res[1])
else:
@@ -16,12 +16,10 @@ class WebSessions(Model):
def createSession(self,user:User):
"""Create a session for the user. Return the session id"""
sid = getrandbits(32)
with self._database.semaphore:
self._database.execute("INSERT INTO sessions VALUES (?,?)",(sid,user.login))
self._database.commit()
self._database.execute("INSERT INTO sessions VALUES (?,?)",(sid,user.login))
self._database.commit()
return sid
def deleteSession(self,sid:int):
with self._database.semaphore:
self._database.execute("DELETE FROM sessions WHERE sid = ?",(sid,))
self._database.commit()
self._database.execute("DELETE FROM sessions WHERE sid = ?",(sid,))
self._database.commit()