1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-12-12 02:52:20 -05:00

Merge remote-tracking branch 'origin/develop' into develop

Conflicts:
	sickbeard/webapi.py
This commit is contained in:
echel0n 2014-12-07 13:00:18 -08:00
commit e7de90f688
7 changed files with 320 additions and 358 deletions

View File

@ -45,7 +45,7 @@ function goListGroup(apikey, L7, L6, L5, L4, L3, L2, L1){
html += $.ajax({
url: sbRoot + "/api/" + apikey + "/" + L1 + L2 + L3 + L4 + L5 + L6 + L7 + GlobalOptions,
async: false,
dataType: "html",
dataType: "html"
}).responseText;
html += '</pre>';

View File

@ -58,7 +58,7 @@ $(document).ready(function(){
$('#api_key').click(function(){ $('#api_key').select() });
$("#generate_new_apikey").click(function(){
$.get(sbRoot + '/config/general/generateKey',
$.get(sbRoot + '/config/general/generateApiKey',
function(data){
if (data.error != undefined) {
alert(data.error);

View File

@ -145,6 +145,7 @@ ANON_REDIRECT = None
USE_API = False
API_KEY = None
API_ROOT = None
ENABLE_HTTPS = False
HTTPS_CERT = None
@ -480,7 +481,7 @@ def get_backlog_cycle_time():
def initialize(consoleLogging=True):
with INIT_LOCK:
global BRANCH, GIT_REMOTE, GIT_REMOTE_URL, CUR_COMMIT_HASH, CUR_COMMIT_BRANCH, ACTUAL_LOG_DIR, LOG_DIR, WEB_PORT, WEB_LOG, ENCRYPTION_VERSION, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, WEB_HOST, WEB_IPV6, USE_API, API_KEY, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \
global BRANCH, GIT_REMOTE, GIT_REMOTE_URL, CUR_COMMIT_HASH, CUR_COMMIT_BRANCH, ACTUAL_LOG_DIR, LOG_DIR, WEB_PORT, WEB_LOG, ENCRYPTION_VERSION, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, WEB_HOST, WEB_IPV6, USE_API, API_KEY, API_ROOT, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \
HANDLE_REVERSE_PROXY, USE_NZBS, USE_TORRENTS, NZB_METHOD, NZB_DIR, DOWNLOAD_PROPERS, RANDOMIZE_PROVIDERS, CHECK_PROPERS_INTERVAL, ALLOW_HIGH_PRIORITY, TORRENT_METHOD, \
SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_CATEGORY_ANIME, SAB_HOST, \
NZBGET_USERNAME, NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_CATEGORY_ANIME, NZBGET_PRIORITY, NZBGET_HOST, NZBGET_USE_HTTPS, backlogSearchScheduler, \

View File

@ -20,6 +20,7 @@ from __future__ import with_statement
import getpass
import os
import random
import re
import shutil
import socket
@ -1432,4 +1433,28 @@ def get_size(start_path='.'):
return total_size
def md5(text):
return hashlib.md5(ek.ss(text)).hexdigest()
return hashlib.md5(ek.ss(text)).hexdigest()
def generateApiKey(*args, **kwargs):
""" Return a new randomized API_KEY
"""
try:
from hashlib import md5
except ImportError:
from md5 import md5
# Create some values to seed md5
t = str(time.time())
r = str(random.random())
# Create the md5 instance and give it the current time
m = md5(t)
# Update the md5 instance with the random variable
m.update(r)
# Return a hex digest of the md5, eg 49f68a5c8493ec2c0bf489821c21fc3b
logger.log(u"New API generated")
return m.hexdigest()

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@
# along with SickRage. If not, see <http://www.gnu.org/licenses/>.
from __future__ import with_statement
import random
import traceback
import os
@ -24,7 +25,6 @@ import time
import urllib
import re
import datetime
import random
import sys
import sickbeard
@ -133,7 +133,7 @@ def haveTORRENT():
return False
class Menus:
def HomeMenu(self):
def HomeMenu(self, *args, **kwargs):
menu = [
{'title': 'Add Shows', 'path': 'home/addShows/', },
{'title': 'Manual Post-Processing', 'path': 'home/postprocess/'},
@ -146,7 +146,7 @@ class Menus:
return menu
def ConfigMenu(self):
def ConfigMenu(self, *args, **kwargs):
menu = [
{'title': 'General', 'path': 'config/general/'},
{'title': 'Backup/Restore', 'path': 'config/backuprestore/'},
@ -160,7 +160,7 @@ class Menus:
return menu
def ManageMenu(self):
def ManageMenu(self, *args, **kwargs):
menu = [
{'title': 'Backlog Overview', 'path': 'manage/backlogOverview/'},
{'title': 'Manage Searches', 'path': 'manage/manageSearches/'},
@ -179,7 +179,7 @@ class Menus:
return menu
def ErrorLogsMenu(self):
def ErrorLogsMenu(self, *args, **kwargs):
menu = [
{'title': 'Clear Errors', 'path': 'errorlogs/clearerrors/'},
# { 'title': 'View Log', 'path': 'errorlogs/viewlog' },
@ -236,7 +236,7 @@ class PageTemplate(Template):
return super(PageTemplate, self).compile(*args, **kwargs)
class BaseHandler(RequestHandler):
def get_current_user(self):
def get_current_user(self, *args, **kwargs):
if sickbeard.WEB_USERNAME and sickbeard.WEB_PASSWORD:
return self.get_secure_cookie('user')
else:
@ -249,7 +249,6 @@ class BaseHandler(RequestHandler):
t.message = message
return t
# Make non basic auth option to get api key
class KeyHandler(RequestHandler):
def get(self, *args, **kwargs):
api_key = None
@ -258,8 +257,8 @@ class KeyHandler(RequestHandler):
username = sickbeard.WEB_USERNAME
password = sickbeard.WEB_PASSWORD
if (self.get_argument('u') == sickbeard.helpers.md5(username) or not username) \
and (self.get_argument('p') == password or not password):
if (self.get_argument('u', None) == username or not username) \
and (self.get_argument('p', None) == password or not password):
api_key = sickbeard.API_KEY
self.write({
@ -270,24 +269,6 @@ class KeyHandler(RequestHandler):
logger.log('Failed doing key request: %s' % (traceback.format_exc()), logger.ERROR)
self.write({'success': False, 'error': 'Failed returning results'})
class UIHandler(RequestHandler):
def add_message(self):
ui.notifications.message('Test 1', 'This is test number 1')
ui.notifications.error('Test 2', 'This is test number 2')
return "ok"
def get_messages(self):
messages = {}
cur_notification_num = 1
for cur_notification in ui.notifications.get_notifications(self.request.remote_ip):
messages['notification-' + str(cur_notification_num)] = {'title': cur_notification.title,
'message': cur_notification.message,
'type': cur_notification.type}
cur_notification_num += 1
return json.dumps(messages)
class WebHandler(BaseHandler):
def write_error(self, status_code, **kwargs):
if status_code == 404:
@ -323,7 +304,7 @@ class WebHandler(BaseHandler):
self.write('Could not load webui module')
return
except:
page_not_found(self)
page_not_found(self, *args, **kwargs)
return
try:
@ -377,14 +358,53 @@ class LogoutHandler(BaseHandler):
@route('(.*)(/?)')
class WebRoot(WebHandler):
def index(self):
def index(self, *args, **kwargs):
self.redirect('/home/')
def robots_txt(self):
def robots_txt(self, *args, **kwargs):
""" Keep web crawlers out """
self.set_header('Content-Type', 'text/plain')
return "User-agent: *\nDisallow: /"
def apibuilder(self, *args, **kwargs):
t = PageTemplate(rh=self, file="apiBuilder.tmpl")
def titler(x):
if not x or sickbeard.SORT_ARTICLE:
return x
if x.lower().startswith('a '):
x = x[2:]
elif x.lower().startswith('an '):
x = x[3:]
elif x.lower().startswith('the '):
x = x[4:]
return x
t.sortedShowList = sorted(sickbeard.showList, lambda x, y: cmp(titler(x.name), titler(y.name)))
seasonSQLResults = {}
episodeSQLResults = {}
myDB = db.DBConnection(row_type="dict")
for curShow in t.sortedShowList:
seasonSQLResults[curShow.indexerid] = myDB.select(
"SELECT DISTINCT season FROM tv_episodes WHERE showid = ? ORDER BY season DESC", [curShow.indexerid])
for curShow in t.sortedShowList:
episodeSQLResults[curShow.indexerid] = myDB.select(
"SELECT DISTINCT season,episode FROM tv_episodes WHERE showid = ? ORDER BY season DESC, episode DESC",
[curShow.indexerid])
t.seasonSQLResults = seasonSQLResults
t.episodeSQLResults = episodeSQLResults
if len(sickbeard.API_KEY) == 32:
t.apikey = sickbeard.API_KEY
else:
t.apikey = "api key not generated"
return t
def showPoster(self, show=None, which=None):
# Redirect initial poster/banner thumb to default images
if which[0:6] == 'poster':
@ -630,9 +650,28 @@ class WebRoot(WebHandler):
return ical
@route('/ui/(.*)(/?)')
class UIHandler(WebRoot):
def add_message(self, *args, **kwargs):
ui.notifications.message('Test 1', 'This is test number 1')
ui.notifications.error('Test 2', 'This is test number 2')
return "ok"
def get_messages(self, *args, **kwargs):
messages = {}
cur_notification_num = 1
for cur_notification in ui.notifications.get_notifications(self.request.remote_ip):
messages['notification-' + str(cur_notification_num)] = {'title': cur_notification.title,
'message': cur_notification.message,
'type': cur_notification.type}
cur_notification_num += 1
return json.dumps(messages)
@route('/home/(.*)(/?)')
class Home(WebRoot):
def index(self):
def index(self, *args, **kwargs):
t = PageTemplate(rh=self, file="home.tmpl")
if sickbeard.ANIME_SPLIT_HOME:
shows = []
@ -3293,6 +3332,10 @@ class ConfigGeneral(Config):
t.submenu = Menus().ConfigMenu()
return t
def generateApiKey(self, *args, **kwargs):
return helpers.generateApiKey()
def saveRootDirs(self, rootDirString=None):
sickbeard.ROOT_DIRS = rootDirString
@ -3322,31 +3365,6 @@ class ConfigGeneral(Config):
sickbeard.save_config()
def generateKey(self, *args, **kwargs):
""" Return a new randomized API_KEY
"""
try:
from hashlib import md5
except ImportError:
from md5 import md5
# Create some values to seed md5
t = str(time.time())
r = str(random.random())
# Create the md5 instance and give it the current time
m = md5(t)
# Update the md5 instance with the random variable
m.update(r)
# Return a hex digest of the md5, eg 49f68a5c8493ec2c0bf489821c21fc3b
logger.log(u"New API generated")
return m.hexdigest()
def saveGeneral(self, log_dir=None, web_port=None, web_log=None, encryption_version=None, web_ipv6=None,
update_shows_on_start=None, trash_remove_show=None, trash_rotate_logs=None, update_frequency=None,
launch_browser=None, web_username=None,
@ -4523,7 +4541,7 @@ class ConfigAnime(Config):
@route('/errorlogs/(.*)(/?)')
class ErrorLogs(WebRoot):
def index(self):
def index(self, *args, **kwargs):
t = PageTemplate(rh=self, file="errorlogs.tmpl")
t.submenu = Menus().ErrorLogsMenu()

View File

@ -1,16 +1,13 @@
import os
import socket
import time
import threading
import sys
import sickbeard
import webserve
import webapi
from sickbeard.webserve import LoginHandler, LogoutHandler
from sickbeard.webserve import LoginHandler, LogoutHandler, KeyHandler
from sickbeard.webapi import ApiHandler
from sickbeard import logger
from sickbeard.helpers import create_https_certificates
from tornado.web import Application, StaticFileHandler, HTTPError
from sickbeard.helpers import create_https_certificates, generateApiKey
from tornado.web import Application, StaticFileHandler, HTTPError, RedirectHandler
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.routes import route
@ -63,8 +60,13 @@ class SRWebServer(threading.Thread):
self.video_root = None
# web root
self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/')) if self.options['web_root'] else '/'
sickbeard.WEB_ROOT = self.options['web_root'].strip('/')
self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/')).strip('/')
sickbeard.WEB_ROOT = self.options['web_root']
# api root
if not sickbeard.API_KEY:
sickbeard.API_KEY = generateApiKey()
self.options['api_root'] = r'%s/api/%s/' % (sickbeard.WEB_ROOT, sickbeard.API_KEY)
# tornado setup
self.enable_https = self.options['enable_https']
@ -97,20 +99,23 @@ class SRWebServer(threading.Thread):
# Main Handlers
self.app.add_handlers(".*$", [
(r'%slogin(/?)' % self.options['web_root'], LoginHandler),
(r'%slogout(/?)' % self.options['web_root'], LogoutHandler)
(r'%s(/?)' % self.options['api_root'], ApiHandler),
(r'%s/getkey(/?)' % self.options['web_root'], KeyHandler),
(r'%s/api/builder' % self.options['web_root'], RedirectHandler, {"url": self.options['web_root'] + '/apibuilder/'}),
(r'%s/login(/?)' % self.options['web_root'], LoginHandler),
(r'%s/logout(/?)' % self.options['web_root'], LogoutHandler)
] + route.get_routes())
# Static Path Handlers
self.app.add_handlers(".*$", [
(r'%s(favicon\.ico)' % self.options['web_root'], MultiStaticFileHandler,
(r'%s/(favicon\.ico)' % self.options['web_root'], MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'images/ico/favicon.ico')]}),
(r'%s%s/(.*)(/?)' % (self.options['web_root'], 'images'), MultiStaticFileHandler,
(r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'images'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'images'),
os.path.join(sickbeard.CACHE_DIR, 'images')]}),
(r'%s%s/(.*)(/?)' % (self.options['web_root'], 'css'), MultiStaticFileHandler,
(r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'css'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'css')]}),
(r'%s%s/(.*)(/?)' % (self.options['web_root'], 'js'), MultiStaticFileHandler,
(r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'js'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'js')]}),
])