1
0
mirror of https://github.com/AR2000AR/openComputers_codes.git synced 2025-09-08 22:51: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 signal import SIGINT, SIGTERM, signal
from string import Template from string import Template
from urllib.parse import parse_qs from urllib.parse import parse_qs
import pathlib
import models.database import models.database
import models.firewall import models.firewall
@@ -23,7 +24,10 @@ from icable.firewall import *
from icable.packet import * from icable.packet import *
from icable.protocol 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) users = models.user.Users(db)
webSessions = models.web.WebSessions(db) webSessions = models.web.WebSessions(db)
networks = models.network.Networks(db) networks = models.network.Networks(db)
@@ -340,7 +344,7 @@ class WebInterface(BaseHTTPRequestHandler):
user_networks.sort() user_networks.sort()
for network in user_networks: for network in user_networks:
dl_button = "" 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'> dl_button = f"""<form action='/network' method='post'>
<input class='ip-cell' type='submit' value='Delete'> <input class='ip-cell' type='submit' value='Delete'>
<input class='ip-cell' type='hidden' name='cmd' value='delete'> <input class='ip-cell' type='hidden' name='cmd' value='delete'>
@@ -357,7 +361,7 @@ class WebInterface(BaseHTTPRequestHandler):
#region firewall #region firewall
mapping['firewallDefault']=firewalls[self.user.subnetid].action.name 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']="" mapping['firewallRuleList']=""
for rule in firewalls[self.user.subnetid].rules: for rule in firewalls[self.user.subnetid].rules:

View File

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

View File

@@ -2,16 +2,12 @@ import threading
import pathlib import pathlib
import sqlite3 import sqlite3
class DatabaseHandler(): class DatabaseHandler(sqlite3.Connection):
def __init__(self,dbPath:str): def __init__(self,*args,**kwargs):
self._semaphore = threading.BoundedSemaphore() super().__init__(*args,check_same_thread=False,detect_types=sqlite3.PARSE_DECLTYPES,**kwargs)
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)
#self._database.row_factory = Row #self._database.row_factory = Row
self._cursor = self._database.cursor() self.executescript("""
self._cursor.executescript("""
BEGIN; BEGIN;
CREATE TABLE IF NOT EXISTS "users" ( CREATE TABLE IF NOT EXISTS "users" (
login TEXT PRIMARY KEY CHECK(typeof("login") = 'text'), login TEXT PRIMARY KEY CHECK(typeof("login") = 'text'),
@@ -46,28 +42,9 @@ class DatabaseHandler():
END; END;
COMMIT; COMMIT;
PRAGMA foreign_keys=ON;""") 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): def __del__(self):
self._cursor.execute("PRAGMA optimize;") self.rollback()
self.database.commit() self.execute("PRAGMA optimize;")
self._cursor.close() self.commit()
self.database.close() self.close()

View File

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

View File

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

View File

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

View File

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