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 handle_get(self): code = self.get_argument('code', None) redirect_uri = "{}://{}{}/account/link".format(self.request.protocol, self.request.host, sickrage.app.config.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() sickrage.app.api.token = token sickrage.app.config.enable_sickrage_api = True if not sickrage.app.config.sub_id or not sickrage.app.config.server_id: sickrage.app.config.sub_id = decoded_token.get('sub') internal_connections = "{}://{}:{}{}".format(self.request.protocol, get_internal_ip(), sickrage.app.config.web_port, sickrage.app.config.web_root) external_connections = "{}://{}:{}{}".format(self.request.protocol, get_external_ip(), sickrage.app.config.web_port, sickrage.app.config.web_root) connections = ','.join([internal_connections, external_connections]) server_id = sickrage.app.api.account.register_server(connections) if server_id: sickrage.app.config.server_id = server_id sickrage.app.config.save() 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 offline_access") if authorization_url: return super(BaseHandler, self).redirect(authorization_url) 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 self.write({'error': 'Token expired'}) except JWTError as e: self.set_status(401) return self.write({'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 sickrage.app.config.general.enable_sickrage_api and not sickrage.app.api.token: exchanged_token = sickrage.app.auth_server.token_exchange( auth_token) if exchanged_token: sickrage.app.api.token = exchanged_token internal_connections = "{}://{}:{}{}".format( self.request.protocol, get_internal_ip(), sickrage.app.config.general.web_port, sickrage.app.config.general.web_root) external_connections = "{}://{}:{}{}".format( self.request.protocol, get_external_ip(), sickrage.app.config.general.web_port, sickrage.app.config.general.web_root) connections = ','.join([internal_connections, external_connections]) if sickrage.app.config.general.server_id and not sickrage.app.api.account.update_server( sickrage.app.config.general.server_id, connections): sickrage.app.config.general.server_id = '' if not sickrage.app.config.general.server_id: server_id = sickrage.app.api.account.register_server(connections) if server_id: sickrage.app.config.general.server_id = server_id sentry_sdk.set_tag('server_id', sickrage.app.config.general.server_id) sickrage.app.config.save()
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 sickrage.app.config.general.enable_sickrage_api and 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') internal_connections = "{}://{}:{}{}".format( self.request.protocol, get_internal_ip(), sickrage.app.config.general.web_port, sickrage.app.config.general.web_root) external_connections = "{}://{}:{}{}".format( self.request.protocol, get_external_ip(), sickrage.app.config.general.web_port, sickrage.app.config.general.web_root) connections = ','.join( [internal_connections, external_connections]) if sickrage.app.config.general.server_id and not sickrage.app.api.account.update_server( sickrage.app.config.general.server_id, connections): sickrage.app.config.general.server_id = '' if not sickrage.app.config.general.server_id: server_id = sickrage.app.api.account.register_server( connections) if server_id: sickrage.app.config.general.server_id = server_id sentry_sdk.set_tag('server_id', sickrage.app.config.general.server_id) sickrage.app.config.save() 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 super(BaseHandler, self).redirect(authorization_url) return self.redirect('/logout')
def launch_browser(self): if not self.no_launch and self.config.general.launch_browser: launch_browser( protocol=('http', 'https')[self.config.general.enable_https], host=(get_internal_ip(), self.web_host)[self.web_host != ''], startport=self.config.general.web_port)
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 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 run(self): self.started = True self.io_loop = IOLoop() # load languages tornado.locale.load_gettext_translations(sickrage.LOCALE_DIR, 'messages') # Check configured web port is correct if sickrage.app.config.general.web_port < 21 or sickrage.app.config.general.web_port > 65535: sickrage.app.config.general.web_port = 8081 # clear mako cache folder mako_cache = os.path.join(sickrage.app.cache_dir, 'mako') if os.path.isdir(mako_cache): shutil.rmtree(mako_cache, ignore_errors=True) # video root if sickrage.app.config.general.root_dirs: root_dirs = sickrage.app.config.general.root_dirs.split('|') self.video_root = root_dirs[int(root_dirs[0]) + 1] # web root if sickrage.app.config.general.web_root: sickrage.app.config.general.web_root = sickrage.app.config.general.web_root = ( '/' + sickrage.app.config.general.web_root.lstrip('/').strip('/')) # api root self.api_v1_root = fr'{sickrage.app.config.general.web_root}/api/(?:v1/)?{sickrage.app.config.general.api_v1_key}' self.api_v2_root = fr'{sickrage.app.config.general.web_root}/api/v2' # tornado setup if sickrage.app.config.general.enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not create_https_certificates( sickrage.app.config.general.https_cert, sickrage.app.config.general.https_key): sickrage.app.log.info( "Unable to create CERT/KEY files, disabling HTTPS") sickrage.app.config.general.enable_https = False if not (os.path.exists(sickrage.app.config.general.https_cert) and os.path.exists(sickrage.app.config.general.https_key)): sickrage.app.log.warning( "Disabled HTTPS because of missing CERT and KEY files") sickrage.app.config.general.enable_https = False # Load templates mako_lookup = TemplateLookup(directories=[sickrage.app.gui_views_dir], module_directory=os.path.join( sickrage.app.cache_dir, 'mako'), filesystem_checks=True, strict_undefined=True, input_encoding='utf-8', output_encoding='utf-8', encoding_errors='replace') templates = {} for root, dirs, files in os.walk(sickrage.app.gui_views_dir): path = root.split(os.sep) for x in sickrage.app.gui_views_dir.split(os.sep): if x in path: del path[path.index(x)] for file in files: filename = '{}/{}'.format('/'.join(path), file).lstrip('/') templates[filename] = mako_lookup.get_template(filename) # Websocket handler self.handlers['websocket_handlers'] = [ (fr'{sickrage.app.config.general.web_root}/ws/ui', WebSocketUIHandler) ] # API v1 Handlers self.handlers['api_v1_handlers'] = [ # api (fr'{self.api_v1_root}(/?.*)', ApiHandler), # api builder (fr'{sickrage.app.config.general.web_root}/api/builder', RedirectHandler, { "url": sickrage.app.config.general.web_root + '/apibuilder/' }), ] # API v2 Handlers self.handlers['api_v2_handlers'] = [ (fr'{self.api_v2_root}/ping', ApiPingHandler), (fr'{self.api_v2_root}/swagger.json', ApiSwaggerDotJsonHandler, { 'api_handlers': 'api_v2_handlers', 'api_version': '2.0.0' }), (fr'{self.api_v2_root}/config', ApiV2ConfigHandler), (fr'{self.api_v2_root}/file-browser', ApiV2FileBrowserHandler), (fr'{self.api_v2_root}/postprocess', Apiv2PostProcessHandler), (fr'{self.api_v2_root}/retrieve-series-metadata', ApiV2RetrieveSeriesMetadataHandler), (fr'{self.api_v2_root}/schedule', ApiV2ScheduleHandler), (fr'{self.api_v2_root}/series-providers', ApiV2SeriesProvidersHandler), (fr'{self.api_v2_root}/series-providers/([a-z]+)/search', ApiV2SeriesProvidersSearchHandler), (fr'{self.api_v2_root}/series-providers/([a-z]+)/languages', ApiV2SeriesProvidersLanguagesHandler), (fr'{self.api_v2_root}/series', ApiV2SeriesHandler), (fr'{self.api_v2_root}/series/(\d+[-][a-z]+)', ApiV2SeriesHandler), (fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/episodes', ApiV2SeriesEpisodesHandler), (fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/images', ApiV2SeriesImagesHandler), (fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/imdb-info', ApiV2SeriesImdbInfoHandler), (fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/blacklist', ApiV2SeriesBlacklistHandler), (fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/whitelist', ApiV2SeriesWhitelistHandler), (fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/refresh', ApiV2SeriesRefreshHandler), (fr'{self.api_v2_root}/series/(\d+[-][a-z]+)/update', ApiV2SeriesUpdateHandler), (fr'{self.api_v2_root}/episodes/rename', ApiV2EpisodesRenameHandler), (fr'{self.api_v2_root}/episodes/(\d+[-][a-z]+)/search', ApiV2EpisodesManualSearchHandler), ] # New UI Static File Handlers self.handlers['new_ui_static_file_handlers'] = [ # media (fr'{sickrage.app.config.general.web_root}/app/static/media/(.*)', StaticImageHandler, { "path": os.path.join(sickrage.app.gui_app_dir, 'static', 'media') }), # css (fr'{sickrage.app.config.general.web_root}/app/static/css/(.*)', StaticNoCacheFileHandler, { "path": os.path.join(sickrage.app.gui_app_dir, 'static', 'css') }), # js (fr'{sickrage.app.config.general.web_root}/app/static/js/(.*)', StaticNoCacheFileHandler, { "path": os.path.join(sickrage.app.gui_app_dir, 'static', 'js') }), # base (fr"{sickrage.app.config.general.web_root}/app/(.*)", tornado.web.StaticFileHandler, { "path": sickrage.app.gui_app_dir, "default_filename": "index.html" }) ] # Static File Handlers self.handlers['static_file_handlers'] = [ # redirect to home (fr"({sickrage.app.config.general.web_root})(/?)", RedirectHandler, { "url": f"{sickrage.app.config.general.web_root}/home" }), # login (fr'{sickrage.app.config.general.web_root}/login(/?)', LoginHandler ), # logout (fr'{sickrage.app.config.general.web_root}/logout(/?)', LogoutHandler), # favicon (fr'{sickrage.app.config.general.web_root}/(favicon\.ico)', StaticNoCacheFileHandler, { "path": os.path.join(sickrage.app.gui_static_dir, 'images/favicon.ico') }), # images (fr'{sickrage.app.config.general.web_root}/images/(.*)', StaticImageHandler, { "path": os.path.join(sickrage.app.gui_static_dir, 'images') }), # css (fr'{sickrage.app.config.general.web_root}/css/(.*)', StaticNoCacheFileHandler, { "path": os.path.join(sickrage.app.gui_static_dir, 'css') }), # scss (fr'{sickrage.app.config.general.web_root}/scss/(.*)', StaticNoCacheFileHandler, { "path": os.path.join(sickrage.app.gui_static_dir, 'scss') }), # fonts (fr'{sickrage.app.config.general.web_root}/fonts/(.*)', StaticNoCacheFileHandler, { "path": os.path.join(sickrage.app.gui_static_dir, 'fonts') }), # javascript (fr'{sickrage.app.config.general.web_root}/js/(.*)', StaticNoCacheFileHandler, { "path": os.path.join(sickrage.app.gui_static_dir, 'js') }), # videos (fr'{sickrage.app.config.general.web_root}/videos/(.*)', StaticNoCacheFileHandler, { "path": self.video_root }), ] # Handlers self.handlers['web_handlers'] = [ (fr'{sickrage.app.config.general.web_root}/robots.txt', RobotsDotTxtHandler), (fr'{sickrage.app.config.general.web_root}/messages.po', MessagesDotPoHandler), (fr'{sickrage.app.config.general.web_root}/quicksearch.json', QuicksearchDotJsonHandler), (fr'{sickrage.app.config.general.web_root}/apibuilder(/?)', APIBulderHandler), (fr'{sickrage.app.config.general.web_root}/setHomeLayout(/?)', SetHomeLayoutHandler), (fr'{sickrage.app.config.general.web_root}/setPosterSortBy(/?)', SetPosterSortByHandler), (fr'{sickrage.app.config.general.web_root}/setPosterSortDir(/?)', SetPosterSortDirHandler), (fr'{sickrage.app.config.general.web_root}/setHistoryLayout(/?)', SetHistoryLayoutHandler), (fr'{sickrage.app.config.general.web_root}/toggleDisplayShowSpecials(/?)', ToggleDisplayShowSpecialsHandler), (fr'{sickrage.app.config.general.web_root}/toggleScheduleDisplayPaused(/?)', ToggleScheduleDisplayPausedHandler), (fr'{sickrage.app.config.general.web_root}/setScheduleSort(/?)', SetScheduleSortHandler), (fr'{sickrage.app.config.general.web_root}/forceSchedulerJob(/?)', ForceSchedulerJobHandler), (fr'{sickrage.app.config.general.web_root}/announcements(/?)', AnnouncementsHandler), (fr'{sickrage.app.config.general.web_root}/announcements/announcementCount(/?)', AnnouncementCountHandler), (fr'{sickrage.app.config.general.web_root}/announcements/mark-seen(/?)', MarkAnnouncementSeenHandler), (fr'{sickrage.app.config.general.web_root}/schedule(/?)', ScheduleHandler), (fr'{sickrage.app.config.general.web_root}/setScheduleLayout(/?)', SetScheduleLayoutHandler), (fr'{sickrage.app.config.general.web_root}/calendar(/?)', CalendarHandler), (fr'{sickrage.app.config.general.web_root}/changelog(/?)', ChangelogHandler), (fr'{sickrage.app.config.general.web_root}/account/link(/?)', AccountLinkHandler), (fr'{sickrage.app.config.general.web_root}/account/unlink(/?)', AccountUnlinkHandler), (fr'{sickrage.app.config.general.web_root}/account/is-linked(/?)', AccountIsLinkedHandler), (fr'{sickrage.app.config.general.web_root}/history(/?)', HistoryHandler), (fr'{sickrage.app.config.general.web_root}/history/clear(/?)', HistoryClearHandler), (fr'{sickrage.app.config.general.web_root}/history/trim(/?)', HistoryTrimHandler), (fr'{sickrage.app.config.general.web_root}/logs(/?)', LogsHandler), (fr'{sickrage.app.config.general.web_root}/logs/errorCount(/?)', ErrorCountHandler), (fr'{sickrage.app.config.general.web_root}/logs/warningCount(/?)', WarningCountHandler), (fr'{sickrage.app.config.general.web_root}/logs/view(/?)', LogsViewHandler), (fr'{sickrage.app.config.general.web_root}/logs/clearAll(/?)', LogsClearAllHanlder), (fr'{sickrage.app.config.general.web_root}/logs/clearWarnings(/?)', LogsClearWarningsHanlder), (fr'{sickrage.app.config.general.web_root}/logs/clearErrors(/?)', LogsClearErrorsHanlder), (fr'{sickrage.app.config.general.web_root}/browser(/?)', WebFileBrowserHandler), (fr'{sickrage.app.config.general.web_root}/browser/complete(/?)', WebFileBrowserCompleteHandler), (fr'{sickrage.app.config.general.web_root}/home(/?)', HomeHandler), (fr'{sickrage.app.config.general.web_root}/home/showProgress(/?)', ShowProgressHandler), (fr'{sickrage.app.config.general.web_root}/home/is-alive(/?)', IsAliveHandler), (fr'{sickrage.app.config.general.web_root}/home/testSABnzbd(/?)', TestSABnzbdHandler), (fr'{sickrage.app.config.general.web_root}/home/testSynologyDSM(/?)', TestSynologyDSMHandler), (fr'{sickrage.app.config.general.web_root}/home/testTorrent(/?)', TestTorrentHandler), (fr'{sickrage.app.config.general.web_root}/home/testFreeMobile(/?)', TestFreeMobileHandler), (fr'{sickrage.app.config.general.web_root}/home/testTelegram(/?)', TestTelegramHandler), (fr'{sickrage.app.config.general.web_root}/home/testJoin(/?)', TestJoinHandler), (fr'{sickrage.app.config.general.web_root}/home/testGrowl(/?)', TestGrowlHandler), (fr'{sickrage.app.config.general.web_root}/home/testProwl(/?)', TestProwlHandler), (fr'{sickrage.app.config.general.web_root}/home/testBoxcar2(/?)', TestBoxcar2Handler), (fr'{sickrage.app.config.general.web_root}/home/testPushover(/?)', TestPushoverHandler), (fr'{sickrage.app.config.general.web_root}/home/twitterStep1(/?)', TwitterStep1Handler), (fr'{sickrage.app.config.general.web_root}/home/twitterStep2(/?)', TwitterStep2Handler), (fr'{sickrage.app.config.general.web_root}/home/testTwitter(/?)', TestTwitterHandler), (fr'{sickrage.app.config.general.web_root}/home/testTwilio(/?)', TestTwilioHandler), (fr'{sickrage.app.config.general.web_root}/home/testSlack(/?)', TestSlackHandler), (fr'{sickrage.app.config.general.web_root}/home/testAlexa(/?)', TestAlexaHandler), (fr'{sickrage.app.config.general.web_root}/home/testDiscord(/?)', TestDiscordHandler), (fr'{sickrage.app.config.general.web_root}/home/testKODI(/?)', TestKODIHandler), (fr'{sickrage.app.config.general.web_root}/home/testPMC(/?)', TestPMCHandler), (fr'{sickrage.app.config.general.web_root}/home/testPMS(/?)', TestPMSHandler), (fr'{sickrage.app.config.general.web_root}/home/testLibnotify(/?)', TestLibnotifyHandler), (fr'{sickrage.app.config.general.web_root}/home/testEMBY(/?)', TestEMBYHandler), (fr'{sickrage.app.config.general.web_root}/home/testNMJ(/?)', TestNMJHandler), (fr'{sickrage.app.config.general.web_root}/home/settingsNMJ(/?)', SettingsNMJHandler), (fr'{sickrage.app.config.general.web_root}/home/testNMJv2(/?)', TestNMJv2Handler), (fr'{sickrage.app.config.general.web_root}/home/settingsNMJv2(/?)', SettingsNMJv2Handler), (fr'{sickrage.app.config.general.web_root}/home/getTraktToken(/?)', GetTraktTokenHandler), (fr'{sickrage.app.config.general.web_root}/home/testTrakt(/?)', TestTraktHandler), (fr'{sickrage.app.config.general.web_root}/home/loadShowNotifyLists(/?)', LoadShowNotifyListsHandler), (fr'{sickrage.app.config.general.web_root}/home/saveShowNotifyList(/?)', SaveShowNotifyListHandler), (fr'{sickrage.app.config.general.web_root}/home/testEmail(/?)', TestEmailHandler), (fr'{sickrage.app.config.general.web_root}/home/testNMA(/?)', TestNMAHandler), (fr'{sickrage.app.config.general.web_root}/home/testPushalot(/?)', TestPushalotHandler), (fr'{sickrage.app.config.general.web_root}/home/testPushbullet(/?)', TestPushbulletHandler), (fr'{sickrage.app.config.general.web_root}/home/getPushbulletDevices(/?)', GetPushbulletDevicesHandler), (fr'{sickrage.app.config.general.web_root}/home/serverStatus(/?)', ServerStatusHandler), (fr'{sickrage.app.config.general.web_root}/home/providerStatus(/?)', ProviderStatusHandler), (fr'{sickrage.app.config.general.web_root}/home/shutdown(/?)', ShutdownHandler), (fr'{sickrage.app.config.general.web_root}/home/restart(/?)', RestartHandler), (fr'{sickrage.app.config.general.web_root}/home/updateCheck(/?)', UpdateCheckHandler), (fr'{sickrage.app.config.general.web_root}/home/update(/?)', UpdateHandler), (fr'{sickrage.app.config.general.web_root}/home/verifyPath(/?)', VerifyPathHandler), (fr'{sickrage.app.config.general.web_root}/home/installRequirements(/?)', InstallRequirementsHandler), (fr'{sickrage.app.config.general.web_root}/home/branchCheckout(/?)', BranchCheckoutHandler), (fr'{sickrage.app.config.general.web_root}/home/displayShow(/?)', DisplayShowHandler), (fr'{sickrage.app.config.general.web_root}/home/togglePause(/?)', TogglePauseHandler), (fr'{sickrage.app.config.general.web_root}/home/deleteShow', DeleteShowHandler), (fr'{sickrage.app.config.general.web_root}/home/refreshShow(/?)', RefreshShowHandler), (fr'{sickrage.app.config.general.web_root}/home/updateShow(/?)', UpdateShowHandler), (fr'{sickrage.app.config.general.web_root}/home/subtitleShow(/?)', SubtitleShowHandler), (fr'{sickrage.app.config.general.web_root}/home/updateKODI(/?)', UpdateKODIHandler), (fr'{sickrage.app.config.general.web_root}/home/updatePLEX(/?)', UpdatePLEXHandler), (fr'{sickrage.app.config.general.web_root}/home/updateEMBY(/?)', UpdateEMBYHandler), (fr'{sickrage.app.config.general.web_root}/home/syncTrakt(/?)', SyncTraktHandler), (fr'{sickrage.app.config.general.web_root}/home/deleteEpisode(/?)', DeleteEpisodeHandler), (fr'{sickrage.app.config.general.web_root}/home/testRename(/?)', TestRenameHandler), (fr'{sickrage.app.config.general.web_root}/home/doRename(/?)', DoRenameHandler), (fr'{sickrage.app.config.general.web_root}/home/searchEpisode(/?)', SearchEpisodeHandler), (fr'{sickrage.app.config.general.web_root}/home/getManualSearchStatus(/?)', GetManualSearchStatusHandler), (fr'{sickrage.app.config.general.web_root}/home/searchEpisodeSubtitles(/?)', SearchEpisodeSubtitlesHandler), (fr'{sickrage.app.config.general.web_root}/home/setSceneNumbering(/?)', SetSceneNumberingHandler), (fr'{sickrage.app.config.general.web_root}/home/retryEpisode(/?)', RetryEpisodeHandler), (fr'{sickrage.app.config.general.web_root}/home/fetch_releasegroups(/?)', FetchReleasegroupsHandler), (fr'{sickrage.app.config.general.web_root}/home/postprocess(/?)', HomePostProcessHandler), (fr'{sickrage.app.config.general.web_root}/home/postprocess/processEpisode(/?)', HomeProcessEpisodeHandler), (fr'{sickrage.app.config.general.web_root}/home/addShows(/?)', HomeAddShowsHandler), (fr'{sickrage.app.config.general.web_root}/home/addShows/searchSeriesProviderForShowName(/?)', SearchSeriesProviderForShowNameHandler), (fr'{sickrage.app.config.general.web_root}/home/addShows/massAddTable(/?)', MassAddTableHandler), (fr'{sickrage.app.config.general.web_root}/home/addShows/newShow(/?)', NewShowHandler), (fr'{sickrage.app.config.general.web_root}/home/addShows/traktShows(/?)', TraktShowsHandler), (fr'{sickrage.app.config.general.web_root}/home/addShows/popularShows(/?)', PopularShowsHandler), (fr'{sickrage.app.config.general.web_root}/home/addShows/addShowToBlacklist(/?)', AddShowToBlacklistHandler), (fr'{sickrage.app.config.general.web_root}/home/addShows/existingShows(/?)', ExistingShowsHandler), (fr'{sickrage.app.config.general.web_root}/home/addShows/addShowByID(/?)', AddShowByIDHandler), (fr'{sickrage.app.config.general.web_root}/home/addShows/addNewShow(/?)', AddNewShowHandler), (fr'{sickrage.app.config.general.web_root}/home/addShows/addExistingShows(/?)', AddExistingShowsHandler), (fr'{sickrage.app.config.general.web_root}/manage(/?)', ManageHandler), (fr'{sickrage.app.config.general.web_root}/manage/editShow(/?)', EditShowHandler), (fr'{sickrage.app.config.general.web_root}/manage/showEpisodeStatuses(/?)', ShowEpisodeStatusesHandler), (fr'{sickrage.app.config.general.web_root}/manage/episodeStatuses(/?)', EpisodeStatusesHandler), (fr'{sickrage.app.config.general.web_root}/manage/changeEpisodeStatuses(/?)', ChangeEpisodeStatusesHandler), (fr'{sickrage.app.config.general.web_root}/manage/setEpisodeStatus(/?)', SetEpisodeStatusHandler), (fr'{sickrage.app.config.general.web_root}/manage/showSubtitleMissed(/?)', ShowSubtitleMissedHandler), (fr'{sickrage.app.config.general.web_root}/manage/subtitleMissed(/?)', SubtitleMissedHandler), (fr'{sickrage.app.config.general.web_root}/manage/downloadSubtitleMissed(/?)', DownloadSubtitleMissedHandler), (fr'{sickrage.app.config.general.web_root}/manage/backlogShow(/?)', BacklogShowHandler), (fr'{sickrage.app.config.general.web_root}/manage/backlogOverview(/?)', BacklogOverviewHandler), (fr'{sickrage.app.config.general.web_root}/manage/massEdit(/?)', MassEditHandler), (fr'{sickrage.app.config.general.web_root}/manage/massUpdate(/?)', MassUpdateHandler), (fr'{sickrage.app.config.general.web_root}/manage/failedDownloads(/?)', FailedDownloadsHandler), (fr'{sickrage.app.config.general.web_root}/manage/manageQueues(/?)', ManageQueuesHandler), (fr'{sickrage.app.config.general.web_root}/manage/manageQueues/forceBacklogSearch(/?)', ForceBacklogSearchHandler), (fr'{sickrage.app.config.general.web_root}/manage/manageQueues/forceDailySearch(/?)', ForceDailySearchHandler), (fr'{sickrage.app.config.general.web_root}/manage/manageQueues/forceFindPropers(/?)', ForceFindPropersHandler), (fr'{sickrage.app.config.general.web_root}/manage/manageQueues/pauseDailySearcher(/?)', PauseDailySearcherHandler), (fr'{sickrage.app.config.general.web_root}/manage/manageQueues/pauseBacklogSearcher(/?)', PauseBacklogSearcherHandler), (fr'{sickrage.app.config.general.web_root}/manage/manageQueues/pausePostProcessor(/?)', PausePostProcessorHandler), (fr'{sickrage.app.config.general.web_root}/config(/?)', ConfigWebHandler), (fr'{sickrage.app.config.general.web_root}/config/reset(/?)', ConfigResetHandler), (fr'{sickrage.app.config.general.web_root}/config/anime(/?)', ConfigAnimeHandler), (fr'{sickrage.app.config.general.web_root}/config/anime/saveAnime(/?)', ConfigSaveAnimeHandler), (fr'{sickrage.app.config.general.web_root}/config/backuprestore(/?)', ConfigBackupRestoreHandler), (fr'{sickrage.app.config.general.web_root}/config/backuprestore/backup(/?)', ConfigBackupHandler), (fr'{sickrage.app.config.general.web_root}/config/backuprestore/restore(/?)', ConfigRestoreHandler), (fr'{sickrage.app.config.general.web_root}/config/backuprestore/saveBackupRestore(/?)', SaveBackupRestoreHandler), (fr'{sickrage.app.config.general.web_root}/config/general(/?)', ConfigGeneralHandler), (fr'{sickrage.app.config.general.web_root}/config/general/generateApiKey(/?)', GenerateApiKeyHandler), (fr'{sickrage.app.config.general.web_root}/config/general/saveRootDirs(/?)', SaveRootDirsHandler), (fr'{sickrage.app.config.general.web_root}/config/general/saveAddShowDefaults(/?)', SaveAddShowDefaultsHandler), (fr'{sickrage.app.config.general.web_root}/config/general/saveGeneral(/?)', SaveGeneralHandler), (fr'{sickrage.app.config.general.web_root}/config/notifications(/?)', ConfigNotificationsHandler), (fr'{sickrage.app.config.general.web_root}/config/notifications/saveNotifications(/?)', SaveNotificationsHandler), (fr'{sickrage.app.config.general.web_root}/config/postProcessing(/?)', ConfigPostProcessingHandler), (fr'{sickrage.app.config.general.web_root}/config/postProcessing/savePostProcessing(/?)', SavePostProcessingHandler), (fr'{sickrage.app.config.general.web_root}/config/postProcessing/testNaming(/?)', TestNamingHandler), (fr'{sickrage.app.config.general.web_root}/config/postProcessing/isNamingValid(/?)', IsNamingPatternValidHandler), (fr'{sickrage.app.config.general.web_root}/config/postProcessing/isRarSupported(/?)', IsRarSupportedHandler), (fr'{sickrage.app.config.general.web_root}/config/providers(/?)', ConfigProvidersHandler), (fr'{sickrage.app.config.general.web_root}/config/providers/canAddNewznabProvider(/?)', CanAddNewznabProviderHandler), (fr'{sickrage.app.config.general.web_root}/config/providers/canAddTorrentRssProvider(/?)', CanAddTorrentRssProviderHandler), (fr'{sickrage.app.config.general.web_root}/config/providers/getNewznabCategories(/?)', GetNewznabCategoriesHandler), (fr'{sickrage.app.config.general.web_root}/config/providers/saveProviders(/?)', SaveProvidersHandler), (fr'{sickrage.app.config.general.web_root}/config/qualitySettings(/?)', ConfigQualitySettingsHandler), (fr'{sickrage.app.config.general.web_root}/config/qualitySettings/saveQualities(/?)', SaveQualitiesHandler), (fr'{sickrage.app.config.general.web_root}/config/search(/?)', ConfigSearchHandler), (fr'{sickrage.app.config.general.web_root}/config/search/saveSearch(/?)', SaveSearchHandler), (fr'{sickrage.app.config.general.web_root}/config/subtitles(/?)', ConfigSubtitlesHandler), (fr'{sickrage.app.config.general.web_root}/config/subtitles/get_code(/?)', ConfigSubtitleGetCodeHandler), (fr'{sickrage.app.config.general.web_root}/config/subtitles/wanted_languages(/?)', ConfigSubtitlesWantedLanguagesHandler), (fr'{sickrage.app.config.general.web_root}/config/subtitles/saveSubtitles(/?)', SaveSubtitlesHandler), ] # Initialize Tornado application self.app = Application( handlers=sum(self.handlers.values(), []), debug=True, autoreload=False, gzip=sickrage.app.config.general.web_use_gzip, cookie_secret=sickrage.app.config.general.web_cookie_secret, login_url='%s/login/' % sickrage.app.config.general.web_root, templates=templates, default_handler_class=NotFoundHandler) # HTTPS Cert/Key object ssl_ctx = None if sickrage.app.config.general.enable_https: ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ssl_ctx.load_cert_chain(sickrage.app.config.general.https_cert, sickrage.app.config.general.https_key) # Web Server self.server = HTTPServer( self.app, ssl_options=ssl_ctx, xheaders=sickrage.app.config.general.handle_reverse_proxy) try: self.server.listen(sickrage.app.config.general.web_port, sickrage.app.web_host) except socket.error as e: sickrage.app.log.warning(e.strerror) raise SystemExit # launch browser window if not sickrage.app.no_launch and sickrage.app.config.general.launch_browser: sickrage.app.scheduler.add_job( launch_browser, args=[('http', 'https')[sickrage.app.config.general.enable_https], (get_internal_ip(), sickrage.app.web_host)[sickrage.app.web_host != ''], sickrage.app.config.general.web_port]) sickrage.app.log.info("SiCKRAGE :: STARTED") sickrage.app.log.info( f"SiCKRAGE :: APP VERSION:[{sickrage.version()}]") sickrage.app.log.info( f"SiCKRAGE :: CONFIG VERSION:[v{sickrage.app.config.db.version}]") sickrage.app.log.info( f"SiCKRAGE :: DATABASE VERSION:[v{sickrage.app.main_db.version}]") sickrage.app.log.info( f"SiCKRAGE :: DATABASE TYPE:[{sickrage.app.db_type}]") sickrage.app.log.info( f"SiCKRAGE :: URL:[{('http', 'https')[sickrage.app.config.general.enable_https]}://{(get_internal_ip(), sickrage.app.web_host)[sickrage.app.web_host != '']}:{sickrage.app.config.general.web_port}/{sickrage.app.config.general.web_root}]" ) self.io_loop.start()
def handle_sso_auth_get(self): code = self.get_argument('code', None) redirect_uri = "{}://{}{}/login".format(self.request.protocol, self.request.host, sickrage.app.config.web_root) 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.sub_id: sickrage.app.config.sub_id = decoded_token.get('sub') sickrage.app.config.save() if sickrage.app.config.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 sickrage.app.config.enable_sickrage_api: if sickrage.app.api.token: sickrage.app.api.logout() sickrage.app.api.token = token except Exception as e: sickrage.app.log.debug('{!r}'.format(e)) return self.redirect('/logout') internal_connections = "{}://{}:{}{}".format(self.request.protocol, get_internal_ip(), sickrage.app.config.web_port, sickrage.app.config.web_root) external_connections = "{}://{}:{}{}".format(self.request.protocol, get_external_ip(), sickrage.app.config.web_port, sickrage.app.config.web_root) connections = ','.join([internal_connections, external_connections]) if not re.match(r'[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}', sickrage.app.config.server_id or ""): server_id = sickrage.app.api.account.register_server(connections) if server_id: sickrage.app.config.server_id = server_id sickrage.app.config.save() else: sickrage.app.api.account.update_server(sickrage.app.config.server_id, connections) redirect_uri = self.get_argument('next', "/{}/".format(sickrage.app.config.default_page)) return self.redirect("{}".format(redirect_uri)) else: authorization_url = sickrage.app.auth_server.authorization_url(redirect_uri=redirect_uri, scope="profile email offline_access") if authorization_url: return super(BaseHandler, self).redirect(authorization_url) return self.redirect('/logout')
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')