cubicweb/server/__init__.py
changeset 11417 5e5e224239c3
parent 11413 c172fa18565e
child 11767 432f87a63057
equal deleted inserted replaced
11416:9c2fbb872e91 11417:5e5e224239c3
    22 """
    22 """
    23 from __future__ import print_function
    23 from __future__ import print_function
    24 
    24 
    25 __docformat__ = "restructuredtext en"
    25 __docformat__ = "restructuredtext en"
    26 
    26 
    27 import sys
       
    28 from os.path import join, exists
       
    29 from glob import glob
       
    30 from contextlib import contextmanager
    27 from contextlib import contextmanager
    31 
    28 
    32 from six import text_type, string_types
    29 from six import text_type, string_types
    33 from six.moves import filter
    30 from six.moves import filter
    34 
    31 
    37 from logilab.common.registry import yes
    34 from logilab.common.registry import yes
    38 from logilab import database
    35 from logilab import database
    39 
    36 
    40 from yams import BASE_GROUPS
    37 from yams import BASE_GROUPS
    41 
    38 
    42 from cubicweb import CW_SOFTWARE_ROOT
       
    43 from cubicweb.appobject import AppObject
    39 from cubicweb.appobject import AppObject
       
    40 
    44 
    41 
    45 class ShuttingDown(BaseException):
    42 class ShuttingDown(BaseException):
    46     """raised when trying to access some resources while the repository is
    43     """raised when trying to access some resources while the repository is
    47     shutting down. Inherit from BaseException so that `except Exception` won't
    44     shutting down. Inherit from BaseException so that `except Exception` won't
    48     catch it.
    45     catch it.
    88 #: security
    85 #: security
    89 DBG_SEC = 64
    86 DBG_SEC = 64
    90 #: more verbosity
    87 #: more verbosity
    91 DBG_MORE = 128
    88 DBG_MORE = 128
    92 #: all level enabled
    89 #: all level enabled
    93 DBG_ALL  = DBG_RQL + DBG_SQL + DBG_REPO + DBG_MS + DBG_HOOKS + DBG_OPS + DBG_SEC + DBG_MORE
    90 DBG_ALL = DBG_RQL + DBG_SQL + DBG_REPO + DBG_MS + DBG_HOOKS + DBG_OPS + DBG_SEC + DBG_MORE
    94 
    91 
    95 _SECURITY_ITEMS = []
    92 _SECURITY_ITEMS = []
    96 _SECURITY_CAPS = ['read', 'add', 'update', 'delete', 'transition']
    93 _SECURITY_CAPS = ['read', 'add', 'update', 'delete', 'transition']
    97 
    94 
    98 #: current debug mode
    95 #: current debug mode
    99 DEBUG = 0
    96 DEBUG = 0
       
    97 
   100 
    98 
   101 @contextmanager
    99 @contextmanager
   102 def tunesecurity(items=(), capabilities=()):
   100 def tunesecurity(items=(), capabilities=()):
   103     """Context manager to use in conjunction with DBG_SEC.
   101     """Context manager to use in conjunction with DBG_SEC.
   104 
   102 
   133     oldactions = _SECURITY_CAPS[:]
   131     oldactions = _SECURITY_CAPS[:]
   134     _SECURITY_CAPS[:] = capabilities
   132     _SECURITY_CAPS[:] = capabilities
   135     yield
   133     yield
   136     _SECURITY_ITEMS[:] = olditems
   134     _SECURITY_ITEMS[:] = olditems
   137     _SECURITY_CAPS[:] = oldactions
   135     _SECURITY_CAPS[:] = oldactions
       
   136 
   138 
   137 
   139 def set_debug(debugmode):
   138 def set_debug(debugmode):
   140     """change the repository debugging mode"""
   139     """change the repository debugging mode"""
   141     global DEBUG
   140     global DEBUG
   142     if not debugmode:
   141     if not debugmode:
   146         for mode in splitstrip(debugmode, sep='|'):
   145         for mode in splitstrip(debugmode, sep='|'):
   147             DEBUG |= globals()[mode]
   146             DEBUG |= globals()[mode]
   148     else:
   147     else:
   149         DEBUG |= debugmode
   148         DEBUG |= debugmode
   150 
   149 
       
   150 
   151 class debugged(object):
   151 class debugged(object):
   152     """Context manager and decorator to help debug the repository.
   152     """Context manager and decorator to help debug the repository.
   153 
   153 
   154     It can be used either as a context manager:
   154     It can be used either as a context manager:
   155 
   155 
   182         return traceback is None
   182         return traceback is None
   183 
   183 
   184     def __call__(self, func):
   184     def __call__(self, func):
   185         """decorate function"""
   185         """decorate function"""
   186         def wrapped(*args, **kwargs):
   186         def wrapped(*args, **kwargs):
   187             _clevel = DEBUG
       
   188             set_debug(self.debugmode)
   187             set_debug(self.debugmode)
   189             try:
   188             try:
   190                 return func(*args, **kwargs)
   189                 return func(*args, **kwargs)
   191             finally:
   190             finally:
   192                 set_debug(self._clevel)
   191                 set_debug(self._clevel)
   193         return wrapped
   192         return wrapped
       
   193 
   194 
   194 
   195 # database initialization ######################################################
   195 # database initialization ######################################################
   196 
   196 
   197 def create_user(session, login, pwd, *groups):
   197 def create_user(session, login, pwd, *groups):
   198     # monkey patch this method if you want to customize admin/anon creation
   198     # monkey patch this method if you want to customize admin/anon creation
   200     user = session.create_entity('CWUser', login=login, upassword=pwd)
   200     user = session.create_entity('CWUser', login=login, upassword=pwd)
   201     for group in groups:
   201     for group in groups:
   202         session.execute('SET U in_group G WHERE U eid %(u)s, G name %(group)s',
   202         session.execute('SET U in_group G WHERE U eid %(u)s, G name %(group)s',
   203                         {'u': user.eid, 'group': text_type(group)})
   203                         {'u': user.eid, 'group': text_type(group)})
   204     return user
   204     return user
       
   205 
   205 
   206 
   206 def init_repository(config, interactive=True, drop=False, vreg=None,
   207 def init_repository(config, interactive=True, drop=False, vreg=None,
   207                     init_config=None):
   208                     init_config=None):
   208     """initialise a repository database by creating tables add filling them
   209     """initialise a repository database by creating tables add filling them
   209     with the minimal set of entities (ie at least the schema, base groups and
   210     with the minimal set of entities (ie at least the schema, base groups and
   287         # sort for eid predicatability as expected in some server tests
   288         # sort for eid predicatability as expected in some server tests
   288         for group in sorted(BASE_GROUPS):
   289         for group in sorted(BASE_GROUPS):
   289             cnx.create_entity('CWGroup', name=text_type(group))
   290             cnx.create_entity('CWGroup', name=text_type(group))
   290         admin = create_user(cnx, login, pwd, u'managers')
   291         admin = create_user(cnx, login, pwd, u'managers')
   291         cnx.execute('SET X owned_by U WHERE X is IN (CWGroup,CWSource), U eid %(u)s',
   292         cnx.execute('SET X owned_by U WHERE X is IN (CWGroup,CWSource), U eid %(u)s',
   292                         {'u': admin.eid})
   293                     {'u': admin.eid})
   293         cnx.commit()
   294         cnx.commit()
   294     repo.shutdown()
   295     repo.shutdown()
   295     # re-login using the admin user
   296     # re-login using the admin user
   296     config._cubes = None # avoid assertion error
   297     config._cubes = None  # avoid assertion error
   297     repo = get_repository(config=config)
   298     repo = get_repository(config=config)
   298     # replace previous schema by the new repo's one. This is necessary so that we give the proper
   299     # replace previous schema by the new repo's one. This is necessary so that we give the proper
   299     # schema to `initialize_schema` above since it will initialize .eid attribute of schema elements
   300     # schema to `initialize_schema` above since it will initialize .eid attribute of schema elements
   300     schema = repo.schema
   301     schema = repo.schema
   301     with connect(repo, login, password=pwd) as cnx:
   302     with connect(repo, login, password=pwd) as cnx:
   302         with cnx.security_enabled(False, False):
   303         with cnx.security_enabled(False, False):
   303             repo.system_source.eid = ssource.eid # redo this manually
   304             repo.system_source.eid = ssource.eid  # redo this manually
   304             handler = config.migration_handler(schema, interactive=False,
   305             handler = config.migration_handler(schema, interactive=False,
   305                                                cnx=cnx, repo=repo)
   306                                                cnx=cnx, repo=repo)
   306             # serialize the schema
   307             # serialize the schema
   307             initialize_schema(config, schema, handler)
   308             initialize_schema(config, schema, handler)
   308             # yoo !
   309             # yoo !
   346         # execute instance's post<event> script (useful in tests)
   347         # execute instance's post<event> script (useful in tests)
   347         mhandler.cmd_exec_event_script('post%s' % event, apphome=True)
   348         mhandler.cmd_exec_event_script('post%s' % event, apphome=True)
   348 
   349 
   349 
   350 
   350 # sqlite'stored procedures have to be registered at connection opening time
   351 # sqlite'stored procedures have to be registered at connection opening time
   351 from logilab.database import SQL_CONNECT_HOOKS
   352 from logilab.database import SQL_CONNECT_HOOKS  # noqa
   352 
   353 
   353 # add to this set relations which should have their add security checking done
   354 # add to this set relations which should have their add security checking done
   354 # *BEFORE* adding the actual relation (done after by default)
   355 # *BEFORE* adding the actual relation (done after by default)
   355 BEFORE_ADD_RELATIONS = set(('owned_by',))
   356 BEFORE_ADD_RELATIONS = set(('owned_by',))
   356 
   357