[IMP] base: Remove private res.partner type
- Improve performances, as the ir.rule restricting private partners visibility is also applied on res.users by inheritance, on each prefetch. - Solve the issue of partners set as followers on records (eg: application form) and then made private, making them impossible to contact via the chatter. - Solve the multiple access issues when trying to access the bank account, or the private address for non HR people like the accountants forcing the usage of sudo in the business code. TaskID: 3101400
This commit is contained in:
@@ -59,7 +59,7 @@
|
||||
<record id="group_account_manager" model="res.groups">
|
||||
<field name="name">Billing Administrator</field>
|
||||
<field name="category_id" ref="base.module_category_accounting_accounting"/>
|
||||
<field name="implied_ids" eval="[(4, ref('group_account_invoice')),(4, ref('base.group_private_addresses'))]"/>
|
||||
<field name="implied_ids" eval="[(4, ref('group_account_invoice'))]"/>
|
||||
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -782,7 +782,7 @@
|
||||
context="{
|
||||
'res_partner_search_mode': (context.get('default_move_type', 'entry') in ('out_invoice', 'out_refund', 'out_receipt') and 'customer') or (context.get('default_move_type', 'entry') in ('in_invoice', 'in_refund', 'in_receipt') and 'supplier') or False,
|
||||
'show_address': 1, 'default_is_company': True, 'show_vat': True}"
|
||||
domain="[('type', '!=', 'private'), ('company_id', 'in', (False, company_id))]"
|
||||
domain="[('company_id', 'in', (False, company_id))]"
|
||||
options='{"always_reload": True, "no_quick_create": True}'
|
||||
attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt'))]}"/>
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@ class AccountMoveSend(models.Model):
|
||||
mail_partner_ids = fields.Many2many(
|
||||
comodel_name='res.partner',
|
||||
string="Recipients",
|
||||
domain=[('type', '!=', 'private')],
|
||||
compute='_compute_mail_partner_ids',
|
||||
store=True,
|
||||
readonly=False,
|
||||
|
||||
@@ -192,7 +192,6 @@
|
||||
<field name="partner_ids" widget="many2manyattendee"
|
||||
placeholder="Select attendees..."
|
||||
context="{'force_email':True}"
|
||||
domain="[('type','!=','private')]"
|
||||
class="oe_inline"
|
||||
attrs="{'readonly': [('user_can_edit', '=', False)]}"
|
||||
/>
|
||||
@@ -321,7 +320,6 @@
|
||||
<field name="partner_ids" widget="many2manyattendee"
|
||||
placeholder="Select attendees..."
|
||||
context="{'force_email':True}"
|
||||
domain="[('type','!=','private')]"
|
||||
class="oe_inline"
|
||||
/>
|
||||
<label for="videocall_location" class="opacity-100"/>
|
||||
|
||||
@@ -53,7 +53,7 @@ class TestDigestCommon(mail_test.MailCommon):
|
||||
previous month
|
||||
"""
|
||||
# regular employee can't necessarily access "private" addresses
|
||||
partners = cls.env['res.partner'].search([('type', '!=', 'private')])
|
||||
partners = cls.env['res.partner'].search([])
|
||||
messages = cls.env['mail.message']
|
||||
counter = itertools.count()
|
||||
|
||||
|
||||
@@ -305,11 +305,11 @@ class GoogleSync(models.AbstractModel):
|
||||
def _get_sync_partner(self, emails):
|
||||
normalized_emails = [email_normalize(contact) for contact in emails if email_normalize(contact)]
|
||||
user_partners = self.env['mail.thread']._mail_search_on_user(normalized_emails, extra_domain=[('share', '=', False)])
|
||||
partners = [user_partner for user_partner in user_partners if user_partner.type != 'private']
|
||||
partners = list(user_partners)
|
||||
remaining = [email for email in normalized_emails if
|
||||
email not in [partner.email_normalized for partner in partners]]
|
||||
if remaining:
|
||||
partners += self.env['mail.thread']._mail_find_partner_from_emails(remaining, records=self, force_create=True, extra_domain=[('type', '!=', 'private')])
|
||||
partners += self.env['mail.thread']._mail_find_partner_from_emails(remaining, records=self, force_create=True)
|
||||
unsorted_partners = self.env['res.partner'].browse([p.id for p in partners])
|
||||
# partners needs to be sorted according to the emails order provided by google
|
||||
k = {value: idx for idx, value in enumerate(emails)}
|
||||
|
||||
@@ -14,6 +14,7 @@ class TestSyncGoogle2Odoo(TestSyncGoogle):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.other_company = self.env['res.company'].create({'name': 'Other Company'})
|
||||
self.public_partner = self.env['res.partner'].create({
|
||||
'name': 'Public Contact',
|
||||
'email': 'public_email@example.com',
|
||||
@@ -22,7 +23,7 @@ class TestSyncGoogle2Odoo(TestSyncGoogle):
|
||||
self.private_partner = self.env['res.partner'].create({
|
||||
'name': 'Private Contact',
|
||||
'email': 'private_email@example.com',
|
||||
'type': 'private',
|
||||
'company_id': self.other_company.id,
|
||||
})
|
||||
|
||||
@property
|
||||
@@ -1270,8 +1271,7 @@ class TestSyncGoogle2Odoo(TestSyncGoogle):
|
||||
self.env['calendar.event']._sync_google2odoo(GoogleEvent([values]))
|
||||
event = self.env['calendar.event'].search([('google_id', '=', values.get('id'))])
|
||||
private_attendee = event.attendee_ids.filtered(lambda e: e.email == self.private_partner.email)
|
||||
self.assertNotEqual(self.private_partner.id, private_attendee.partner_id.id)
|
||||
self.assertNotEqual(private_attendee.partner_id.type, 'private')
|
||||
self.assertEqual(self.private_partner.id, private_attendee.partner_id.id)
|
||||
self.assertGoogleAPINotCalled()
|
||||
|
||||
@patch_api
|
||||
@@ -1297,7 +1297,7 @@ class TestSyncGoogle2Odoo(TestSyncGoogle):
|
||||
recurrence = self.env['calendar.recurrence'].search([('google_id', '=', values.get('id'))])
|
||||
events = recurrence.calendar_event_ids
|
||||
private_attendees = events.mapped('attendee_ids').filtered(lambda e: e.email == self.private_partner.email)
|
||||
self.assertTrue(all([a.partner_id.id != self.private_partner.id for a in private_attendees]))
|
||||
self.assertTrue(all([a.partner_id == self.private_partner for a in private_attendees]))
|
||||
self.assertTrue(all([a.partner_id.type != 'private' for a in private_attendees]))
|
||||
self.assertGoogleAPINotCalled()
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<record id="group_hr_user" model="res.groups">
|
||||
<field name="name">Officer: Manage all employees</field>
|
||||
<field name="category_id" ref="base.module_category_human_resources_employees"/>
|
||||
<field name="implied_ids" eval="[(6, 0, [ref('base.group_private_addresses'), ref('base.group_user')])]"/>
|
||||
<field name="implied_ids" eval="[(6, 0, [ref('base.group_user')])]"/>
|
||||
<field name="comment">The user will be able to approve document created by employees.</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -385,7 +385,6 @@ class Applicant(models.Model):
|
||||
raise UserError(_('You must define a Contact Name for this applicant.'))
|
||||
self.partner_id = self.env['res.partner'].create({
|
||||
'is_company': False,
|
||||
'type': 'private',
|
||||
'name': self.partner_name,
|
||||
'email': self.email_from,
|
||||
'phone': self.partner_phone,
|
||||
@@ -550,7 +549,6 @@ class Applicant(models.Model):
|
||||
if new_partner:
|
||||
if new_partner.create_date.date() == fields.Date.today():
|
||||
new_partner.write({
|
||||
'type': 'private',
|
||||
'name': self.partner_name or self.email_from,
|
||||
'phone': self.partner_phone,
|
||||
'mobile': self.partner_mobile,
|
||||
@@ -571,7 +569,6 @@ class Applicant(models.Model):
|
||||
raise UserError(_('Please provide an applicant name.'))
|
||||
self.partner_id = self.env['res.partner'].create({
|
||||
'is_company': False,
|
||||
'type': 'private',
|
||||
'name': self.partner_name,
|
||||
'email': self.email_from,
|
||||
'phone': self.partner_phone,
|
||||
|
||||
@@ -33,7 +33,6 @@ class ApplicantSendMail(models.TransientModel):
|
||||
if not applicant.partner_id:
|
||||
applicant.partner_id = self.env['res.partner'].create({
|
||||
'is_company': False,
|
||||
'type': 'private',
|
||||
'name': applicant.partner_name,
|
||||
'email': applicant.email_from,
|
||||
'phone': applicant.partner_phone,
|
||||
|
||||
@@ -40,7 +40,6 @@ class Applicant(models.Model):
|
||||
raise UserError(_('Please provide an applicant name.'))
|
||||
self.partner_id = self.env['res.partner'].sudo().create({
|
||||
'is_company': False,
|
||||
'type': 'private',
|
||||
'name': self.partner_name,
|
||||
'email': self.email_from,
|
||||
'phone': self.partner_phone,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="hr_recruitment.group_hr_recruitment_interviewer" model="res.groups">
|
||||
<field name="implied_ids" eval="[Command.link(ref('survey.group_survey_user')), Command.link(ref('base.group_private_addresses'))]"/>
|
||||
<field name="implied_ids" eval="[Command.link(ref('survey.group_survey_user'))]"/>
|
||||
<field name="comment">It will also allow to send surveys and see the resume.</field>
|
||||
</record>
|
||||
<record id="survey.survey_user_input_rule_survey_user_read" model="ir.rule">
|
||||
|
||||
@@ -62,7 +62,6 @@ class ResPartner(models.Model):
|
||||
]
|
||||
),
|
||||
[("active", "=", True)],
|
||||
[("type", "!=", "private")],
|
||||
[("user_ids", "!=", False)],
|
||||
[("user_ids.active", "=", True)],
|
||||
[("user_ids.share", "=", False)],
|
||||
|
||||
@@ -29,7 +29,7 @@ class Followers(models.Model):
|
||||
res_id = fields.Many2oneReference(
|
||||
'Related Document ID', index=True, help='Id of the followed resource', model_field='res_model')
|
||||
partner_id = fields.Many2one(
|
||||
'res.partner', string='Related Partner', index=True, ondelete='cascade', required=True, domain=[('type', '!=', 'private')])
|
||||
'res.partner', string='Related Partner', index=True, ondelete='cascade', required=True)
|
||||
subtype_ids = fields.Many2many(
|
||||
'mail.message.subtype', string='Subtype',
|
||||
help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall.")
|
||||
|
||||
@@ -3795,7 +3795,7 @@ class MailThread(models.AbstractModel):
|
||||
|
||||
# filter inactive and private addresses
|
||||
if partner_ids and not adding_current:
|
||||
partner_ids = self.env['res.partner'].sudo().search([('id', 'in', partner_ids), ('active', '=', True), ('type', '!=', 'private')]).ids
|
||||
partner_ids = self.env['res.partner'].sudo().search([('id', 'in', partner_ids), ('active', '=', True)]).ids
|
||||
|
||||
return self._message_subscribe(partner_ids, subtype_ids, customer_ids=customer_ids)
|
||||
|
||||
|
||||
@@ -281,7 +281,6 @@ class Partner(models.Model):
|
||||
[('email', 'ilike', search)],
|
||||
]),
|
||||
[('active', '=', True)],
|
||||
[('type', '!=', 'private')],
|
||||
])
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -40,7 +40,6 @@ class TestMailComposer(MailCommon):
|
||||
'name': 'Test template with mso conditionals',
|
||||
})
|
||||
|
||||
|
||||
@tagged('mail_composer')
|
||||
class TestMailComposerForm(TestMailComposer):
|
||||
""" Test mail composer form view usage. """
|
||||
@@ -48,23 +47,23 @@ class TestMailComposerForm(TestMailComposer):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMailComposerForm, cls).setUpClass()
|
||||
|
||||
cls.user_employee.write({'groups_id': [
|
||||
(4, cls.env.ref('base.group_private_addresses').id),
|
||||
(4, cls.env.ref('base.group_partner_manager').id),
|
||||
]})
|
||||
cls.other_company = cls.env['res.company'].create({'name': 'Other Company'})
|
||||
cls.user_employee.write({
|
||||
'groups_id': [(4, cls.env.ref('base.group_partner_manager').id)],
|
||||
'company_ids': [(4, cls.other_company.id)]
|
||||
})
|
||||
cls.partner_private, cls.partner_private_2, cls.partner_classic = cls.env['res.partner'].create([
|
||||
{
|
||||
'email': 'private.customer@text.example.com',
|
||||
'phone': '0032455112233',
|
||||
'name': 'Private Customer',
|
||||
'type': 'private',
|
||||
'company_id': cls.other_company.id,
|
||||
},
|
||||
{
|
||||
'email': 'private.customer.2@test.example.com',
|
||||
'phone': '0032455445566',
|
||||
'name': 'Private Customer 2',
|
||||
'type': 'private',
|
||||
'company_id': cls.other_company.id,
|
||||
},
|
||||
{
|
||||
'email': 'not.private@test.example.com',
|
||||
@@ -143,8 +142,8 @@ class TestMailComposerForm(TestMailComposer):
|
||||
def test_composer_default_recipients_private_norights(self):
|
||||
""" Test usage of a private partner in composer when not having the
|
||||
rights to see them, as default value """
|
||||
self.user_employee.write({'groups_id': [
|
||||
(3, self.env.ref('base.group_private_addresses').id),
|
||||
self.user_employee.write({'company_ids': [
|
||||
(3, self.other_company.id),
|
||||
]})
|
||||
with self.assertRaises(AccessError):
|
||||
_name = self.partner_private.with_env(self.env).name
|
||||
@@ -162,7 +161,7 @@ class TestMailComposerForm(TestMailComposer):
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
@users('employee')
|
||||
def test_composer_template_recipients_private(self):
|
||||
""" Test usage of a private partner in composer, comint from template
|
||||
""" Test usage of a private partner in composer, coming from template
|
||||
value """
|
||||
email_to_new = 'new.customer@test.example.com'
|
||||
self.mail_template.write({
|
||||
@@ -198,9 +197,8 @@ class TestMailComposerForm(TestMailComposer):
|
||||
)
|
||||
saved_form = form.save()
|
||||
self.assertEqual(
|
||||
# saved_form.partner_ids, partner_private + partner_classic + partner_private_2 + new_partner,
|
||||
saved_form.partner_ids, partner_classic + new_partner,
|
||||
'Template value is kept at save (FIXME: loosing private partner)'
|
||||
saved_form.partner_ids, partner_private + partner_classic + partner_private_2 + new_partner,
|
||||
'Template value is kept at save'
|
||||
)
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
@@ -210,8 +208,8 @@ class TestMailComposerForm(TestMailComposer):
|
||||
self.assertIn('<h1>Hello sir!</h1>', message.body)
|
||||
# self.assertEqual(message.partner_ids, partner_private + partner_classic + partner_private_2 + new_partner)
|
||||
self.assertEqual(
|
||||
message.partner_ids, partner_classic + new_partner,
|
||||
'FIXME: loosing private partner'
|
||||
message.partner_ids, partner_private + partner_classic + partner_private_2 + new_partner,
|
||||
'Should not loosing unreadable partners'
|
||||
)
|
||||
self.assertEqual(message.subject, 'MSO FTW')
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<field name="email_from"/>
|
||||
<field name="email_to"/>
|
||||
<field name="recipient_ids" widget="many2many_tags"
|
||||
domain="[('type', '!=', 'private'), ('active', '=', True)]"/>
|
||||
domain="[('active', '=', True)]"/>
|
||||
<field name="email_cc"/>
|
||||
<field name="reply_to"/>
|
||||
<field name="scheduled_date" placeholder="YYYY-MM-DD HH:MM:SS"/>
|
||||
|
||||
@@ -74,12 +74,6 @@ class MailComposer(models.TransientModel):
|
||||
for fname in result if fname in fields_list
|
||||
}
|
||||
|
||||
def _partner_ids_domain(self):
|
||||
return expression.OR([
|
||||
[('type', '!=', 'private')],
|
||||
[('id', 'in', self.env.context.get('default_partner_ids', []))],
|
||||
])
|
||||
|
||||
# content
|
||||
subject = fields.Char(
|
||||
'Subject',
|
||||
@@ -158,7 +152,6 @@ class MailComposer(models.TransientModel):
|
||||
partner_ids = fields.Many2many(
|
||||
'res.partner', 'mail_compose_message_res_partner_rel',
|
||||
'wizard_id', 'partner_id', 'Additional Contacts',
|
||||
domain=_partner_ids_domain,
|
||||
compute='_compute_partner_ids', readonly=False, store=True)
|
||||
# sending
|
||||
auto_delete = fields.Boolean(
|
||||
|
||||
@@ -40,7 +40,7 @@ class Invite(models.TransientModel):
|
||||
|
||||
res_model = fields.Char('Related Document Model', required=True, help='Model of the followed resource')
|
||||
res_id = fields.Integer('Related Document ID', help='Id of the followed resource')
|
||||
partner_ids = fields.Many2many('res.partner', string='Recipients', domain=[('type', '!=', 'private')])
|
||||
partner_ids = fields.Many2many('res.partner', string='Recipients')
|
||||
message = fields.Html('Message')
|
||||
notify = fields.Boolean('Send Notification', default=True)
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ class SaleOrder(models.Model):
|
||||
required=True, readonly=False, change_default=True, index=True,
|
||||
tracking=1,
|
||||
states=READONLY_FIELD_STATES,
|
||||
domain="[('type', '!=', 'private'), ('company_id', 'in', (False, company_id))]")
|
||||
domain="[('company_id', 'in', (False, company_id))]")
|
||||
state = fields.Selection(
|
||||
selection=SALE_ORDER_STATE,
|
||||
string="Status",
|
||||
|
||||
@@ -215,14 +215,16 @@ class BaseFollowersTest(MailCommon):
|
||||
|
||||
@users('employee')
|
||||
def test_followers_private_address(self):
|
||||
""" Test standard API does not subscribe private addresses """
|
||||
private_address = self.env['res.partner'].sudo().create({
|
||||
""" Test standard API does subscribe IDs the user can't read """
|
||||
other_company = self.env['res.company'].sudo().create({'name': 'Other Company'})
|
||||
private_address = self.env['res.partner'].create({
|
||||
'name': 'Private Address',
|
||||
'type': 'private',
|
||||
'company_id': other_company.id,
|
||||
})
|
||||
self.env.user.write({'company_ids': [(3, other_company.id)]})
|
||||
document = self.env['mail.test.simple'].browse(self.test_record.id)
|
||||
document.message_subscribe(partner_ids=(self.partner_portal | private_address).ids)
|
||||
self.assertEqual(document.message_follower_ids.partner_id, self.partner_portal)
|
||||
self.assertEqual(document.message_follower_ids.partner_id, self.partner_portal | private_address)
|
||||
|
||||
# works through low-level API
|
||||
document._message_subscribe(partner_ids=(self.partner_portal | private_address).ids)
|
||||
|
||||
@@ -336,22 +336,14 @@ class TestMailgateway(MailCommon):
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread')
|
||||
def test_message_process_followers(self):
|
||||
""" Incoming email: recognized author not archived and not odoobot:
|
||||
added as follower. Also test corner cases: archived, private. """
|
||||
partner_archived, partner_private = self.env['res.partner'].create([
|
||||
{
|
||||
'active': False,
|
||||
'email': 'archived.customer@text.example.com',
|
||||
'phone': '0032455112233',
|
||||
'name': 'Archived Customer',
|
||||
'type': 'contact',
|
||||
},
|
||||
{
|
||||
'email': 'private.customer@text.example.com',
|
||||
'phone': '0032455112233',
|
||||
'name': 'Private Customer',
|
||||
'type': 'private',
|
||||
},
|
||||
])
|
||||
added as follower. Also test corner cases: archived. """
|
||||
partner_archived = self.env['res.partner'].create({
|
||||
'active': False,
|
||||
'email': 'archived.customer@text.example.com',
|
||||
'phone': '0032455112233',
|
||||
'name': 'Archived Customer',
|
||||
'type': 'contact',
|
||||
})
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
record = self.format_and_process(MAIL_TEMPLATE, self.partner_1.email_formatted, 'groups@test.com')
|
||||
@@ -406,19 +398,6 @@ class TestMailgateway(MailCommon):
|
||||
self.assertEqual(record4.message_partner_ids, self.env['res.partner'],
|
||||
'message_process: odoobot -> no follower')
|
||||
|
||||
# private partner
|
||||
with self.mock_mail_gateway():
|
||||
record5 = self.format_and_process(
|
||||
MAIL_TEMPLATE, partner_private.email_formatted, 'groups@test.com',
|
||||
subject='Private Partner')
|
||||
|
||||
self.assertEqual(record5.message_ids[0].author_id, partner_private)
|
||||
self.assertEqual(record5.message_ids[0].email_from, partner_private.email_formatted)
|
||||
self.assertEqual(record5.message_follower_ids.partner_id, partner_private,
|
||||
'message_process: private partner is recognized')
|
||||
self.assertEqual(record5.message_partner_ids, partner_private,
|
||||
'message_process: private partner is recognized')
|
||||
|
||||
# --------------------------------------------------
|
||||
# Author recognition
|
||||
# --------------------------------------------------
|
||||
|
||||
@@ -231,7 +231,6 @@ class Partner(models.Model):
|
||||
[('contact', 'Contact'),
|
||||
('invoice', 'Invoice Address'),
|
||||
('delivery', 'Delivery Address'),
|
||||
('private', 'Private Address'),
|
||||
('other', 'Other Address'),
|
||||
], string='Address Type',
|
||||
default='contact',
|
||||
|
||||
@@ -96,7 +96,7 @@ class Partner(models.Model):
|
||||
('employee', populate.cartesian([True, False], [0.1, 0.9])),
|
||||
('email', populate.iterate(
|
||||
[False, '', 'email{counter}@example.com', '<contact 万> contact{counter}@anotherexample.com', 'invalid_email'])),
|
||||
('type', populate.constant('contact')), # todo add more logic, manage 'invoice', 'delivery', 'other', 'private'
|
||||
('type', populate.constant('contact')), # todo add more logic, manage 'invoice', 'delivery', 'other'
|
||||
('is_company', populate.iterate([True, False], [0.05, 0.95])),
|
||||
('_address', generate_address),
|
||||
('state_id', populate.compute(get_state)),
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record id="group_private_addresses" model="res.groups">
|
||||
<field name="name">Access to Private Addresses</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
<data noupdate="1">
|
||||
<!-- TODO Remove me? Ony group system -->
|
||||
<record model="ir.rule" id="res_users_log_rule">
|
||||
@@ -76,37 +71,6 @@
|
||||
<field name="domain_force">[('create_uid', '=', user.id)]</field>
|
||||
</record>
|
||||
|
||||
<!-- Security restriction for private addresses -->
|
||||
<record id="res_partner_rule_private_employee" model="ir.rule">
|
||||
<field name="name">res.partner.rule.private.employee</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="domain_force">
|
||||
['|', ('type', '!=', 'private'), ('type', '=', False)]
|
||||
</field>
|
||||
<field name="groups" eval="[
|
||||
Command.link(ref('base.group_user')),
|
||||
]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_unlink" eval="True"/>
|
||||
</record>
|
||||
<!-- Relex previous rule for group_private_addresses -->
|
||||
<record id="res_partner_rule_private_group" model="ir.rule">
|
||||
<field name="name">res.partner.rule.private.group</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="domain_force">
|
||||
[('type', '=', 'private')]
|
||||
</field>
|
||||
<field name="groups" eval="[
|
||||
Command.link(ref('base.group_private_addresses'))
|
||||
]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_unlink" eval="True"/>
|
||||
</record>
|
||||
|
||||
<!-- Restrict modifications on ir.filters to owner only -->
|
||||
<record id="ir_filters_admin_all_rights_rule" model="ir.rule">
|
||||
<field name="name">ir.filters.admin.all.rights</field>
|
||||
|
||||
@@ -339,14 +339,6 @@ ZeroDivisionError: division by zero""" % self.test_server_action.id
|
||||
self_demo.with_context(self.context).run()
|
||||
self.assertEqual(self.test_partner.date, date.today())
|
||||
|
||||
# but can not write on private address
|
||||
self.test_partner.type = "private"
|
||||
with self.assertRaises(AccessError):
|
||||
self.test_partner.with_user(user_demo.id).check_access_rule("write")
|
||||
# nor execute a server action on it
|
||||
with self.assertRaises(AccessError), mute_logger('odoo.addons.base.models.ir_actions'):
|
||||
self_demo.with_context(self.context).run()
|
||||
|
||||
|
||||
class TestCustomFields(common.TransactionCase):
|
||||
MODEL = 'res.partner'
|
||||
|
||||
@@ -309,9 +309,6 @@
|
||||
<p class="mb-0" attrs="{'invisible': [('type', '!=', 'delivery')]}">
|
||||
<span>Preferred address for all deliveries. Selected by default when you deliver an order that belongs to this company.</span>
|
||||
</p>
|
||||
<p class="mb-0" attrs="{'invisible': [('type', '!=', 'private')]}">
|
||||
<span>Private addresses are only visible by authorized users and contain sensitive data (employee home addresses, ...).</span>
|
||||
</p>
|
||||
<p class="mb-0" attrs="{'invisible': [('type', '!=', 'other')]}">
|
||||
<span>Other address for the company (e.g. subsidiary, ...)</span>
|
||||
</p>
|
||||
|
||||
@@ -1051,23 +1051,6 @@ class ModelChildNoCheck(models.Model):
|
||||
parent_id = fields.Many2one('test_new_api.model_parent', check_company=False)
|
||||
|
||||
|
||||
class ModelPrivateAddressOnchange(models.Model):
|
||||
_name = 'test_new_api.model_private_address_onchange'
|
||||
_description = 'Model Private Address Onchange'
|
||||
_check_company_auto = True
|
||||
|
||||
name = fields.Char()
|
||||
company_id = fields.Many2one('res.company', required=True)
|
||||
address_id = fields.Many2one('res.partner', check_company=True)
|
||||
|
||||
@api.onchange('name')
|
||||
def _onchange_name(self):
|
||||
if self.name and not self.address_id:
|
||||
self.address_id = self.env['res.partner'].sudo().create({
|
||||
'name': self.name,
|
||||
'type': 'private',
|
||||
})
|
||||
|
||||
# model with explicit and stored field 'display_name'
|
||||
class Display(models.Model):
|
||||
_name = 'test_new_api.display'
|
||||
|
||||
@@ -54,7 +54,6 @@ access_test_new_api_inverse_m2o_ref,access_test_new_api_inverse_m2o_ref,model_te
|
||||
access_test_new_api_model_binary,access_test_new_api_model_binary,model_test_new_api_model_binary,base.group_system,1,1,1,1
|
||||
access_test_new_api_model_child_m2o,access_test_new_api_model_child_m2o,model_test_new_api_model_child_m2o,base.group_system,1,1,1,1
|
||||
access_test_new_api_model_parent_m2o,access_test_new_api_model_parent_m2o,model_test_new_api_model_parent_m2o,base.group_system,1,1,1,1
|
||||
access_test_new_api_model_private_address_onchange,access_test_new_api_model_private_address_onchange,model_test_new_api_model_private_address_onchange,base.group_user,1,1,1,1
|
||||
access_test_new_api_partner,access_test_new_api_partner,test_new_api.model_test_new_api_partner,base.group_system,1,1,1,1
|
||||
access_test_new_api_req_m2o_transient,access_test_new_api_req_m2o_transient,model_test_new_api_req_m2o_transient,base.group_system,0,0,0,0
|
||||
access_test_new_api_country,access_test_new_api_country,model_test_new_api_country,base.group_user,1,1,1,1
|
||||
|
||||
|
@@ -176,25 +176,6 @@ class TestCompanyCheck(common.TransactionCase):
|
||||
[self.company_a.id, self.company_c.id],
|
||||
)
|
||||
|
||||
def test_company_check_no_access(self):
|
||||
""" Test that company_check validates correctly the companies on
|
||||
the different records, even if the use has no access to one of the
|
||||
records, example, a private address set by an onchange
|
||||
"""
|
||||
|
||||
user = self.env['res.users'].create({
|
||||
'name': 'My Classic User',
|
||||
'login': 'My Classic User',
|
||||
'groups_id': [Command.set(self.env.ref('base.group_user').ids)],
|
||||
})
|
||||
|
||||
with common.Form(self.env['test_new_api.model_private_address_onchange'].with_user(user)) as form:
|
||||
form.name = 'My Classic Name'
|
||||
form.company_id = self.env.user.company_id
|
||||
with self.assertRaises(AccessError):
|
||||
form.address_id.name
|
||||
form.save()
|
||||
|
||||
def test_company_sticky_with_context(self):
|
||||
context = frozendict({'nothing_to_see_here': True})
|
||||
companies_1 = frozendict({'allowed_company_ids': [1]})
|
||||
|
||||
Reference in New Issue
Block a user