mirror of
https://github.com/janeczku/calibre-web
synced 2024-11-09 11:30:00 +00:00
Update login routine (remember me working)
This commit is contained in:
parent
c09e1ed203
commit
1d3a768dfe
@ -19,12 +19,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import ast
|
||||
import hashlib
|
||||
|
||||
from .cw_login import LoginManager
|
||||
from flask import session
|
||||
|
||||
from .cw_login import LoginManager, confirm_login
|
||||
from flask import session, current_app
|
||||
from .cw_login.utils import decode_cookie
|
||||
from .cw_login.signals import user_loaded_from_cookie
|
||||
|
||||
|
||||
class MyLoginManager(LoginManager):
|
||||
@ -36,19 +36,5 @@ class MyLoginManager(LoginManager):
|
||||
return super(). _session_protection_failed()
|
||||
return False
|
||||
|
||||
def _load_user_from_remember_cookie(self, cookie):
|
||||
user_id = decode_cookie(cookie)
|
||||
if user_id is not None:
|
||||
session["_user_id"] = user_id
|
||||
session["_fresh"] = False
|
||||
user = None
|
||||
if self._user_callback:
|
||||
user = self._user_callback(user_id, None, None)
|
||||
if user is not None:
|
||||
app = current_app._get_current_object()
|
||||
user_loaded_from_cookie.send(app, user=user)
|
||||
# if session was restored from remember me cookie make login valid
|
||||
confirm_login()
|
||||
return user
|
||||
return None
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
import hashlib
|
||||
|
||||
from flask import abort
|
||||
from flask import current_app
|
||||
@ -9,6 +10,8 @@ from flask import has_app_context
|
||||
from flask import redirect
|
||||
from flask import request
|
||||
from flask import session
|
||||
from itsdangerous import URLSafeSerializer
|
||||
from flask.json.tag import TaggedJSONSerializer
|
||||
|
||||
from .config import AUTH_HEADER_NAME
|
||||
from .config import COOKIE_DURATION
|
||||
@ -32,8 +35,7 @@ from .signals import user_needs_refresh
|
||||
from .signals import user_unauthorized
|
||||
from .utils import _create_identifier
|
||||
from .utils import _user_context_processor
|
||||
from .utils import decode_cookie
|
||||
from .utils import encode_cookie
|
||||
from .utils import confirm_login
|
||||
from .utils import expand_login_view
|
||||
from .utils import login_url as make_login_url
|
||||
from .utils import make_next_param
|
||||
@ -323,7 +325,7 @@ class LoginManager:
|
||||
if self._user_callback is None and self._request_callback is None:
|
||||
raise Exception(
|
||||
"Missing user_loader or request_loader. Refer to "
|
||||
"http://flask-login.readthedocs.io/#how-it-works "
|
||||
"https://flask-login.readthedocs.io/#how-it-works "
|
||||
"for more info."
|
||||
)
|
||||
|
||||
@ -361,7 +363,8 @@ class LoginManager:
|
||||
elif header_name in request.headers:
|
||||
header = request.headers[header_name]
|
||||
user = self._load_user_from_header(header)
|
||||
|
||||
if not user:
|
||||
self._update_request_context_with_user()
|
||||
return self._update_request_context_with_user(user)
|
||||
|
||||
def _session_protection_failed(self):
|
||||
@ -393,16 +396,32 @@ class LoginManager:
|
||||
return False
|
||||
|
||||
def _load_user_from_remember_cookie(self, cookie):
|
||||
user_id = decode_cookie(cookie)
|
||||
if user_id is not None:
|
||||
session["_user_id"] = user_id
|
||||
signer_kwargs = dict(
|
||||
key_derivation="hmac", digest_method=staticmethod(hashlib.sha1)
|
||||
)
|
||||
try:
|
||||
remember_dict = URLSafeSerializer(
|
||||
current_app.secret_key,
|
||||
salt="remember",
|
||||
serializer=TaggedJSONSerializer(),
|
||||
signer_kwargs=signer_kwargs,
|
||||
).loads(cookie)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
if remember_dict['user'] is not None:
|
||||
session["_user_id"] = remember_dict['user']
|
||||
if "_random" not in session:
|
||||
session["_random"] = remember_dict['random']
|
||||
session["_fresh"] = False
|
||||
user = None
|
||||
if self._user_callback:
|
||||
user = self._user_callback(user_id)
|
||||
user = self._user_callback(remember_dict['user'], session["_random"], None)
|
||||
if user is not None:
|
||||
app = current_app._get_current_object()
|
||||
user_loaded_from_cookie.send(app, user=user)
|
||||
# if session was restored from remember me cookie make login valid
|
||||
confirm_login()
|
||||
return user
|
||||
return None
|
||||
|
||||
@ -461,7 +480,17 @@ class LoginManager:
|
||||
duration = config.get("REMEMBER_COOKIE_DURATION", COOKIE_DURATION)
|
||||
|
||||
# prepare data
|
||||
data = encode_cookie(str(session["_user_id"]))
|
||||
max_age = int(current_app.permanent_session_lifetime.total_seconds())
|
||||
signer_kwargs = dict(
|
||||
key_derivation="hmac", digest_method=staticmethod(hashlib.sha1)
|
||||
)
|
||||
# save
|
||||
data = URLSafeSerializer(
|
||||
current_app.secret_key,
|
||||
salt="remember",
|
||||
serializer=TaggedJSONSerializer(),
|
||||
signer_kwargs=signer_kwargs,
|
||||
).dumps({"user":session["_user_id"], "random":session["_random"]})
|
||||
|
||||
if isinstance(duration, int):
|
||||
duration = timedelta(seconds=duration)
|
||||
|
20
cps/ub.py
20
cps/ub.py
@ -74,10 +74,9 @@ def store_user_session():
|
||||
_user = flask_session.get('_user_id', "")
|
||||
_id = flask_session.get('_id', "")
|
||||
_random = flask_session.get('_random', "")
|
||||
|
||||
if flask_session.get('_user_id', ""):
|
||||
try:
|
||||
if not check_user_session(_user, _id):
|
||||
if not check_user_session(_user, _id, _random):
|
||||
expiry = int((datetime.datetime.now() + datetime.timedelta(days=31)).timestamp())
|
||||
user_session = User_Sessions(_user, _id, _random, expiry)
|
||||
session.add(user_session)
|
||||
@ -103,10 +102,12 @@ def delete_user_session(user_id, session_key):
|
||||
log.exception(ex)
|
||||
|
||||
|
||||
def check_user_session(user_id, session_key):
|
||||
def check_user_session(user_id, session_key, random):
|
||||
try:
|
||||
found = session.query(User_Sessions).filter(User_Sessions.user_id==user_id,
|
||||
User_Sessions.session_key==session_key).one_or_none()
|
||||
User_Sessions.session_key==session_key,
|
||||
User_Sessions.random == random,
|
||||
).one_or_none()
|
||||
if found is not None:
|
||||
new_expiry = int((datetime.datetime.now() + datetime.timedelta(days=31)).timestamp())
|
||||
if new_expiry - found.expiry > 86400:
|
||||
@ -614,10 +615,13 @@ def migrate_Database(_session):
|
||||
def clean_database(_session):
|
||||
# Remove expired remote login tokens
|
||||
now = datetime.datetime.now()
|
||||
_session.query(RemoteAuthToken).filter(now > RemoteAuthToken.expiration).\
|
||||
filter(RemoteAuthToken.token_type != 1).delete()
|
||||
_session.commit()
|
||||
|
||||
try:
|
||||
_session.query(RemoteAuthToken).filter(now > RemoteAuthToken.expiration).\
|
||||
filter(RemoteAuthToken.token_type != 1).delete()
|
||||
_session.commit()
|
||||
except exc.OperationalError: # Database is not writeable
|
||||
print('Settings database is not writeable. Exiting...')
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
# Save downloaded books per user in calibre-web's own database
|
||||
|
@ -40,7 +40,6 @@ def verify_password(username, password):
|
||||
if user.name.lower() == "guest":
|
||||
if config.config_anonbrowse == 1:
|
||||
return user
|
||||
limiter.check()
|
||||
if config.config_login_type == constants.LOGIN_LDAP and services.ldap:
|
||||
login_result, error = services.ldap.bind_user(user.name, password)
|
||||
if login_result:
|
||||
@ -48,9 +47,11 @@ def verify_password(username, password):
|
||||
return user
|
||||
if error is not None:
|
||||
log.error(error)
|
||||
elif check_password_hash(str(user.password), password):
|
||||
[limiter.limiter.storage.clear(k.key) for k in limiter.current_limits]
|
||||
return user
|
||||
else:
|
||||
limiter.check()
|
||||
if check_password_hash(str(user.password), password):
|
||||
[limiter.limiter.storage.clear(k.key) for k in limiter.current_limits]
|
||||
return user
|
||||
ip_address = request.headers.get('X-Forwarded-For', request.remote_addr)
|
||||
log.warning('OPDS Login failed for user "%s" IP-address: %s', username, ip_address)
|
||||
return None
|
||||
@ -127,9 +128,13 @@ def load_user_from_reverse_proxy_header(req):
|
||||
@lm.user_loader
|
||||
def load_user(user_id, random, session_key):
|
||||
user = ub.session.query(ub.User).filter(ub.User.id == int(user_id)).first()
|
||||
if random and session_key:
|
||||
if session_key:
|
||||
entry = ub.session.query(ub.User_Sessions).filter(ub.User_Sessions.random == random,
|
||||
ub.User_Sessions.session_key == session_key).first()
|
||||
ub.User_Sessions.session_key == session_key).first()
|
||||
if not entry or entry.user_id != user.id:
|
||||
return None
|
||||
elif random:
|
||||
entry = ub.session.query(ub.User_Sessions).filter(ub.User_Sessions.random == random).first()
|
||||
if not entry or entry.user_id != user.id:
|
||||
return None
|
||||
return user
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user