Select final, but dirty
This commit is contained in:
BIN
db/other.db
BIN
db/other.db
Binary file not shown.
BIN
db/test.db
BIN
db/test.db
Binary file not shown.
Binary file not shown.
88
modules/htmlize.py
Normal file
88
modules/htmlize.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import config
|
||||||
|
|
||||||
|
def tabelize(table_list):
|
||||||
|
''' Construct a table out of
|
||||||
|
|
||||||
|
Connect to DB, execute a query and return data
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*table_list:* tuple() / list(), rows and items as tuples / lists
|
||||||
|
|
||||||
|
Sets:
|
||||||
|
*N/A*
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
*table:* str(), html table code made from tuples / lists
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
*N/A*
|
||||||
|
|
||||||
|
'''
|
||||||
|
table = '<table>'
|
||||||
|
for row in table_list:
|
||||||
|
table += '<tr>'
|
||||||
|
if not isinstance(row, (list,tuple)):
|
||||||
|
table += f"<td> {row} </td>"
|
||||||
|
else:
|
||||||
|
for item in row:
|
||||||
|
table += f"<td> {item} </td>"
|
||||||
|
table += '</tr>'
|
||||||
|
table += '</table>'
|
||||||
|
return table
|
||||||
|
|
||||||
|
def tabelize_links(table_list):
|
||||||
|
''' Making a table with links
|
||||||
|
|
||||||
|
Constructs a clickable link in HTML, so that the link points to ./link
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*table_list:* tuple() / list(), rows and items as tuples / lists
|
||||||
|
|
||||||
|
Sets:
|
||||||
|
*N/A*
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
*table:* str(), html table code made from tuples / lists
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
*N/A*
|
||||||
|
|
||||||
|
'''
|
||||||
|
table = '<table>'
|
||||||
|
for row in table_list:
|
||||||
|
table += '<tr>'
|
||||||
|
if not isinstance(row, (list, tuple)):
|
||||||
|
table += f"<td> <a href=\"./{row}/\">{row}</a> </td>"
|
||||||
|
else:
|
||||||
|
for item in row:
|
||||||
|
table += f"<td> <a href=\"./{item}/\">{item}</a> </td>"
|
||||||
|
table += '</tr>'
|
||||||
|
table += '</table>'
|
||||||
|
return table
|
||||||
|
|
||||||
|
def read_html(filename, _STATIC_DIR):
|
||||||
|
'''Read a html file
|
||||||
|
|
||||||
|
Reads a file from a selected static directory - needs to be set as static
|
||||||
|
in the cherrypy (chttpd.py).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
``filename`` *str()*, plain filename, without any path specification,
|
||||||
|
without extension
|
||||||
|
``_STATIC_DIR`` *str()*, path relative to the project root,
|
||||||
|
where chttpd.py resides
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
*str()*, parsed html code from the read file, or a HTML
|
||||||
|
formatted error if file cannot be read for any reason
|
||||||
|
|
||||||
|
Exceptions:
|
||||||
|
On file read fail, string with Exception text is returned
|
||||||
|
|
||||||
|
'''
|
||||||
|
read_path = config._ROOT+ _STATIC_DIR + filename + '.html'
|
||||||
|
try:
|
||||||
|
with open(read_path, 'r') as handle:
|
||||||
|
return handle.read()
|
||||||
|
except Exception as e:
|
||||||
|
return """<div>ERROR: {}!</div><br>{}""".format(e, read_path)
|
||||||
@@ -3,8 +3,57 @@ import cherrypy
|
|||||||
import config
|
import config
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import os
|
import os
|
||||||
|
import json
|
||||||
|
from modules import htmlize
|
||||||
|
|
||||||
|
class Checker(object):
|
||||||
|
def __init__(self):
|
||||||
|
''' Sanity check
|
||||||
|
|
||||||
|
Describes tables in DB, or lists the contents
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*None*
|
||||||
|
|
||||||
|
Sets:
|
||||||
|
*N/A:* Nothing yet
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
*N/A:* boolean(), valid, or not?
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
*N/A* Nothing yet
|
||||||
|
|
||||||
|
'''
|
||||||
|
__name__ = "SQLite SQL validator"
|
||||||
|
|
||||||
|
def is_table(db, table):
|
||||||
|
''' Checks if table exists in a DB
|
||||||
|
|
||||||
|
Escaping, sanitizing and checking what are we sending to the DB
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*query* Query to be sent to the DB
|
||||||
|
|
||||||
|
Sets:
|
||||||
|
*N/A*
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
*result:* bool(), is the code to be executed OK, or not
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
*N/A*
|
||||||
|
|
||||||
|
'''
|
||||||
|
db_file = f"{config._ROOT}/{config._DB_PATH}/{db}"
|
||||||
|
try:
|
||||||
|
open(db_file)
|
||||||
|
except Exception as e:
|
||||||
|
result = [ False, e ]
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class select(object):
|
class select(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
''' SELECT method for API
|
''' SELECT method for API
|
||||||
@@ -28,26 +77,6 @@ class select(object):
|
|||||||
self.html = ''
|
self.html = ''
|
||||||
self.json = ''
|
self.json = ''
|
||||||
|
|
||||||
def CheckSelect(self):
|
|
||||||
''' Checks and sanitizes a query
|
|
||||||
|
|
||||||
Escaping, sanitizing and checking what are we sending to the DB
|
|
||||||
|
|
||||||
Args:
|
|
||||||
*query* Query to be sent to the DB
|
|
||||||
|
|
||||||
Sets:
|
|
||||||
*N/A*
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
*result:* bool(), is the code to be executed OK, or not
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
*N/A*
|
|
||||||
|
|
||||||
'''
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _cp_dispatch(self, vpath):
|
def _cp_dispatch(self, vpath):
|
||||||
''' Modify the request path, REST way
|
''' Modify the request path, REST way
|
||||||
|
|
||||||
@@ -69,11 +98,17 @@ class select(object):
|
|||||||
*N/A*
|
*N/A*
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
dbs = os.listdir(f"{config._ROOT}/{config._DB_PATH}")
|
||||||
if len(vpath) == 1:
|
if len(vpath) == 1:
|
||||||
cherrypy.request.params['schema'] = vpath.pop()
|
schema = vpath.pop()
|
||||||
return self
|
if schema in dbs:
|
||||||
|
cherrypy.request.params['schema'] = schema
|
||||||
|
return self
|
||||||
|
else:
|
||||||
|
del schema
|
||||||
|
return self
|
||||||
|
|
||||||
if len(vpath) == 2:
|
elif len(vpath) == 2:
|
||||||
cherrypy.request.params['table'] = vpath.pop()
|
cherrypy.request.params['table'] = vpath.pop()
|
||||||
cherrypy.request.params['db'] = vpath.pop()
|
cherrypy.request.params['db'] = vpath.pop()
|
||||||
cherrypy.request.params['values'] = '*'
|
cherrypy.request.params['values'] = '*'
|
||||||
@@ -100,11 +135,21 @@ class select(object):
|
|||||||
*N/A*
|
*N/A*
|
||||||
|
|
||||||
'''
|
'''
|
||||||
db_file = f"{config._ROOT}/{db}"
|
db_file = f"{config._ROOT}/{config._DB_PATH}/{db}"
|
||||||
try:
|
if os.path.exists(db_file):
|
||||||
open(db_file)
|
error = False
|
||||||
except Exception as e:
|
if os.path.isfile(db_file):
|
||||||
raise RuntimeError(f"ERROR: Unable to read DB file: {e}")
|
error = False
|
||||||
|
else:
|
||||||
|
error = f"{db_file} is not a standard file"
|
||||||
|
html_result = htmlize.read_html('error', '/templates/')
|
||||||
|
result = html_result.format(_error=error)
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
error = f"{db_file} does not exist"
|
||||||
|
html_result = htmlize.read_html('error', '/templates/')
|
||||||
|
result = html_result.format(_error=error)
|
||||||
|
return result
|
||||||
conn = sqlite3.connect(db_file)
|
conn = sqlite3.connect(db_file)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
if len(kwargs) == 0:
|
if len(kwargs) == 0:
|
||||||
@@ -117,32 +162,6 @@ class select(object):
|
|||||||
conn.close()
|
conn.close()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def tabelize(self, table_list):
|
|
||||||
''' Calling the actual data from DB
|
|
||||||
|
|
||||||
Connect to DB, execute a query and return data
|
|
||||||
|
|
||||||
Args:
|
|
||||||
*table_list:* tuple() / list(), rows and items as tuples / lists
|
|
||||||
|
|
||||||
Sets:
|
|
||||||
*N/A*
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
*table:* str(), html table code made from tuples / lists
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
*N/A*
|
|
||||||
|
|
||||||
'''
|
|
||||||
table = '<table>'
|
|
||||||
for row in table_list:
|
|
||||||
table += '<tr>'
|
|
||||||
for item in row:
|
|
||||||
table += f"<td> {item} </td>"
|
|
||||||
table += '</tr>'
|
|
||||||
table += '</table>'
|
|
||||||
return table
|
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def index(self, **kwargs):
|
def index(self, **kwargs):
|
||||||
@@ -166,19 +185,74 @@ class select(object):
|
|||||||
*N/A*
|
*N/A*
|
||||||
|
|
||||||
'''
|
'''
|
||||||
if 'schema' in kwargs.keys():
|
|
||||||
result = self.sqlite_wrapper(
|
|
||||||
kwargs["schema"]
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
result = self.sqlite_wrapper(
|
|
||||||
kwargs['db'],
|
|
||||||
table=kwargs['table'],
|
|
||||||
values=kwargs['values']
|
|
||||||
)
|
|
||||||
self.html = ''
|
self.html = ''
|
||||||
self.html += self.tabelize(result)
|
self.json = {}
|
||||||
return self.html
|
url = cherrypy.url()
|
||||||
|
if 'schema' in kwargs.keys():
|
||||||
|
# No table is defined, we want the 'schema' of the DB
|
||||||
|
try:
|
||||||
|
db = kwargs["schema"]
|
||||||
|
result = self.sqlite_wrapper(db)
|
||||||
|
status = 'OK'
|
||||||
|
except Exception as e:
|
||||||
|
result = ''
|
||||||
|
status = f"ERROR: {e}"
|
||||||
|
self.html = htmlize.read_html('schema','/templates/')
|
||||||
|
# schema has weird structure, returns (val,) hence schema[0]
|
||||||
|
# [2] - third element '[0]CREATE [1]TABLE [2]'xyz' ...
|
||||||
|
tables = [schema[0].split(' ')[2].strip('\'') for schema in result]
|
||||||
|
self.html = self.html.format(
|
||||||
|
_db=db,
|
||||||
|
_schema=htmlize.tabelize(result),
|
||||||
|
_tables=htmlize.tabelize_links(tables),
|
||||||
|
_status=status
|
||||||
|
)
|
||||||
|
self.json.update({
|
||||||
|
"result": {"tables": tables},
|
||||||
|
"status": status
|
||||||
|
})
|
||||||
|
elif 'table' in kwargs.keys():
|
||||||
|
# In case a table is defined, what are the values?
|
||||||
|
db = kwargs['db']
|
||||||
|
table = kwargs['table']
|
||||||
|
try:
|
||||||
|
result = self.sqlite_wrapper(
|
||||||
|
db,
|
||||||
|
table=table,
|
||||||
|
values=kwargs['values']
|
||||||
|
)
|
||||||
|
status = 'OK'
|
||||||
|
except Exception as e:
|
||||||
|
result = ''
|
||||||
|
status = f"ERROR: {e}"
|
||||||
|
self.html = htmlize.read_html('table','/templates/')
|
||||||
|
self.html = self.html.format(
|
||||||
|
_db=db,
|
||||||
|
_table=table,
|
||||||
|
_rows=htmlize.tabelize(result),
|
||||||
|
_status=status
|
||||||
|
)
|
||||||
|
self.json.update({
|
||||||
|
"result": {"rows": result},
|
||||||
|
"status": status
|
||||||
|
})
|
||||||
|
elif url.split('/')[-2] == 'select':
|
||||||
|
#No DB, nor table is defined, list DBs in config._DB_PATH
|
||||||
|
dbs = os.listdir(f"{config._ROOT}/{config._DB_PATH}")
|
||||||
|
result = [db for db in dbs]
|
||||||
|
self.html += htmlize.tabelize_links(result)
|
||||||
|
self.json.update({
|
||||||
|
"result":{"databases": result},
|
||||||
|
"status": "OK"
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
result = htmlize.read_html('error', '/templates/')
|
||||||
|
e = f'DB is non existent, or wrong parameter specified. Check URL'
|
||||||
|
return result.format(_error=e)
|
||||||
|
if 'json' in kwargs.keys():
|
||||||
|
return json.dumps(self.json)
|
||||||
|
else:
|
||||||
|
return self.html
|
||||||
|
|
||||||
|
|
||||||
class insert(object):
|
class insert(object):
|
||||||
|
|||||||
6
templates/dbs.html
Normal file
6
templates/dbs.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<h2>DB Schema for {_db}</h2>
|
||||||
|
{_schema}
|
||||||
|
<h3>Tables:</h3>
|
||||||
|
{_tables}
|
||||||
|
<hr>
|
||||||
|
<div>Result: {_status}</div>
|
||||||
2
templates/error.html
Normal file
2
templates/error.html
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<h1>ERROR</h1>
|
||||||
|
<p>{_error}</p>
|
||||||
6
templates/schema.html
Normal file
6
templates/schema.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<h2>DB Schema for {_db}</h2>
|
||||||
|
{_schema}
|
||||||
|
<h3>Tables:</h3>
|
||||||
|
{_tables}
|
||||||
|
<hr>
|
||||||
|
<div>Result: {_status}</div>
|
||||||
6
templates/table.html
Normal file
6
templates/table.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<h2>DB '{_db}' / Table '{_table}'</h2>
|
||||||
|
<div>
|
||||||
|
{_rows}
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div>Result: {_status}</div>
|
||||||
Reference in New Issue
Block a user