mirror of
https://github.com/janeczku/calibre-web
synced 2025-01-13 02:40:29 +00:00
better logged in session protection
This commit is contained in:
parent
e245a147d9
commit
a63baa1758
@ -34,6 +34,7 @@ from babel.dates import format_datetime
|
|||||||
from flask import Blueprint, flash, redirect, url_for, abort, request, make_response, send_from_directory, g, Response
|
from flask import Blueprint, flash, redirect, url_for, abort, request, make_response, send_from_directory, g, Response
|
||||||
from flask_login import login_required, current_user, logout_user, confirm_login
|
from flask_login import login_required, current_user, logout_user, confirm_login
|
||||||
from flask_babel import gettext as _
|
from flask_babel import gettext as _
|
||||||
|
from flask import session as flask_session
|
||||||
from sqlalchemy import and_
|
from sqlalchemy import and_
|
||||||
from sqlalchemy.orm.attributes import flag_modified
|
from sqlalchemy.orm.attributes import flag_modified
|
||||||
from sqlalchemy.exc import IntegrityError, OperationalError, InvalidRequestError
|
from sqlalchemy.exc import IntegrityError, OperationalError, InvalidRequestError
|
||||||
@ -98,8 +99,11 @@ def admin_required(f):
|
|||||||
|
|
||||||
@admi.before_app_request
|
@admi.before_app_request
|
||||||
def before_request():
|
def before_request():
|
||||||
|
# make remember me function work
|
||||||
if current_user.is_authenticated:
|
if current_user.is_authenticated:
|
||||||
confirm_login()
|
confirm_login()
|
||||||
|
if not ub.check_user_session(current_user.id, flask_session.get('_id')) and 'opds' not in request.path:
|
||||||
|
logout_user()
|
||||||
g.constants = constants
|
g.constants = constants
|
||||||
g.user = current_user
|
g.user = current_user
|
||||||
g.allow_registration = config.config_public_reg
|
g.allow_registration = config.config_public_reg
|
||||||
|
45
cps/ub.py
45
cps/ub.py
@ -27,6 +27,8 @@ from flask import session as flask_session
|
|||||||
from binascii import hexlify
|
from binascii import hexlify
|
||||||
|
|
||||||
from flask_login import AnonymousUserMixin, current_user
|
from flask_login import AnonymousUserMixin, current_user
|
||||||
|
from flask_login import user_logged_in
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from flask_dance.consumer.backend.sqla import OAuthConsumerMixin
|
from flask_dance.consumer.backend.sqla import OAuthConsumerMixin
|
||||||
@ -61,6 +63,36 @@ Base = declarative_base()
|
|||||||
searched_ids = {}
|
searched_ids = {}
|
||||||
|
|
||||||
|
|
||||||
|
def signal_store_user_session(object, user):
|
||||||
|
store_user_session()
|
||||||
|
|
||||||
|
def store_user_session():
|
||||||
|
if flask_session.get('_user_id', ""):
|
||||||
|
try:
|
||||||
|
if not check_user_session(flask_session.get('_user_id', ""), flask_session.get('_id', "")):
|
||||||
|
user_session = User_Sessions(flask_session.get('_user_id', ""), flask_session.get('_id', ""))
|
||||||
|
session.add(user_session)
|
||||||
|
session.commit()
|
||||||
|
except (exc.OperationalError, exc.InvalidRequestError):
|
||||||
|
session.rollback()
|
||||||
|
# log.debug(flask_session.get('_id', ""))
|
||||||
|
|
||||||
|
def delete_user_session(user_id, session_key):
|
||||||
|
try:
|
||||||
|
# log.debug(session_key)
|
||||||
|
session.query(User_Sessions).filter(User_Sessions.user_id==user_id,
|
||||||
|
User_Sessions.session_key==session_key).delete()
|
||||||
|
session.commit()
|
||||||
|
except (exc.OperationalError, exc.InvalidRequestError):
|
||||||
|
session.rollback()
|
||||||
|
|
||||||
|
|
||||||
|
def check_user_session(user_id, session_key):
|
||||||
|
return bool(session.query(User_Sessions).filter(User_Sessions.user_id==user_id,
|
||||||
|
User_Sessions.session_key==session_key).one_or_none())
|
||||||
|
|
||||||
|
user_logged_in.connect(signal_store_user_session)
|
||||||
|
|
||||||
def store_ids(result):
|
def store_ids(result):
|
||||||
ids = list()
|
ids = list()
|
||||||
for element in result:
|
for element in result:
|
||||||
@ -72,7 +104,7 @@ class UserBase:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_authenticated(self):
|
def is_authenticated(self):
|
||||||
return True
|
return self.is_active
|
||||||
|
|
||||||
def _has_role(self, role_flag):
|
def _has_role(self, role_flag):
|
||||||
return constants.has_flag(self.role, role_flag)
|
return constants.has_flag(self.role, role_flag)
|
||||||
@ -261,6 +293,17 @@ class Anonymous(AnonymousUserMixin, UserBase):
|
|||||||
flask_session['view'][page][prop] = value
|
flask_session['view'][page][prop] = value
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
class User_Sessions(Base):
|
||||||
|
__tablename__ = 'user_session'
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
user_id = Column(Integer, ForeignKey('user.id'))
|
||||||
|
session_key = Column(String, default="")
|
||||||
|
|
||||||
|
def __init__(self, user_id, session_key):
|
||||||
|
self.user_id = user_id
|
||||||
|
self.session_key = session_key
|
||||||
|
|
||||||
|
|
||||||
# Baseclass representing Shelfs in calibre-web in app.db
|
# Baseclass representing Shelfs in calibre-web in app.db
|
||||||
class Shelf(Base):
|
class Shelf(Base):
|
||||||
|
@ -21,7 +21,8 @@ import binascii
|
|||||||
|
|
||||||
from sqlalchemy.sql.expression import func
|
from sqlalchemy.sql.expression import func
|
||||||
from werkzeug.security import check_password_hash
|
from werkzeug.security import check_password_hash
|
||||||
from flask_login import login_required
|
from flask_login import login_required, login_user
|
||||||
|
|
||||||
|
|
||||||
from . import lm, ub, config, constants, services
|
from . import lm, ub, config, constants, services
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ def load_user_from_request(request):
|
|||||||
if rp_header_username:
|
if rp_header_username:
|
||||||
user = _fetch_user_by_name(rp_header_username)
|
user = _fetch_user_by_name(rp_header_username)
|
||||||
if user:
|
if user:
|
||||||
|
login_user(user)
|
||||||
return user
|
return user
|
||||||
|
|
||||||
auth_header = request.headers.get("Authorization")
|
auth_header = request.headers.get("Authorization")
|
||||||
|
@ -1523,7 +1523,6 @@ def login():
|
|||||||
login_result, error = services.ldap.bind_user(form['username'], form['password'])
|
login_result, error = services.ldap.bind_user(form['username'], form['password'])
|
||||||
if login_result:
|
if login_result:
|
||||||
login_user(user, remember=bool(form.get('remember_me')))
|
login_user(user, remember=bool(form.get('remember_me')))
|
||||||
#ub.store_user_session()
|
|
||||||
log.debug(u"You are now logged in as: '%s'", user.name)
|
log.debug(u"You are now logged in as: '%s'", user.name)
|
||||||
flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.name),
|
flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.name),
|
||||||
category="success")
|
category="success")
|
||||||
@ -1531,7 +1530,6 @@ def login():
|
|||||||
elif login_result is None and user and check_password_hash(str(user.password), form['password']) \
|
elif login_result is None and user and check_password_hash(str(user.password), form['password']) \
|
||||||
and user.name != "Guest":
|
and user.name != "Guest":
|
||||||
login_user(user, remember=bool(form.get('remember_me')))
|
login_user(user, remember=bool(form.get('remember_me')))
|
||||||
#ub.store_user_session()
|
|
||||||
log.info("Local Fallback Login as: '%s'", user.name)
|
log.info("Local Fallback Login as: '%s'", user.name)
|
||||||
flash(_(u"Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known",
|
flash(_(u"Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known",
|
||||||
nickname=user.name),
|
nickname=user.name),
|
||||||
@ -1561,7 +1559,6 @@ def login():
|
|||||||
else:
|
else:
|
||||||
if user and check_password_hash(str(user.password), form['password']) and user.name != "Guest":
|
if user and check_password_hash(str(user.password), form['password']) and user.name != "Guest":
|
||||||
login_user(user, remember=bool(form.get('remember_me')))
|
login_user(user, remember=bool(form.get('remember_me')))
|
||||||
# ub.store_user_session()
|
|
||||||
log.debug(u"You are now logged in as: '%s'", user.name)
|
log.debug(u"You are now logged in as: '%s'", user.name)
|
||||||
flash(_(u"You are now logged in as: '%(nickname)s'", nickname=user.name), category="success")
|
flash(_(u"You are now logged in as: '%(nickname)s'", nickname=user.name), category="success")
|
||||||
config.config_is_initial = False
|
config.config_is_initial = False
|
||||||
@ -1585,7 +1582,7 @@ def login():
|
|||||||
@login_required
|
@login_required
|
||||||
def logout():
|
def logout():
|
||||||
if current_user is not None and current_user.is_authenticated:
|
if current_user is not None and current_user.is_authenticated:
|
||||||
# ub.delete_user_session(current_user.id, flask_session.get('_id',""))
|
ub.delete_user_session(current_user.id, flask_session.get('_id',""))
|
||||||
logout_user()
|
logout_user()
|
||||||
if feature_support['oauth'] and (config.config_login_type == 2 or config.config_login_type == 3):
|
if feature_support['oauth'] and (config.config_login_type == 2 or config.config_login_type == 3):
|
||||||
logout_oauth_user()
|
logout_oauth_user()
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user