tvid/tvid/server.py

131 lines
4.2 KiB
Python

#!/usr/bin/env python3
# this is a quick hack, to be improved later. trying to do the simplest
# thing that will possibly work.
## # TODO
##
## * put page content into templates/static files
## * clean up FIXME
import bottle
from bottle import route, run, request, response, redirect
from bottle import HTTPError, template
from sqlalchemy.ext.declarative import declarative_base
from bottle.ext import sqlalchemy
from pprint import pprint
from sqlalchemy import create_engine
import os
import random
import string
from datetime import datetime
VERSION = '0.0.1'
PORT = os.environ.get('PORT', 8080)
DEBUG = os.environ.get('DEBUG', False)
SQLITE_FILENAME = os.environ.get('SQLITE_FILENAME','/data/db.sqlite')
DATABASE_URL = os.environ.get('DATABASE_URL','sqlite:///' + SQLITE_FILENAME)
ADMINPSK = os.environ.get('ADMINPSK','hunter2')
# sorry for global
SQLBASE = declarative_base()
# FIXME make this skip letters not in base58
def randomUpper(count):
return ''.join(random.choice(string.ascii_uppercase) for _ in range(count))
# FIXME maybe make the IDs longer
def genRandomTVID():
tvid = str(randomUpper(3) + "-" + randomUpper(3))
return tvid
def serve():
app = bottle.Bottle()
# pull in models
from .db import TV
engine = create_engine(DATABASE_URL, echo=True)
plugin = sqlalchemy.Plugin(
engine, # SQLAlchemy engine created with create_engine function.
SQLBASE.metadata, # SQLAlchemy metadata, required only if create=True.
keyword='db', # Keyword used to inject session database in a route (default 'db').
create=True, # If it is true, execute `metadata.create_all(engine)` when plugin is applied (default False).
commit=True, # If it is true, plugin commit changes after route is executed (default True).
use_kwargs=False
)
app.install(plugin)
# here we cookie them if they have no cookie, then redirect them to the
# cookie'd value (whether preexisting or new).
@app.get('/')
def indexpage():
c = request.get_cookie("tvid")
if c:
# redirect
redirect('/tv/' + c)
else:
newid = genRandomTVID()
response.set_cookie("tvid", newid)
redirect('/tv/' + newid)
@app.get('/style.css')
def stylesheet():
return template('style')
# here we check to see if they have a redirect URL in the db. if they do
# we send them there. if they don't, we display their ID really big,
# reloading the page once per hour.
@app.get('/tv/<displayid>')
def tvpage(db, displayid=None):
# FIXME regex check id to make sure displayid is right format,
# return error if not
if id is None:
return template('nocookie')
# check db for tv id
tv = db.query(TV).filter_by(displayid=displayid).first()
if tv:
tv.lastSeen = datetime.now()
db.add(tv)
if tv.target:
redirect(tv.target)
else:
return template('displayid', id=displayid, version=VERSION)
else:
# otherwise, just show their display ID bigly and keep them
# bouncing periodically until some admin configures them
# a target:
# update lastseen here:
newtv = TV(displayid=displayid,lastSeen=datetime.now())
db.add(newtv)
return template('displayid', id=displayid, version=VERSION)
# here we display the administration list of TVs if logged in
# if logged out then redirect to /login
# FIXME make this use sessions instead of just storing PSK in a cookie
# https://bottlepy.org/docs/dev/recipes.html
@app.get('/admin')
def adminpage():
c = request.get_cookie("adminpw")
# FIXME check their 'adminpw' cookie here, redirect to /loign
return "Hello World!"
# here we ask for a password and cookie them and bounce them back to /admin
@app.get('/login')
def checklogin():
raise NotImplementedError()
#response.set_cookie("adminpw", whatever)
redirect('/login')
@app.get('/logut')
def logout():
response.set_cookie("adminpw", "")
redirect('/login')
app.run(host='0.0.0.0', port=PORT, debug=DEBUG)