From b0f1086e1b2176c8ba23b9b151e788b319be0110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Lef=C3=A8vre?= Date: Tue, 17 Dec 2019 15:55:54 +0100 Subject: [PATCH] [REF] calendar: Hide event private fields Some fields of a calendar event are private. The previous implementation was deleted while refactoring recurring events. This commit cleanly re-implements the feature. Task 2126717 PR #42031 PR Enterprise odoo/enterprise#8006 --- addons/calendar/models/calendar_event.py | 56 ++++++++++++++++++++++++ addons/crm/models/crm_lead.py | 2 +- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/addons/calendar/models/calendar_event.py b/addons/calendar/models/calendar_event.py index 98d92296257..2d29ec18c61 100644 --- a/addons/calendar/models/calendar_event.py +++ b/addons/calendar/models/calendar_event.py @@ -117,6 +117,13 @@ class Meeting(models.Model): def _get_time_fields(self): return {'start', 'stop', 'start_date', 'stop_date', 'start_datetime', 'stop_datetime'} + @api.model + def _get_public_fields(self): + return self._get_recurrent_fields() | { + 'id', 'active', 'allday', 'start', 'stop', 'display_start', + 'display_stop', 'duration', 'user_id', 'state', 'interval', + 'count', 'rrule', 'recurrence_id', 'show_as'} + @api.model def _get_display_time(self, start, stop, zduration, zallday): """ Return date and time (from to from) based on duration with timezone in string. Eg : @@ -705,8 +712,57 @@ class Meeting(models.Model): self.env['calendar.alarm_manager']._notify_next_alarm(meeting.partner_ids.ids) return meeting + def read(self, fields=None, load='_classic_read'): + def hide(field, value): + """ + :param field: field name + :param value: field value + :return: obfuscated field value + """ + if field in {'name', 'display_name'}: + return _('Busy') + return [] if isinstance(value, list) else False + + def split_privacy(events): + """ + :param events: list of event values (dict) + :return: tuple(private events, public events) + """ + private = [event for event in events if event.get('privacy') == 'private'] + public = [event for event in events if event.get('privacy') != 'private'] + return private, public + + def my_events(events): + """ + :param events: list of event values (dict) + :return: tuple(my events, other events) + """ + my = [event for event in events if event.get('user_id') and event.get('user_id')[0] == self.env.uid] + others = [event for event in events if not event.get('user_id') or event.get('user_id')[0] != self.env.uid] + return my, others + + def obfuscated(events): + """ + :param events: list of event values (dict) + :return: events with private field values obfuscated + """ + public_fields = self._get_public_fields() + return [{ + field: hide(field, value) if field not in public_fields else value + for field, value in event.items() + } for event in events] + + events = super().read(fields=fields + ['privacy', 'user_id'], load=load) + private_events, public_events = split_privacy(events) + my_private_events, others_private_events = my_events(private_events) + + return public_events + my_private_events + obfuscated(others_private_events) + @api.model def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True): + private_fields = set(groupby) - self._get_public_fields() + if not self.env.su and private_fields: + raise UserError(_("Grouping by %s is not allowed." % ', '.join([self._fields[field_name].string for field_name in private_fields]))) if 'date' in groupby: raise UserError(_('Group by date is not supported, use the calendar view instead.')) return super(Meeting, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy) diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index f791d4be431..d71d4bf6ec3 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -293,7 +293,7 @@ class Lead(models.Model): lead.expected_revenue = round((lead.planned_revenue or 0.0) * (lead.probability or 0) / 100.0, 2) def _compute_meeting_count(self): - meeting_data = self.env['calendar.event'].read_group([('opportunity_id', 'in', self.ids)], ['opportunity_id'], ['opportunity_id']) + meeting_data = self.env['calendar.event'].sudo().read_group([('opportunity_id', 'in', self.ids)], ['opportunity_id'], ['opportunity_id']) mapped_data = {m['opportunity_id'][0]: m['opportunity_id_count'] for m in meeting_data} for lead in self: lead.meeting_count = mapped_data.get(lead.id, 0)