cuchulufm/cuchulu/libraries/sessionplugin.py

234 lines
6.6 KiB
Python

from bottle import request, response
from itsdangerous.url_safe import URLSafeTimedSerializer
from cuchulu.libraries.keyutils import create_key_encrypt, create_key_encrypt_256, create_key
try:
from settings import config
except ModuleNotFoundError:
class config:
cookie_name='cuchulu.session'
key_encrypt=create_key_encrypt_256(30)
session_opts={'session.data_dir': 'sessions', 'session.type': 'file', 'session.path': 'cuchulu'}
import inspect
class Session(dict):
"""Class for create sessions using itsdangerous library"""
def __init__(self, *args, **kwargs):
"""Class for create sessions using itsdangerous library"""
self.update(*args, **kwargs)
self.changed=False
self.safe=None
def __setitem__(self, item, value):
"""Method for set items in session
With this method, session instance set changed property for know that the session was changed and saved
Args:
item (str): The key of the session item
value (mixed): The value of the session item
"""
super(Session, self).__setitem__(item, value)
self.changed=True
def __delitem__(self, item):
"""Method for delete items in session
With this method, session instance set changed property for know that the session was cleaning.
Args:
item (str): The key of the session item
value (mixed): The value of the session item
"""
super(Session, self).__delitem__(item)
self.changed=True
# If use redirect or abort, you can save the session before of redirection
def save(self):
"""Method for save the session
When bottle make a redirect, directly make a raise exception and not save session. With this method you can save the session before the raise.
"""
print('get_save')
if self.changed:
if not self.safe:
self.safe=URLSafeTimedSerializer(config.key_encrypt)
self.changed=False
#if not max_age:
response.set_cookie(config.cookie_name, self.safe.dumps(self), path=config.session_opts['session.path'], httponly=True)
"""
def __del__(self):
self.save()
print('exit')
"""
def get_session():
"""Function for get the session from request object from bottle"""
return request.environ.get('session')
def session_plugin(callback):
def wrapper(*args, **kwargs):
cookie=request.get_cookie(config.cookie_name)
safe=None
if not cookie:
session=Session()
else:
safe=URLSafeTimedSerializer(config.key_encrypt)
try:
session=Session(safe.loads(cookie))
if type(session).__name__!='Session':
session=Session()
session.safe=safe
except:
session=Session()
if 'session' in kwargs:
kwargs['session']=session
#For compatibility with old sessions server-side style.
request.environ['session']=session
rv=callback(*args, **kwargs)
if request.environ['session'].changed:
if not safe:
safe=URLSafeTimedSerializer(config.key_encrypt)
#if not max_age:
response.set_cookie(config.cookie_name, safe.dumps(session), path=config.session_opts['session.path'], httponly=True)
return rv
return wrapper
#class SessionPlugin2(object):
class SessionPlugin(object):
name = 'session'
api = 2
def __init__(self, keyword='session'):
self.keyword=keyword
self.session={}
def setup(self, app):
''' Make sure that other installed plugins don't affect the same keyword argument.'''
for other in app.plugins:
if not isinstance(other, SessionPlugin): continue
if other.keyword == self.keyword:
raise PluginError("Found another login plugin with "\
"conflicting settings (non-unique keyword).")
def apply(self, callback, context):
# Test if the original callback accepts a 'session' keyword.
# Ignore it if it does not need a login handle.
conf = context.config.get(self.keyword) or {}
keyword = conf.get('keyword', self.keyword)
args = inspect.getfullargspec(context.callback)[0]
"""
if keyword not in args:
return callback
"""
if keyword in args:
#print(args[keyword])
self.session[callback.__name__]=True
else:
self.session[callback.__name__]=False
#print(callback.__name__)
def wrapper(*args, **kwargs):
cookie=request.get_cookie(config.cookie_name)
safe=None
if not cookie:
session=Session()
else:
safe=URLSafeTimedSerializer(config.key_encrypt)
try:
session=Session(safe.loads(cookie))
if type(session).__name__!='Session':
session=Session()
except:
session=Session()
#if 'session' in kwargs:
#print(kwargs)
if self.session[callback.__name__]:
kwargs['session']=session
#For compatibility with old sessions server-side style.
request.environ['session']=session
request.environ['session'].changed=False
rv=callback(*args, **kwargs)
#if request.environ['session'].changed:
request.environ['session'].save()
"""
if session.changed:
#print('changed')
if not safe:
safe=URLSafeTimedSerializer(config.key_encrypt)
#if not max_age:
response.set_cookie(config.cookie_name, safe.dumps(session), path=config.session_opts['session.path'], httponly=True)
"""
return rv
return wrapper