mirror of
https://github.com/Mailu/Mailu.git
synced 2024-12-14 10:53:30 +02:00
Lazy loading of KVSessionExtension
- call cleanup_sessions on first kvstore access this allows to run cmdline actions without redis (and makes it faster) - Allow development using DictStore by setting REDIS_ADDRESS to the empty string in env - don't sign 64bit random session id as suggested by nextgens
This commit is contained in:
parent
1fd7a9c578
commit
83b1fbb9d6
@ -1,8 +1,8 @@
|
|||||||
|
""" Mailu admin app
|
||||||
|
"""
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
import flask_bootstrap
|
import flask_bootstrap
|
||||||
import redis
|
|
||||||
from flask_kvsession import KVSessionExtension
|
|
||||||
from simplekv.memory.redisstore import RedisStore
|
|
||||||
|
|
||||||
from mailu import utils, debug, models, manage, configuration
|
from mailu import utils, debug, models, manage, configuration
|
||||||
|
|
||||||
@ -20,7 +20,8 @@ def create_app_from_config(config):
|
|||||||
# Initialize application extensions
|
# Initialize application extensions
|
||||||
config.init_app(app)
|
config.init_app(app)
|
||||||
models.db.init_app(app)
|
models.db.init_app(app)
|
||||||
KVSessionExtension(RedisStore(redis.StrictRedis().from_url('redis://{0}/3'.format(config['REDIS_ADDRESS']))), app).cleanup_sessions(app)
|
utils.kvsession.init_kvstore(config)
|
||||||
|
utils.kvsession.init_app(app)
|
||||||
utils.limiter.init_app(app)
|
utils.limiter.init_app(app)
|
||||||
utils.babel.init_app(app)
|
utils.babel.init_app(app)
|
||||||
utils.login.init_app(app)
|
utils.login.init_app(app)
|
||||||
@ -53,8 +54,7 @@ def create_app_from_config(config):
|
|||||||
|
|
||||||
|
|
||||||
def create_app():
|
def create_app():
|
||||||
""" Create a new application based on the config module
|
""" Create a new application based on the config module
|
||||||
"""
|
"""
|
||||||
config = configuration.ConfigManager()
|
config = configuration.ConfigManager()
|
||||||
return create_app_from_config(config)
|
return create_app_from_config(config)
|
||||||
|
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
from mailu import models, limiter
|
""" Mailu admin app utilities
|
||||||
|
"""
|
||||||
|
|
||||||
|
from mailu import limiter
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
import flask_login
|
import flask_login
|
||||||
import flask_script
|
|
||||||
import flask_migrate
|
import flask_migrate
|
||||||
import flask_babel
|
import flask_babel
|
||||||
|
import flask_kvsession
|
||||||
|
import redis
|
||||||
|
|
||||||
|
from simplekv.memory import DictStore
|
||||||
|
from simplekv.memory.redisstore import RedisStore
|
||||||
|
from itsdangerous.encoding import want_bytes
|
||||||
from werkzeug.contrib import fixers
|
from werkzeug.contrib import fixers
|
||||||
|
|
||||||
|
|
||||||
@ -33,6 +40,10 @@ def get_locale():
|
|||||||
|
|
||||||
# Proxy fixer
|
# Proxy fixer
|
||||||
class PrefixMiddleware(object):
|
class PrefixMiddleware(object):
|
||||||
|
""" fix proxy headers """
|
||||||
|
def __init__(self):
|
||||||
|
self.app = None
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
prefix = environ.get('HTTP_X_FORWARDED_PREFIX', '')
|
prefix = environ.get('HTTP_X_FORWARDED_PREFIX', '')
|
||||||
if prefix:
|
if prefix:
|
||||||
@ -48,3 +59,53 @@ proxy = PrefixMiddleware()
|
|||||||
|
|
||||||
# Data migrate
|
# Data migrate
|
||||||
migrate = flask_migrate.Migrate()
|
migrate = flask_migrate.Migrate()
|
||||||
|
|
||||||
|
|
||||||
|
# session store
|
||||||
|
class NullSigner(object):
|
||||||
|
"""NullSigner does not sign nor unsign"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
def sign(self, value):
|
||||||
|
"""Signs the given string."""
|
||||||
|
return want_bytes(value)
|
||||||
|
def unsign(self, signed_value):
|
||||||
|
"""Unsigns the given string."""
|
||||||
|
return want_bytes(signed_value)
|
||||||
|
|
||||||
|
class KVSessionIntf(flask_kvsession.KVSessionInterface):
|
||||||
|
""" KVSession interface allowing to run int function on first access """
|
||||||
|
def __init__(self, app, init_fn=None):
|
||||||
|
if init_fn:
|
||||||
|
app.kvsession_init = init_fn
|
||||||
|
else:
|
||||||
|
self._first_run(None)
|
||||||
|
def _first_run(self, app):
|
||||||
|
if app:
|
||||||
|
app.kvsession_init()
|
||||||
|
self.open_session = super().open_session
|
||||||
|
self.save_session = super().save_session
|
||||||
|
def open_session(self, app, request):
|
||||||
|
self._first_run(app)
|
||||||
|
return super().open_session(app, request)
|
||||||
|
def save_session(self, app, session, response):
|
||||||
|
self._first_run(app)
|
||||||
|
return super().save_session(app, session, response)
|
||||||
|
|
||||||
|
class KVSessionExt(flask_kvsession.KVSessionExtension):
|
||||||
|
""" Activates Flask-KVSession for an application. """
|
||||||
|
def init_kvstore(self, config):
|
||||||
|
""" Initialize kvstore - fallback to DictStore without REDIS_ADDRESS """
|
||||||
|
if addr := config.get('REDIS_ADDRESS'):
|
||||||
|
self.default_kvstore = RedisStore(redis.StrictRedis().from_url(f'redis://{addr}/3'))
|
||||||
|
else:
|
||||||
|
self.default_kvstore = DictStore()
|
||||||
|
|
||||||
|
def init_app(self, app, session_kvstore=None):
|
||||||
|
""" Initialize application and KVSession. """
|
||||||
|
super().init_app(app, session_kvstore)
|
||||||
|
app.session_interface = KVSessionIntf(app, self.cleanup_sessions)
|
||||||
|
|
||||||
|
kvsession = KVSessionExt()
|
||||||
|
|
||||||
|
flask_kvsession.Signer = NullSigner
|
||||||
|
@ -39,6 +39,7 @@ python-editor==1.0.4
|
|||||||
pytz==2019.1
|
pytz==2019.1
|
||||||
PyYAML==5.1
|
PyYAML==5.1
|
||||||
redis==3.2.1
|
redis==3.2.1
|
||||||
|
simplekv==0.14.1
|
||||||
#alpine3:12 provides six==1.15.0
|
#alpine3:12 provides six==1.15.0
|
||||||
#six==1.12.0
|
#six==1.12.0
|
||||||
socrate==0.1.1
|
socrate==0.1.1
|
||||||
|
Loading…
Reference in New Issue
Block a user