当我尝试允许基本用户读取附件 (ir.attachment) 时,我在 Odoo 中遇到访问错误。具体来说,该错误表明用户 (id=6) 对某些附件没有“读取”访问权限,尽管已创建旨在授予此访问权限的记录规则。
错误信息
呃哦!看来您偶然发现了一些绝密记录。
抱歉,约翰 (id=6) 没有“读取”权限:
归咎于以下规则:
安全规则:
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- HR Announcement Multi Company rule -->
<record id="hr_announcement_rule_company" model="ir.rule">
<field name="name">HR Announcement Multi Company</field>
<field name="model_id" ref="model_hr_announcement"/>
<field eval="True" name="global"/>
<field name="domain_force">
['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
</field>
</record>
</odoo>
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_hr_announcement_admin,access.hr.announcement.admin,model_hr_announcement,hr.group_hr_manager,1,1,1,1
access_hr_announcement_user,access.hr.announcement.user,model_hr_announcement,hr.group_hr_user,1,1,1,1
access_hr_announcement_employee,access.hr.announcement.employee,model_hr_announcement,base.group_user,1,0,0,0
** 我的代码屏幕截图是:**
我希望当基本用户(例如 id=6 的 john)尝试访问 Odoo 中的附件时,他们应该能够查看所有附件而不会遇到任何访问错误。具体来说,我希望他们看到以下内容:
附件名称:Bharathikannan Malaikkannan (1).pdf 访问级别:用户应对此附件以及他们有权访问的任何其他附件拥有“读取”访问权限。
Odoo 中的附加权通常不是这样运作的。附件有 关于访问权的具体实施。访问权限或多或少反映了附件所附业务模型的访问权限。
例如:如果用户拥有发票的读取权限 (account.move),它还可以读取这些发票的附加文件。
这个特殊功能主要是通过重写模块
models.Model.check()
中模型ir.attachment
上的base
方法来实现。
对于 Odoo 16 的代码,带有一些可以理解的注释:
@api.model
def check(self, mode, values=None):
""" Restricts the access to an ir.attachment, according to referred mode """
if self.env.is_superuser():
return True
# Always require an internal user (aka, employee) to access to a attachment
if not (self.env.is_admin() or self.env.user._is_internal()):
raise AccessError(_("Sorry, you are not allowed to access this document."))
# collect the records to check (by model)
model_ids = defaultdict(set) # {model_name: set(ids)}
if self:
# DLE P173: `test_01_portal_attachment`
self.env['ir.attachment'].flush_model(['res_model', 'res_id', 'create_uid', 'public', 'res_field'])
self._cr.execute('SELECT res_model, res_id, create_uid, public, res_field FROM ir_attachment WHERE id IN %s', [tuple(self.ids)])
for res_model, res_id, create_uid, public, res_field in self._cr.fetchall():
if public and mode == 'read':
continue
if not self.env.is_system() and (res_field or (not res_id and create_uid != self.env.uid)):
raise AccessError(_("Sorry, you are not allowed to access this document."))
if not (res_model and res_id):
continue
model_ids[res_model].add(res_id)
if values and values.get('res_model') and values.get('res_id'):
model_ids[values['res_model']].add(values['res_id'])
# check access rights on the records
for res_model, res_ids in model_ids.items():
# ignore attachments that are not attached to a resource anymore
# when checking access rights (resource was deleted but attachment
# was not)
if res_model not in self.env:
continue
if res_model == 'res.users' and len(res_ids) == 1 and self.env.uid == list(res_ids)[0]:
# by default a user cannot write on itself, despite the list of writeable fields
# e.g. in the case of a user inserting an image into his image signature
# we need to bypass this check which would needlessly throw us away
continue
records = self.env[res_model].browse(res_ids).exists()
# For related models, check if we can write to the model, as unlinking
# and creating attachments can be seen as an update to the model
access_mode = 'write' if mode in ('create', 'unlink') else mode
records.check_access_rights(access_mode)
records.check_access_rule(access_mode)