mirror of git://git.psyced.org/git/pypsyc
118 lines
3.5 KiB
Python
118 lines
3.5 KiB
Python
"""
|
|
pypsyc.server.webif
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
:copyright: 2010 by Manuel Jacob
|
|
:license: MIT
|
|
"""
|
|
from collections import MutableMapping
|
|
from logging import getLogger
|
|
from os import urandom
|
|
from sqlite3 import IntegrityError
|
|
|
|
from flask import Flask, request, flash, url_for, redirect, render_template
|
|
from greenlet import greenlet
|
|
from twisted.internet import reactor
|
|
from twisted.web.server import Site
|
|
from twisted.web.wsgi import WSGIResource
|
|
|
|
|
|
log = getLogger(__name__)
|
|
|
|
app = Flask(__name__)
|
|
app.jinja_env.trim_blocks = True
|
|
|
|
|
|
@app.route('/')
|
|
def index():
|
|
return render_template('index.html')
|
|
|
|
@app.route('/register', methods=['GET', 'POST'])
|
|
def register():
|
|
error = None
|
|
if request.method == 'POST':
|
|
username = request.form.get('username')
|
|
password = request.form.get('password')
|
|
password2 = request.form.get('password2')
|
|
if not username:
|
|
error = 'please specify a valid username'
|
|
elif '~' + username in server.root.children:
|
|
error = 'username already in use'
|
|
elif not password or len(password) < 6:
|
|
error = 'your password must have at least 6 characters'
|
|
elif password != password2:
|
|
error = 'the two passwords do not match'
|
|
else:
|
|
server.register_person(username, password)
|
|
flash("you were registered")
|
|
return redirect(url_for('index'))
|
|
return render_template('register.html', error=error)
|
|
|
|
|
|
class PersistentStore(MutableMapping):
|
|
def __init__(self):
|
|
server.database.execute('CREATE TABLE IF NOT EXISTS webif_store ('
|
|
'key TEXT, value BLOB, PRIMARY KEY (key))')
|
|
|
|
def __getitem__(self, key):
|
|
sql = 'SELECT value FROM webif_store WHERE key = ?'
|
|
ret = server.database.fetch(sql, key)
|
|
if not ret:
|
|
raise KeyError
|
|
return ret[0][0]
|
|
|
|
def __setitem__(self, key, value):
|
|
try:
|
|
sql = 'INSERT INTO webif_store VALUES (?, ?)'
|
|
server.database.execute(sql, key, value)
|
|
except IntegrityError:
|
|
sql = 'UPDATE webif_store SET value = ? WHERE key = ?'
|
|
server.database.execute(sql, value, key)
|
|
|
|
def __delitem__(self, key):
|
|
server.database.execute('DELETE FROM webif_store WHERE key = ?', key)
|
|
|
|
def __iter__(self):
|
|
sql = 'SELECT key FROM webif_store'
|
|
return (ret[0] for ret in server.database.fetch(sql))
|
|
|
|
def __len__(self):
|
|
return server.database.fetch('SELECT count(*) FROM webif_store')[0][0]
|
|
|
|
|
|
class _Reactor(object):
|
|
def callFromThread(self, f, *args, **kwds):
|
|
f(*args, **kwds)
|
|
|
|
class _Threadpool(object):
|
|
def callInThread(self, f, *args, **kwds):
|
|
greenlet(f).switch(*args, **kwds)
|
|
|
|
def run_webif(server_, interface, port, context_factory):
|
|
global server
|
|
server = server_
|
|
global store
|
|
store = PersistentStore()
|
|
try:
|
|
app.secret_key = store['secret_key']
|
|
except:
|
|
app.secret_key = store['secret_key'] = urandom(20)
|
|
assert len(app.secret_key) == 20
|
|
|
|
site = Site(WSGIResource(_Reactor(), _Threadpool(), app.wsgi_app))
|
|
if context_factory is None:
|
|
log.warning("listening on localhost because ssl is disabled")
|
|
reactor.listenTCP(port, site, interface='localhost')
|
|
else:
|
|
reactor.listenSSL(port, site, context_factory, interface=interface)
|
|
|
|
|
|
if __name__ == '__main__': # pragma: no cover
|
|
from minimock import Mock
|
|
server = Mock('server')
|
|
server.root.children = {}
|
|
|
|
app.debug = True
|
|
app.secret_key='debug key'
|
|
app.run(port=8080)
|