cubicweb/entities/authobjs.py
changeset 11057 0b59724cb3f2
parent 10612 84468b90e9c1
child 11348 70337ad23145
equal deleted inserted replaced
11052:058bb3dc685f 11057:0b59724cb3f2
       
     1 # copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
       
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
       
     3 #
       
     4 # This file is part of CubicWeb.
       
     5 #
       
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
       
     7 # terms of the GNU Lesser General Public License as published by the Free
       
     8 # Software Foundation, either version 2.1 of the License, or (at your option)
       
     9 # any later version.
       
    10 #
       
    11 # CubicWeb is distributed in the hope that it will be useful, but WITHOUT
       
    12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
       
    13 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
       
    14 # details.
       
    15 #
       
    16 # You should have received a copy of the GNU Lesser General Public License along
       
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
       
    18 """entity classes user and group entities"""
       
    19 
       
    20 __docformat__ = "restructuredtext en"
       
    21 
       
    22 from six import string_types
       
    23 
       
    24 from logilab.common.decorators import cached
       
    25 
       
    26 from cubicweb import Unauthorized
       
    27 from cubicweb.entities import AnyEntity, fetch_config
       
    28 
       
    29 class CWGroup(AnyEntity):
       
    30     __regid__ = 'CWGroup'
       
    31     fetch_attrs, cw_fetch_order = fetch_config(['name'])
       
    32     cw_fetch_unrelated_order = cw_fetch_order
       
    33 
       
    34     def dc_long_title(self):
       
    35         name = self.name
       
    36         trname = self._cw._(name)
       
    37         if trname != name:
       
    38             return '%s (%s)' % (name, trname)
       
    39         return name
       
    40 
       
    41     @cached
       
    42     def num_users(self):
       
    43         """return the number of users in this group"""
       
    44         return self._cw.execute('Any COUNT(U) WHERE U in_group G, G eid %(g)s',
       
    45                                 {'g': self.eid})[0][0]
       
    46 
       
    47 
       
    48 class CWUser(AnyEntity):
       
    49     __regid__ = 'CWUser'
       
    50     fetch_attrs, cw_fetch_order = fetch_config(['login', 'firstname', 'surname'])
       
    51     cw_fetch_unrelated_order = cw_fetch_order
       
    52 
       
    53     # used by repository to check if  the user can log in or not
       
    54     AUTHENTICABLE_STATES = ('activated',)
       
    55 
       
    56     # low level utilities #####################################################
       
    57     def __init__(self, *args, **kwargs):
       
    58         groups = kwargs.pop('groups', None)
       
    59         properties = kwargs.pop('properties', None)
       
    60         super(CWUser, self).__init__(*args, **kwargs)
       
    61         if groups is not None:
       
    62             self._groups = groups
       
    63         if properties is not None:
       
    64             self._properties = properties
       
    65 
       
    66     @property
       
    67     def groups(self):
       
    68         try:
       
    69             return self._groups
       
    70         except AttributeError:
       
    71             self._groups = set(g.name for g in self.in_group)
       
    72             return self._groups
       
    73 
       
    74     @property
       
    75     def properties(self):
       
    76         try:
       
    77             return self._properties
       
    78         except AttributeError:
       
    79             self._properties = dict(
       
    80                 self._cw.execute(
       
    81                     'Any K, V WHERE P for_user U, U eid %(userid)s, '
       
    82                     'P pkey K, P value V',
       
    83                     {'userid': self.eid}))
       
    84             return self._properties
       
    85 
       
    86     def prefered_language(self, language=None):
       
    87         """return language used by this user, if explicitly defined (eg not
       
    88         using http negociation)
       
    89         """
       
    90         language = language or self.property_value('ui.language')
       
    91         vreg = self._cw.vreg
       
    92         try:
       
    93             vreg.config.translations[language]
       
    94         except KeyError:
       
    95             language = vreg.property_value('ui.language')
       
    96             assert language in vreg.config.translations[language], language
       
    97         return language
       
    98 
       
    99     def property_value(self, key):
       
   100         try:
       
   101             # properties stored on the user aren't correctly typed
       
   102             # (e.g. all values are unicode string)
       
   103             return self._cw.vreg.typed_value(key, self.properties[key])
       
   104         except KeyError:
       
   105             pass
       
   106         except ValueError:
       
   107             self.warning('incorrect value for eproperty %s of user %s',
       
   108                          key, self.login)
       
   109         return self._cw.vreg.property_value(key)
       
   110 
       
   111     def set_property(self, pkey, value):
       
   112         value = unicode(value)
       
   113         try:
       
   114             prop = self._cw.execute(
       
   115                 'CWProperty X WHERE X pkey %(k)s, X for_user U, U eid %(u)s',
       
   116                 {'k': pkey, 'u': self.eid}).get_entity(0, 0)
       
   117         except Exception:
       
   118             kwargs = dict(pkey=unicode(pkey), value=value)
       
   119             if self.is_in_group('managers'):
       
   120                 kwargs['for_user'] = self
       
   121             self._cw.create_entity('CWProperty', **kwargs)
       
   122         else:
       
   123             prop.cw_set(value=value)
       
   124 
       
   125     def matching_groups(self, groups):
       
   126         """return the number of the given group(s) in which the user is
       
   127 
       
   128         :type groups: str or iterable(str)
       
   129         :param groups: a group name or an iterable on group names
       
   130         """
       
   131         if isinstance(groups, string_types):
       
   132             groups = frozenset((groups,))
       
   133         elif isinstance(groups, (tuple, list)):
       
   134             groups = frozenset(groups)
       
   135         return len(groups & self.groups) # XXX return the resulting set instead of its size
       
   136 
       
   137     def is_in_group(self, group):
       
   138         """convience / shortcut method to test if the user belongs to `group`
       
   139         """
       
   140         return group in self.groups
       
   141 
       
   142     def is_anonymous(self):
       
   143         """ checks if user is an anonymous user"""
       
   144         #FIXME on the web-side anonymous user is detected according
       
   145         # to config['anonymous-user'], we don't have this info on
       
   146         # the server side.
       
   147         return self.groups == frozenset(('guests', ))
       
   148 
       
   149     def owns(self, eid):
       
   150         try:
       
   151             return self._cw.execute(
       
   152                 'Any X WHERE X eid %(x)s, X owned_by U, U eid %(u)s',
       
   153                 {'x': eid, 'u': self.eid})
       
   154         except Unauthorized:
       
   155             return False
       
   156     owns = cached(owns, keyarg=1)
       
   157 
       
   158     # presentation utilities ##################################################
       
   159 
       
   160     def name(self):
       
   161         """construct a name using firstname / surname or login if not defined"""
       
   162 
       
   163         if self.firstname and self.surname:
       
   164             return self._cw._('%(firstname)s %(surname)s') % {
       
   165                 'firstname': self.firstname, 'surname' : self.surname}
       
   166         if self.firstname:
       
   167             return self.firstname
       
   168         return self.login
       
   169 
       
   170     def dc_title(self):
       
   171         return self.login
       
   172 
       
   173     dc_long_title = name
       
   174 
       
   175     def __call__(self, *args, **kwargs):
       
   176         """ugly hack for compatibility betweeb dbapi and repo api
       
   177 
       
   178         In the dbapi, Connection and Session have a ``user`` method to
       
   179         generated a user for a request In the repo api, Connection and Session
       
   180         have a user attribute inherited from SessionRequestBase prototype. This
       
   181         ugly hack allows to not break user of the user method.
       
   182 
       
   183         XXX Deprecate me ASAP"""
       
   184         return self
       
   185 
       
   186 from logilab.common.deprecation import class_renamed
       
   187 EUser = class_renamed('EUser', CWUser)
       
   188 EGroup = class_renamed('EGroup', CWGroup)