2018-01-07 23:09:25 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
2018-01-08 21:56:05 +00:00
|
|
|
import os
|
2018-01-18 08:39:06 +00:00
|
|
|
import base64
|
2018-01-07 23:09:25 +00:00
|
|
|
import bottle
|
|
|
|
import sqlite3
|
2018-01-08 00:16:34 +00:00
|
|
|
import sendmail
|
2018-01-08 21:56:05 +00:00
|
|
|
import pytoml as toml
|
|
|
|
import jwt
|
|
|
|
import pylibscrypt
|
|
|
|
|
2018-01-07 23:09:25 +00:00
|
|
|
|
|
|
|
class Datagetter(object):
|
|
|
|
def __init__(self):
|
2018-01-26 14:19:03 +00:00
|
|
|
self.db = "../ticketfrei.sqlite"
|
2018-01-07 23:09:25 +00:00
|
|
|
self.conn = self.create_connection(self.db)
|
|
|
|
self.cur = self.conn.cursor()
|
|
|
|
|
|
|
|
def create_connection(self, db_file):
|
|
|
|
""" create a database connection to the SQLite database
|
|
|
|
specified by the db_file
|
|
|
|
:param db_file: database file
|
|
|
|
:return: Connection object or None
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
conn = sqlite3.connect(db_file)
|
|
|
|
return conn
|
|
|
|
except sqlite3.Error as e:
|
|
|
|
print(e)
|
|
|
|
return None
|
|
|
|
|
2018-01-18 08:39:06 +00:00
|
|
|
|
2018-01-07 23:09:25 +00:00
|
|
|
app = application = bottle.Bottle()
|
|
|
|
|
2018-01-18 08:39:06 +00:00
|
|
|
|
2018-01-07 23:09:25 +00:00
|
|
|
@app.route('/login', method="POST")
|
|
|
|
def login():
|
|
|
|
"""
|
|
|
|
Login to the ticketfrei account with credentials from the user table.
|
|
|
|
|
|
|
|
:return: bot.py Session Cookie
|
|
|
|
"""
|
|
|
|
uname = bottle.request.forms.get('uname')
|
|
|
|
psw = bottle.request.forms.get('psw')
|
2018-01-18 08:39:06 +00:00
|
|
|
psw = psw.encode("utf-8")
|
2018-01-26 14:19:03 +00:00
|
|
|
db.cur.execute("SELECT pass_hashed FROM user WHERE email=?;", (uname, )), psw
|
|
|
|
pass_hashed = db.cur.fetchone()
|
|
|
|
print(pass_hashed)
|
|
|
|
if pylibscrypt.scrypt_mcf_check(pass_hashed, psw):
|
2018-01-07 23:09:25 +00:00
|
|
|
# :todo Generate Session Cookie and give to user
|
|
|
|
return bottle.static_file("../static/bot.html", root="../static")
|
|
|
|
else:
|
|
|
|
return "Wrong Credentials."
|
|
|
|
|
2018-01-18 08:39:06 +00:00
|
|
|
|
2018-01-07 23:09:25 +00:00
|
|
|
@app.route('/register', method="POST")
|
|
|
|
def register():
|
|
|
|
"""
|
|
|
|
Login to the ticketfrei account with credentials from the user table.
|
|
|
|
|
|
|
|
:return: bot.py Session Cookie
|
|
|
|
"""
|
2018-01-08 00:16:34 +00:00
|
|
|
email = bottle.request.forms.get('email')
|
2018-01-07 23:09:25 +00:00
|
|
|
psw = bottle.request.forms.get('psw')
|
|
|
|
pswrepeat = bottle.request.forms.get('psw-repeat')
|
|
|
|
if pswrepeat != psw:
|
|
|
|
return "ERROR: Passwords don't match. Try again."
|
|
|
|
|
2018-01-26 14:19:03 +00:00
|
|
|
# check if email is already in use
|
|
|
|
|
2018-01-08 00:16:34 +00:00
|
|
|
# needs to be encoded somehow
|
2018-01-18 08:39:06 +00:00
|
|
|
psw = psw.encode("utf-8")
|
|
|
|
psw = pylibscrypt.scrypt_mcf(psw)
|
|
|
|
psw = base64.encodebytes(psw)
|
|
|
|
psw = psw.decode("ascii")
|
|
|
|
payload = {"email": email, "psw_hashed": psw} # hash password
|
2018-01-08 21:56:05 +00:00
|
|
|
encoded_jwt = jwt.encode(payload, secret)
|
|
|
|
confirmlink = "ticketfrei.links-tech.org/confirm?" + encoded_jwt
|
2018-01-08 00:16:34 +00:00
|
|
|
config = ""
|
|
|
|
m = sendmail.Mailer(config)
|
|
|
|
m.send("Complete your registration here: " + confirmlink, email, "[Ticketfrei] Confirm your account")
|
|
|
|
return "We sent you an E-Mail. Please click on the confirmation link."
|
|
|
|
|
|
|
|
|
|
|
|
# How can I parse the arguments from the URI?
|
|
|
|
# https://ticketfrei.links-tech.org/confirm?user=asdf&pass=sup3rs3cur3
|
2018-01-08 21:56:05 +00:00
|
|
|
@app.route('/confirm', method="GET")
|
2018-01-08 00:16:34 +00:00
|
|
|
def confirmaccount():
|
|
|
|
"""
|
|
|
|
Confirm the account creation and create a database entry.
|
|
|
|
:return: Redirection to bot.html
|
|
|
|
"""
|
2018-01-08 21:56:05 +00:00
|
|
|
encoded_jwt = bottle.request.forms.get('encoded_jwt')
|
|
|
|
dict = jwt.decode(encoded_jwt, secret)
|
|
|
|
uname = dict["email"]
|
|
|
|
pass_hashed = dict["psw_hashed"]
|
|
|
|
print(uname, pass_hashed)
|
2018-01-08 00:16:34 +00:00
|
|
|
active = "1"
|
2018-01-26 14:19:03 +00:00
|
|
|
db.cur.execute("INSERT INTO user(id, email, pass_hashed, enabled) VALUES(?, ?, ?, ?);", (uname, pass_hashed, active, True))
|
|
|
|
db.conn.commit()
|
2018-01-18 08:39:06 +00:00
|
|
|
return bottle.static_file("../static/bot.html", root='../static')
|
2018-01-08 00:16:34 +00:00
|
|
|
|
2018-01-07 23:09:25 +00:00
|
|
|
|
|
|
|
@app.route('/static/<filename:path>')
|
|
|
|
def static(filename):
|
|
|
|
"""
|
|
|
|
Serve static files
|
|
|
|
"""
|
|
|
|
return bottle.static_file(filename, root='../static')
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/')
|
|
|
|
def show_index():
|
|
|
|
"""
|
|
|
|
The front "index" page
|
|
|
|
:return: /static/index.html
|
|
|
|
"""
|
|
|
|
return bottle.static_file("../static/index.html", root='../static')
|
|
|
|
|
|
|
|
|
|
|
|
class StripPathMiddleware(object):
|
|
|
|
"""
|
|
|
|
Get that slash out of the request
|
|
|
|
"""
|
|
|
|
def __init__(self, a):
|
|
|
|
self.a = a
|
|
|
|
|
|
|
|
def __call__(self, e, h):
|
|
|
|
e['PATH_INFO'] = e['PATH_INFO'].rstrip('/')
|
|
|
|
return self.a(e, h)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2018-01-08 21:56:05 +00:00
|
|
|
with open('../config.toml') as configfile:
|
|
|
|
config = toml.load(configfile)
|
|
|
|
|
2018-01-07 23:09:25 +00:00
|
|
|
global db
|
2018-01-08 21:56:05 +00:00
|
|
|
global secret
|
|
|
|
secret = os.urandom(32)
|
2018-01-07 23:09:25 +00:00
|
|
|
db = Datagetter()
|
2018-01-26 14:19:03 +00:00
|
|
|
try:
|
|
|
|
bottle.run(app=StripPathMiddleware(app), host='0.0.0.0', port=8080)
|
|
|
|
finally:
|
|
|
|
db.conn.close()
|