initial
This commit is contained in:
2
tvid/__init__.py
Normal file
2
tvid/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .server import serve
|
||||
|
||||
16
tvid/db.py
Normal file
16
tvid/db.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from sqlalchemy import Column, Sequence, Integer, String, DateTime
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
from .server import SQLBASE
|
||||
|
||||
Base = SQLBASE
|
||||
# YAGNI just set admin pw in an env var for now and dont support changing it
|
||||
# yet
|
||||
#class Settings(Base):
|
||||
|
||||
class TV(Base):
|
||||
__tablename__ = 'tvs'
|
||||
id = Column(Integer, Sequence('id_seq'), primary_key=True)
|
||||
displayid = Column(String(20))
|
||||
lastSeen = Column(DateTime)
|
||||
target = Column(String(255))
|
||||
130
tvid/server.py
Normal file
130
tvid/server.py
Normal file
@@ -0,0 +1,130 @@
|
||||
#!/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)
|
||||
Reference in New Issue
Block a user