cubicweb/server/session.py
changeset 11919 3a6746dfc57f
parent 11892 08cf02efc7ce
child 11929 fcbd6b251d81
equal deleted inserted replaced
11918:a88101bf9f87 11919:3a6746dfc57f
     1 # copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     1 # copyright 2003-2017 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     3 #
     3 #
     4 # This file is part of CubicWeb.
     4 # This file is part of CubicWeb.
     5 #
     5 #
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
   107     """
   107     """
   108     def __init__(self, cnx, mode, *categories):
   108     def __init__(self, cnx, mode, *categories):
   109         assert mode in (HOOKS_ALLOW_ALL, HOOKS_DENY_ALL)
   109         assert mode in (HOOKS_ALLOW_ALL, HOOKS_DENY_ALL)
   110         self.cnx = cnx
   110         self.cnx = cnx
   111         self.mode = mode
   111         self.mode = mode
   112         self.categories = categories
   112         self.categories = set(categories)
   113         self.oldmode = None
   113         self.old_mode = None
   114         self.changes = ()
   114         self.old_categories = None
   115 
   115 
   116     def __enter__(self):
   116     def __enter__(self):
   117         self.oldmode = self.cnx.hooks_mode
   117         self.old_mode = self.cnx._hooks_mode
   118         self.cnx.hooks_mode = self.mode
   118         self.old_categories = self.cnx._hooks_categories
   119         if self.mode is HOOKS_DENY_ALL:
   119         self.cnx._hooks_mode = self.mode
   120             self.changes = self.cnx.enable_hook_categories(*self.categories)
   120         self.cnx._hooks_categories = self.categories
   121         else:
       
   122             self.changes = self.cnx.disable_hook_categories(*self.categories)
       
   123 
   121 
   124     def __exit__(self, exctype, exc, traceback):
   122     def __exit__(self, exctype, exc, traceback):
   125         try:
   123         self.cnx._hooks_mode = self.old_mode
   126             if self.categories:
   124         self.cnx._hooks_categories = self.old_categories
   127                 if self.mode is HOOKS_DENY_ALL:
       
   128                     self.cnx.disable_hook_categories(*self.categories)
       
   129                 else:
       
   130                     self.cnx.enable_hook_categories(*self.categories)
       
   131         finally:
       
   132             self.cnx.hooks_mode = self.oldmode
       
   133 
   125 
   134 
   126 
   135 @deprecated('[3.17] use <object>.security_enabled instead')
   127 @deprecated('[3.17] use <object>.security_enabled instead')
   136 def security_enabled(obj, *args, **kwargs):
   128 def security_enabled(obj, *args, **kwargs):
   137     return obj.security_enabled(*args, **kwargs)
   129     return obj.security_enabled(*args, **kwargs)
   236       'uncommitable' (some :exc:`ValidationError` or :exc:`Unauthorized` error
   228       'uncommitable' (some :exc:`ValidationError` or :exc:`Unauthorized` error
   237       has been raised during the transaction and so it must be rolled back).
   229       has been raised during the transaction and so it must be rolled back).
   238 
   230 
   239     Hooks controls:
   231     Hooks controls:
   240 
   232 
   241       :attr:`hooks_mode`, may be either `HOOKS_ALLOW_ALL` or `HOOKS_DENY_ALL`.
   233     .. automethod:: cubicweb.server.session.Connection.deny_all_hooks_but
   242 
   234     .. automethod:: cubicweb.server.session.Connection.allow_all_hooks_but
   243       :attr:`enabled_hook_cats`, when :attr:`hooks_mode` is
       
   244       `HOOKS_DENY_ALL`, this set contains hooks categories that are enabled.
       
   245 
       
   246       :attr:`disabled_hook_cats`, when :attr:`hooks_mode` is
       
   247       `HOOKS_ALLOW_ALL`, this set contains hooks categories that are disabled.
       
   248 
   235 
   249     Security level Management:
   236     Security level Management:
   250 
   237 
   251       :attr:`read_security` and :attr:`write_security`, boolean flags telling if
   238       :attr:`read_security` and :attr:`write_security`, boolean flags telling if
   252       read/write security is currently activated.
   239       read/write security is currently activated.
   281         self.pending_operations = []
   268         self.pending_operations = []
   282         #: (None, 'precommit', 'postcommit', 'uncommitable')
   269         #: (None, 'precommit', 'postcommit', 'uncommitable')
   283         self.commit_state = None
   270         self.commit_state = None
   284 
   271 
   285         # hook control attribute
   272         # hook control attribute
   286         self.hooks_mode = HOOKS_ALLOW_ALL
   273         # `_hooks_mode`, may be either `HOOKS_ALLOW_ALL` or `HOOKS_DENY_ALL`.
   287         self.disabled_hook_cats = set()
   274         self._hooks_mode = HOOKS_ALLOW_ALL
   288         self.enabled_hook_cats = set()
   275         # `_hooks_categories`, when :attr:`_hooks_mode` is `HOOKS_DENY_ALL`,
       
   276         # this set contains hooks categories that are enabled ;
       
   277         # when :attr:`_hooks_mode` is `HOOKS_ALLOW_ALL`, it contains hooks
       
   278         # categories that are disabled.
       
   279         self._hooks_categories = set()
   289         self.pruned_hooks_cache = {}
   280         self.pruned_hooks_cache = {}
   290 
   281 
   291         # security control attributes
   282         # security control attributes
   292         self._read_security = DEFAULT_SECURITY  # handled by a property
   283         self._read_security = DEFAULT_SECURITY  # handled by a property
   293         self.write_security = DEFAULT_SECURITY
   284         self.write_security = DEFAULT_SECURITY
   672 
   663 
   673     # Hooks control ###########################################################
   664     # Hooks control ###########################################################
   674 
   665 
   675     @_open_only
   666     @_open_only
   676     def allow_all_hooks_but(self, *categories):
   667     def allow_all_hooks_but(self, *categories):
       
   668         """Context manager to enable all hooks but those in the given
       
   669         categories.
       
   670         """
   677         return _hooks_control(self, HOOKS_ALLOW_ALL, *categories)
   671         return _hooks_control(self, HOOKS_ALLOW_ALL, *categories)
   678 
   672 
   679     @_open_only
   673     @_open_only
   680     def deny_all_hooks_but(self, *categories):
   674     def deny_all_hooks_but(self, *categories):
       
   675         """Context manager to disable all hooks but those in the given
       
   676         categories.
       
   677         """
   681         return _hooks_control(self, HOOKS_DENY_ALL, *categories)
   678         return _hooks_control(self, HOOKS_DENY_ALL, *categories)
   682 
       
   683     @_open_only
       
   684     def disable_hook_categories(self, *categories):
       
   685         """disable the given hook categories:
       
   686 
       
   687         - on HOOKS_DENY_ALL mode, ensure those categories are not enabled
       
   688         - on HOOKS_ALLOW_ALL mode, ensure those categories are disabled
       
   689         """
       
   690         changes = set()
       
   691         self.pruned_hooks_cache.clear()
       
   692         categories = set(categories)
       
   693         if self.hooks_mode is HOOKS_DENY_ALL:
       
   694             enabledcats = self.enabled_hook_cats
       
   695             changes = enabledcats & categories
       
   696             enabledcats -= changes  # changes is small hence faster
       
   697         else:
       
   698             disabledcats = self.disabled_hook_cats
       
   699             changes = categories - disabledcats
       
   700             disabledcats |= changes  # changes is small hence faster
       
   701         return tuple(changes)
       
   702 
       
   703     @_open_only
       
   704     def enable_hook_categories(self, *categories):
       
   705         """enable the given hook categories:
       
   706 
       
   707         - on HOOKS_DENY_ALL mode, ensure those categories are enabled
       
   708         - on HOOKS_ALLOW_ALL mode, ensure those categories are not disabled
       
   709         """
       
   710         changes = set()
       
   711         self.pruned_hooks_cache.clear()
       
   712         categories = set(categories)
       
   713         if self.hooks_mode is HOOKS_DENY_ALL:
       
   714             enabledcats = self.enabled_hook_cats
       
   715             changes = categories - enabledcats
       
   716             enabledcats |= changes  # changes is small hence faster
       
   717         else:
       
   718             disabledcats = self.disabled_hook_cats
       
   719             changes = disabledcats & categories
       
   720             disabledcats -= changes  # changes is small hence faster
       
   721         return tuple(changes)
       
   722 
   679 
   723     @_open_only
   680     @_open_only
   724     def is_hook_category_activated(self, category):
   681     def is_hook_category_activated(self, category):
   725         """return a boolean telling if the given category is currently activated
   682         """return a boolean telling if the given category is currently activated
   726         or not
   683         or not
   727         """
   684         """
   728         if self.hooks_mode is HOOKS_DENY_ALL:
   685         if self._hooks_mode is HOOKS_DENY_ALL:
   729             return category in self.enabled_hook_cats
   686             return category in self._hooks_categories
   730         return category not in self.disabled_hook_cats
   687         return category not in self._hooks_categories
   731 
   688 
   732     @_open_only
   689     @_open_only
   733     def is_hook_activated(self, hook):
   690     def is_hook_activated(self, hook):
   734         """return a boolean telling if the given hook class is currently
   691         """return a boolean telling if the given hook class is currently
   735         activated or not
   692         activated or not