def server_checkup(self): if self.config.general.server_id: server_status = self.api.server.get_status( self.config.general.server_id) if server_status and not server_status['registered']: # re-register server server_id = self.api.server.register_server( ip_addresses=','.join([get_internal_ip()]), web_protocol=('http', 'https')[self.config.general.enable_https], web_port=self.config.general.web_port, web_root=self.config.general.web_root, server_version=sickrage.version(), ) if server_id: self.log.info( 'Re-registered SiCKRAGE server with SiCKRAGE API') sentry_sdk.set_tag('server_id', self.config.general.server_id) self.config.general.server_id = server_id self.config.save(mark_dirty=True) else: self.log.debug('Updating SiCKRAGE server data on SiCKRAGE API') # update server information self.api.server.update_server( server_id=self.config.general.server_id, ip_addresses=','.join([get_internal_ip()]), web_protocol=('http', 'https')[self.config.general.enable_https], web_port=self.config.general.web_port, web_root=self.config.general.web_root, server_version=sickrage.version(), )
def init_sentry(self): # sentry log handler sentry_logging = LoggingIntegration( level=logging.INFO, # Capture info and above as breadcrumbs event_level=logging.ERROR # Send errors as events ) # init sentry logging sentry_sdk.init( dsn= "https://[email protected]/2?verify_ssl=0", integrations=[sentry_logging], release=sickrage.version(), environment=('master', 'develop')['dev' in sickrage.version()], ignore_errors=[ 'KeyboardInterrupt', 'PermissionError', 'FileNotFoundError', 'EpisodeNotFoundException' ]) # sentry tags sentry_tags = { 'platform': platform.platform(), 'locale': repr(locale.getdefaultlocale()), 'python': platform.python_version() } # set sentry tags for tag_key, tag_value in sentry_tags.items(): sentry_sdk.set_tag(tag_key, tag_value)
def init_sentry(self): # sentry log handler sentry_logging = LoggingIntegration( level=logging.INFO, # Capture info and above as breadcrumbs event_level=logging.ERROR # Send errors as events ) # init sentry logging sentry_sdk.init( dsn="https://[email protected]/2?verify_ssl=0", integrations=[sentry_logging], release=sickrage.version(), environment=('master', 'develop')['dev' in sickrage.version()], ignore_errors=[ 'KeyboardInterrupt', 'PermissionError', 'FileNotFoundError', 'EpisodeNotFoundException' ] ) # sentry tags sentry_tags = { 'platform': platform.platform(), 'locale': repr(locale.getdefaultlocale()), 'python': platform.python_version(), 'install_type': sickrage.install_type() } # set sentry tags for tag_key, tag_value in sentry_tags.items(): sentry_sdk.set_tag(tag_key, tag_value) # set loggers to ignore ignored_loggers = [ 'enzyme.parsers.ebml.core', 'subliminal.core', 'subliminal.utils', 'subliminal.refiners.tvdb', 'subliminal.refiners.metadata', 'subliminal.providers.tvsubtitles', 'pika.connection', 'pika.adapters.base_connection', 'pika.adapters.utils.io_services_utils', 'pika.adapters.utils.connection_workflow', 'pika.adapters.utils.selector_ioloop_adapter' ] for item in ignored_loggers: ignore_logger(item)
def started(): self.log.info("SiCKRAGE :: STARTED") self.log.info("SiCKRAGE :: APP VERSION:[{}]".format(sickrage.version())) self.log.info("SiCKRAGE :: CONFIG VERSION:[v{}]".format(self.config.config_version)) self.log.info("SiCKRAGE :: DATABASE VERSION:[v{}]".format(self.main_db.version)) self.log.info("SiCKRAGE :: DATABASE TYPE:[{}]".format(self.db_type)) self.log.info("SiCKRAGE :: URL:[{}://{}:{}{}]".format(('http', 'https')[self.config.enable_https], self.config.web_host, self.config.web_port, self.config.web_root))
def start(self): # remove all handlers self.handlers = [] # sentry log handler sentry_client = raven.Client('https://*****:*****@sentry.sickrage.ca/4?verify_ssl=0', release=sickrage.version(), repos={'sickrage': {'name': 'sickrage/sickrage'}}) sentry_handler = SentryHandler(client=sentry_client, tags={'platform': platform.platform()}) sentry_handler.setLevel(self.logLevels['ERROR']) sentry_handler.set_name('sentry') self.addHandler(sentry_handler) # console log handler if self.consoleLogging: console_handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s %(levelname)s::%(threadName)s::%(message)s', '%H:%M:%S') console_handler.setFormatter(formatter) console_handler.setLevel(self.logLevels['INFO'] if not self.debugLogging else self.logLevels['DEBUG']) self.addHandler(console_handler) # file log handlers if self.logFile: # make logs folder if it doesn't exist if not os.path.exists(os.path.dirname(self.logFile)): if not makeDir(os.path.dirname(self.logFile)): return if sickrage.app.developer: rfh = FileHandler( filename=self.logFile, ) else: rfh = RotatingFileHandler( filename=self.logFile, maxBytes=self.logSize, backupCount=self.logNr ) rfh_errors = RotatingFileHandler( filename=self.logFile.replace('.log', '.error.log'), maxBytes=self.logSize, backupCount=self.logNr ) formatter = logging.Formatter('%(asctime)s %(levelname)s::%(threadName)s::%(message)s', '%Y-%m-%d %H:%M:%S') rfh.setFormatter(formatter) rfh.setLevel(self.logLevels['INFO'] if not self.debugLogging else self.logLevels['DEBUG']) self.addHandler(rfh) rfh_errors.setFormatter(formatter) rfh_errors.setLevel(self.logLevels['ERROR']) self.addHandler(rfh_errors)
def __init__(self): super(PLEXNotifier, self).__init__() self.name = 'plex' self.headers = { 'X-Plex-Device-Name': 'SiCKRAGE', 'X-Plex-Product': 'SiCKRAGE Notifier', 'X-Plex-Client-Identifier': sickrage.app.user_agent, 'X-Plex-Version': sickrage.version() }
def set_default_headers(self): self.set_header('X-SiCKRAGE-Server', sickrage.version()) self.set_header("Access-Control-Allow-Origin", "*") self.set_header( "Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, X-SiCKRAGE-Server" ) self.set_header('Access-Control-Allow-Methods', 'POST, GET, PUT, PATCH, DELETE, OPTIONS') self.set_header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
def current_branch(self): return ("master", "develop")["dev" in sickrage.version()]
def version(self): return sickrage.version()
def prepare(self): super(APIBaseHandler, self).prepare() method_name = self.request.method.lower() if method_name == 'options': return certs = sickrage.app.auth_server.certs() auth_header = self.request.headers.get('Authorization') if auth_header: if 'bearer' in auth_header.lower(): try: token = auth_header.strip('Bearer').strip() decoded_token = sickrage.app.auth_server.decode_token(token, certs) if not sickrage.app.config.user.sub_id: sickrage.app.config.user.sub_id = decoded_token.get('sub') sickrage.app.config.save(mark_dirty=True) if sickrage.app.config.user.sub_id == decoded_token.get('sub'): save_config = False if not sickrage.app.config.user.username: sickrage.app.config.user.username = decoded_token.get('preferred_username') save_config = True if not sickrage.app.config.user.email: sickrage.app.config.user.email = decoded_token.get('email') save_config = True if not sickrage.app.config.user.permissions == UserPermission.SUPERUSER: sickrage.app.config.user.permissions = UserPermission.SUPERUSER save_config = True if save_config: sickrage.app.config.save() if sickrage.app.config.user.sub_id == decoded_token.get('sub'): sentry_sdk.set_user({ 'id': sickrage.app.config.user.sub_id, 'username': sickrage.app.config.user.username, 'email': sickrage.app.config.user.email }) if sickrage.app.config.user.sub_id != decoded_token.get('sub'): return self._unauthorized(error='user is not authorized') if not sickrage.app.api.token: exchanged_token = sickrage.app.auth_server.token_exchange(token) if exchanged_token: sickrage.app.api.token = exchanged_token if not sickrage.app.config.general.server_id: server_id = sickrage.app.api.server.register_server( ip_addresses=','.join([get_internal_ip()]), web_protocol=self.request.protocol, web_port=sickrage.app.config.general.web_port, web_root=sickrage.app.config.general.web_root, server_version=sickrage.version() ) if server_id: sickrage.app.config.general.server_id = server_id sickrage.app.config.save() if sickrage.app.config.general.server_id: sentry_sdk.set_tag('server_id', sickrage.app.config.general.server_id) method = self.run_async(getattr(self, method_name)) setattr(self, method_name, method) except Exception: return self._unauthorized(error='failed to decode token') else: return self._unauthorized(error='invalid authorization request') else: return self._unauthorized(error='authorization header missing')
def _find_installed_version(): return sickrage.version() or ""
def start(self): # remove all handlers self.handlers = [] # sentry log handler sentry_client = raven.Client( 'https://*****:*****@sentry.sickrage.ca/4?verify_ssl=0', release=sickrage.version(), repos={'sickrage': { 'name': 'sickrage/sickrage' }}) sentry_handler = SentryHandler(client=sentry_client, tags={'platform': platform.platform()}) sentry_handler.setLevel(self.logLevels['ERROR']) sentry_handler.set_name('sentry') self.addHandler(sentry_handler) # console log handler if self.consoleLogging: console_handler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s %(levelname)s::%(threadName)s::%(message)s', '%H:%M:%S') console_handler.setFormatter(formatter) console_handler.setLevel(self.logLevels['INFO'] if not self. debugLogging else self.logLevels['DEBUG']) self.addHandler(console_handler) # file log handlers if self.logFile: # make logs folder if it doesn't exist if not os.path.exists(os.path.dirname(self.logFile)): if not makeDir(os.path.dirname(self.logFile)): return if sickrage.app.developer: rfh = FileHandler(filename=self.logFile, ) else: rfh = RotatingFileHandler(filename=self.logFile, maxBytes=self.logSize, backupCount=self.logNr) rfh_errors = RotatingFileHandler(filename=self.logFile.replace( '.log', '.error.log'), maxBytes=self.logSize, backupCount=self.logNr) formatter = logging.Formatter( '%(asctime)s %(levelname)s::%(threadName)s::%(message)s', '%Y-%m-%d %H:%M:%S') rfh.setFormatter(formatter) rfh.setLevel(self.logLevels['INFO'] if not self.debugLogging else self.logLevels['DEBUG']) self.addHandler(rfh) rfh_errors.setFormatter(formatter) rfh_errors.setLevel(self.logLevels['ERROR']) self.addHandler(rfh_errors)
def start(self): self.started = True # load languages tornado.locale.load_gettext_translations(sickrage.LOCALE_DIR, 'messages') # clear mako cache folder mako_cache = os.path.join(sickrage.app.cache_dir, 'mako') if os.path.isdir(mako_cache): shutil.rmtree(mako_cache) # video root if sickrage.app.config.root_dirs: root_dirs = sickrage.app.config.root_dirs.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] # web root if sickrage.app.config.web_root: sickrage.app.config.web_root = sickrage.app.config.web_root = ( '/' + sickrage.app.config.web_root.lstrip('/').strip('/')) # api root self.api_root = r'%s/api/%s' % (sickrage.app.config.web_root, sickrage.app.config.api_key) # tornado setup if sickrage.app.config.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not ( sickrage.app.config.https_cert and os.path.exists( sickrage.app.config.https_cert)) or not ( sickrage.app.config.https_key and os.path.exists(sickrage.app.config.https_key)): if not create_https_certificates(sickrage.app.config.https_cert, sickrage.app.config.https_key): sickrage.app.log.info("Unable to create CERT/KEY files, disabling HTTPS") sickrage.app.config.enable_https = False if not (os.path.exists(sickrage.app.config.https_cert) and os.path.exists( sickrage.app.config.https_key)): sickrage.app.log.warning("Disabled HTTPS because of missing CERT and KEY files") sickrage.app.config.enable_https = False # Load the app self.app = Application( debug=True, autoreload=False, gzip=sickrage.app.config.web_use_gzip, cookie_secret=sickrage.app.config.web_cookie_secret, login_url='%s/login/' % sickrage.app.config.web_root) # Websocket handler self.app.add_handlers(".*$", [ (r'%s/ws/ui' % sickrage.app.config.web_root, WebSocketUIHandler) ]) # Static File Handlers self.app.add_handlers('.*$', [ # api (r'%s/api/(\w{32})(/?.*)' % sickrage.app.config.web_root, ApiHandler), # redirect to home (r"(%s)" % sickrage.app.config.web_root, RedirectHandler, {"url": "%s/home" % sickrage.app.config.web_root}), # api builder (r'%s/api/builder' % sickrage.app.config.web_root, RedirectHandler, {"url": sickrage.app.config.web_root + '/apibuilder/'}), # login (r'%s/login(/?)' % sickrage.app.config.web_root, LoginHandler), # logout (r'%s/logout(/?)' % sickrage.app.config.web_root, LogoutHandler), # calendar (r'%s/calendar' % sickrage.app.config.web_root, CalendarHandler), # favicon (r'%s/(favicon\.ico)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'images/favicon.ico')}), # images (r'%s/images/(.*)' % sickrage.app.config.web_root, StaticImageHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'images')}), # css (r'%s/css/(.*)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'css')}), # scss (r'%s/scss/(.*)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'scss')}), # fonts (r'%s/fonts/(.*)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'fonts')}), # javascript (r'%s/js/(.*)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'js')}), # videos (r'%s/videos/(.*)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": self.video_root}), ]) # Web Handlers self.app.add_handlers('.*$', Route.get_routes(sickrage.app.config.web_root)) # HTTPS Cert/Key object ssl_ctx = None if sickrage.app.config.enable_https: ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ssl_ctx.load_cert_chain(sickrage.app.config.https_cert, sickrage.app.config.https_key) # Web Server self.server = HTTPServer(self.app, ssl_options=ssl_ctx, xheaders=sickrage.app.config.handle_reverse_proxy) try: self.server.listen(sickrage.app.config.web_port) sickrage.app.log.info( "SiCKRAGE :: STARTED") sickrage.app.log.info( "SiCKRAGE :: VERSION:[{}]".format(sickrage.version())) sickrage.app.log.info( "SiCKRAGE :: CONFIG:[{}] [v{}]".format(sickrage.app.config_file, sickrage.app.config.config_version)) sickrage.app.log.info( "SiCKRAGE :: DATABASE:[v{}]".format(sickrage.app.main_db.version)) sickrage.app.log.info( "SiCKRAGE :: URL:[{}://{}:{}{}]".format(('http', 'https')[sickrage.app.config.enable_https], sickrage.app.config.web_host, sickrage.app.config.web_port, sickrage.app.config.web_root)) except socket.error as e: sickrage.app.log.warning(e.strerror) raise SystemExit
def handle_sso_auth_get(self): code = self.get_argument('code', None) redirect_uri = f"{self.request.protocol}://{self.request.host}{sickrage.app.config.general.web_root}/login" if code: try: token = sickrage.app.auth_server.authorization_code( code, redirect_uri) if not token: return self.redirect('/logout') certs = sickrage.app.auth_server.certs() if not certs: return self.redirect('/logout') decoded_token = sickrage.app.auth_server.decode_token( token['access_token'], certs) if not decoded_token: return self.redirect('/logout') if not decoded_token.get('sub'): return self.redirect('/logout') self.set_secure_cookie('_sr_access_token', token['access_token']) self.set_secure_cookie('_sr_refresh_token', token['refresh_token']) if not sickrage.app.config.user.sub_id: sickrage.app.config.user.sub_id = decoded_token.get('sub') sickrage.app.config.save(mark_dirty=True) if sickrage.app.config.user.sub_id == decoded_token.get('sub'): save_config = False if not sickrage.app.config.user.username: sickrage.app.config.user.username = decoded_token.get( 'preferred_username') save_config = True if not sickrage.app.config.user.email: sickrage.app.config.user.email = decoded_token.get( 'email') save_config = True if not sickrage.app.config.user.permissions == UserPermission.SUPERUSER: sickrage.app.config.user.permissions = UserPermission.SUPERUSER save_config = True if save_config: sickrage.app.config.save() if sickrage.app.config.user.sub_id == decoded_token.get('sub'): sentry_sdk.set_user({ 'id': sickrage.app.config.user.sub_id, 'username': sickrage.app.config.user.username, 'email': sickrage.app.config.user.email }) if sickrage.app.config.user.sub_id != decoded_token.get('sub'): if sickrage.app.api.token: allowed_usernames = sickrage.app.api.allowed_usernames( )['data'] if not decoded_token.get( 'preferred_username') in allowed_usernames: sickrage.app.log.debug( "USERNAME:{} IP:{} - WEB-UI ACCESS DENIED". format(decoded_token.get('preferred_username'), self.request.remote_ip)) return self.redirect('/logout') else: return self.redirect('/logout') elif not sickrage.app.api.token: exchanged_token = sickrage.app.auth_server.token_exchange( token['access_token']) if exchanged_token: sickrage.app.api.token = exchanged_token except Exception as e: sickrage.app.log.debug('{!r}'.format(e)) return self.redirect('/logout') if not sickrage.app.config.general.server_id: server_id = sickrage.app.api.server.register_server( ip_addresses=','.join([get_internal_ip()]), web_protocol=self.request.protocol, web_port=sickrage.app.config.general.web_port, web_root=sickrage.app.config.general.web_root, server_version=sickrage.version()) if server_id: sickrage.app.config.general.server_id = server_id sickrage.app.config.save() if sickrage.app.config.general.server_id: sentry_sdk.set_tag('server_id', sickrage.app.config.general.server_id) redirect_uri = self.get_argument( 'next', "/{}/".format(sickrage.app.config.general.default_page.value)) return self.redirect("{}".format(redirect_uri)) else: authorization_url = sickrage.app.auth_server.authorization_url( redirect_uri=redirect_uri, scope="profile email") if authorization_url: return self.redirect(authorization_url, add_web_root=False) return self.redirect('/logout')
def start(self): self.started = True # load languages tornado.locale.load_gettext_translations(sickrage.LOCALE_DIR, 'messages') # clear mako cache folder mako_cache = os.path.join(sickrage.app.cache_dir, 'mako') if os.path.isdir(mako_cache): shutil.rmtree(mako_cache) # video root if sickrage.app.config.root_dirs: root_dirs = sickrage.app.config.root_dirs.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] # web root if sickrage.app.config.web_root: sickrage.app.config.web_root = sickrage.app.config.web_root = ( '/' + sickrage.app.config.web_root.lstrip('/').strip('/')) # api root self.api_root = r'%s/api/%s' % (sickrage.app.config.web_root, sickrage.app.config.api_key) # tornado setup if sickrage.app.config.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not ( sickrage.app.config.https_cert and os.path.exists( sickrage.app.config.https_cert)) or not ( sickrage.app.config.https_key and os.path.exists(sickrage.app.config.https_key)): if not create_https_certificates(sickrage.app.config.https_cert, sickrage.app.config.https_key): sickrage.app.log.info("Unable to create CERT/KEY files, disabling HTTPS") sickrage.app.config.enable_https = False if not (os.path.exists(sickrage.app.config.https_cert) and os.path.exists( sickrage.app.config.https_key)): sickrage.app.log.warning("Disabled HTTPS because of missing CERT and KEY files") sickrage.app.config.enable_https = False # Load the app self.app = Application( debug=True, autoreload=False, gzip=sickrage.app.config.web_use_gzip, cookie_secret=sickrage.app.config.web_cookie_secret, login_url='%s/login/' % sickrage.app.config.web_root) # Websocket handler self.app.add_handlers(".*$", [ (r'%s/ws/ui' % sickrage.app.config.web_root, WebSocketUIHandler) ]) # Static File Handlers self.app.add_handlers('.*$', [ # api (r'%s(/?.*)' % self.api_root, ApiHandler), # redirect to home (r"(%s)" % sickrage.app.config.web_root, RedirectHandler, {"url": "%s/home" % sickrage.app.config.web_root}), # api key (r'%s/getkey(/?.*)' % sickrage.app.config.web_root, KeyHandler), # api builder (r'%s/api/builder' % sickrage.app.config.web_root, RedirectHandler, {"url": sickrage.app.config.web_root + '/apibuilder/'}), # login (r'%s/login(/?)' % sickrage.app.config.web_root, LoginHandler), # logout (r'%s/logout(/?)' % sickrage.app.config.web_root, LogoutHandler), # calendar (r'%s/calendar' % sickrage.app.config.web_root, CalendarHandler), # favicon (r'%s/(favicon\.ico)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'images/favicon.ico')}), # images (r'%s/images/(.*)' % sickrage.app.config.web_root, StaticImageHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'images')}), # css (r'%s/css/(.*)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'css')}), # scss (r'%s/scss/(.*)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'scss')}), # fonts (r'%s/fonts/(.*)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'fonts')}), # javascript (r'%s/js/(.*)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": os.path.join(sickrage.app.config.gui_static_dir, 'js')}), # videos (r'%s/videos/(.*)' % sickrage.app.config.web_root, StaticNoCacheFileHandler, {"path": self.video_root}), ]) # Web Handlers self.app.add_handlers('.*$', Route.get_routes(sickrage.app.config.web_root)) self.server = HTTPServer(self.app, xheaders=sickrage.app.config.handle_reverse_proxy) if sickrage.app.config.enable_https: self.server.ssl_options = { "certfile": sickrage.app.config.https_cert, "keyfile": sickrage.app.config.https_key } try: self.server.listen(sickrage.app.config.web_port) sickrage.app.log.info( "SiCKRAGE :: STARTED") sickrage.app.log.info( "SiCKRAGE :: VERSION:[{}]".format(sickrage.version())) sickrage.app.log.info( "SiCKRAGE :: CONFIG:[{}] [v{}]".format(sickrage.app.config_file, sickrage.app.config.config_version)) sickrage.app.log.info( "SiCKRAGE :: DATABASE:[v{}]".format(sickrage.app.main_db.version)) sickrage.app.log.info( "SiCKRAGE :: URL:[{}://{}:{}{}]".format(('http', 'https')[sickrage.app.config.enable_https], sickrage.app.config.web_host, sickrage.app.config.web_port, sickrage.app.config.web_root)) # launch browser window if all([not sickrage.app.no_launch, sickrage.app.config.launch_browser]) or sickrage.app.config.view_changelog: threading.Thread(None, lambda: launch_browser( ('http', 'https')[sickrage.app.config.enable_https], sickrage.app.config.web_host, sickrage.app.config.web_port ), name="LAUNCH-BROWSER").start() except socket.error as e: sickrage.app.log.warning(e.strerror) raise SystemExit
def get(self, *args, **kwargs): code = self.get_argument('code', None) redirect_uri = "{}://{}{}/account/link".format(self.request.protocol, self.request.host, sickrage.app.config.general.web_root) if code: token = sickrage.app.auth_server.authorization_code(code, redirect_uri) if not token: return self.redirect('/account/link') certs = sickrage.app.auth_server.certs() if not certs: return self.redirect('/account/link') decoded_token = sickrage.app.auth_server.decode_token(token['access_token'], certs) if not decoded_token: return self.redirect('/account/link') # if sickrage.app.api.token: # sickrage.app.api.logout() exchanged_token = sickrage.app.auth_server.token_exchange(token['access_token']) if exchanged_token: sickrage.app.api.token = exchanged_token sickrage.app.config.general.enable_sickrage_api = True if not sickrage.app.config.user.sub_id: sickrage.app.config.user.sub_id = decoded_token.get('sub_id') sickrage.app.config.user.username = decoded_token.get('preferred_username') sickrage.app.config.user.email = decoded_token.get('email') sickrage.app.config.user.permissions = UserPermission.SUPERUSER sentry_sdk.set_user({ 'id': sickrage.app.config.user.sub_id, 'username': sickrage.app.config.user.username, 'email': sickrage.app.config.user.email }) if not sickrage.app.config.general.server_id: server_id = sickrage.app.api.server.register_server( ip_addresses=','.join([get_internal_ip()]), web_protocol=self.request.protocol, web_port=sickrage.app.config.general.web_port, web_root=sickrage.app.config.general.web_root, server_version=sickrage.version() ) if server_id: sickrage.app.config.general.server_id = server_id if sickrage.app.config.general.server_id: sentry_sdk.set_tag('server_id', sickrage.app.config.general.server_id) sickrage.app.config.save(mark_dirty=True) sickrage.app.alerts.message(_('Linked SiCKRAGE account to SiCKRAGE API')) else: authorization_url = sickrage.app.auth_server.authorization_url(redirect_uri=redirect_uri, scope="profile email") if authorization_url: return self.redirect(authorization_url, add_web_root=False) return self.redirect('/account/link')
def handle_jwt_auth_get(self): certs = sickrage.app.auth_server.certs() auth_token = self.request.headers['Authorization'].strip( 'Bearer').strip() try: decoded_token = sickrage.app.auth_server.decode_token( auth_token, certs) except ExpiredSignatureError: self.set_status(401) return {'error': 'Token expired'} except JWTError as e: self.set_status(401) return {'error': f'Improper JWT token supplied, {e!r}'} if not sickrage.app.config.user.sub_id: sickrage.app.config.user.sub_id = decoded_token.get('sub') sickrage.app.config.save(mark_dirty=True) if sickrage.app.config.user.sub_id == decoded_token.get('sub'): save_config = False if not sickrage.app.config.user.username: sickrage.app.config.user.username = decoded_token.get( 'preferred_username') save_config = True if not sickrage.app.config.user.email: sickrage.app.config.user.email = decoded_token.get('email') save_config = True if not sickrage.app.config.user.permissions == UserPermission.SUPERUSER: sickrage.app.config.user.permissions = UserPermission.SUPERUSER save_config = True if save_config: sickrage.app.config.save() if sickrage.app.config.user.sub_id == decoded_token.get('sub'): sentry_sdk.set_user({ 'id': sickrage.app.config.user.sub_id, 'username': sickrage.app.config.user.username, 'email': sickrage.app.config.user.email }) if sickrage.app.config.user.sub_id != decoded_token.get('sub'): return if not sickrage.app.api.token: exchanged_token = sickrage.app.auth_server.token_exchange( auth_token) if exchanged_token: sickrage.app.api.token = exchanged_token if not sickrage.app.config.general.server_id: server_id = sickrage.app.api.server.register_server( ip_addresses=','.join([get_internal_ip()]), web_protocol=self.request.protocol, web_port=sickrage.app.config.general.web_port, web_root=sickrage.app.config.general.web_root, server_version=sickrage.version()) if server_id: sickrage.app.config.general.server_id = server_id sickrage.app.config.save() if sickrage.app.config.general.server_id: sentry_sdk.set_tag('server_id', sickrage.app.config.general.server_id)
def start(self): self.started = True # thread name threading.currentThread().setName('CORE') # event loop policy that allows loop creation on any thread. asyncio.set_event_loop_policy(AnyThreadEventLoopPolicy()) # scheduler self.scheduler = BackgroundScheduler({'apscheduler.timezone': 'UTC'}) # init core classes self.api = API() self.main_db = MainDB(self.db_type, self.db_prefix, self.db_host, self.db_port, self.db_username, self.db_password) self.cache_db = CacheDB(self.db_type, self.db_prefix, self.db_host, self.db_port, self.db_username, self.db_password) self.notifier_providers = NotifierProviders() self.metadata_providers = MetadataProviders() self.search_providers = SearchProviders() self.log = Logger() self.config = Config() self.alerts = Notifications() self.wserver = WebServer() self.show_queue = ShowQueue() self.search_queue = SearchQueue() self.postprocessor_queue = PostProcessorQueue() self.version_updater = VersionUpdater() self.show_updater = ShowUpdater() self.tz_updater = TimeZoneUpdater() self.rsscache_updater = RSSCacheUpdater() self.daily_searcher = DailySearcher() self.failed_snatch_searcher = FailedSnatchSearcher() self.backlog_searcher = BacklogSearcher() self.proper_searcher = ProperSearcher() self.trakt_searcher = TraktSearcher() self.subtitle_searcher = SubtitleSearcher() self.auto_postprocessor = AutoPostProcessor() self.upnp_client = UPNPClient() self.announcements = Announcements() # authorization sso client self.auth_server = AuthServer() # check available space try: self.log.info("Performing disk space checks") total_space, available_space = get_free_space(self.data_dir) if available_space < 100: self.log.warning('Shutting down as SiCKRAGE needs some space to work. You\'ll get corrupted data otherwise. Only %sMB left', available_space) return except Exception: self.log.error('Failed getting disk space: %s', traceback.format_exc()) # check if we need to perform a restore first if os.path.exists(os.path.abspath(os.path.join(self.data_dir, 'restore'))): self.log.info('Performing restore of backup files') success = restore_app_data(os.path.abspath(os.path.join(self.data_dir, 'restore')), self.data_dir) self.log.info("Restoring SiCKRAGE backup: %s!" % ("FAILED", "SUCCESSFUL")[success]) if success: # self.main_db = MainDB(self.db_type, self.db_prefix, self.db_host, self.db_port, self.db_username, self.db_password) # self.cache_db = CacheDB(self.db_type, self.db_prefix, self.db_host, self.db_port, self.db_username, self.db_password) shutil.rmtree(os.path.abspath(os.path.join(self.data_dir, 'restore')), ignore_errors=True) # migrate old database file names to new ones if os.path.isfile(os.path.abspath(os.path.join(self.data_dir, 'sickbeard.db'))): if os.path.isfile(os.path.join(self.data_dir, 'sickrage.db')): helpers.move_file(os.path.join(self.data_dir, 'sickrage.db'), os.path.join(self.data_dir, '{}.bak-{}' .format('sickrage.db', datetime.datetime.now().strftime( '%Y%m%d_%H%M%S')))) helpers.move_file(os.path.abspath(os.path.join(self.data_dir, 'sickbeard.db')), os.path.abspath(os.path.join(self.data_dir, 'sickrage.db'))) # init encryption public and private keys encryption.initialize() # load config self.config.load() # set language self.config.change_gui_lang(self.config.gui_lang) # set socket timeout socket.setdefaulttimeout(self.config.socket_timeout) # setup logger settings self.log.logSize = self.config.log_size self.log.logNr = self.config.log_nr self.log.logFile = os.path.join(self.data_dir, 'logs', 'sickrage.log') self.log.debugLogging = self.config.debug self.log.consoleLogging = not self.quiet # start logger self.log.start() # perform database startup actions for db in [self.main_db, self.cache_db]: # perform integrity check self.log.info("Performing integrity check on {} database".format(db.name)) db.integrity_check() # migrate database self.log.info("Performing migrations on {} database".format(db.name)) db.migrate() # upgrade database self.log.info("Performing upgrades on {} database".format(db.name)) db.upgrade() # cleanup self.log.info("Performing cleanup on {} database".format(db.name)) db.cleanup() # user agent if self.config.random_user_agent: self.user_agent = UserAgent().random uses_netloc.append('scgi') FancyURLopener.version = self.user_agent # set torrent client web url torrent_webui_url(True) if self.config.default_page not in ('schedule', 'history', 'IRC'): self.config.default_page = 'home' # attempt to help prevent users from breaking links by using a bad url if not self.config.anon_redirect.endswith('?'): self.config.anon_redirect = '' if not re.match(r'\d+\|[^|]+(?:\|[^|]+)*', self.config.root_dirs): self.config.root_dirs = '' self.config.naming_force_folders = check_force_season_folders() if self.config.nzb_method not in ('blackhole', 'sabnzbd', 'nzbget'): self.config.nzb_method = 'blackhole' if self.config.torrent_method not in ('blackhole', 'utorrent', 'transmission', 'deluge', 'deluged', 'download_station', 'rtorrent', 'qbittorrent', 'mlnet', 'putio'): self.config.torrent_method = 'blackhole' if self.config.autopostprocessor_freq < self.config.min_autopostprocessor_freq: self.config.autopostprocessor_freq = self.config.min_autopostprocessor_freq if self.config.daily_searcher_freq < self.config.min_daily_searcher_freq: self.config.daily_searcher_freq = self.config.min_daily_searcher_freq if self.config.backlog_searcher_freq < self.config.min_backlog_searcher_freq: self.config.backlog_searcher_freq = self.config.min_backlog_searcher_freq if self.config.version_updater_freq < self.config.min_version_updater_freq: self.config.version_updater_freq = self.config.min_version_updater_freq if self.config.subtitle_searcher_freq < self.config.min_subtitle_searcher_freq: self.config.subtitle_searcher_freq = self.config.min_subtitle_searcher_freq if self.config.failed_snatch_age < self.config.min_failed_snatch_age: self.config.failed_snatch_age = self.config.min_failed_snatch_age if self.config.proper_searcher_interval not in ('15m', '45m', '90m', '4h', 'daily'): self.config.proper_searcher_interval = 'daily' if self.config.showupdate_hour < 0 or self.config.showupdate_hour > 23: self.config.showupdate_hour = 0 # add version checker job self.scheduler.add_job( self.version_updater.task, IntervalTrigger( hours=self.config.version_updater_freq, timezone='utc' ), name=self.version_updater.name, id=self.version_updater.name ) # add network timezones updater job self.scheduler.add_job( self.tz_updater.task, IntervalTrigger( days=1, timezone='utc' ), name=self.tz_updater.name, id=self.tz_updater.name ) # add show updater job self.scheduler.add_job( self.show_updater.task, IntervalTrigger( days=1, start_date=datetime.datetime.now().replace(hour=self.config.showupdate_hour), timezone='utc' ), name=self.show_updater.name, id=self.show_updater.name ) # add rss cache updater job self.scheduler.add_job( self.rsscache_updater.task, IntervalTrigger( minutes=15, timezone='utc' ), name=self.rsscache_updater.name, id=self.rsscache_updater.name ) # add daily search job self.scheduler.add_job( self.daily_searcher.task, IntervalTrigger( minutes=self.config.daily_searcher_freq, start_date=datetime.datetime.now() + datetime.timedelta(minutes=4), timezone='utc' ), name=self.daily_searcher.name, id=self.daily_searcher.name ) # add failed snatch search job self.scheduler.add_job( self.failed_snatch_searcher.task, IntervalTrigger( hours=1, start_date=datetime.datetime.now() + datetime.timedelta(minutes=4), timezone='utc' ), name=self.failed_snatch_searcher.name, id=self.failed_snatch_searcher.name ) # add backlog search job self.scheduler.add_job( self.backlog_searcher.task, IntervalTrigger( minutes=self.config.backlog_searcher_freq, start_date=datetime.datetime.now() + datetime.timedelta(minutes=30), timezone='utc' ), name=self.backlog_searcher.name, id=self.backlog_searcher.name ) # add auto-postprocessing job self.scheduler.add_job( self.auto_postprocessor.task, IntervalTrigger( minutes=self.config.autopostprocessor_freq, timezone='utc' ), name=self.auto_postprocessor.name, id=self.auto_postprocessor.name ) # add find proper job self.scheduler.add_job( self.proper_searcher.task, IntervalTrigger( minutes={ '15m': 15, '45m': 45, '90m': 90, '4h': 4 * 60, 'daily': 24 * 60 }[self.config.proper_searcher_interval], timezone='utc' ), name=self.proper_searcher.name, id=self.proper_searcher.name ) # add trakt.tv checker job self.scheduler.add_job( self.trakt_searcher.task, IntervalTrigger( hours=1, timezone='utc' ), name=self.trakt_searcher.name, id=self.trakt_searcher.name ) # add subtitles finder job self.scheduler.add_job( self.subtitle_searcher.task, IntervalTrigger( hours=self.config.subtitle_searcher_freq, timezone='utc' ), name=self.subtitle_searcher.name, id=self.subtitle_searcher.name ) # add upnp client job self.scheduler.add_job( self.upnp_client.task, IntervalTrigger( seconds=self.upnp_client._nat_portmap_lifetime, timezone='utc' ), name=self.upnp_client.name, id=self.upnp_client.name ) # add announcements job self.scheduler.add_job( self.announcements.task, IntervalTrigger( minutes=15, timezone='utc' ), name=self.announcements.name, id=self.announcements.name ) # add provider URL update job self.scheduler.add_job( self.search_providers.task, IntervalTrigger( hours=1, timezone='utc' ), name=self.search_providers.name, id=self.search_providers.name ) # start queues self.search_queue.start_worker(self.config.max_queue_workers) self.show_queue.start_worker(self.config.max_queue_workers) self.postprocessor_queue.start_worker(self.config.max_queue_workers) # start web server self.wserver.start() # fire off jobs now self.scheduler.get_job(self.version_updater.name).modify(next_run_time=datetime.datetime.utcnow()) self.scheduler.get_job(self.tz_updater.name).modify(next_run_time=datetime.datetime.utcnow()) self.scheduler.get_job(self.announcements.name).modify(next_run_time=datetime.datetime.utcnow()) self.scheduler.get_job(self.search_providers.name).modify(next_run_time=datetime.datetime.utcnow()) # start scheduler service self.scheduler.start() # load shows self.scheduler.add_job(self.load_shows) # launch browser window if all([not sickrage.app.no_launch, sickrage.app.config.launch_browser]): self.scheduler.add_job(launch_browser, args=[('http', 'https')[sickrage.app.config.enable_https], sickrage.app.config.web_host, sickrage.app.config.web_port]) self.log.info("SiCKRAGE :: STARTED") self.log.info("SiCKRAGE :: APP VERSION:[{}]".format(sickrage.version())) self.log.info("SiCKRAGE :: CONFIG VERSION:[v{}]".format(self.config.config_version)) self.log.info("SiCKRAGE :: DATABASE VERSION:[v{}]".format(self.main_db.version)) self.log.info("SiCKRAGE :: DATABASE TYPE:[{}]".format(self.db_type)) self.log.info("SiCKRAGE :: URL:[{}://{}:{}/{}]".format(('http', 'https')[self.config.enable_https], (self.config.web_host, get_lan_ip())[self.config.web_host == '0.0.0.0'], self.config.web_port, self.config.web_root))
def start(self): # remove all handlers self.handlers.clear() sentry_ignore_exceptions = [ 'KeyboardInterrupt', 'PermissionError', 'FileNotFoundError', 'EpisodeNotFoundException' ] # sentry log handler sentry_client = raven.Client( 'https://[email protected]/2?verify_ssl=0', release=sickrage.version(), repos={'sickrage': {'name': 'sickrage/sickrage'}}, ignore_exceptions=sentry_ignore_exceptions ) sentry_tags = { 'platform': platform.platform(), 'locale': locale.getdefaultlocale(), 'python': platform.python_version() } if sickrage.app.config and sickrage.app.config.sub_id: sentry_tags.update({'sub_id': sickrage.app.config.sub_id}) if sickrage.app.config and sickrage.app.config.server_id: sentry_tags.update({'server_id': sickrage.app.config.server_id}) sentry_handler = SentryHandler(client=sentry_client, ignore_exceptions=sentry_ignore_exceptions, tags=sentry_tags) sentry_handler.setLevel(self.logLevels['ERROR']) sentry_handler.set_name('sentry') self.addHandler(sentry_handler) # console log handler if self.consoleLogging: console_handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s %(levelname)s::%(threadName)s::%(message)s', '%H:%M:%S') console_handler.setFormatter(formatter) console_handler.setLevel(self.logLevels['INFO'] if not self.debugLogging else self.logLevels['DEBUG']) self.addHandler(console_handler) # file log handlers if self.logFile: # make logs folder if it doesn't exist if not os.path.exists(os.path.dirname(self.logFile)): if not make_dir(os.path.dirname(self.logFile)): return if sickrage.app.developer: rfh = FileHandler( filename=self.logFile, ) else: rfh = RotatingFileHandler( filename=self.logFile, maxBytes=self.logSize, backupCount=self.logNr ) rfh_errors = RotatingFileHandler( filename=self.logFile.replace('.log', '.error.log'), maxBytes=self.logSize, backupCount=self.logNr ) formatter = logging.Formatter('%(asctime)s %(levelname)s::%(threadName)s::%(message)s', '%Y-%m-%d %H:%M:%S') rfh.setFormatter(formatter) rfh.setLevel(self.logLevels['INFO'] if not self.debugLogging else self.logLevels['DEBUG']) self.addHandler(rfh) rfh_errors.setFormatter(formatter) rfh_errors.setLevel(self.logLevels['ERROR']) self.addHandler(rfh_errors)
def start(self): # remove all handlers self.handlers = [] # sentry log handler sentry_client = raven.Client( 'https://*****:*****@sentry.sickrage.ca/5?verify_ssl=0', release=sickrage.version(), repos={'sickrage': { 'name': 'sickrage/sickrage' }}) sentry_tags = { 'platform': platform.platform(), 'locale': sys.getdefaultencoding(), 'python': sys.version_info } if sickrage.app.config and sickrage.app.config.sub_id: sentry_tags.update({'sub_id': sickrage.app.config.sub_id}) if sickrage.app.config and sickrage.app.config.app_id: sentry_tags.update({'app_id': sickrage.app.config.app_id}) sentry_handler = SentryHandler(client=sentry_client, tags=sentry_tags) sentry_handler.setLevel(self.logLevels['ERROR']) sentry_handler.set_name('sentry') self.addHandler(sentry_handler) # console log handler if self.consoleLogging: console_handler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s %(levelname)s::%(threadName)s::%(message)s', '%H:%M:%S') console_handler.setFormatter(formatter) console_handler.setLevel(self.logLevels['INFO'] if not self. debugLogging else self.logLevels['DEBUG']) self.addHandler(console_handler) # file log handlers if self.logFile: # make logs folder if it doesn't exist if not os.path.exists(os.path.dirname(self.logFile)): if not make_dir(os.path.dirname(self.logFile)): return if sickrage.app.developer: rfh = FileHandler(filename=self.logFile, ) else: rfh = RotatingFileHandler(filename=self.logFile, maxBytes=self.logSize, backupCount=self.logNr) rfh_errors = RotatingFileHandler(filename=self.logFile.replace( '.log', '.error.log'), maxBytes=self.logSize, backupCount=self.logNr) formatter = logging.Formatter( '%(asctime)s %(levelname)s::%(threadName)s::%(message)s', '%Y-%m-%d %H:%M:%S') rfh.setFormatter(formatter) rfh.setLevel(self.logLevels['INFO'] if not self.debugLogging else self.logLevels['DEBUG']) self.addHandler(rfh) rfh_errors.setFormatter(formatter) rfh_errors.setLevel(self.logLevels['ERROR']) self.addHandler(rfh_errors)