Added new WebUI login interface

This commit is contained in:
echel0n 2014-12-07 12:58:41 -08:00
parent e2be96542d
commit 5f58282260
6 changed files with 200 additions and 100 deletions

View File

@ -3134,3 +3134,73 @@ pnotify.css
margin-top: -12px; margin-top: -12px;
margin-right: -10px; margin-right: -10px;
} }
/* =======================================================================
login.css
========================================================================== */
.login {
display: block;
}
.login h1 {
padding: 0 0 10px;
font-size: 60px;
font-family: Lobster;
font-weight: normal;
}
.login form {
padding: 0;
height: 300px;
width: 400px;
position: fixed;
left: 50%;
top: 50%;
margin: -200px 0 0 -200px;
}
@media all and (max-width: 480px) {
.login form {
padding: 0;
height: 300px;
width: 90%;
position: absolute;
left: 5%;
top: 10px;
margin: 0;
}
}
.login .ctrlHolder {
padding: 0;
margin: 0 0 20px;
}
.login .ctrlHolder:hover {
background: none;
}
.login input[type=text],
.login input[type=password] {
width: 100% !important;
font-size: 25px;
padding: 14px !important;
}
.login .remember_me {
font-size: 15px;
float: left;
width: 150px;
padding: 20px 0;
}
.login .remember_me .check {
margin: 5px 5px 0 0;
}
.login .button {
font-size: 25px;
padding: 20px;
float: right;
}

View File

@ -140,6 +140,7 @@
<a class="navbar-brand" href="$sbRoot/home/" title="SickRage"><img alt="SickRage" src="$sbRoot/images/sickrage.png" style="height: 50px;" class="img-responsive pull-left" /></a> <a class="navbar-brand" href="$sbRoot/home/" title="SickRage"><img alt="SickRage" src="$sbRoot/images/sickrage.png" style="height: 50px;" class="img-responsive pull-left" /></a>
</div> </div>
#if $sbLogin:
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li id="NAVhome" class="dropdown"> <li id="NAVhome" class="dropdown">
@ -215,11 +216,12 @@
<li><a href="$sbRoot/manage/manageSearches/forceVersionCheck"><i class="menu-icon-update"></i>&nbsp;Force Version Check</a></li> <li><a href="$sbRoot/manage/manageSearches/forceVersionCheck"><i class="menu-icon-update"></i>&nbsp;Force Version Check</a></li>
<li><a href="$sbRoot/home/restart/?pid=$sbPID" class="confirm restart"><i class="menu-icon-restart"></i>&nbsp;Restart</a></li> <li><a href="$sbRoot/home/restart/?pid=$sbPID" class="confirm restart"><i class="menu-icon-restart"></i>&nbsp;Restart</a></li>
<li><a href="$sbRoot/home/shutdown/?pid=$sbPID" class="confirm shutdown"><i class="menu-icon-shutdown"></i>&nbsp;Shutdown</a></li> <li><a href="$sbRoot/home/shutdown/?pid=$sbPID" class="confirm shutdown"><i class="menu-icon-shutdown"></i>&nbsp;Shutdown</a></li>
<li><a href="$sbRoot/logout" class="confirm logout"><i class="menu-icon-shutdown"></i>&nbsp;Logout</a></li>
</ul> </ul>
</li> </li>
<li id="donate"><a href="http://sr-upgrade.appspot.com" rel="noreferrer" onclick="window.open('${sickbeard.ANON_REDIRECT}' + this.href); return false;"><img src="$sbRoot/images/donate.jpg" alt="[donate]" class="navbaricon hidden-xs" /></a></li> <li id="donate"><a href="http://sr-upgrade.appspot.com" rel="noreferrer" onclick="window.open('${sickbeard.ANON_REDIRECT}' + this.href); return false;"><img src="$sbRoot/images/donate.jpg" alt="[donate]" class="navbaricon hidden-xs" /></a></li>
</ul> </ul>
#end if
</div><!-- /.navbar-collapse --> </div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid --> </div><!-- /.container-fluid -->
</nav> </nav>

View File

@ -0,0 +1,21 @@
#import sickbeard
#set global $title="Login"
#set global $sbPath = ".."
#set global $topmenu="login"#
#import os.path
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_top.tmpl")
<div class="login">
<form action="" method="post">
<h1>SickRage</h1>
<div class="ctrlHolder"><input class="inlay" name="username" type="text" placeholder="Username" autocomplete="off" /></div>
<div class="ctrlHolder"><input class="inlay" name="password" type="password" placeholder="Password" autocomplete="off" /></div>
<div class="ctrlHolder">
<label class="remember_me" title="for 30 days"><input class="inlay" id="remember_me" name="remember_me" type="checkbox" value="1" checked="checked" /> Remember me</label>
<input class="button" name="submit" type="submit" value="Login" />
</div>
</form>
</div>

View File

@ -25,9 +25,10 @@ import urllib
import datetime import datetime
import re import re
import traceback import traceback
import sickbeard
import webserve
import sickbeard
from sickbeard.webserve import PageTemplate
from sickbeard import db, logger, exceptions, history, ui, helpers from sickbeard import db, logger, exceptions, history, ui, helpers
from sickbeard import encodingKludge as ek from sickbeard import encodingKludge as ek
from sickbeard import search_queue from sickbeard import search_queue
@ -46,6 +47,9 @@ except ImportError:
from lib import subliminal from lib import subliminal
from tornado.web import RequestHandler
from tornado.routes import route
indexer_ids = ["indexerid", "tvdbid", "tvrageid"] indexer_ids = ["indexerid", "tvdbid", "tvrageid"]
dateFormat = "%Y-%m-%d" dateFormat = "%Y-%m-%d"
@ -67,7 +71,8 @@ result_type_map = {RESULT_SUCCESS: "success",
} }
# basically everything except RESULT_SUCCESS / success is bad # basically everything except RESULT_SUCCESS / success is bad
class Api(webserve.MainHandler): @route('/api/(.*)(/?)')
class ApiHandler(RequestHandler):
""" api class that returns json results """ """ api class that returns json results """
version = 4 # use an int since float-point is unpredictible version = 4 # use an int since float-point is unpredictible
intent = 4 intent = 4
@ -123,7 +128,7 @@ class Api(webserve.MainHandler):
def builder(self): def builder(self):
""" expose the api-builder template """ """ expose the api-builder template """
t = webserve.PageTemplate(headers=self.request.headers, file="apiBuilder.tmpl") t = PageTemplate(headers=self.request.headers, file="apiBuilder.tmpl")
def titler(x): def titler(x):
if not x or sickbeard.SORT_ARTICLE: if not x or sickbeard.SORT_ARTICLE:
@ -159,7 +164,7 @@ class Api(webserve.MainHandler):
else: else:
t.apikey = "api key not generated" t.apikey = "api key not generated"
return webserve._munge(t) return t
def _out_as_json(self, dict): def _out_as_json(self, dict):
self.set_header("Content-Type", "application/json;charset=UTF-8'") self.set_header("Content-Type", "application/json;charset=UTF-8'")
@ -298,7 +303,7 @@ def filter_params(cmd, args, kwargs):
return curArgs, curKwargs return curArgs, curKwargs
class ApiCall(object): class ApiCall(ApiHandler):
_help = {"desc": "No help message available. Please tell the devs that a help msg is missing for this cmd"} _help = {"desc": "No help message available. Please tell the devs that a help msg is missing for this cmd"}
def __init__(self, handler, args, kwargs): def __init__(self, handler, args, kwargs):
@ -1440,7 +1445,7 @@ class CMD_SickBeard(ApiCall):
def run(self): def run(self):
""" display misc sickrage related information """ """ display misc sickrage related information """
data = {"sb_version": sickbeard.BRANCH, "api_version": Api.version, data = {"sb_version": sickbeard.BRANCH, "api_version": self.version,
"api_commands": sorted(_functionMaper.keys())} "api_commands": sorted(_functionMaper.keys())}
return _responds(RESULT_SUCCESS, data) return _responds(RESULT_SUCCESS, data)
@ -2425,9 +2430,6 @@ class CMD_ShowPause(ApiCall):
showObj.paused = 0 showObj.paused = 0
return _responds(RESULT_SUCCESS, msg=str(showObj.name) + " has been unpaused") return _responds(RESULT_SUCCESS, msg=str(showObj.name) + " has been unpaused")
return _responds(RESULT_FAILURE, msg=str(showObj.name) + " was unable to be paused")
class CMD_ShowRefresh(ApiCall): class CMD_ShowRefresh(ApiCall):
_help = {"desc": "refresh a show in sickrage", _help = {"desc": "refresh a show in sickrage",
"requiredParameters": { "requiredParameters": {

View File

@ -18,8 +18,6 @@
from __future__ import with_statement from __future__ import with_statement
import base64
import functools
import traceback import traceback
import os import os
import time import time
@ -77,8 +75,9 @@ except ImportError:
from Cheetah.Template import Template from Cheetah.Template import Template
import tornado.escape
from tornado.routes import route from tornado.routes import route
from tornado.web import RequestHandler from tornado.web import RequestHandler, authenticated
from bug_tracker import BugTracker from bug_tracker import BugTracker
@ -87,38 +86,6 @@ def check_basic_auth(username, password):
if username == sickbeard.WEB_USERNAME and password == sickbeard.WEB_PASSWORD: if username == sickbeard.WEB_USERNAME and password == sickbeard.WEB_PASSWORD:
return True return True
def basic_auth(checkfunc, realm="Authentication Required!"):
def wrap(method):
def request_auth(self):
self.set_header('WWW-Authenticate', 'Basic realm=%s' % realm)
self.set_status(401)
self.finish()
return False
@functools.wraps(method)
def wrapper(self, *args, **kwargs):
if not (sickbeard.WEB_USERNAME and sickbeard.WEB_PASSWORD):
return method(self, *args, **kwargs)
auth = self.request.headers.get('Authorization')
if auth is None or not auth.startswith('Basic '):
return request_auth(self)
auth = auth[6:]
try:
username, password = base64.decodestring(auth).split(':', 2)
except:
return request_auth(self)
if checkfunc(username, password):
self.request.basic_auth = (username, password)
return method(self, *args, **kwargs)
else:
return request_auth(self)
return wrapper
return wrap
def page_not_found(rh): def page_not_found(rh):
index_url = sickbeard.WEB_ROOT index_url = sickbeard.WEB_ROOT
url = rh.request.uri[len(index_url):] url = rh.request.uri[len(index_url):]
@ -221,7 +188,7 @@ class Menus:
return menu return menu
class PageTemplate(Template): class PageTemplate(Template):
def __init__(self, headers, *args, **kwargs): def __init__(self, rh, *args, **kwargs):
kwargs['file'] = os.path.join(sickbeard.PROG_DIR, "gui/" + sickbeard.GUI_NAME + "/interfaces/default/", kwargs['file']) kwargs['file'] = os.path.join(sickbeard.PROG_DIR, "gui/" + sickbeard.GUI_NAME + "/interfaces/default/", kwargs['file'])
super(PageTemplate, self).__init__(*args, **kwargs) super(PageTemplate, self).__init__(*args, **kwargs)
@ -231,19 +198,20 @@ class PageTemplate(Template):
self.sbHttpsEnabled = sickbeard.ENABLE_HTTPS self.sbHttpsEnabled = sickbeard.ENABLE_HTTPS
self.sbHandleReverseProxy = sickbeard.HANDLE_REVERSE_PROXY self.sbHandleReverseProxy = sickbeard.HANDLE_REVERSE_PROXY
self.sbThemeName = sickbeard.THEME_NAME self.sbThemeName = sickbeard.THEME_NAME
self.sbLogin = rh.get_current_user()
if headers['Host'][0] == '[': if rh.request.headers['Host'][0] == '[':
self.sbHost = re.match("^\[.*\]", headers['Host'], re.X | re.M | re.S).group(0) self.sbHost = re.match("^\[.*\]", rh.request.headers['Host'], re.X | re.M | re.S).group(0)
else: else:
self.sbHost = re.match("^[^:]+", headers['Host'], re.X | re.M | re.S).group(0) self.sbHost = re.match("^[^:]+", rh.request.headers['Host'], re.X | re.M | re.S).group(0)
if "X-Forwarded-Host" in headers: if "X-Forwarded-Host" in rh.request.headers:
self.sbHost = headers['X-Forwarded-Host'] self.sbHost = rh.request.headers['X-Forwarded-Host']
if "X-Forwarded-Port" in headers: if "X-Forwarded-Port" in rh.request.headers:
sbHttpPort = headers['X-Forwarded-Port'] sbHttpPort = rh.request.headers['X-Forwarded-Port']
self.sbHttpsPort = sbHttpPort self.sbHttpsPort = sbHttpPort
if "X-Forwarded-Proto" in headers: if "X-Forwarded-Proto" in rh.request.headers:
self.sbHttpsEnabled = True if headers['X-Forwarded-Proto'] == 'https' else False self.sbHttpsEnabled = True if rh.request.headers['X-Forwarded-Proto'] == 'https' else False
logPageTitle = 'Logs &amp; Errors' logPageTitle = 'Logs &amp; Errors'
if len(classes.ErrorViewer.errors): if len(classes.ErrorViewer.errors):
@ -268,8 +236,14 @@ class PageTemplate(Template):
return super(PageTemplate, self).compile(*args, **kwargs) return super(PageTemplate, self).compile(*args, **kwargs)
class BaseHandler(RequestHandler): class BaseHandler(RequestHandler):
def get_current_user(self):
if sickbeard.WEB_USERNAME and sickbeard.WEB_PASSWORD:
return self.get_secure_cookie('user')
else:
return True
def _genericMessage(self, subject, message): def _genericMessage(self, subject, message):
t = PageTemplate(headers=self.request.headers, file="genericMessage.tmpl") t = PageTemplate(rh=self, file="genericMessage.tmpl")
t.submenu = Menus().HomeMenu() t.submenu = Menus().HomeMenu()
t.subject = subject t.subject = subject
t.message = message t.message = message
@ -296,7 +270,7 @@ class KeyHandler(RequestHandler):
logger.log('Failed doing key request: %s' % (traceback.format_exc()), logger.ERROR) logger.log('Failed doing key request: %s' % (traceback.format_exc()), logger.ERROR)
self.write({'success': False, 'error': 'Failed returning results'}) self.write({'success': False, 'error': 'Failed returning results'})
class UI(RequestHandler): class UIHandler(RequestHandler):
def add_message(self): def add_message(self):
ui.notifications.message('Test 1', 'This is test number 1') ui.notifications.message('Test 1', 'This is test number 1')
ui.notifications.error('Test 2', 'This is test number 2') ui.notifications.error('Test 2', 'This is test number 2')
@ -338,8 +312,7 @@ class WebHandler(BaseHandler):
</body> </body>
</html>""" % (error, error, </html>""" % (error, error,
trace_info, request_info)) trace_info, request_info))
@authenticated
@basic_auth(check_basic_auth, "SickRage")
def get(self, route, *args, **kwargs): def get(self, route, *args, **kwargs):
route = route.strip('/') route = route.strip('/')
@ -372,6 +345,36 @@ class WebHandler(BaseHandler):
logger.log("Failed doing web request '%s': %s" % (route, traceback.format_exc()), logger.ERROR) logger.log("Failed doing web request '%s': %s" % (route, traceback.format_exc()), logger.ERROR)
self.write({'success': False, 'error': 'Failed returning results'}) self.write({'success': False, 'error': 'Failed returning results'})
class LoginHandler(BaseHandler):
def get(self, *args, **kwargs):
if self.get_current_user():
self.redirect('%shome/' % sickbeard.WEB_ROOT)
else:
t = PageTemplate(rh=self, file="login.tmpl")
self.write(ek.ss(t).encode('utf-8', 'xmlcharrefreplace'))
def post(self, *args, **kwargs):
api_key = None
username = sickbeard.WEB_USERNAME
password = sickbeard.WEB_PASSWORD
if (self.get_argument('username') == username or not username) and (self.get_argument('password') == password or not password):
api_key = sickbeard.API_KEY
if api_key:
remember_me = int(self.get_argument('remember_me', default=0) or 0)
self.set_secure_cookie('user', api_key, expires_days=30 if remember_me > 0 else None)
self.redirect('%shome/' % sickbeard.WEB_ROOT)
class LogoutHandler(BaseHandler):
def get(self, *args, **kwargs):
self.clear_cookie("user")
self.redirect('%slogin/' % sickbeard.WEB_ROOT)
@route('(.*)(/?)') @route('(.*)(/?)')
class WebRoot(WebHandler): class WebRoot(WebHandler):
def index(self): def index(self):
@ -529,7 +532,7 @@ class WebRoot(WebHandler):
sql_results.sort(sorts[sickbeard.COMING_EPS_SORT]) sql_results.sort(sorts[sickbeard.COMING_EPS_SORT])
t = PageTemplate(headers=self.request.headers, file="comingEpisodes.tmpl") t = PageTemplate(rh=self, file="comingEpisodes.tmpl")
# paused_item = { 'title': '', 'path': 'toggleComingEpsDisplayPaused' } # paused_item = { 'title': '', 'path': 'toggleComingEpsDisplayPaused' }
# paused_item['title'] = 'Hide Paused' if sickbeard.COMING_EPS_DISPLAY_PAUSED else 'Show Paused' # paused_item['title'] = 'Hide Paused' if sickbeard.COMING_EPS_DISPLAY_PAUSED else 'Show Paused'
paused_item = {'title': 'View Paused:', 'path': {'': ''}} paused_item = {'title': 'View Paused:', 'path': {'': ''}}
@ -630,7 +633,7 @@ class WebRoot(WebHandler):
@route('/home/(.*)(/?)') @route('/home/(.*)(/?)')
class Home(WebRoot): class Home(WebRoot):
def index(self): def index(self):
t = PageTemplate(headers=self.request.headers, file="home.tmpl") t = PageTemplate(rh=self, file="home.tmpl")
if sickbeard.ANIME_SPLIT_HOME: if sickbeard.ANIME_SPLIT_HOME:
shows = [] shows = []
anime = [] anime = []
@ -955,7 +958,7 @@ class Home(WebRoot):
if str(pid) != str(sickbeard.PID): if str(pid) != str(sickbeard.PID):
self.redirect("/home/") self.redirect("/home/")
t = PageTemplate(headers=self.request.headers, file="restart.tmpl") t = PageTemplate(rh=self, file="restart.tmpl")
t.submenu = Menus().HomeMenu() t.submenu = Menus().HomeMenu()
# restart # restart
@ -973,7 +976,7 @@ class Home(WebRoot):
# do a hard restart # do a hard restart
sickbeard.events.put(sickbeard.events.SystemEvent.RESTART) sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
t = PageTemplate(headers=self.request.headers, file="restart_bare.tmpl") t = PageTemplate(rh=self, file="restart_bare.tmpl")
return t return t
else: else:
return self._genericMessage("Update Failed", return self._genericMessage("Update Failed",
@ -1005,7 +1008,7 @@ class Home(WebRoot):
[showObj.indexerid] [showObj.indexerid]
) )
t = PageTemplate(headers=self.request.headers, file="displayShow.tmpl") t = PageTemplate(rh=self, file="displayShow.tmpl")
t.submenu = [{'title': 'Edit', 'path': 'home/editShow?show=%d' % showObj.indexerid}] t.submenu = [{'title': 'Edit', 'path': 'home/editShow?show=%d' % showObj.indexerid}]
try: try:
@ -1163,7 +1166,7 @@ class Home(WebRoot):
showObj.exceptions = scene_exceptions.get_scene_exceptions(showObj.indexerid) showObj.exceptions = scene_exceptions.get_scene_exceptions(showObj.indexerid)
if not location and not anyQualities and not bestQualities and not flatten_folders: if not location and not anyQualities and not bestQualities and not flatten_folders:
t = PageTemplate(headers=self.request.headers, file="editShow.tmpl") t = PageTemplate(rh=self, file="editShow.tmpl")
t.submenu = Menus().HomeMenu() t.submenu = Menus().HomeMenu()
if showObj.is_anime: if showObj.is_anime:
@ -1646,7 +1649,7 @@ class Home(WebRoot):
# present season DESC episode DESC on screen # present season DESC episode DESC on screen
ep_obj_rename_list.reverse() ep_obj_rename_list.reverse()
t = PageTemplate(headers=self.request.headers, file="testRename.tmpl") t = PageTemplate(rh=self, file="testRename.tmpl")
t.submenu = [{'title': 'Edit', 'path': 'home/editShow?show=%d' % showObj.indexerid}] t.submenu = [{'title': 'Edit', 'path': 'home/editShow?show=%d' % showObj.indexerid}]
t.ep_obj_list = ep_obj_rename_list t.ep_obj_list = ep_obj_rename_list
t.show = showObj t.show = showObj
@ -1923,7 +1926,7 @@ class Home(WebRoot):
class HomePostProcess(Home): class HomePostProcess(Home):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="home_postprocess.tmpl") t = PageTemplate(rh=self, file="home_postprocess.tmpl")
t.submenu = Menus().HomeMenu() t.submenu = Menus().HomeMenu()
return t return t
@ -1960,7 +1963,7 @@ class HomePostProcess(Home):
class NewHomeAddShows(Home): class NewHomeAddShows(Home):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="home_addShows.tmpl") t = PageTemplate(rh=self, file="home_addShows.tmpl")
t.submenu = Menus().HomeMenu() t.submenu = Menus().HomeMenu()
return t return t
@ -2014,7 +2017,7 @@ class NewHomeAddShows(Home):
def massAddTable(self, rootDir=None): def massAddTable(self, rootDir=None):
t = PageTemplate(headers=self.request.headers, file="home_massAddTable.tmpl") t = PageTemplate(rh=self, file="home_massAddTable.tmpl")
t.submenu = Menus().HomeMenu() t.submenu = Menus().HomeMenu()
if not rootDir: if not rootDir:
@ -2100,7 +2103,7 @@ class NewHomeAddShows(Home):
Display the new show page which collects a tvdb id, folder, and extra options and Display the new show page which collects a tvdb id, folder, and extra options and
posts them to addNewShow posts them to addNewShow
""" """
t = PageTemplate(headers=self.request.headers, file="home_newShow.tmpl") t = PageTemplate(rh=self, file="home_newShow.tmpl")
t.submenu = Menus().HomeMenu() t.submenu = Menus().HomeMenu()
indexer, show_dir, indexer_id, show_name = self.split_extra_show(show_to_add) indexer, show_dir, indexer_id, show_name = self.split_extra_show(show_to_add)
@ -2144,7 +2147,7 @@ class NewHomeAddShows(Home):
Display the new show page which collects a tvdb id, folder, and extra options and Display the new show page which collects a tvdb id, folder, and extra options and
posts them to addNewShow posts them to addNewShow
""" """
t = PageTemplate(headers=self.request.headers, file="home_recommendedShows.tmpl") t = PageTemplate(rh=self, file="home_recommendedShows.tmpl")
t.submenu = Menus().HomeMenu() t.submenu = Menus().HomeMenu()
return t return t
@ -2194,7 +2197,7 @@ class NewHomeAddShows(Home):
Display the new show page which collects a tvdb id, folder, and extra options and Display the new show page which collects a tvdb id, folder, and extra options and
posts them to addNewShow posts them to addNewShow
""" """
t = PageTemplate(headers=self.request.headers, file="home_trendingShows.tmpl") t = PageTemplate(rh=self, file="home_trendingShows.tmpl")
t.submenu = Menus().HomeMenu() t.submenu = Menus().HomeMenu()
t.trending_shows = [] t.trending_shows = []
@ -2221,7 +2224,7 @@ class NewHomeAddShows(Home):
""" """
Prints out the page to add existing shows from a root dir Prints out the page to add existing shows from a root dir
""" """
t = PageTemplate(headers=self.request.headers, file="home_addExistingShow.tmpl") t = PageTemplate(rh=self, file="home_addExistingShow.tmpl")
t.submenu = Menus().HomeMenu() t.submenu = Menus().HomeMenu()
return t return t
@ -2450,7 +2453,7 @@ class NewHomeAddShows(Home):
@route('/manage/(.*)(/?)') @route('/manage/(.*)(/?)')
class Manage(WebRoot): class Manage(WebRoot):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="manage.tmpl") t = PageTemplate(rh=self, file="manage.tmpl")
t.submenu = Menus().ManageMenu() t.submenu = Menus().ManageMenu()
return t return t
@ -2487,7 +2490,7 @@ class Manage(WebRoot):
else: else:
status_list = [] status_list = []
t = PageTemplate(headers=self.request.headers, file="manage_episodeStatuses.tmpl") t = PageTemplate(rh=self, file="manage_episodeStatuses.tmpl")
t.submenu = Menus().ManageMenu() t.submenu = Menus().ManageMenu()
t.whichStatus = whichStatus t.whichStatus = whichStatus
@ -2596,7 +2599,7 @@ class Manage(WebRoot):
def subtitleMissed(self, whichSubs=None): def subtitleMissed(self, whichSubs=None):
t = PageTemplate(headers=self.request.headers, file="manage_subtitleMissed.tmpl") t = PageTemplate(rh=self, file="manage_subtitleMissed.tmpl")
t.submenu = Menus().ManageMenu() t.submenu = Menus().ManageMenu()
t.whichSubs = whichSubs t.whichSubs = whichSubs
@ -2681,7 +2684,7 @@ class Manage(WebRoot):
def backlogOverview(self, *args, **kwargs): def backlogOverview(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="manage_backlogOverview.tmpl") t = PageTemplate(rh=self, file="manage_backlogOverview.tmpl")
t.submenu = Menus().ManageMenu() t.submenu = Menus().ManageMenu()
showCounts = {} showCounts = {}
@ -2723,7 +2726,7 @@ class Manage(WebRoot):
def massEdit(self, toEdit=None): def massEdit(self, toEdit=None):
t = PageTemplate(headers=self.request.headers, file="manage_massEdit.tmpl") t = PageTemplate(rh=self, file="manage_massEdit.tmpl")
t.submenu = Menus().ManageMenu() t.submenu = Menus().ManageMenu()
if not toEdit: if not toEdit:
@ -3073,7 +3076,7 @@ class Manage(WebRoot):
def manageTorrents(self, *args, **kwargs): def manageTorrents(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="manage_torrents.tmpl") t = PageTemplate(rh=self, file="manage_torrents.tmpl")
t.info_download_station = '' t.info_download_station = ''
t.submenu = Menus().ManageMenu() t.submenu = Menus().ManageMenu()
@ -3114,7 +3117,7 @@ class Manage(WebRoot):
if toRemove: if toRemove:
self.redirect('/manage/failedDownloads/') self.redirect('/manage/failedDownloads/')
t = PageTemplate(headers=self.request.headers, file="manage_failedDownloads.tmpl") t = PageTemplate(rh=self, file="manage_failedDownloads.tmpl")
t.failedResults = sqlResults t.failedResults = sqlResults
t.limit = limit t.limit = limit
t.submenu = Menus().ManageMenu() t.submenu = Menus().ManageMenu()
@ -3124,7 +3127,7 @@ class Manage(WebRoot):
@route('/manage/manageSearches/(.*)(/?)') @route('/manage/manageSearches/(.*)(/?)')
class ManageSearches(Manage): class ManageSearches(Manage):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="manage_manageSearches.tmpl") t = PageTemplate(rh=self, file="manage_manageSearches.tmpl")
# t.backlogPI = sickbeard.backlogSearchScheduler.action.getProgressIndicator() # t.backlogPI = sickbeard.backlogSearchScheduler.action.getProgressIndicator()
t.backlogPaused = sickbeard.searchQueueScheduler.action.is_backlog_paused() # @UndefinedVariable t.backlogPaused = sickbeard.searchQueueScheduler.action.is_backlog_paused() # @UndefinedVariable
t.backlogRunning = sickbeard.searchQueueScheduler.action.is_backlog_in_progress() # @UndefinedVariable t.backlogRunning = sickbeard.searchQueueScheduler.action.is_backlog_in_progress() # @UndefinedVariable
@ -3244,7 +3247,7 @@ class History(WebRoot):
history['actions'].append(action) history['actions'].append(action)
history['actions'].sort(key=lambda x: x['time'], reverse=True) history['actions'].sort(key=lambda x: x['time'], reverse=True)
t = PageTemplate(headers=self.request.headers, file="history.tmpl") t = PageTemplate(rh=self, file="history.tmpl")
t.historyResults = sqlResults t.historyResults = sqlResults
t.compactResults = compact t.compactResults = compact
t.limit = limit t.limit = limit
@ -3277,7 +3280,7 @@ class History(WebRoot):
@route('/config/(.*)(/?)') @route('/config/(.*)(/?)')
class Config(WebRoot): class Config(WebRoot):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="config.tmpl") t = PageTemplate(rh=self, file="config.tmpl")
t.submenu = Menus().ConfigMenu() t.submenu = Menus().ConfigMenu()
return t return t
@ -3286,11 +3289,10 @@ class Config(WebRoot):
class ConfigGeneral(Config): class ConfigGeneral(Config):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="config_general.tmpl") t = PageTemplate(rh=self, file="config_general.tmpl")
t.submenu = Menus().ConfigMenu() t.submenu = Menus().ConfigMenu()
return t return t
def saveRootDirs(self, rootDirString=None): def saveRootDirs(self, rootDirString=None):
sickbeard.ROOT_DIRS = rootDirString sickbeard.ROOT_DIRS = rootDirString
@ -3442,7 +3444,7 @@ class ConfigGeneral(Config):
@route('/config/backuprestore/(.*)(/?)') @route('/config/backuprestore/(.*)(/?)')
class ConfigBackupRestore(Config): class ConfigBackupRestore(Config):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="config_backuprestore.tmpl") t = PageTemplate(rh=self, file="config_backuprestore.tmpl")
t.submenu = Menus().ConfigMenu() t.submenu = Menus().ConfigMenu()
return t return t
@ -3490,7 +3492,7 @@ class ConfigBackupRestore(Config):
class ConfigSearch(Config): class ConfigSearch(Config):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="config_search.tmpl") t = PageTemplate(rh=self, file="config_search.tmpl")
t.submenu = Menus().ConfigMenu() t.submenu = Menus().ConfigMenu()
return t return t
@ -3582,7 +3584,7 @@ class ConfigSearch(Config):
class ConfigPostProcessing(Config): class ConfigPostProcessing(Config):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="config_postProcessing.tmpl") t = PageTemplate(rh=self, file="config_postProcessing.tmpl")
t.submenu = Menus().ConfigMenu() t.submenu = Menus().ConfigMenu()
return t return t
@ -3780,7 +3782,7 @@ class ConfigPostProcessing(Config):
@route('/config/providers/(.*)(/?)') @route('/config/providers/(.*)(/?)')
class ConfigProviders(Config): class ConfigProviders(Config):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="config_providers.tmpl") t = PageTemplate(rh=self, file="config_providers.tmpl")
t.submenu = Menus().ConfigMenu() t.submenu = Menus().ConfigMenu()
return t return t
@ -4218,7 +4220,7 @@ class ConfigProviders(Config):
@route('/config/notifications/(.*)(/?)') @route('/config/notifications/(.*)(/?)')
class ConfigNotifications(Config): class ConfigNotifications(Config):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="config_notifications.tmpl") t = PageTemplate(rh=self, file="config_notifications.tmpl")
t.submenu = Menus().ConfigMenu() t.submenu = Menus().ConfigMenu()
return t return t
@ -4427,7 +4429,7 @@ class ConfigNotifications(Config):
@route('/config/subtitles/(.*)(/?)') @route('/config/subtitles/(.*)(/?)')
class ConfigSubtitles(Config): class ConfigSubtitles(Config):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="config_subtitles.tmpl") t = PageTemplate(rh=self, file="config_subtitles.tmpl")
t.submenu = Menus().ConfigMenu() t.submenu = Menus().ConfigMenu()
return t return t
@ -4491,7 +4493,7 @@ class ConfigSubtitles(Config):
class ConfigAnime(Config): class ConfigAnime(Config):
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
t = PageTemplate(headers=self.request.headers, file="config_anime.tmpl") t = PageTemplate(rh=self, file="config_anime.tmpl")
t.submenu = Menus().ConfigMenu() t.submenu = Menus().ConfigMenu()
return t return t
@ -4523,7 +4525,7 @@ class ConfigAnime(Config):
class ErrorLogs(WebRoot): class ErrorLogs(WebRoot):
def index(self): def index(self):
t = PageTemplate(headers=self.request.headers, file="errorlogs.tmpl") t = PageTemplate(rh=self, file="errorlogs.tmpl")
t.submenu = Menus().ErrorLogsMenu() t.submenu = Menus().ErrorLogsMenu()
return t return t
@ -4536,7 +4538,7 @@ class ErrorLogs(WebRoot):
def viewlog(self, minLevel=logger.MESSAGE, maxLines=500): def viewlog(self, minLevel=logger.MESSAGE, maxLines=500):
t = PageTemplate(headers=self.request.headers, file="viewlogs.tmpl") t = PageTemplate(rh=self, file="viewlogs.tmpl")
t.submenu = Menus().ErrorLogsMenu() t.submenu = Menus().ErrorLogsMenu()
minLevel = int(minLevel) minLevel = int(minLevel)

View File

@ -7,9 +7,10 @@ import sickbeard
import webserve import webserve
import webapi import webapi
from sickbeard.webserve import LoginHandler, LogoutHandler
from sickbeard import logger from sickbeard import logger
from sickbeard.helpers import create_https_certificates from sickbeard.helpers import create_https_certificates
from tornado.web import Application, StaticFileHandler, RedirectHandler, HTTPError from tornado.web import Application, StaticFileHandler, HTTPError
from tornado.httpserver import HTTPServer from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
from tornado.routes import route from tornado.routes import route
@ -91,12 +92,14 @@ class SRWebServer(threading.Thread):
gzip=True, gzip=True,
xheaders=sickbeard.HANDLE_REVERSE_PROXY, xheaders=sickbeard.HANDLE_REVERSE_PROXY,
cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=', cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=',
username=self.options['username'], login_url='%slogin/' % self.options['web_root'],
password=self.options['password'],
) )
# Main Handlers # Main Handlers
self.app.add_handlers(".*$", [] + route.get_routes()) self.app.add_handlers(".*$", [
(r'%slogin(/?)' % self.options['web_root'], LoginHandler),
(r'%slogout(/?)' % self.options['web_root'], LogoutHandler)
] + route.get_routes())
# Static Path Handlers # Static Path Handlers
self.app.add_handlers(".*$", [ self.app.add_handlers(".*$", [