import os import time import traceback from couchpotato.api import api_docs, api_docs_missing, api from couchpotato.core.event import fireEvent from couchpotato.core.helpers.variable import md5, tryInt from couchpotato.core.logger import CPLog from couchpotato.environment import Env from tornado import template from tornado.web import RequestHandler, authenticated log = CPLog(__name__) views = {} template_loader = template.Loader(os.path.join(os.path.dirname(__file__), 'templates')) class BaseHandler(RequestHandler): def get_current_user(self): username = Env.setting('username') password = Env.setting('password') if username and password: return self.get_secure_cookie('user') else: # Login when no username or password are set return True # Main web handler class WebHandler(BaseHandler): @authenticated def get(self, route, *args, **kwargs): route = route.strip('/') if not views.get(route): page_not_found(self) return try: if route == 'robots.txt': self.set_header('Content-Type', 'text/plain') self.write(views[route]()) except: log.error("Failed doing web request '%s': %s", (route, traceback.format_exc())) self.write({'success': False, 'error': 'Failed returning results'}) def addView(route, func): views[route] = func def get_db(): return Env.get('db') # Web view def index(): return template_loader.load('index.html').generate(sep = os.sep, fireEvent = fireEvent, Env = Env) addView('', index) # Web view def robots(): return 'User-agent: * \n' \ 'Disallow: /' addView('robots.txt', robots) # API docs def apiDocs(): routes = list(api.keys()) if api_docs.get(''): del api_docs[''] del api_docs_missing[''] return template_loader.load('api.html').generate(fireEvent = fireEvent, routes = sorted(routes), api_docs = api_docs, api_docs_missing = sorted(api_docs_missing), Env = Env) addView('docs', apiDocs) # Database debug manager def databaseManage(): return template_loader.load('database.html').generate(fireEvent = fireEvent, Env = Env) addView('database', databaseManage) # Make non basic auth option to get api key class KeyHandler(RequestHandler): def get(self, *args, **kwargs): api_key = None try: username = Env.setting('username') password = Env.setting('password') if (self.get_argument('u') == md5(username) or not username) and (self.get_argument('p') == password or not password): api_key = Env.setting('api_key') self.write({ 'success': api_key is not None, 'api_key': api_key }) except: log.error('Failed doing key request: %s', (traceback.format_exc())) self.write({'success': False, 'error': 'Failed returning results'}) class LoginHandler(BaseHandler): def get(self, *args, **kwargs): if self.get_current_user(): self.redirect(Env.get('web_base')) else: self.write(template_loader.load('login.html').generate(sep = os.sep, fireEvent = fireEvent, Env = Env)) def post(self, *args, **kwargs): api_key = None username = Env.setting('username') password = Env.setting('password') if (self.get_argument('username') == username or not username) and (md5(self.get_argument('password')) == password or not password): api_key = Env.setting('api_key') if api_key: remember_me = tryInt(self.get_argument('remember_me', default = 0)) self.set_secure_cookie('user', api_key, expires_days = 30 if remember_me > 0 else None) self.redirect(Env.get('web_base')) class LogoutHandler(BaseHandler): def get(self, *args, **kwargs): self.clear_cookie('user') self.redirect('%slogin/' % Env.get('web_base')) def page_not_found(rh): index_url = Env.get('web_base') url = rh.request.uri[len(index_url):] if url[:3] != 'api': r = index_url + '#' + url.lstrip('/') rh.redirect(r) else: if not Env.get('dev'): time.sleep(0.1) rh.set_status(404) rh.write('Wrong API key used')