[FIX] mail: allow regular users to create mail non-dynamic templates

closes odoo/odoo#90896

X-original-commit: 96770827e42615c43b70bdae6529fb76ac66c518
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
This commit is contained in:
Denis Ledoux
2022-05-09 17:05:43 +02:00
parent 618d94988f
commit dd2958a760
6 changed files with 104 additions and 5 deletions
+1
View File
@@ -4856,6 +4856,7 @@ msgstr ""
#. module: mail
#: code:addons/mail/models/mail_render_mixin.py:0
#: code:addons/mail/models/mail_render_mixin.py:0
#: code:addons/mail/models/mail_render_mixin.py:0
#, python-format
msgid "Only users belonging to the \"%s\" group can modify dynamic templates."
msgstr ""
+59
View File
@@ -127,6 +127,23 @@ class MailRenderMixin(models.AbstractModel):
# allow specifying rendering options directly from field when using the render mixin
return name in ['render_engine', 'render_options'] or super()._valid_field_parameter(field, name)
@api.model_create_multi
def create(self, values_list):
record = super().create(values_list)
if self._unrestricted_rendering:
# If the rendering is unrestricted (e.g. mail.template),
# check the user is part of the mail editor group to create a new template if the template is dynamic
record._check_access_right_dynamic_template()
return record
def write(self, vals):
super().write(vals)
if self._unrestricted_rendering:
# If the rendering is unrestricted (e.g. mail.template),
# check the user is part of the mail editor group to modify a template if the template is dynamic
self._check_access_right_dynamic_template()
return True
# ------------------------------------------------------------
# TOOLS
# ------------------------------------------------------------
@@ -214,6 +231,48 @@ class MailRenderMixin(models.AbstractModel):
""").format(preview_markup)
return tools.prepend_html_content(html, html_preview)
return html
# ------------------------------------------------------------
# SECURITY
# ------------------------------------------------------------
def _is_dynamic(self):
for template in self:
for fname, field in template._fields.items():
engine = getattr(field, 'render_engine', 'inline_template')
if engine in ('qweb', 'qweb_view'):
if self._is_dynamic_template_qweb(template[fname]):
return True
else:
if self._is_dynamic_template_inline_template(template[fname]):
return True
return False
@api.model
def _is_dynamic_template_qweb(self, template_src):
if template_src:
try:
node = html.fragment_fromstring(template_src, create_parent='div')
self.env["ir.qweb"].with_context(raise_on_code=True)._compile(node)
except QWebException as e:
if isinstance(e.__cause__, PermissionError):
return True
raise
return False
@api.model
def _is_dynamic_template_inline_template(self, template_txt):
if template_txt:
template_instructions = parse_inline_template(str(template_txt))
if len(template_instructions) > 1 or template_instructions[0][1]:
return True
return False
def _check_access_right_dynamic_template(self):
if not self.env.su and not self.env.user.has_group('mail.group_mail_template_editor') and self._is_dynamic():
group = self.env.ref('mail.group_mail_template_editor')
raise AccessError(_('Only users belonging to the "%s" group can modify dynamic templates.', group.name))
# ------------------------------------------------------------
# RENDERING
# ------------------------------------------------------------
+1 -1
View File
@@ -31,7 +31,7 @@ access_mail_tracking_value_portal,mail.tracking.value.portal,model_mail_tracking
access_mail_tracking_value_user,mail.tracking.value.user,model_mail_tracking_value,base.group_user,0,0,0,0
access_mail_tracking_value_system,mail.tracking.value.system,model_mail_tracking_value,base.group_system,1,1,1,1
access_publisher_warranty_contract_all,publisher.warranty.contract.all,model_publisher_warranty_contract,,1,1,1,1
access_mail_template,mail.template,model_mail_template,base.group_user,1,0,0,0
access_mail_template,mail.template,model_mail_template,base.group_user,1,1,1,1
access_mail_template_editor,mail.template_editor,model_mail_template,mail.group_mail_template_editor,1,1,1,1
access_mail_template_system,mail.template_system,model_mail_template,base.group_system,1,1,1,1
access_mail_shortcode,mail.shortcode,model_mail_shortcode,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
31 access_mail_tracking_value_user mail.tracking.value.user model_mail_tracking_value base.group_user 0 0 0 0
32 access_mail_tracking_value_system mail.tracking.value.system model_mail_tracking_value base.group_system 1 1 1 1
33 access_publisher_warranty_contract_all publisher.warranty.contract.all model_publisher_warranty_contract 1 1 1 1
34 access_mail_template mail.template model_mail_template base.group_user 1 0 1 0 1 0 1
35 access_mail_template_editor mail.template_editor model_mail_template mail.group_mail_template_editor 1 1 1 1
36 access_mail_template_system mail.template_system model_mail_template base.group_system 1 1 1 1
37 access_mail_shortcode mail.shortcode model_mail_shortcode base.group_user 1 1 1 1
+22
View File
@@ -65,6 +65,28 @@
<field name="perm_unlink" eval="False"/>
</record>
<record id="mail_template_employee_rule" model="ir.rule">
<field name="name">Employees can only change their own templates</field>
<field name="model_id" ref="model_mail_template"/>
<field name="domain_force">[('create_uid', '=', user.id)]</field>
<field name="groups" eval="[Command.link(ref('base.group_user'))]"/>
<field name="perm_create" eval="True"/>
<field name="perm_read" eval="False"/>
<field name="perm_write" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
<record id="mail_template_editor_rule" model="ir.rule">
<field name="name">Mail Template Editors - Edit All Templates</field>
<field name="model_id" ref="model_mail_template"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[Command.link(ref('group_mail_template_editor')), Command.link(ref('base.group_system'))]"/>
<field name="perm_create" eval="True"/>
<field name="perm_read" eval="False"/>
<field name="perm_write" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
<record id="res_users_settings_rule_admin" model="ir.rule">
<field name="name">Administrators can access all User Settings.</field>
<field name="model_id" ref="model_res_users_settings"/>
+19 -3
View File
@@ -57,9 +57,25 @@ class TestMailTemplate(MailCommon):
mail_template.with_user(self.user_admin).name = 'New name'
self.assertEqual(mail_template.name, 'New name')
# Standard employee can not
# Standard employee can create and edit non-dynamic templates
employee_template = self.env['mail.template'].with_user(self.user_employee).create({'body_html': '<p>foo</p>'})
employee_template.with_user(self.user_employee).body_html = '<p>bar</p>'
employee_template = self.env['mail.template'].with_user(self.user_employee).create({'email_to': 'foo@bar.com'})
employee_template.with_user(self.user_employee).email_to = 'bar@foo.com'
# Standard employee cannot create and edit templates with dynamic qweb
with self.assertRaises(AccessError):
self.env['mail.template'].with_user(self.user_employee).create({})
self.env['mail.template'].with_user(self.user_employee).create({'body_html': '<p t-esc="\'foo\'"></p>'})
with self.assertRaises(AccessError):
mail_template.with_user(self.user_employee).name = 'Test write'
mail_template.with_user(self.user_employee).body_html = '<p t-esc="\'foo\'"></p>'
# Standard employee cannot create and edit templates with dynamic inline fields
with self.assertRaises(AccessError):
self.env['mail.template'].with_user(self.user_employee).create({'email_to': '{{ object.partner_id.email }}'})
with self.assertRaises(AccessError):
mail_template.with_user(self.user_employee).email_to = '{{ object.partner_id.email }}'
@@ -66,8 +66,9 @@
<button string="Send" attrs="{'invisible': [('is_log', '=', True)]}" name="action_send_mail" type="object" class="btn-primary o_mail_send" data-hotkey="q"/>
<button string="Log" attrs="{'invisible': [('is_log', '=', False)]}" name="action_send_mail" type="object" class="btn-primary" data-hotkey="q"/>
<button string="Cancel" class="btn-secondary" special="cancel" data-hotkey="z" />
<button icon="fa-lg fa-save" type="object" groups="mail.group_mail_template_editor"
<button icon="fa-lg fa-save" type="object"
name="action_save_as_template" string="Save as new template"
attrs="{'invisible': [('can_edit_body', '=', False)]}"
class="float-right btn-secondary" help="Save as a new template" data-hotkey="w"/>
</footer>
</form>