#!/usr/bin/env python3 import os import urllib.parse import cleancss import tornado.gen import tornado.escape import tornado.httpclient import tornado.ioloop import tornado.web import config import db class BaseHandler(tornado.web.RequestHandler): def render(self, *args, **kwargs): kwargs['api_host'] = config.api_host kwargs['web_host'] = config.web_host return super(BaseHandler, self).render(*args, **kwargs) def render_string(self, *args, **kwargs): s = super(BaseHandler, self).render_string(*args, **kwargs) return s.replace(b'\n', b'') # this is like Django's {% spaceless %} def get_current_user(self): user_id = self.get_secure_cookie('user_id') if user_id: return { 'id': int(user_id), 'username': self.get_secure_cookie('username'), } def create_session(self, user_id, username): self.set_secure_cookie('user_id', str(user_id)) self.set_secure_cookie('username', username) @property def db(self): return self.application.db class MainHandler(BaseHandler): @tornado.gen.coroutine def get(self): self.render('home.html') class RegisterHandler(BaseHandler): @tornado.gen.coroutine def get(self): self.render('register.html') @tornado.gen.coroutine def post(self): username = self.get_argument('username', '') password = self.get_argument('password', '') user_id = yield self.db.create_user(username, password) self.create_session(user_id, username) self.redirect('/') class LoginHandler(BaseHandler): @tornado.gen.coroutine def get(self): self.render('login.html') @tornado.gen.coroutine def post(self): username = self.get_argument('username', '') password = self.get_argument('password', '') user = yield self.db.check_user(username, password) if user: self.create_session(user['id'], user['username']) self.redirect('/') else: self.render('login.html') class LogoutHandler(BaseHandler): def get(self): self.clear_all_cookies() self.redirect('/') class ServersHandler(BaseHandler): @tornado.web.authenticated @tornado.gen.coroutine def get(self): groups = servers = None user_id = self.current_user['id'] groups = yield self.db.get_groups(user_id) servers = yield self.db.get_servers(user_id) self.render('servers.html', groups=groups, servers=servers) class StatsHandler(BaseHandler): @tornado.web.authenticated @tornado.gen.coroutine def get(self, group_id, server_id): group_id = int(group_id) api_key = yield self.db.get_api_key(group_id) servers = yield self.db.get_servers(self.current_user['id']) self.render('stats.html', group_id=group_id, api_key=api_key, servers=servers[group_id]) class GroupsHandler(BaseHandler): @tornado.web.authenticated @tornado.gen.coroutine def get(self): user_id = self.current_user['id'] groups = yield self.db.get_groups(user_id) self.render('groups.html', groups=groups) class GroupCreateHandler(BaseHandler): @tornado.web.authenticated @tornado.gen.coroutine def post(self): yield self.db.create_group(self.current_user['id'], self.get_body_argument('name')) self.redirect('/') class GroupInviteHandler(BaseHandler): @tornado.web.authenticated @tornado.gen.coroutine def post(self): group_id = int(self.get_body_argument('group')) yield self.db.invite_user_group(self.get_body_argument('username'), group_id) self.redirect('/') class CSSHandler(tornado.web.RequestHandler): def get(self, css_path): css_path = os.path.join(os.path.dirname(__file__), 'static', css_path) + '.ccss' with open(css_path, 'r') as f: self.set_header('Content-Type', 'text/css') self.write(cleancss.convert(f)) if __name__ == '__main__': app = tornado.web.Application( handlers=[ (r'/', MainHandler), (r'/register', RegisterHandler), (r'/login', LoginHandler), (r'/logout', LogoutHandler), (r'/servers', ServersHandler), (r'/stats/(\d+)/(\d+)', StatsHandler), (r'/groups', GroupsHandler), (r'/groups/create', GroupCreateHandler), (r'/groups/invite', GroupInviteHandler), (r'/(css/.+)\.css', CSSHandler), ], template_path=os.path.join(os.path.dirname(__file__), 'templates'), static_path=os.path.join(os.path.dirname(__file__), 'static'), login_url='/login', cookie_secret=config.cookie_secret, debug=config.debug, ) app.listen(config.web_port) app.db = db.MomokoDB() print('listening on :%d' % config.web_port) tornado.ioloop.IOLoop.instance().start()