[MERGE] forward port of branch saas-4 up to 7ecaab9
[odoo/odoo.git] / addons / mail / res_users.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2009-Today OpenERP SA (<http://www.openerp.com>)
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>
19 #
20 ##############################################################################
21
22 from openerp.osv import fields, osv
23 from openerp import SUPERUSER_ID
24 from openerp.tools.translate import _
25
26
27 class res_users(osv.Model):
28     """ Update of res.users class
29         - add a preference about sending emails about notifications
30         - make a new user follow itself
31         - add a welcome message
32         - add suggestion preference
33     """
34     _name = 'res.users'
35     _inherit = ['res.users']
36     _inherits = {'mail.alias': 'alias_id'}
37
38     _columns = {
39         'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="restrict", required=True,
40             help="Email address internally associated with this user. Incoming "\
41                  "emails will appear in the user's notifications."),
42         'display_groups_suggestions': fields.boolean("Display Groups Suggestions"),
43     }
44
45     _defaults = {
46         'display_groups_suggestions': True,
47     }
48
49     def __init__(self, pool, cr):
50         """ Override of __init__ to add access rights on notification_email_send
51             and alias fields. Access rights are disabled by default, but allowed
52             on some specific fields defined in self.SELF_{READ/WRITE}ABLE_FIELDS.
53         """
54         init_res = super(res_users, self).__init__(pool, cr)
55         # duplicate list to avoid modifying the original reference
56         self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
57         self.SELF_WRITEABLE_FIELDS.extend(['notify_email', 'display_groups_suggestions'])
58         # duplicate list to avoid modifying the original reference
59         self.SELF_READABLE_FIELDS = list(self.SELF_READABLE_FIELDS)
60         self.SELF_READABLE_FIELDS.extend(['notify_email', 'alias_domain', 'alias_name', 'display_groups_suggestions'])
61         return init_res
62
63     def _auto_init(self, cr, context=None):
64         """ Installation hook: aliases, partner following themselves """
65         # create aliases for all users and avoid constraint errors
66         return self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(res_users, self)._auto_init,
67             self._name, self._columns['alias_id'], 'login', alias_force_key='id', context=context)
68
69     def create(self, cr, uid, data, context=None):
70         if not data.get('login', False):
71             raise osv.except_osv(_('Invalid Action!'), _('You may not create a user. To create new users, you should use the "Settings > Users" menu.'))
72         if context is None:
73             context = {}
74
75         create_context = dict(context, alias_model_name=self._name, alias_parent_model_name=self._name)
76         user_id = super(res_users, self).create(cr, uid, data, context=create_context)
77         user = self.browse(cr, uid, user_id, context=context)
78         self.pool.get('mail.alias').write(cr, SUPERUSER_ID, [user.alias_id.id], {"alias_force_thread_id": user_id, "alias_parent_thread_id": user_id}, context)
79
80         # create a welcome message
81         self._create_welcome_message(cr, uid, user, context=context)
82         return user_id
83
84     def copy_data(self, *args, **kwargs):
85         data = super(res_users, self).copy_data(*args, **kwargs)
86         if data and data.get('alias_name'):
87             data['alias_name'] = data['login']
88         return data
89
90     def _create_welcome_message(self, cr, uid, user, context=None):
91         if not self.has_group(cr, uid, 'base.group_user'):
92             return False
93         company_name = user.company_id.name if user.company_id else ''
94         body = _('%s has joined the %s network.') % (user.name, company_name)
95         # TODO change SUPERUSER_ID into user.id but catch errors
96         return self.pool.get('res.partner').message_post(cr, SUPERUSER_ID, [user.partner_id.id],
97             body=body, context=context)
98
99     def unlink(self, cr, uid, ids, context=None):
100         # Cascade-delete mail aliases as well, as they should not exist without the user.
101         alias_pool = self.pool.get('mail.alias')
102         alias_ids = [user.alias_id.id for user in self.browse(cr, uid, ids, context=context) if user.alias_id]
103         res = super(res_users, self).unlink(cr, uid, ids, context=context)
104         alias_pool.unlink(cr, uid, alias_ids, context=context)
105         return res
106
107     def _message_post_get_pid(self, cr, uid, thread_id, context=None):
108         assert thread_id, "res.users does not support posting global messages"
109         if context and 'thread_model' in context:
110             context['thread_model'] = 'res.users'
111         if isinstance(thread_id, (list, tuple)):
112             thread_id = thread_id[0]
113         return self.browse(cr, SUPERUSER_ID, thread_id).partner_id.id
114
115     def message_post(self, cr, uid, thread_id, context=None, **kwargs):
116         """ Redirect the posting of message on res.users to the related partner.
117             This is done because when giving the context of Chatter on the
118             various mailboxes, we do not have access to the current partner_id. """
119         if isinstance(thread_id, (list, tuple)):
120             thread_id = thread_id[0]
121         current_pids = []
122         partner_ids = kwargs.get('partner_ids', [])
123         user_pid = self._message_post_get_pid(cr, uid, thread_id, context=context)
124         for partner_id in partner_ids:
125             if isinstance(partner_id, (list, tuple)) and partner_id[0] == 4 and len(partner_id) == 2:
126                 current_pids.append(partner_id[1])
127             elif isinstance(partner_id, (list, tuple)) and partner_id[0] == 6 and len(partner_id) == 3:
128                 current_pids.append(partner_id[2])
129             elif isinstance(partner_id, (int, long)):
130                 current_pids.append(partner_id)
131         if user_pid not in current_pids:
132             partner_ids.append(user_pid)
133         kwargs['partner_ids'] = partner_ids
134         return self.pool.get('mail.thread').message_post(cr, uid, False, **kwargs)
135
136     def message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None):
137         return True
138
139     def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
140         return True
141
142     def message_get_partner_info_from_emails(self, cr, uid, emails, link_mail=False, context=None):
143         return self.pool.get('mail.thread').message_get_partner_info_from_emails(cr, uid, emails, link_mail=link_mail, context=context)
144
145     def message_get_suggested_recipients(self, cr, uid, ids, context=None):
146         return dict.fromkeys(ids, list())
147
148     def stop_showing_groups_suggestions(self, cr, uid, user_id, context=None):
149         """Update display_groups_suggestions value to False"""
150         if context is None:
151             context = {}
152         self.write(cr, uid, user_id, {"display_groups_suggestions": False}, context)
153
154
155 class res_users_mail_group(osv.Model):
156     """ Update of res.users class
157         - if adding groups to an user, check mail.groups linked to this user
158           group, and the user. This is done by overriding the write method.
159     """
160     _name = 'res.users'
161     _inherit = ['res.users']
162
163     # FP Note: to improve, post processing may be better ?
164     def write(self, cr, uid, ids, vals, context=None):
165         write_res = super(res_users_mail_group, self).write(cr, uid, ids, vals, context=context)
166         if vals.get('groups_id'):
167             # form: {'group_ids': [(3, 10), (3, 3), (4, 10), (4, 3)]} or {'group_ids': [(6, 0, [ids]}
168             user_group_ids = [command[1] for command in vals['groups_id'] if command[0] == 4]
169             user_group_ids += [id for command in vals['groups_id'] if command[0] == 6 for id in command[2]]
170             mail_group_obj = self.pool.get('mail.group')
171             mail_group_ids = mail_group_obj.search(cr, uid, [('group_ids', 'in', user_group_ids)], context=context)
172             mail_group_obj.message_subscribe_users(cr, uid, mail_group_ids, ids, context=context)
173         return write_res
174
175 class res_groups_mail_group(osv.Model):
176     """ Update of res.groups class
177         - if adding users from a group, check mail.groups linked to this user
178           group and subscribe them. This is done by overriding the write method.
179     """
180     _name = 'res.groups'
181     _inherit = 'res.groups'
182
183     # FP Note: to improve, post processeing, after the super may be better
184     def write(self, cr, uid, ids, vals, context=None):
185         write_res = super(res_groups_mail_group, self).write(cr, uid, ids, vals, context=context)
186         if vals.get('users'):
187             # form: {'group_ids': [(3, 10), (3, 3), (4, 10), (4, 3)]} or {'group_ids': [(6, 0, [ids]}
188             user_ids = [command[1] for command in vals['users'] if command[0] == 4]
189             user_ids += [id for command in vals['users'] if command[0] == 6 for id in command[2]]
190             mail_group_obj = self.pool.get('mail.group')
191             mail_group_ids = mail_group_obj.search(cr, uid, [('group_ids', 'in', ids)], context=context)
192             mail_group_obj.message_subscribe_users(cr, uid, mail_group_ids, user_ids, context=context)
193         return write_res