2018-01-15 03:28:42 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- encoding: UTF-8 -*-
|
|
|
|
# This file is part of Mylar.
|
|
|
|
#
|
|
|
|
# Mylar is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# Mylar is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with Mylar. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#
|
|
|
|
######
|
|
|
|
# Form based authentication for CherryPy. Requires the
|
|
|
|
# Session tool to be loaded.
|
|
|
|
###### from cherrypy/tools on github
|
|
|
|
|
|
|
|
import cherrypy
|
|
|
|
from cherrypy.lib.static import serve_file
|
|
|
|
from cgi import escape
|
2018-02-18 21:49:33 +00:00
|
|
|
#from datetime import datetime, timedelta
|
2018-01-15 03:28:42 +00:00
|
|
|
import urllib
|
2018-02-18 22:18:11 +00:00
|
|
|
import re
|
2018-01-16 17:35:34 +00:00
|
|
|
import mylar
|
2019-03-29 14:18:08 +00:00
|
|
|
from mylar import logger, encrypted
|
2018-01-15 03:28:42 +00:00
|
|
|
|
|
|
|
SESSION_KEY = '_cp_username'
|
|
|
|
|
|
|
|
def check_credentials(username, password):
|
|
|
|
"""Verifies credentials for username and password.
|
|
|
|
Returns None on success or a string describing the error on failure"""
|
|
|
|
# Adapt to your needs
|
|
|
|
forms_user = cherrypy.request.config['auth.forms_username']
|
|
|
|
forms_pass = cherrypy.request.config['auth.forms_password']
|
2019-03-29 14:18:08 +00:00
|
|
|
edc = encrypted.Encryptor(forms_pass)
|
|
|
|
ed_chk = edc.decrypt_it()
|
|
|
|
if mylar.CONFIG.ENCRYPT_PASSWORDS is True:
|
|
|
|
if username == forms_user and all([ed_chk['status'] is True, ed_chk['password'] == password]):
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
return u"Incorrect username or password."
|
2018-01-15 03:28:42 +00:00
|
|
|
else:
|
2019-03-29 14:18:08 +00:00
|
|
|
if username == forms_user and password == forms_pass:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
return u"Incorrect username or password."
|
2018-01-15 03:28:42 +00:00
|
|
|
|
|
|
|
def check_auth(*args, **kwargs):
|
|
|
|
"""A tool that looks in config for 'auth.require'. If found and it
|
|
|
|
is not None, a login is required and the entry is evaluated as a list of
|
|
|
|
conditions that the user must fulfill"""
|
|
|
|
conditions = cherrypy.request.config.get('auth.require', None)
|
2018-02-18 21:49:33 +00:00
|
|
|
get_params = urllib.quote(cherrypy.request.request_line.split()[1])
|
2018-01-15 03:28:42 +00:00
|
|
|
if conditions is not None:
|
|
|
|
username = cherrypy.session.get(SESSION_KEY)
|
|
|
|
if username:
|
|
|
|
cherrypy.request.login = username
|
|
|
|
for condition in conditions:
|
|
|
|
# A condition is just a callable that returns true or false
|
|
|
|
if not condition():
|
2018-02-18 21:49:33 +00:00
|
|
|
raise cherrypy.HTTPRedirect(mylar.CONFIG.HTTP_ROOT + "auth/login?from_page=%s" % get_params)
|
2018-01-15 03:28:42 +00:00
|
|
|
else:
|
2018-02-18 21:49:33 +00:00
|
|
|
raise cherrypy.HTTPRedirect(mylar.CONFIG.HTTP_ROOT + "auth/login?from_page=%s" % get_params)
|
2018-01-15 03:28:42 +00:00
|
|
|
|
|
|
|
cherrypy.tools.auth = cherrypy.Tool('before_handler', check_auth)
|
|
|
|
|
|
|
|
def require(*conditions):
|
|
|
|
"""A decorator that appends conditions to the auth.require config
|
|
|
|
variable."""
|
|
|
|
def decorate(f):
|
|
|
|
if not hasattr(f, '_cp_config'):
|
|
|
|
f._cp_config = dict()
|
|
|
|
if 'auth.require' not in f._cp_config:
|
|
|
|
f._cp_config['auth.require'] = []
|
|
|
|
f._cp_config['auth.require'].extend(conditions)
|
|
|
|
return f
|
|
|
|
return decorate
|
|
|
|
|
|
|
|
|
|
|
|
# Conditions are callables that return True
|
|
|
|
# if the user fulfills the conditions they define, False otherwise
|
|
|
|
#
|
|
|
|
# They can access the current username as cherrypy.request.login
|
|
|
|
#
|
|
|
|
# Define those at will however suits the application.
|
|
|
|
|
|
|
|
def member_of(groupname):
|
|
|
|
def check():
|
|
|
|
# replace with actual check if <username> is in <groupname>
|
|
|
|
return cherrypy.request.login == 'joe' and groupname == 'admin'
|
|
|
|
return check
|
|
|
|
|
|
|
|
def name_is(reqd_username):
|
|
|
|
return lambda: reqd_username == cherrypy.request.login
|
|
|
|
|
|
|
|
# These might be handy
|
|
|
|
|
|
|
|
def any_of(*conditions):
|
|
|
|
"""Returns True if any of the conditions match"""
|
|
|
|
def check():
|
|
|
|
for c in conditions:
|
|
|
|
if c():
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
return check
|
|
|
|
|
|
|
|
# By default all conditions are required, but this might still be
|
|
|
|
# needed if you want to use it inside of an any_of(...) condition
|
|
|
|
def all_of(*conditions):
|
|
|
|
"""Returns True if all of the conditions match"""
|
|
|
|
def check():
|
|
|
|
for c in conditions:
|
|
|
|
if not c():
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
return check
|
|
|
|
|
|
|
|
# Controller to provide login and logout actions
|
|
|
|
|
|
|
|
class AuthController(object):
|
|
|
|
def on_login(self, username):
|
|
|
|
"""Called on successful login"""
|
IMP: Added Choose specific Download option to manually select from result list on Upcoming/Details/Weekly tabs, IMP: Added Wanted storyarcs to the overall Wanted section so now will search as per global options (storyarc issues can be displayed optionally on Wanted tab), IMP: Added custom url option for image banners/posters for storyarcs, IMP: updated Cherrypy, FIX: Fixed ComicRN not working when forms authentication used - in conjunction updated autoProcessComics to 2.0 which now uses apikey instead of user/pass, IMP: Alternate Series Covers option for alternating existing series image to the most current issue image, IMP: Added overall series total to series page for reference, IMP: Search workflow completely changed to accomodate more than one indexer - now will simultaneously sumbit initial request to each provider, wait 30s submit additional as required at 30s intervals, FIX: Removed TPSE as an option and relabelled to just Public Torrents, IMP: Added direct backlog search to WWT option (pack support will follow), FIX: Removed line about configparser being required for ComicTagger usage, IMP: Test code in place for newzab testing, FIX: Fixed layout problem with torrents that are in auto-snatch status on weekly tab, IMP: backend code improvements to allow for better alias usage and annual linking directly from WS, IMP: Updated systemd init-scripts with read.me, IMP: When post-processing, will now check for available destination free space before actually moving files, IMP: Will copy during metatagging to cache folder instead of move being an option so cleanup is cleaner if something fails, FIX: Changed readinglist table to storyarcs for clarity, IMP: When post-processing issues, will now only update the one issue status and adjust totals accordingly (instead of doing a complete rescan of the series), FIX: Clear out empty ID's from the Failed DB on startup, IMP: Initial code-run at REST API interface, FIX: Fixed some matching problems with 32p due to case, IMP: removed apikeys from log entries that were accidentally logging, IMP: When searching 32p, if items get packed up - will now delete the cached reference so new items of the same can be located, IMP: ForceSearch option switched to scheduler so simultaneous runs should not occur, FIX: Fixed manual metatagging error that would occur if multiple destination directories existed
2018-02-16 19:57:01 +00:00
|
|
|
logger.info('%s successfully logged on.' % username)
|
2018-01-15 03:28:42 +00:00
|
|
|
# not needed or used for Mylar currently
|
|
|
|
|
|
|
|
def on_logout(self, username):
|
|
|
|
"""Called on logout"""
|
|
|
|
# not needed or used for Mylar currently
|
|
|
|
|
2018-02-18 21:49:33 +00:00
|
|
|
def get_loginform(self, username, msg="Enter login information", from_page="/"):
|
2018-01-15 03:28:42 +00:00
|
|
|
from mylar.webserve import serve_template
|
2018-02-21 18:51:25 +00:00
|
|
|
return serve_template(templatename="login.html", username=escape(username, True), title="Login", from_page=from_page)
|
2018-01-15 03:28:42 +00:00
|
|
|
|
|
|
|
@cherrypy.expose
|
2018-02-18 21:49:33 +00:00
|
|
|
def login(self, current_username=None, current_password=None, remember_me='0', from_page="/"):
|
IMP: Added Choose specific Download option to manually select from result list on Upcoming/Details/Weekly tabs, IMP: Added Wanted storyarcs to the overall Wanted section so now will search as per global options (storyarc issues can be displayed optionally on Wanted tab), IMP: Added custom url option for image banners/posters for storyarcs, IMP: updated Cherrypy, FIX: Fixed ComicRN not working when forms authentication used - in conjunction updated autoProcessComics to 2.0 which now uses apikey instead of user/pass, IMP: Alternate Series Covers option for alternating existing series image to the most current issue image, IMP: Added overall series total to series page for reference, IMP: Search workflow completely changed to accomodate more than one indexer - now will simultaneously sumbit initial request to each provider, wait 30s submit additional as required at 30s intervals, FIX: Removed TPSE as an option and relabelled to just Public Torrents, IMP: Added direct backlog search to WWT option (pack support will follow), FIX: Removed line about configparser being required for ComicTagger usage, IMP: Test code in place for newzab testing, FIX: Fixed layout problem with torrents that are in auto-snatch status on weekly tab, IMP: backend code improvements to allow for better alias usage and annual linking directly from WS, IMP: Updated systemd init-scripts with read.me, IMP: When post-processing, will now check for available destination free space before actually moving files, IMP: Will copy during metatagging to cache folder instead of move being an option so cleanup is cleaner if something fails, FIX: Changed readinglist table to storyarcs for clarity, IMP: When post-processing issues, will now only update the one issue status and adjust totals accordingly (instead of doing a complete rescan of the series), FIX: Clear out empty ID's from the Failed DB on startup, IMP: Initial code-run at REST API interface, FIX: Fixed some matching problems with 32p due to case, IMP: removed apikeys from log entries that were accidentally logging, IMP: When searching 32p, if items get packed up - will now delete the cached reference so new items of the same can be located, IMP: ForceSearch option switched to scheduler so simultaneous runs should not occur, FIX: Fixed manual metatagging error that would occur if multiple destination directories existed
2018-02-16 19:57:01 +00:00
|
|
|
if current_username is None or current_password is None:
|
2018-02-18 21:49:33 +00:00
|
|
|
return self.get_loginform("", from_page=from_page)
|
2018-01-15 03:28:42 +00:00
|
|
|
|
IMP: Added Choose specific Download option to manually select from result list on Upcoming/Details/Weekly tabs, IMP: Added Wanted storyarcs to the overall Wanted section so now will search as per global options (storyarc issues can be displayed optionally on Wanted tab), IMP: Added custom url option for image banners/posters for storyarcs, IMP: updated Cherrypy, FIX: Fixed ComicRN not working when forms authentication used - in conjunction updated autoProcessComics to 2.0 which now uses apikey instead of user/pass, IMP: Alternate Series Covers option for alternating existing series image to the most current issue image, IMP: Added overall series total to series page for reference, IMP: Search workflow completely changed to accomodate more than one indexer - now will simultaneously sumbit initial request to each provider, wait 30s submit additional as required at 30s intervals, FIX: Removed TPSE as an option and relabelled to just Public Torrents, IMP: Added direct backlog search to WWT option (pack support will follow), FIX: Removed line about configparser being required for ComicTagger usage, IMP: Test code in place for newzab testing, FIX: Fixed layout problem with torrents that are in auto-snatch status on weekly tab, IMP: backend code improvements to allow for better alias usage and annual linking directly from WS, IMP: Updated systemd init-scripts with read.me, IMP: When post-processing, will now check for available destination free space before actually moving files, IMP: Will copy during metatagging to cache folder instead of move being an option so cleanup is cleaner if something fails, FIX: Changed readinglist table to storyarcs for clarity, IMP: When post-processing issues, will now only update the one issue status and adjust totals accordingly (instead of doing a complete rescan of the series), FIX: Clear out empty ID's from the Failed DB on startup, IMP: Initial code-run at REST API interface, FIX: Fixed some matching problems with 32p due to case, IMP: removed apikeys from log entries that were accidentally logging, IMP: When searching 32p, if items get packed up - will now delete the cached reference so new items of the same can be located, IMP: ForceSearch option switched to scheduler so simultaneous runs should not occur, FIX: Fixed manual metatagging error that would occur if multiple destination directories existed
2018-02-16 19:57:01 +00:00
|
|
|
error_msg = check_credentials(current_username, current_password)
|
2018-01-15 03:28:42 +00:00
|
|
|
if error_msg:
|
2018-02-18 21:49:33 +00:00
|
|
|
return self.get_loginform(current_username, error_msg, from_page)
|
2018-01-15 03:28:42 +00:00
|
|
|
else:
|
2018-02-21 19:54:29 +00:00
|
|
|
#if all([from_page != "/", from_page != "//"]):
|
|
|
|
# from_page = from_page
|
|
|
|
#if mylar.OS_DETECT == 'Windows':
|
|
|
|
# if mylar.CONFIG.HTTP_ROOT != "//":
|
|
|
|
# from_page = re.sub(mylar.CONFIG.HTTP_ROOT, '', from_page,1).strip()
|
|
|
|
#else:
|
|
|
|
# #if mylar.CONFIG.HTTP_ROOT != "/":
|
|
|
|
# from_page = re.sub(mylar.CONFIG.HTTP_ROOT, '', from_page,1).strip()
|
2018-01-15 03:28:42 +00:00
|
|
|
cherrypy.session.regenerate()
|
IMP: Added Choose specific Download option to manually select from result list on Upcoming/Details/Weekly tabs, IMP: Added Wanted storyarcs to the overall Wanted section so now will search as per global options (storyarc issues can be displayed optionally on Wanted tab), IMP: Added custom url option for image banners/posters for storyarcs, IMP: updated Cherrypy, FIX: Fixed ComicRN not working when forms authentication used - in conjunction updated autoProcessComics to 2.0 which now uses apikey instead of user/pass, IMP: Alternate Series Covers option for alternating existing series image to the most current issue image, IMP: Added overall series total to series page for reference, IMP: Search workflow completely changed to accomodate more than one indexer - now will simultaneously sumbit initial request to each provider, wait 30s submit additional as required at 30s intervals, FIX: Removed TPSE as an option and relabelled to just Public Torrents, IMP: Added direct backlog search to WWT option (pack support will follow), FIX: Removed line about configparser being required for ComicTagger usage, IMP: Test code in place for newzab testing, FIX: Fixed layout problem with torrents that are in auto-snatch status on weekly tab, IMP: backend code improvements to allow for better alias usage and annual linking directly from WS, IMP: Updated systemd init-scripts with read.me, IMP: When post-processing, will now check for available destination free space before actually moving files, IMP: Will copy during metatagging to cache folder instead of move being an option so cleanup is cleaner if something fails, FIX: Changed readinglist table to storyarcs for clarity, IMP: When post-processing issues, will now only update the one issue status and adjust totals accordingly (instead of doing a complete rescan of the series), FIX: Clear out empty ID's from the Failed DB on startup, IMP: Initial code-run at REST API interface, FIX: Fixed some matching problems with 32p due to case, IMP: removed apikeys from log entries that were accidentally logging, IMP: When searching 32p, if items get packed up - will now delete the cached reference so new items of the same can be located, IMP: ForceSearch option switched to scheduler so simultaneous runs should not occur, FIX: Fixed manual metatagging error that would occur if multiple destination directories existed
2018-02-16 19:57:01 +00:00
|
|
|
cherrypy.session[SESSION_KEY] = cherrypy.request.login = current_username
|
2018-02-18 21:49:33 +00:00
|
|
|
#expiry = datetime.now() + (timedelta(days=30) if remember_me == '1' else timedelta(minutes=60))
|
|
|
|
#cherrypy.session[SESSION_KEY] = {'user': cherrypy.request.login,
|
|
|
|
# 'expiry': expiry}
|
IMP: Added Choose specific Download option to manually select from result list on Upcoming/Details/Weekly tabs, IMP: Added Wanted storyarcs to the overall Wanted section so now will search as per global options (storyarc issues can be displayed optionally on Wanted tab), IMP: Added custom url option for image banners/posters for storyarcs, IMP: updated Cherrypy, FIX: Fixed ComicRN not working when forms authentication used - in conjunction updated autoProcessComics to 2.0 which now uses apikey instead of user/pass, IMP: Alternate Series Covers option for alternating existing series image to the most current issue image, IMP: Added overall series total to series page for reference, IMP: Search workflow completely changed to accomodate more than one indexer - now will simultaneously sumbit initial request to each provider, wait 30s submit additional as required at 30s intervals, FIX: Removed TPSE as an option and relabelled to just Public Torrents, IMP: Added direct backlog search to WWT option (pack support will follow), FIX: Removed line about configparser being required for ComicTagger usage, IMP: Test code in place for newzab testing, FIX: Fixed layout problem with torrents that are in auto-snatch status on weekly tab, IMP: backend code improvements to allow for better alias usage and annual linking directly from WS, IMP: Updated systemd init-scripts with read.me, IMP: When post-processing, will now check for available destination free space before actually moving files, IMP: Will copy during metatagging to cache folder instead of move being an option so cleanup is cleaner if something fails, FIX: Changed readinglist table to storyarcs for clarity, IMP: When post-processing issues, will now only update the one issue status and adjust totals accordingly (instead of doing a complete rescan of the series), FIX: Clear out empty ID's from the Failed DB on startup, IMP: Initial code-run at REST API interface, FIX: Fixed some matching problems with 32p due to case, IMP: removed apikeys from log entries that were accidentally logging, IMP: When searching 32p, if items get packed up - will now delete the cached reference so new items of the same can be located, IMP: ForceSearch option switched to scheduler so simultaneous runs should not occur, FIX: Fixed manual metatagging error that would occur if multiple destination directories existed
2018-02-16 19:57:01 +00:00
|
|
|
self.on_login(current_username)
|
2018-02-18 21:49:33 +00:00
|
|
|
raise cherrypy.HTTPRedirect(from_page or mylar.CONFIG.HTTP_ROOT)
|
2018-01-15 03:28:42 +00:00
|
|
|
|
|
|
|
@cherrypy.expose
|
2018-02-18 21:49:33 +00:00
|
|
|
def logout(self, from_page="/"):
|
2018-01-15 03:28:42 +00:00
|
|
|
sess = cherrypy.session
|
|
|
|
username = sess.get(SESSION_KEY, None)
|
|
|
|
sess[SESSION_KEY] = None
|
2018-10-19 16:38:27 +00:00
|
|
|
return self.get_loginform("", from_page=from_page)
|
2018-01-15 03:28:42 +00:00
|
|
|
if username:
|
|
|
|
cherrypy.request.login = None
|
|
|
|
self.on_logout(username)
|
2018-02-18 21:49:33 +00:00
|
|
|
raise cherrypy.HTTPRedirect(from_page or mylar.CONFIG.HTTP_ROOT)
|
2018-01-15 03:28:42 +00:00
|
|
|
|