From c3bd73a068c91142618155e0849ddffdc45acf08 Mon Sep 17 00:00:00 2001 From: Michael Rodin Date: Thu, 19 Oct 2023 13:25:59 +0200 Subject: [PATCH] Adding archives Added functionality to add archives. --- ER-rar-index.graphml | 91 ++++++++++++++++++++++++++++++-------- flask/app.py | 93 ++++++++++++++++++++++++--------------- flask/func.py | 40 ++++++++++++++--- flask/static/add.css | 4 ++ flask/static/base.css | 10 +++++ flask/templates/add.html | 34 ++++++++++++++ flask/templates/base.html | 1 + 7 files changed, 212 insertions(+), 61 deletions(-) create mode 100644 flask/static/add.css create mode 100644 flask/templates/add.html diff --git a/ER-rar-index.graphml b/ER-rar-index.graphml index 6ed562a..5d25a36 100644 --- a/ER-rar-index.graphml +++ b/ER-rar-index.graphml @@ -36,10 +36,12 @@ - - - - + + + + + + @@ -135,7 +137,6 @@ ID LABEL - CATEGORY TYPE @@ -165,7 +166,7 @@ - + ArchLab @@ -253,7 +254,7 @@ 8 - + @@ -281,53 +282,105 @@ + + + + + + + + 9 + + + + + + + + CatLabType + + + ID + CATID + LABID + + + + + + + + + + + + + + ArchLab + + + ID + ARCHID + LABID + + + + + + + + + - + - + - + - + - + - + - + - + - + + + + - + - + - + diff --git a/flask/app.py b/flask/app.py index 7a1610d..806876c 100644 --- a/flask/app.py +++ b/flask/app.py @@ -19,7 +19,7 @@ def timectime(s): def convsize(s): sizes=("B","KB","MB","GB","TB") n=0 - while s > 1000: + while s >= 1000: n+=1 s=s/1000 return str("%.2f" % s)+sizes[n] @@ -28,31 +28,48 @@ def convsize(s): @app.route('/') def homepage(): # try to get userdata, else logout state - print(request.base_url) - try: - logged_in,userdata=get_login_info(request.cookies.get('session')) - except Exception as e: - logged_in,userdata=False,() - #try: # TODO: CLEAN! - # # get sesskey and get info about user - # sesskey=request.cookies.get('session') - # res,userid=db.check_sesskey(sesskey) - # if not res: - # return 500 - # userdata=db.get_user_info(userid) - # logged_in=True - #except Exception as e: - # logged_in=False - # userdata=() + logged_in,userdata=get_login_info(request.cookies.get('session')) archives=db.get_n_archives() return render_template("home.html", title="Homepage",userdata=userdata,login=logged_in,archives=archives) @app.route('/user') @app.route('/user/') def userpage(userid:int=0): - if userid == 0: + logged_in,userdata=get_login_info(request.cookies.get('session')) + if not logged_in: return make_response(redirect('/')) +@app.route('/add', methods=['GET','POST']) +def addpage(): + # try to get userdata, else yeet to the homepage + logged_in,userdata=get_login_info(request.cookies.get('session')) + if not logged_in: + return make_response(redirect('/')) + # POST: check and add archive, show confirmation/error message at the end + if request.method == 'POST': + postdict={} + # get and save all inputs, error if one doesn't exist or is wrong type + for i,itype in [("name",str),("hash",str),("category",int),("size",float)]: + try: + postdict[i]=itype(request.form[i]) + except Exception as e: + return "

ERROR: All fields need to be filled and don't play with their names!

Go back and try again." + + try: + postdict["size"]=postdict["size"]*int(request.form['size_multiplier']) + except Exception as e: + return "

ERROR: All fields need to be filled and don't play with their names!

Go back and try again." + postdict["owner"]=userdata[0] + res,archid=db.add_archive(postdict) + if res: + return make_response(redirect(f"/view/{str(archid)}")) + else: + return f"

ERROR: {archid}

Go back and try again.", 400 + + # GET: return normal page + htmlcatlist=get_category_selection(False) + return render_template("add.html", title="Add Archive",categories=htmlcatlist) + @app.route('/login', methods=["GET","POST"]) def loginpage(): # POST: Process login request @@ -78,10 +95,7 @@ def loginpage(): @app.route('/search') def searchpage(): # try to get userdata, else logout state - try: - logged_in,userdata=get_login_info(request.cookies.get('session')) - except Exception as e: - logged_in,userdata=False,() + logged_in,userdata=get_login_info(request.cookies.get('session')) # try to set all required variables, else defaults try: @@ -103,26 +117,18 @@ def searchpage(): count=20 archives=db.get_n_archives(sorttype,category,keywords,count) - catlist=db.get_all_categories() - htmlcatlist=[] - # parse all categories and sort them into select box - for cat in catlist: - if not cat[2]: - htmlcatlist.append((cat[0],cat[1])) - parent=cat[1] - parentid=cat[0] - for i in catlist: - if i[2] == parentid: - htmlcatlist.append((i[0],f"{parent}/{i[1]}")) + htmlcatlist=get_category_selection() return render_template("search.html", title="Advanced Search",categories=htmlcatlist,userdata=userdata,login=logged_in,archives=archives) ## FUNCTIONS ## Checks if given sesskey is valid and returns user data -## OUTPUT: (if sesskey valid) logged_in:bool=True, userdata:tup -## (if sesskey invalid) +## OUTPUT: (if sesskey valid) logged_in:bool=True, userdata:tuple +## (if sesskey invalid) logged_in:bool=False, userdata:tuple=() def get_login_info(sesskey:str): + if not sesskey: + return False,() logged_in,userid=db.check_sesskey(sesskey) if logged_in: userdata=db.get_user_info(userid) @@ -135,6 +141,23 @@ def setcookie(name:str,value:str,lifetime:int=10000): resp.set_cookie(name, value, max_age=lifetime) return resp +## Gets all categories and returns them (with or without parents) +## OUTPUT: […,(ID:int,NAME:str),…] +def get_category_selection(include_parents:bool=True): + catlist=db.get_all_categories() + htmlcatlist=[] + # parse all categories and sort them into list + for cat in catlist: + if not cat[2]: + if include_parents: + htmlcatlist.append((cat[0],cat[1])) + parent=cat[1] + parentid=cat[0] + for i in catlist: + if i[2] == parentid: + htmlcatlist.append((i[0],f"{parent}/{i[1]}")) + return htmlcatlist + ## API CALLS (NO THANKS) # main driver function diff --git a/flask/func.py b/flask/func.py index 649e198..b3c6d6b 100644 --- a/flask/func.py +++ b/flask/func.py @@ -1,7 +1,7 @@ ## MAIN FUNCTIONS FILE FOR BACK-BACKEND OF FLASK import mariadb as sql from os import environ -import time +import time,re ## params populated with environment variables, defaults can be changed for a permanent solution conn_params={ @@ -23,7 +23,7 @@ class db: self.cur.execute("""CREATE TABLE IF NOT EXISTS Archs( ID int PRIMARY KEY AUTO_INCREMENT, NAME text NOT NULL, - HASH text NOT NULL, + HASH text NOT NULL UNIQUE, SIZE int NOT NULL, IMPORTED int, CATEGORY int, @@ -55,10 +55,14 @@ class db: ARCHID int NOT NULL, LABID int NOT NULL );""") + self.cur.execute("""CREATE TABLE IF NOT EXISTS CatLabType( + ID int PRIMARY KEY AUTO_INCREMENT, + CATID int NOT NULL, + LABID int NOT NULL + );""") self.cur.execute("""CREATE TABLE IF NOT EXISTS Labs( ID int PRIMARY KEY AUTO_INCREMENT, LABEL text NOT NULL, - CATEGORY text, TYPE int NOT NULL );""") self.cur.execute("""CREATE TABLE IF NOT EXISTS LabType( @@ -99,8 +103,30 @@ class db: self.cur.execute(f"SELECT * FROM Users WHERE ID='{userid}'") return self.cur.fetchone() + ## Checks information for errors and adds archive to the DB + ## OUTPUT: (if successful) res:bool=True, ID:int + ## (if unsuccessful) res:bool=False, str + def add_archive(self, archive:dict): + # Check everything for errors or malicious things + archive["hash"]=archive["hash"].upper() + if not re.match('[A-Z0-9]{40}', archive["hash"]): + return False, "Hash needs to be 40 characters in hexadecimal (SHA-1)." + if re.match('.*[^A-Za-z0-9\. _-].*', archive["name"]): + return False, "The name contains illegal characters. Allowed chars: '[A-Za-z0-9\. _-]'" + print(archive["name"]) + + curtime=time.time() + try: + self.cur.execute(f"INSERT INTO Archs(NAME,HASH,SIZE,IMPORTED,CATEGORY,OWNER) VALUES('{archive['name']}','{archive['hash']}',{archive['size']},{curtime},{archive['category']},{archive['owner']})") + except Exception as e: # hash needs to be unique + return False, e + self.cur.execute(f"SELECT ID FROM Archs WHERE HASH='{archive['hash']}'") + archid=self.cur.fetchone() + return True,archid[0] + + ## Returns all relevant information about one (1) archive - ## OUTPUT: archive:tuple=(NAME:str,HASH:str,IMPORTED[UNIX]:int,CATEGORY,str,CATEGORY.DESCRIPTION:str,UNAME:str,DNAME:str) + ## OUTPUT: archive:tuple=(NAME:str,HASH:str,IMPORTED[UNIX]:int,CATEGORY,str,CATEGORY.DESCRIPTION:str,UNAME:str,DNAME:str), ## labels:array=[…,(LABEL:str,CATEGORY:str,CATDESC:str,LABTYPE:str,LABDESC:str),…] def get_archive_info(self, hash:str): self.cur.execute(f"""SELECT Archs.NAME,Archs.HASH,Archs.IMPORTED,Cats.CATEGORY,Cats.DESCRIPTION,Users.UNAME,Users.DNAME FROM Archs @@ -146,14 +172,14 @@ class db: # Get all children of category (if exist) and put into query string categories=self.get_all_categories() - catlist=[category] + catlist=[str(category)] for i in categories: if i[2] == int(category): catlist.append(str(i[0])) - category="(" + ",".join(catlist) + ")" + categories="(" + ",".join(catlist) + ")" self.cur.execute(f"""SELECT ID,NAME,SIZE,IMPORTED FROM Archs - {"WHERE 1=1" if category==0 else " WHERE CATEGORY IN " + category} + {"WHERE 1=1" if category==0 else " WHERE CATEGORY IN " + categories} {keyword_string} ORDER BY {sorttype} LIMIT {count};""") archives=self.cur.fetchall() diff --git a/flask/static/add.css b/flask/static/add.css new file mode 100644 index 0000000..4982aec --- /dev/null +++ b/flask/static/add.css @@ -0,0 +1,4 @@ +div.grid-container { + display: grid; + grid-template-columns: max-content max-content; +} \ No newline at end of file diff --git a/flask/static/base.css b/flask/static/base.css index 0fd47dd..d759416 100644 --- a/flask/static/base.css +++ b/flask/static/base.css @@ -15,6 +15,16 @@ header { display: flex; } +header > a { + margin: auto; + height: 2em; + width: 2em; +} +a > img { + height: 2em; + width: 2em; +} + header > div#container { flex-grow: 1; display: flex; diff --git a/flask/templates/add.html b/flask/templates/add.html new file mode 100644 index 0000000..c560712 --- /dev/null +++ b/flask/templates/add.html @@ -0,0 +1,34 @@ +{% extends "base.html" %} + +{% block meta %} + +{% endblock %} + +{% block content %} +
+
+
Name:
+
+
Hash:
+
+
Category:
+
+ +
+
Size:
+
+ + +
+ +
+
+{% endblock %} \ No newline at end of file diff --git a/flask/templates/base.html b/flask/templates/base.html index d60ed25..55e2ece 100644 --- a/flask/templates/base.html +++ b/flask/templates/base.html @@ -10,6 +10,7 @@
+ favicon {{title}}