server/repository.py
changeset 8433 ff9d6d269877
parent 8393 77c7158916c1
child 8456 c912d82f2166
equal deleted inserted replaced
8432:96b4f7a35e6c 8433:ff9d6d269877
   252         self.sources_by_eid = {}
   252         self.sources_by_eid = {}
   253         if self.config.quick_start \
   253         if self.config.quick_start \
   254                or not 'CWSource' in self.schema: # # 3.10 migration
   254                or not 'CWSource' in self.schema: # # 3.10 migration
   255             self.system_source.init_creating()
   255             self.system_source.init_creating()
   256             return
   256             return
   257         session = self.internal_session()
   257         with self.internal_session() as session:
   258         try:
       
   259             # FIXME: sources should be ordered (add_entity priority)
   258             # FIXME: sources should be ordered (add_entity priority)
   260             for sourceent in session.execute(
   259             for sourceent in session.execute(
   261                 'Any S, SN, SA, SC WHERE S is_instance_of CWSource, '
   260                 'Any S, SN, SA, SC WHERE S is_instance_of CWSource, '
   262                 'S name SN, S type SA, S config SC').entities():
   261                 'S name SN, S type SA, S config SC').entities():
   263                 if sourceent.name == 'system':
   262                 if sourceent.name == 'system':
   264                     self.system_source.eid = sourceent.eid
   263                     self.system_source.eid = sourceent.eid
   265                     self.sources_by_eid[sourceent.eid] = self.system_source
   264                     self.sources_by_eid[sourceent.eid] = self.system_source
   266                     self.system_source.init(True, sourceent)
   265                     self.system_source.init(True, sourceent)
   267                     continue
   266                     continue
   268                 self.add_source(sourceent, add_to_cnxsets=False)
   267                 self.add_source(sourceent, add_to_cnxsets=False)
   269         finally:
       
   270             session.close()
       
   271 
   268 
   272     def _clear_planning_caches(self):
   269     def _clear_planning_caches(self):
   273         for cache in ('source_defs', 'is_multi_sources_relation',
   270         for cache in ('source_defs', 'is_multi_sources_relation',
   274                       'can_cross_relation', 'rel_type_sources'):
   271                       'can_cross_relation', 'rel_type_sources'):
   275             clear_cache(self, cache)
   272             clear_cache(self, cache)
   335         from cubicweb.server.schemaserial import deserialize_schema
   332         from cubicweb.server.schemaserial import deserialize_schema
   336         self.info('loading schema from the repository')
   333         self.info('loading schema from the repository')
   337         appschema = schema.CubicWebSchema(self.config.appid)
   334         appschema = schema.CubicWebSchema(self.config.appid)
   338         self.set_schema(self.config.load_bootstrap_schema(), resetvreg=False)
   335         self.set_schema(self.config.load_bootstrap_schema(), resetvreg=False)
   339         self.debug('deserializing db schema into %s %#x', appschema.name, id(appschema))
   336         self.debug('deserializing db schema into %s %#x', appschema.name, id(appschema))
   340         session = self.internal_session()
   337         with self.internal_session() as session:
   341         try:
       
   342             try:
   338             try:
   343                 deserialize_schema(appschema, session)
   339                 deserialize_schema(appschema, session)
   344             except BadSchemaDefinition:
   340             except BadSchemaDefinition:
   345                 raise
   341                 raise
   346             except Exception, ex:
   342             except Exception, ex:
   347                 import traceback
   343                 import traceback
   348                 traceback.print_exc()
   344                 traceback.print_exc()
   349                 raise Exception('Is the database initialised ? (cause: %s)' %
   345                 raise Exception('Is the database initialised ? (cause: %s)' %
   350                                 (ex.args and ex.args[0].strip() or 'unknown')), \
   346                                 (ex.args and ex.args[0].strip() or 'unknown')), \
   351                                 None, sys.exc_info()[-1]
   347                                 None, sys.exc_info()[-1]
   352         finally:
       
   353             session.close()
       
   354         self.set_schema(appschema)
   348         self.set_schema(appschema)
   355 
   349 
   356 
   350 
   357     def _prepare_startup(self):
   351     def _prepare_startup(self):
   358         """Prepare "Repository as a server" for startup.
   352         """Prepare "Repository as a server" for startup.
   629 
   623 
   630         This is a public method, not requiring a session id.
   624         This is a public method, not requiring a session id.
   631         """
   625         """
   632         from logilab.common.changelog import Version
   626         from logilab.common.changelog import Version
   633         vcconf = {}
   627         vcconf = {}
   634         session = self.internal_session()
   628         with self.internal_session() as session:
   635         try:
       
   636             for pk, version in session.execute(
   629             for pk, version in session.execute(
   637                 'Any K,V WHERE P is CWProperty, P value V, P pkey K, '
   630                 'Any K,V WHERE P is CWProperty, P value V, P pkey K, '
   638                 'P pkey ~="system.version.%"', build_descr=False):
   631                 'P pkey ~="system.version.%"', build_descr=False):
   639                 cube = pk.split('.')[-1]
   632                 cube = pk.split('.')[-1]
   640                 # XXX cubicweb migration
   633                 # XXX cubicweb migration
   649                         fsversion = self.config.cubicweb_version()
   642                         fsversion = self.config.cubicweb_version()
   650                     if version < fsversion:
   643                     if version < fsversion:
   651                         msg = ('instance has %s version %s but %s '
   644                         msg = ('instance has %s version %s but %s '
   652                                'is installed. Run "cubicweb-ctl upgrade".')
   645                                'is installed. Run "cubicweb-ctl upgrade".')
   653                         raise ExecutionError(msg % (cube, version, fsversion))
   646                         raise ExecutionError(msg % (cube, version, fsversion))
   654         finally:
       
   655             session.close()
       
   656         return vcconf
   647         return vcconf
   657 
   648 
   658     @cached
   649     @cached
   659     def source_defs(self):
   650     def source_defs(self):
   660         """Return the a dictionary containing source uris as value and a
   651         """Return the a dictionary containing source uris as value and a
   671     def properties(self):
   662     def properties(self):
   672         """Return a result set containing system wide properties.
   663         """Return a result set containing system wide properties.
   673 
   664 
   674         This is a public method, not requiring a session id.
   665         This is a public method, not requiring a session id.
   675         """
   666         """
   676         session = self.internal_session()
   667         with self.internal_session() as session:
   677         try:
       
   678             # don't use session.execute, we don't want rset.req set
   668             # don't use session.execute, we don't want rset.req set
   679             return self.querier.execute(session, 'Any K,V WHERE P is CWProperty,'
   669             return self.querier.execute(session, 'Any K,V WHERE P is CWProperty,'
   680                                         'P pkey K, P value V, NOT P for_user U',
   670                                         'P pkey K, P value V, NOT P for_user U',
   681                                         build_descr=False)
   671                                         build_descr=False)
   682         finally:
       
   683             session.close()
       
   684 
   672 
   685     # XXX protect this method: anonymous should be allowed and registration
   673     # XXX protect this method: anonymous should be allowed and registration
   686     # plugged
   674     # plugged
   687     def register_user(self, login, password, email=None, **kwargs):
   675     def register_user(self, login, password, email=None, **kwargs):
   688         """check a user with the given login exists, if not create it with the
   676         """check a user with the given login exists, if not create it with the
   689         given password. This method is designed to be used for anonymous
   677         given password. This method is designed to be used for anonymous
   690         registration on public web site.
   678         registration on public web site.
   691         """
   679         """
   692         session = self.internal_session()
   680         with self.internal_session() as session:
   693         # for consistency, keep same error as unique check hook (although not required)
   681             # for consistency, keep same error as unique check hook (although not required)
   694         errmsg = session._('the value "%s" is already used, use another one')
   682             errmsg = session._('the value "%s" is already used, use another one')
   695         try:
       
   696             if (session.execute('CWUser X WHERE X login %(login)s', {'login': login},
   683             if (session.execute('CWUser X WHERE X login %(login)s', {'login': login},
   697                                 build_descr=False)
   684                                 build_descr=False)
   698                 or session.execute('CWUser X WHERE X use_email C, C address %(login)s',
   685                 or session.execute('CWUser X WHERE X use_email C, C address %(login)s',
   699                                    {'login': login}, build_descr=False)):
   686                                    {'login': login}, build_descr=False)):
   700                 qname = role_name('login', 'subject')
   687                 qname = role_name('login', 'subject')
   717                     raise ValidationError(None, {qname: errmsg % d['email']})
   704                     raise ValidationError(None, {qname: errmsg % d['email']})
   718                 session.execute('INSERT EmailAddress X: X address %(email)s, '
   705                 session.execute('INSERT EmailAddress X: X address %(email)s, '
   719                                 'U primary_email X, U use_email X '
   706                                 'U primary_email X, U use_email X '
   720                                 'WHERE U login %(login)s', d, build_descr=False)
   707                                 'WHERE U login %(login)s', d, build_descr=False)
   721             session.commit()
   708             session.commit()
   722         finally:
       
   723             session.close()
       
   724         return True
   709         return True
   725 
   710 
   726     def find_users(self, fetch_attrs, **query_attrs):
   711     def find_users(self, fetch_attrs, **query_attrs):
   727         """yield user attributes for cwusers matching the given query_attrs
   712         """yield user attributes for cwusers matching the given query_attrs
   728         (the result set cannot survive this method call)
   713         (the result set cannot survive this method call)
   741                                      if not rschema.meta)
   726                                      if not rschema.meta)
   742         cwuserattrs = self._cwuser_attrs
   727         cwuserattrs = self._cwuser_attrs
   743         for k in chain(fetch_attrs, query_attrs.iterkeys()):
   728         for k in chain(fetch_attrs, query_attrs.iterkeys()):
   744             if k not in cwuserattrs:
   729             if k not in cwuserattrs:
   745                 raise Exception('bad input for find_user')
   730                 raise Exception('bad input for find_user')
   746         session = self.internal_session()
   731         with self.internal_session() as session:
   747         try:
       
   748             varmaker = rqlvar_maker()
   732             varmaker = rqlvar_maker()
   749             vars = [(attr, varmaker.next()) for attr in fetch_attrs]
   733             vars = [(attr, varmaker.next()) for attr in fetch_attrs]
   750             rql = 'Any %s WHERE X is CWUser, ' % ','.join(var[1] for var in vars)
   734             rql = 'Any %s WHERE X is CWUser, ' % ','.join(var[1] for var in vars)
   751             rql += ','.join('X %s %s' % (var[0], var[1]) for var in vars) + ','
   735             rql += ','.join('X %s %s' % (var[0], var[1]) for var in vars) + ','
   752             rset = session.execute(rql + ','.join('X %s %%(%s)s' % (attr, attr)
   736             rset = session.execute(rql + ','.join('X %s %%(%s)s' % (attr, attr)
   753                                                   for attr in query_attrs.iterkeys()),
   737                                                   for attr in query_attrs.iterkeys()),
   754                                    query_attrs)
   738                                    query_attrs)
   755             return rset.rows
   739             return rset.rows
   756         finally:
       
   757             session.close()
       
   758 
   740 
   759     def connect(self, login, **kwargs):
   741     def connect(self, login, **kwargs):
   760         """open a connection for a given user
   742         """open a connection for a given user
   761 
   743 
   762         base_url may be needed to send mails
   744         base_url may be needed to send mails
   764 
   746 
   765         raise `AuthenticationError` if the authentication failed
   747         raise `AuthenticationError` if the authentication failed
   766         raise `ConnectionError` if we can't open a connection
   748         raise `ConnectionError` if we can't open a connection
   767         """
   749         """
   768         # use an internal connection
   750         # use an internal connection
   769         session = self.internal_session()
   751         with self.internal_session() as session:
   770         # try to get a user object
   752             # try to get a user object
   771         cnxprops = kwargs.pop('cnxprops', None)
   753             cnxprops = kwargs.pop('cnxprops', None)
   772         try:
       
   773             user = self.authenticate_user(session, login, **kwargs)
   754             user = self.authenticate_user(session, login, **kwargs)
   774         finally:
       
   775             session.close()
       
   776         session = Session(user, self, cnxprops)
   755         session = Session(user, self, cnxprops)
   777         user._cw = user.cw_rset.req = session
   756         user._cw = user.cw_rset.req = session
   778         user.cw_clear_relation_cache()
   757         user.cw_clear_relation_cache()
   779         self._sessions[session.id] = session
   758         self._sessions[session.id] = session
   780         self.info('opened session %s for user %s', session.id, login)
   759         self.info('opened session %s for user %s', session.id, login)
   983           modified since the given timestamp (actually entities whose full text
   962           modified since the given timestamp (actually entities whose full text
   984           index content has changed)
   963           index content has changed)
   985         * list of (etype, eid) of entities of the given types which have been
   964         * list of (etype, eid) of entities of the given types which have been
   986           deleted since the given timestamp
   965           deleted since the given timestamp
   987         """
   966         """
   988         session = self.internal_session()
   967         with self.internal_session() as session:
   989         updatetime = datetime.utcnow()
   968             updatetime = datetime.utcnow()
   990         try:
       
   991             modentities, delentities = self.system_source.modified_entities(
   969             modentities, delentities = self.system_source.modified_entities(
   992                 session, etypes, mtime)
   970                 session, etypes, mtime)
   993             return updatetime, modentities, delentities
   971             return updatetime, modentities, delentities
   994         finally:
       
   995             session.close()
       
   996 
   972 
   997     # session handling ########################################################
   973     # session handling ########################################################
   998 
   974 
   999     def close_sessions(self):
   975     def close_sessions(self):
  1000         """close every opened sessions"""
   976         """close every opened sessions"""