You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

205 lines
5.5 KiB

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.encoding import sp
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:
self.write(views[route](self))
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(*args):
return template_loader.load('index.html').generate(sep = os.sep, fireEvent = fireEvent, Env = Env)
addView('', index)
# Web view
def robots(handler):
handler.set_header('Content-Type', 'text/plain')
return 'User-agent: * \n' \
'Disallow: /'
addView('robots.txt', robots)
# Manifest
def manifest(handler):
web_base = Env.get('web_base')
static_base = Env.get('static_path')
lines = [
'CACHE MANIFEST',
'# %s theme' % ('dark' if Env.setting('dark_theme') else 'light'),
'',
'CACHE:',
''
]
if not Env.get('dev'):
# CSS
for url in fireEvent('clientscript.get_styles', single = True):
lines.append(web_base + url)
# Scripts
for url in fireEvent('clientscript.get_scripts', single = True):
lines.append(web_base + url)
# Favicon
lines.append(static_base + 'images/favicon.ico')
# Fonts
font_folder = sp(os.path.join(Env.get('app_dir'), 'couchpotato', 'static', 'fonts'))
for subfolder, dirs, files in os.walk(font_folder, topdown = False):
for file in files:
if '.woff' in file:
lines.append(static_base + 'fonts/' + file + ('?%s' % os.path.getmtime(os.path.join(font_folder, file))))
else:
lines.append('# Not caching anything in dev mode')
# End lines
lines.extend(['',
'NETWORK: ',
'*'])
handler.set_header('Content-Type', 'text/cache-manifest')
return '\n'.join(lines)
addView('couchpotato.appcache', manifest)
# API docs
def apiDocs(*args):
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(*args):
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')