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""" |