2009-10-20 10:52:23 +00:00
# -*- coding: utf-8 -*-
2007-05-18 12:29:43 +00:00
##############################################################################
2010-03-19 10:58:38 +00:00
#
2009-10-14 12:32:15 +00:00
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
2008-06-16 11:00:21 +00:00
#
2008-11-03 18:27:16 +00:00
# This program is free software: you can redistribute it and/or modify
2009-10-14 12:32:15 +00:00
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
2007-05-18 12:29:43 +00:00
#
2008-11-03 18:27:16 +00:00
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2009-10-14 12:32:15 +00:00
# GNU Affero General Public License for more details.
2007-05-18 12:29:43 +00:00
#
2009-10-14 12:32:15 +00:00
# You should have received a copy of the GNU Affero General Public License
2010-03-19 10:58:38 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2007-05-18 12:29:43 +00:00
#
##############################################################################
import time
2012-12-10 15:27:23 +00:00
2011-09-26 09:01:56 +00:00
from openerp import SUPERUSER_ID
2012-12-10 15:27:23 +00:00
from openerp import tools
from openerp . osv import fields , osv , expression
from openerp . tools . safe_eval import safe_eval as eval
from openerp . tools . misc import unquote as unquote
2011-05-31 14:43:18 +00:00
2007-05-18 12:29:43 +00:00
class ir_rule ( osv . osv ) :
2008-07-22 14:24:36 +00:00
_name = ' ir.rule '
2010-12-10 22:42:58 +00:00
_order = ' name '
2010-06-10 14:57:22 +00:00
_MODES = [ ' read ' , ' write ' , ' create ' , ' unlink ' ]
2008-07-22 14:24:36 +00:00
2011-04-08 14:02:41 +00:00
def _eval_context_for_combinations ( self ) :
""" Returns a dictionary to use as evaluation context for
ir . rule domains , when the goal is to obtain python lists
that are easier to parse and combine , but not to
actually execute them . """
return { ' user ' : unquote ( ' user ' ) ,
' time ' : unquote ( ' time ' ) }
def _eval_context ( self , cr , uid ) :
""" Returns a dictionary to use as evaluation context for
ir . rule domains . """
2012-08-31 13:53:09 +00:00
return { ' user ' : self . pool . get ( ' res.users ' ) . browse ( cr , SUPERUSER_ID , uid ) ,
2011-04-08 14:02:41 +00:00
' time ' : time }
2011-03-02 11:08:16 +00:00
def _domain_force_get ( self , cr , uid , ids , field_name , arg , context = None ) :
2008-07-22 14:24:36 +00:00
res = { }
2011-04-08 14:02:41 +00:00
eval_context = self . _eval_context ( cr , uid )
2008-07-22 14:24:36 +00:00
for rule in self . browse ( cr , uid , ids , context ) :
2011-02-28 11:44:20 +00:00
if rule . domain_force :
2012-12-04 14:26:50 +00:00
res [ rule . id ] = expression . normalize_domain ( eval ( rule . domain_force , eval_context ) )
2011-02-28 11:44:20 +00:00
else :
res [ rule . id ] = [ ]
2010-04-29 12:01:58 +00:00
return res
2010-03-19 10:58:38 +00:00
2011-03-02 11:08:16 +00:00
def _get_value ( self , cr , uid , ids , field_name , arg , context = None ) :
2010-04-29 12:01:58 +00:00
res = { }
for rule in self . browse ( cr , uid , ids , context ) :
if not rule . groups :
res [ rule . id ] = True
2008-07-22 14:24:36 +00:00
else :
2010-04-29 12:01:58 +00:00
res [ rule . id ] = False
2008-07-22 14:24:36 +00:00
return res
2010-12-09 10:57:33 +00:00
def _check_model_obj ( self , cr , uid , ids , context = None ) :
2013-03-29 14:07:23 +00:00
return not any ( self . pool [ rule . model_id . model ] . is_transient ( ) for rule in self . browse ( cr , uid , ids , context ) )
2010-04-29 12:01:58 +00:00
2012-02-13 11:01:44 +00:00
def _check_model_name ( self , cr , uid , ids , context = None ) :
# Don't allow rules on rules records (this model).
return not any ( rule . model_id . model == self . _name for rule in self . browse ( cr , uid , ids , context ) )
2008-07-22 14:24:36 +00:00
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Name ' , select = 1 ) ,
2012-07-13 17:37:34 +00:00
' active ' : fields . boolean ( ' Active ' , help = " If you uncheck the active field, it will disable the record rule without deleting it (if you delete a native record rule, it may be re-created when you reload the module. " ) ,
2012-02-27 15:21:35 +00:00
' model_id ' : fields . many2one ( ' ir.model ' , ' Object ' , select = 1 , required = True , ondelete = " cascade " ) ,
2012-01-04 13:30:27 +00:00
' global ' : fields . function ( _get_value , string = ' Global ' , type = ' boolean ' , store = True , help = " If no group is specified the rule is global and applied to everyone " ) ,
2010-04-29 12:01:58 +00:00
' groups ' : fields . many2many ( ' res.groups ' , ' rule_group_rel ' , ' rule_group_id ' , ' group_id ' , ' Groups ' ) ,
2010-08-05 13:46:26 +00:00
' domain_force ' : fields . text ( ' Domain ' ) ,
2014-07-06 14:44:26 +00:00
' domain ' : fields . function ( _domain_force_get , string = ' Domain ' , type = ' binary ' ) ,
2012-04-23 11:20:41 +00:00
' perm_read ' : fields . boolean ( ' Apply for Read ' ) ,
' perm_write ' : fields . boolean ( ' Apply for Write ' ) ,
' perm_create ' : fields . boolean ( ' Apply for Create ' ) ,
' perm_unlink ' : fields . boolean ( ' Apply for Delete ' )
2010-03-19 10:58:38 +00:00
}
2010-04-29 12:01:58 +00:00
_order = ' model_id DESC '
2010-03-19 10:58:38 +00:00
_defaults = {
2012-07-13 17:37:34 +00:00
' active ' : True ,
2010-04-29 12:01:58 +00:00
' perm_read ' : True ,
' perm_write ' : True ,
' perm_create ' : True ,
' perm_unlink ' : True ,
' global ' : True ,
2008-07-22 14:24:36 +00:00
}
2010-03-19 10:58:38 +00:00
_sql_constraints = [
2010-09-09 11:02:11 +00:00
( ' no_access_rights ' , ' CHECK (perm_read!=False or perm_write!=False or perm_create!=False or perm_unlink!=False) ' , ' Rule must have at least one checked access right ! ' ) ,
2010-03-19 10:58:38 +00:00
]
2010-04-29 12:01:58 +00:00
_constraints = [
2012-02-13 11:01:44 +00:00
( _check_model_obj , ' Rules can not be applied on Transient models. ' , [ ' model_id ' ] ) ,
( _check_model_name , ' Rules can not be applied on the Record Rules model. ' , [ ' model_id ' ] ) ,
2010-04-29 12:01:58 +00:00
]
2008-07-22 14:24:36 +00:00
2011-06-08 03:03:30 +00:00
@tools.ormcache ( )
2010-04-29 15:35:12 +00:00
def _compute_domain ( self , cr , uid , model_name , mode = " read " ) :
2010-06-10 14:57:22 +00:00
if mode not in self . _MODES :
raise ValueError ( ' Invalid mode: %r ' % ( mode , ) )
2010-04-29 12:01:58 +00:00
2011-09-26 09:01:56 +00:00
if uid == SUPERUSER_ID :
2010-04-29 15:35:12 +00:00
return None
2010-03-19 10:58:38 +00:00
cr . execute ( """ SELECT r.id
FROM ir_rule r
2010-04-29 12:01:58 +00:00
JOIN ir_model m ON ( r . model_id = m . id )
2008-07-22 14:24:36 +00:00
WHERE m . model = % s
2012-07-13 17:37:34 +00:00
AND r . active is True
2010-03-19 10:58:38 +00:00
AND r . perm_ """ + mode + """
2010-04-29 12:01:58 +00:00
AND ( r . id IN ( SELECT rule_group_id FROM rule_group_rel g_rel
2008-07-22 14:24:36 +00:00
JOIN res_groups_users_rel u_rel ON ( g_rel . group_id = u_rel . gid )
2010-04-29 12:01:58 +00:00
WHERE u_rel . uid = % s ) OR r . global ) """ , (model_name, uid))
2011-05-31 14:43:18 +00:00
rule_ids = [ x [ 0 ] for x in cr . fetchall ( ) ]
if rule_ids :
# browse user as super-admin root to avoid access errors!
2011-09-26 09:01:56 +00:00
user = self . pool . get ( ' res.users ' ) . browse ( cr , SUPERUSER_ID , uid )
2011-05-31 14:43:18 +00:00
global_domains = [ ] # list of domains
group_domains = { } # map: group -> list of domains
2011-09-26 09:01:56 +00:00
for rule in self . browse ( cr , SUPERUSER_ID , rule_ids ) :
2011-06-01 13:55:26 +00:00
# read 'domain' as UID to have the correct eval context for the rule.
2014-07-06 14:44:26 +00:00
rule_domain = self . read ( cr , uid , [ rule . id ] , [ ' domain ' ] ) [ 0 ] [ ' domain ' ]
2012-12-04 14:26:50 +00:00
dom = expression . normalize_domain ( rule_domain )
2010-08-17 18:35:50 +00:00
for group in rule . groups :
2011-05-31 14:43:18 +00:00
if group in user . groups_id :
group_domains . setdefault ( group , [ ] ) . append ( dom )
2010-08-17 18:35:50 +00:00
if not rule . groups :
2011-05-31 14:43:18 +00:00
global_domains . append ( dom )
# combine global domains and group domains
if group_domains :
2011-06-01 13:01:56 +00:00
group_domain = expression . OR ( map ( expression . OR , group_domains . values ( ) ) )
2011-05-31 14:43:18 +00:00
else :
group_domain = [ ]
domain = expression . AND ( global_domains + [ group_domain ] )
return domain
2010-08-17 18:35:50 +00:00
return [ ]
2010-04-29 15:35:12 +00:00
2010-06-10 14:57:22 +00:00
def clear_cache ( self , cr , uid ) :
2011-08-24 17:22:37 +00:00
self . _compute_domain . clear_cache ( self )
2010-06-10 14:57:22 +00:00
2011-03-02 11:08:16 +00:00
def domain_get ( self , cr , uid , model_name , mode = ' read ' , context = None ) :
2011-06-08 03:03:30 +00:00
dom = self . _compute_domain ( cr , uid , model_name , mode )
2010-04-29 15:35:12 +00:00
if dom :
2011-03-02 08:35:38 +00:00
# _where_calc is called as superuser. This means that rules can
# involve objects on which the real uid has no acces rights.
# This means also there is no implicit restriction (e.g. an object
# references another object the user can't see).
2013-03-29 14:07:23 +00:00
query = self . pool [ model_name ] . _where_calc ( cr , SUPERUSER_ID , dom , active_test = False )
2010-09-30 13:24:03 +00:00
return query . where_clause , query . where_clause_params , query . tables
2013-03-29 14:07:23 +00:00
return [ ] , [ ] , [ ' " ' + self . pool [ model_name ] . _table + ' " ' ]
2008-07-22 14:24:36 +00:00
def unlink ( self , cr , uid , ids , context = None ) :
res = super ( ir_rule , self ) . unlink ( cr , uid , ids , context = context )
2011-08-24 17:22:37 +00:00
self . clear_cache ( cr , uid )
2008-07-22 14:24:36 +00:00
return res
2011-06-08 09:25:15 +00:00
def create ( self , cr , uid , vals , context = None ) :
res = super ( ir_rule , self ) . create ( cr , uid , vals , context = context )
2011-08-24 17:22:37 +00:00
self . clear_cache ( cr , uid )
2008-07-22 14:24:36 +00:00
return res
def write ( self , cr , uid , ids , vals , context = None ) :
res = super ( ir_rule , self ) . write ( cr , uid , ids , vals , context = context )
2011-08-24 17:22:37 +00:00
self . clear_cache ( cr , uid )
2008-07-22 14:24:36 +00:00
return res
2007-05-18 12:29:43 +00:00
2008-07-23 15:01:27 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: