forked from s3lph/matemat
First, horrible config file support.
This commit is contained in:
parent
2347908381
commit
a52f09fc58
10 changed files with 86 additions and 28 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,3 +9,4 @@
|
||||||
|
|
||||||
*.sqlite3
|
*.sqlite3
|
||||||
*.db
|
*.db
|
||||||
|
**/matemat.conf
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
|
|
||||||
__version__ = '2.0'
|
__version__ = '2.0'
|
||||||
|
|
||||||
|
from .config import parse_config_file
|
||||||
|
|
|
@ -1,16 +1,23 @@
|
||||||
|
|
||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from matemat import parse_config_file
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Those imports are actually needed, as they implicitly register pagelets.
|
# Those imports are actually needed, as they implicitly register pagelets.
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
from matemat.webserver.pagelets import *
|
from matemat.webserver.pagelets import *
|
||||||
from matemat.webserver import MatematWebserver
|
from matemat.webserver import MatematWebserver
|
||||||
|
|
||||||
# Read HTTP port from command line
|
# Use config file name from command line, if present
|
||||||
port: int = 8080
|
configfile: str = '/etc/matemat.conf'
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
port = int(sys.argv[1])
|
configfile = sys.argv[1]
|
||||||
|
|
||||||
|
# Parse the config file
|
||||||
|
config: Dict[str, Any] = parse_config_file(configfile)
|
||||||
|
|
||||||
# Start the web server
|
# Start the web server
|
||||||
MatematWebserver(port=port).start()
|
MatematWebserver(**config).start()
|
||||||
|
|
29
matemat/config.py
Normal file
29
matemat/config.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
from configparser import ConfigParser, NoSectionError
|
||||||
|
|
||||||
|
|
||||||
|
def parse_config_file(path: str) -> Dict[str, Any]:
|
||||||
|
config: Dict[str, Any] = dict()
|
||||||
|
|
||||||
|
parser: ConfigParser = ConfigParser()
|
||||||
|
parser.read(path, 'utf-8')
|
||||||
|
if 'Matemat' not in parser.sections():
|
||||||
|
raise NoSectionError(f'Section "matemat" missing in file {path}')
|
||||||
|
config['listen'] = parser['Matemat'].get('Address', '::')
|
||||||
|
config['port'] = int(parser['Matemat'].get('Port', '8080'))
|
||||||
|
config['dbpath'] = parser['Matemat'].get('DatabaseFile', '/var/matemat/db/matemat.sqlite3')
|
||||||
|
config['staticroot'] = parser['Matemat'].get('StaticPath', '/var/matemat/static/')
|
||||||
|
config['templateroot'] = parser['Matemat'].get('TemplatePath', '/var/matemat/templates/')
|
||||||
|
|
||||||
|
config['pagelet_arguments']: Dict[str, str] = dict()
|
||||||
|
config['pagelet_arguments']['DatabaseFile'] = config['dbpath']
|
||||||
|
config['pagelet_arguments']['StaticPath'] = config['staticroot']
|
||||||
|
config['pagelet_arguments']['TemplatePath'] = config['templateroot']
|
||||||
|
|
||||||
|
if 'Pagelets' in parser.sections():
|
||||||
|
for k, v in parser['Pagelets'].items():
|
||||||
|
config['pagelet_arguments'][k] = v
|
||||||
|
|
||||||
|
return config
|
|
@ -34,7 +34,8 @@ _PAGELET_PATHS: Dict[str, Callable[[str, # HTTP method (GET, POST, ...)
|
||||||
str, # Request path
|
str, # Request path
|
||||||
RequestArguments, # HTTP Request arguments
|
RequestArguments, # HTTP Request arguments
|
||||||
Dict[str, Any], # Session vars
|
Dict[str, Any], # Session vars
|
||||||
Dict[str, str]], # Response headers
|
Dict[str, str], # Response headers
|
||||||
|
Dict[str, str]], # Items from the [Pagelets] section in the config file
|
||||||
Union[ # Return type: either a response body, or a redirect
|
Union[ # Return type: either a response body, or a redirect
|
||||||
bytes, str, # Response body: will assign HTTP/1.0 200 OK
|
bytes, str, # Response body: will assign HTTP/1.0 200 OK
|
||||||
PageletResponse, # A generic response
|
PageletResponse, # A generic response
|
||||||
|
@ -77,6 +78,7 @@ def pagelet(path: str):
|
||||||
str,
|
str,
|
||||||
RequestArguments,
|
RequestArguments,
|
||||||
Dict[str, Any],
|
Dict[str, Any],
|
||||||
|
Dict[str, str],
|
||||||
Dict[str, str]],
|
Dict[str, str]],
|
||||||
Union[
|
Union[
|
||||||
bytes, str,
|
bytes, str,
|
||||||
|
@ -102,12 +104,17 @@ class MatematHTTPServer(HTTPServer):
|
||||||
handler: Type[BaseHTTPRequestHandler],
|
handler: Type[BaseHTTPRequestHandler],
|
||||||
staticroot: str,
|
staticroot: str,
|
||||||
templateroot: str,
|
templateroot: str,
|
||||||
|
dbpath: str,
|
||||||
|
pagelet_arguments: Dict[str, str],
|
||||||
bind_and_activate: bool = True) -> None:
|
bind_and_activate: bool = True) -> None:
|
||||||
super().__init__(server_address, handler, bind_and_activate)
|
super().__init__(server_address, handler, bind_and_activate)
|
||||||
# Resolve webroot directory
|
# Resolve webroot directory and database file
|
||||||
self.webroot = os.path.abspath(staticroot)
|
self.webroot = os.path.abspath(staticroot)
|
||||||
|
self.database_file = os.path.abspath(dbpath)
|
||||||
# Set up session vars dict
|
# Set up session vars dict
|
||||||
self.session_vars: Dict[str, Tuple[datetime, Dict[str, Any]]] = dict()
|
self.session_vars: Dict[str, Tuple[datetime, Dict[str, Any]]] = dict()
|
||||||
|
# Set up pagelet arguments dict
|
||||||
|
self.pagelet_arguments = pagelet_arguments
|
||||||
# Set up the Jinja2 environment
|
# Set up the Jinja2 environment
|
||||||
self.jinja_env: jinja2.Environment = jinja2.Environment(
|
self.jinja_env: jinja2.Environment = jinja2.Environment(
|
||||||
loader=jinja2.FileSystemLoader(os.path.abspath(templateroot))
|
loader=jinja2.FileSystemLoader(os.path.abspath(templateroot))
|
||||||
|
@ -130,10 +137,12 @@ class MatematWebserver(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
listen: str = '::',
|
listen: str,
|
||||||
port: int = 80,
|
port: int,
|
||||||
staticroot: str = './static',
|
staticroot: str,
|
||||||
templateroot: str = './templates') -> None:
|
templateroot: str,
|
||||||
|
dbpath: str,
|
||||||
|
pagelet_arguments: Dict[str, str]) -> None:
|
||||||
"""
|
"""
|
||||||
Instantiate a MatematWebserver.
|
Instantiate a MatematWebserver.
|
||||||
|
|
||||||
|
@ -141,16 +150,14 @@ class MatematWebserver(object):
|
||||||
:param port: The TCP port to listen on.
|
:param port: The TCP port to listen on.
|
||||||
:param staticroot: Path to the static webroot directory.
|
:param staticroot: Path to the static webroot directory.
|
||||||
:param templateroot: Path to the Jinja2 templates root directory.
|
:param templateroot: Path to the Jinja2 templates root directory.
|
||||||
|
:param dbpath: Path to the database file.
|
||||||
"""
|
"""
|
||||||
if len(listen) == 0:
|
|
||||||
# Empty string should be interpreted as all addresses
|
|
||||||
listen = '::'
|
|
||||||
# IPv4 address detection heuristic
|
# IPv4 address detection heuristic
|
||||||
if ':' not in listen and '.' in listen:
|
if ':' not in listen and '.' in listen:
|
||||||
# Rewrite IPv4 address to IPv6-mapped form
|
# Rewrite IPv4 address to IPv6-mapped form
|
||||||
listen = f'::ffff:{listen}'
|
listen = f'::ffff:{listen}'
|
||||||
# Create the http server
|
# Create the http server
|
||||||
self._httpd = MatematHTTPServer((listen, port), HttpHandler, staticroot, templateroot)
|
self._httpd = MatematHTTPServer((listen, port), HttpHandler, staticroot, templateroot, dbpath, pagelet_arguments)
|
||||||
|
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -289,8 +296,14 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
'Content-Type': 'text/html',
|
'Content-Type': 'text/html',
|
||||||
'Cache-Control': 'no-cache'
|
'Cache-Control': 'no-cache'
|
||||||
}
|
}
|
||||||
|
print(self.server.pagelet_arguments)
|
||||||
# Call the pagelet function
|
# Call the pagelet function
|
||||||
pagelet_res = _PAGELET_PATHS[path](method, path, args, self.session_vars, headers)
|
pagelet_res = _PAGELET_PATHS[path](method,
|
||||||
|
path,
|
||||||
|
args,
|
||||||
|
self.session_vars,
|
||||||
|
headers,
|
||||||
|
self.server.pagelet_arguments)
|
||||||
# Parse the pagelet's return value, vielding a HTTP status code and a response body
|
# Parse the pagelet's return value, vielding a HTTP status code and a response body
|
||||||
hsc, data = self._parse_pagelet_result(pagelet_res, headers)
|
hsc, data = self._parse_pagelet_result(pagelet_res, headers)
|
||||||
# Send the HTTP status code
|
# Send the HTTP status code
|
||||||
|
|
|
@ -12,14 +12,15 @@ def login_page(method: str,
|
||||||
path: str,
|
path: str,
|
||||||
args: RequestArguments,
|
args: RequestArguments,
|
||||||
session_vars: Dict[str, Any],
|
session_vars: Dict[str, Any],
|
||||||
headers: Dict[str, str])\
|
headers: Dict[str, str],
|
||||||
|
config: Dict[str, str])\
|
||||||
-> Union[bytes, str, PageletResponse]:
|
-> Union[bytes, str, PageletResponse]:
|
||||||
if 'user' in session_vars:
|
if 'user' in session_vars:
|
||||||
return RedirectResponse('/')
|
return RedirectResponse('/')
|
||||||
if method == 'GET':
|
if method == 'GET':
|
||||||
return TemplateResponse('login.html')
|
return TemplateResponse('login.html', setupname=config['name'])
|
||||||
elif method == 'POST':
|
elif method == 'POST':
|
||||||
with MatematDatabase('test.db') as db:
|
with MatematDatabase(config['DatabaseFile']) as db:
|
||||||
try:
|
try:
|
||||||
user: User = db.login(str(args.username), str(args.password))
|
user: User = db.login(str(args.username), str(args.password))
|
||||||
except AuthenticationError:
|
except AuthenticationError:
|
||||||
|
|
|
@ -9,7 +9,8 @@ def logout(method: str,
|
||||||
path: str,
|
path: str,
|
||||||
args: RequestArguments,
|
args: RequestArguments,
|
||||||
session_vars: Dict[str, Any],
|
session_vars: Dict[str, Any],
|
||||||
headers: Dict[str, str])\
|
headers: Dict[str, str],
|
||||||
|
config: Dict[str, str])\
|
||||||
-> Union[bytes, str, PageletResponse]:
|
-> Union[bytes, str, PageletResponse]:
|
||||||
if 'user' in session_vars:
|
if 'user' in session_vars:
|
||||||
del session_vars['user']
|
del session_vars['user']
|
||||||
|
|
|
@ -11,13 +11,14 @@ def main_page(method: str,
|
||||||
path: str,
|
path: str,
|
||||||
args: RequestArguments,
|
args: RequestArguments,
|
||||||
session_vars: Dict[str, Any],
|
session_vars: Dict[str, Any],
|
||||||
headers: Dict[str, str])\
|
headers: Dict[str, str],
|
||||||
|
config: Dict[str, str])\
|
||||||
-> Union[bytes, str, PageletResponse]:
|
-> Union[bytes, str, PageletResponse]:
|
||||||
with MatematDatabase('test.db') as db:
|
with MatematDatabase(config['DatabaseFile']) as db:
|
||||||
if 'user' in session_vars:
|
if 'user' in session_vars:
|
||||||
user: User = session_vars['user']
|
user: User = session_vars['user']
|
||||||
products = db.list_products()
|
products = db.list_products()
|
||||||
return TemplateResponse('main.html', user=user, list=products)
|
return TemplateResponse('main.html', user=user, list=products, setupname=config['name'])
|
||||||
else:
|
else:
|
||||||
users = db.list_users()
|
users = db.list_users()
|
||||||
return TemplateResponse('main.html', list=users)
|
return TemplateResponse('main.html', list=users, setupname=config['name'])
|
||||||
|
|
|
@ -14,14 +14,17 @@ def touchkey_page(method: str,
|
||||||
path: str,
|
path: str,
|
||||||
args: RequestArguments,
|
args: RequestArguments,
|
||||||
session_vars: Dict[str, Any],
|
session_vars: Dict[str, Any],
|
||||||
headers: Dict[str, str])\
|
headers: Dict[str, str],
|
||||||
|
config: Dict[str, str])\
|
||||||
-> Union[bytes, str, PageletResponse]:
|
-> Union[bytes, str, PageletResponse]:
|
||||||
if 'user' in session_vars:
|
if 'user' in session_vars:
|
||||||
return RedirectResponse('/')
|
return RedirectResponse('/')
|
||||||
if method == 'GET':
|
if method == 'GET':
|
||||||
return TemplateResponse('touchkey.html', username=str(args.username) if 'username' in args else None)
|
return TemplateResponse('touchkey.html',
|
||||||
|
username=str(args.username) if 'username' in args else None,
|
||||||
|
setupname=config['name'])
|
||||||
elif method == 'POST':
|
elif method == 'POST':
|
||||||
with MatematDatabase('test.db') as db:
|
with MatematDatabase(config['DatabaseFile']) as db:
|
||||||
try:
|
try:
|
||||||
user: User = db.login(str(args.username), touchkey=str(args.touchkey))
|
user: User = db.login(str(args.username), touchkey=str(args.touchkey))
|
||||||
except AuthenticationError:
|
except AuthenticationError:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Matemat</title>
|
<title>{{ setupname }}</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
color: #f0f0f0;
|
color: #f0f0f0;
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Matemat {{__version__}}</h1>
|
<h1>{{ setupname }}</h1>
|
||||||
{% block main %}
|
{% block main %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in a new issue