simplify session's code

This commit is contained in:
Emmanuel Garette 2019-12-03 21:20:28 +01:00
parent bb1fdcbad0
commit b944a609a5
3 changed files with 133 additions and 165 deletions

View File

@ -13,19 +13,18 @@ from ...register import register
from ...config import ROOT_CACHE_DIR, DATABASE_DIR, DEBUG, ROUGAIL_DTD_PATH
from ...context import Context
from ...utils import _
from ...error import CallError, NotAllowedError, RegistrationError
from ...error import CallError, RegistrationError
from ...logger import log
if not isdir(ROOT_CACHE_DIR):
raise RegistrationError(_(f'unable to find the cache dir "{ROOT_CACHE_DIR}"'))
class Risotto(Controller):
servermodel = {}
server = {}
def __init__(self) -> None:
for dirname in [ROOT_CACHE_DIR, DATABASE_DIR, ROUGAIL_DTD_PATH]:
if not isdir(dirname):
raise RegistrationError(_(f'unable to find the cache dir "{dirname}"'))
self.save_storage = Storage(engine='sqlite3', dir_database=DATABASE_DIR)
super().__init__()

View File

@ -21,19 +21,47 @@ class Risotto(Controller):
def __init__(self):
self.modify_storage = Storage(engine='dictionary')
def valid_user(self,
session_id: str,
risotto_context: Context,
type: str) -> None:
""" check if current user is the session owner
def get_storage(self,
type: str):
if type == 'server':
return storage_server
return storage_servermodel
def get_session(self,
session_id: str,
type: str) -> Dict:
""" Get session information from storage
"""
if type == 'server':
storage = storage_server
else:
storage = storage_servermodel
username = risotto_context.username
if username != storage.get_session(session_id)['username']:
raise NotAllowedError()
return storage.get_session(session_id)
def get_session_informations(self,
risotto_context: Context,
session_id: str,
type: str) -> Dict:
""" format session with a session ID name
"""
session = self.get_session(session_id,
type,
risotto_context.username)
return self.format_session(session_id,
session)
def format_session(self,
session_name: str,
session: Dict) -> Dict:
""" format session
"""
return {'session_id': session_name,
'id': session['id'],
'username': session['username'],
'timestamp': session['timestamp'],
'namespace': session['namespace'],
'mode': session['mode'],
'debug': session['debug']}
@register(['v1.session.server.start', 'v1.session.servermodel.start'], None)
async def start_session(self,
@ -46,44 +74,47 @@ class Risotto(Controller):
if type == 'server':
if id not in config_module.server:
raise Exception(_(f'cannot find {type} with id {id}'))
server = config_module.server[id]
config = server['server']
storage = storage_server
config = config_module.server[id]['server']
else:
if id not in config_module.servermodel:
raise Exception(_(f'cannot find {type} with id {id}'))
config = config_module.servermodel[id]
storage = storage_servermodel
# check if a session already exists, in this case returns it
session_list = self.list_sessions(type)
for sess in session_list:
if sess['id'] == id and sess['username'] == risotto_context.username:
session_id = sess['session_id']
session = self.get_session(session_id, type)
return self.format_session(session_id, session)
storage = self.get_storage(type)
# check if a session already exists
sessions = storage.get_sessions()
for session in sessions.values():
if sess['id'] == id:
if sess['username'] == risotto_context.username:
# same user so returns it
return self.format_session(session['session_id'], session)
else:
raise CallError(_(f'{username} already edits this configuration'))
# create a new session
while True:
session_id = 'z' + hexlify(urandom(23)).decode()
if not storage.has_session(session_id):
if not session_id in sessions:
break
else:
print('session {} already exists'.format(session_id))
username = risotto_context.username
storage.add_session(session_id,
config,
id,
username,
risotto_context.username,
self.modify_storage)
# return session's information
return self.get_session_informations(session_id,
type)
@register(['v1.session.server.list', 'v1.session.servermodel.list'], None)
async def list_session_server(self,
risotto_context: Context):
risotto_context: Context) -> Dict:
type = risotto_context.message.rsplit('.', 2)[-2]
return self.list_sessions(type)
storage = self.get_storage(type,
risotto_context.username)
return [self.format_session(session_id, session) or session_id, session in storage.get_sessions().items()]
@register(['v1.session.server.filter', 'v1.session.servermodel.filter'], None)
async def filter_session(self,
@ -93,10 +124,10 @@ class Risotto(Controller):
mode: str,
debug: Optional[bool]):
type = risotto_context.message.rsplit('.', 2)[-2]
if type == 'server':
storage = storage_server
else:
storage = storage_servermodel
storage = self.get_storage(type)
# to validate the session right
storage.get_session(session_id,
username)
if namespace is not None:
storage.set_namespace(session_id,
namespace)
@ -122,11 +153,9 @@ class Risotto(Controller):
value_multi: Optional[List]) -> Dict:
type = risotto_context.message.rsplit('.', 2)[-2]
session = self.get_session(session_id,
type)
ret = {'session_id': session_id,
'name': name}
if index is not None:
ret['index'] = index
type,
risotto_context.username)
# if multi and not follower the value is in fact in value_multi
option = session['config'].option(name).option
if option.ismulti() and not option.isfollower():
value = value_multi
@ -138,12 +167,14 @@ class Risotto(Controller):
update['index'] = index
updates = {'updates': [update]}
session['option'].updates(updates)
ret['status'] = 'ok'
except Exception as err:
if DEBUG:
print_exc()
ret['message'] = str(err)
ret['status'] = 'error'
raise CallError(str(err))
ret = {'session_id': session_id,
'name': name}
if index is not None:
ret['index'] = index
return ret
@register(['v1.session.server.validate', 'v1.session.servermodel.validate'], None)
@ -151,37 +182,36 @@ class Risotto(Controller):
risotto_context: Context,
session_id: str) -> Dict:
type = risotto_context.message.rsplit('.', 2)[-2]
session = self.get_session(session_id, type)
ret = {}
session = self.get_session(session_id,
type,
risotto_context.username)
try:
session['config'].forcepermissive.option(session['namespace']).value.dict()
except Exception as err:
ret['status'] = 'error'
ret['message'] = str(err)
else:
if type == 'server':
mandatories = list(session['config'].forcepermissive.value.mandatory())
if mandatories:
ret['status'] = 'incomplete'
ret['mandatories'] = mandatories
raise CallError(str(err))
if type == 'server':
mandatories = list(session['config'].forcepermissive.value.mandatory())
if mandatories:
if len(mandatories) == 1:
mandatories = mandatories[0]
msg = _('the parameter "--{mandatories}" is mandatory')
else:
ret['status'] = 'ok'
else:
ret['status'] = 'ok'
return ret
mandatories = '", "--'.join(mandatories)
msg = _('parameters "{mandatories}" are mandatories')
raise CallError(msg)
return self.format_session(session_id,
session)
@register(['v1.session.server.get', 'v1.session.servermodel.get'], None)
async def get_session_(self,
risotto_context: Context,
session_id: str) -> Dict:
async def get_session_server(self,
risotto_context: Context,
session_id: str) -> Dict:
type = risotto_context.message.rsplit('.', 2)[-2]
info = self.get_session_informations(session_id,
type)
info['content'] = session_id
session = self.get_session(session_id,
type)
type,
risotto_context.username)
info = self.format_session(session_id, session)
info['content'] = dumps(session['option'].value.dict(fullpath=True))
return info
@register(['v1.session.server.stop', 'v1.session.servermodel.stop'], None)
@ -190,18 +220,14 @@ class Risotto(Controller):
session_id: str,
save: bool) -> Dict:
type = risotto_context.message.rsplit('.', 2)[-2]
self.valid_user(session_id,
risotto_context,
type)
session = self.get_session(session_id,
type)
storage = self.get_storage(type)
session = storage.get_session(session_id,
risotto_context.username)
id_ = session['id']
config_module = dispatcher.get_service('config')
if type == 'server':
storage = storage_server
config = config_module.server[id_]['server']
else:
storage = storage_servermodel
config = config_module.servermodel[id_]
if save:
modif_config = session['config']
@ -215,66 +241,15 @@ class Risotto(Controller):
request,
risotto_context: Context,
session_id: str) -> Dict:
self.valid_user(session_id,
risotto_context,
'server')
session = storage_server.get_session(session_id)
return self.load_dict(session)
session = storage_server.get_session(session_id,
risotto_context.username)
return session['option'].dict(remotable='all')
@register_http('v1', '/config/servermodel/{session_id}')
async def get_servermodel_api(self,
request,
risotto_context: Context,
session_id: str) -> Dict:
self.valid_user(session_id,
risotto_context,
'servermodel')
session = storage_servermodel.get_session(session_id)
return self.load_dict(session)
def get_session(self,
session_id: str,
type: str) -> Dict:
""" Get session information from storage
"""
if type == 'server':
return storage_server.get_session(session_id)
return storage_servermodel.get_session(session_id)
def get_session_informations(self,
session_id: str,
type: str) -> Dict:
""" format session with a session ID name
"""
session = self.get_session(session_id,
type)
return self.format_session(session_id,
session)
def format_session(self,
session_name: str,
session: Dict) -> Dict:
""" format session
"""
return {'session_id': session_name,
'id': session['id'],
'username': session['username'],
'timestamp': session['timestamp'],
'namespace': session['namespace'],
'mode': session['mode'],
'debug': session['debug']}
def list_sessions(self,
type: str) -> List:
ret = []
if type == 'server':
storage = storage_server
else:
storage = storage_servermodel
for session_id, session in storage.get_sessions().items():
ret.append(self.format_session(session_id, session))
return ret
def load_dict(self,
session: Dict) -> Dict:
session = storage_servermodel.get_session(session_id,
risotto_context.username)
return session['option'].dict(remotable='all')

View File

@ -1,6 +1,8 @@
import time
from typing import Dict
from tiramisu import Config
from rougail import modes
from ...error import CallError, NotAllowedError
class StorageError(Exception):
@ -13,23 +15,15 @@ class Storage(object):
def __init__(self):
self.sessions = {}
def has_session(self,
id: int):
return id in self.sessions
def add_session(self,
session_id: int,
orig_config: Config,
server_id: int,
username: str,
config_storage):
for session in self.sessions.values():
if session['id'] == server_id:
raise Storage(_(f'{username} already edits this configuration'))
prefix_id = f'{session_id}_'
config_name = self.get_config_name(server_id)
config_id = f'{prefix_id}{config_name}'
print(config_id)
# copy Config and all it's parents
meta = orig_config.config.deepcopy(session_id=config_id,
@ -41,11 +35,12 @@ class Storage(object):
while True:
try:
children = list(config.config.list())
except:
break
if children:
if not children:
# it's an empty metaconfig
break
config = children[0]
else:
except:
# it's a config, so no "list" method
break
config.property.read_write()
# set the default owner
@ -66,35 +61,12 @@ class Storage(object):
self.set_namespace(session_id,
'creole')
def set_namespace(self,
session_id: int,
namespace: str):
self.sessions[session_id]['option'] = self.sessions[session_id]['config'].option(namespace)
self.sessions[session_id]['namespace'] = namespace
def get_sessions(self):
return self.sessions;
def del_session(self,
id: int):
del self.sessions[id]
def get_session(self,
id: int):
if id not in self.sessions:
raise Exception(f'the session {id} not exists')
return self.sessions[id]
def get_username(self,
id: int):
return self.get_session(id)['username']
def set_config_mode(self,
id: int,
mode: str):
""" Define which edition mode to select
"""
config = self.get_session(id)['config']
config = self.session[id]['config']
for mode_level in modes.values():
if modes[mode] < mode_level:
config.property.add(mode_level.name)
@ -105,13 +77,35 @@ class Storage(object):
def set_config_debug(self, id_, is_debug):
""" Enable/Disable debug mode
"""
config = self.get_session(id_)['config']
config = self.session[id_]['config']
if is_debug:
config.property.pop('hidden')
else:
config.property.add('hidden')
self.sessions[id_]['debug'] = is_debug
def set_namespace(self,
session_id: int,
namespace: str):
self.sessions[session_id]['option'] = self.sessions[session_id]['config'].option(namespace)
self.sessions[session_id]['namespace'] = namespace
def get_sessions(self):
return self.sessions;
def get_session(self,
id: int,
username: str) -> Dict:
if id not in self.sessions:
raise Exception(f'the session {id} not exists')
if username != storage.get_session(session_id)['username']:
raise NotAllowedError()
return self.sessions[id]
def del_session(self,
id: int):
del self.sessions[id]
class StorageServer(Storage):
def get_config_name(self,