[MERGE] from master
[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 api
24 from openerp import SUPERUSER_ID
25 from openerp.tools.translate import _
26 import openerp
27
28
29 class res_users(osv.Model):
30     """ Update of res.users class
31         - add a preference about sending emails about notifications
32         - make a new user follow itself
33         - add a welcome message
34         - add suggestion preference
35     """
36     _name = 'res.users'
37     _inherit = ['res.users']
38     _inherits = {'mail.alias': 'alias_id'}
39
40     _columns = {
41         'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="restrict", required=True,
42             help="Email address internally associated with this user. Incoming "\
43                  "emails will appear in the user's notifications.", copy=False, auto_join=True),
44         'display_groups_suggestions': fields.boolean("Display Groups Suggestions"),
45     }
46
47     _defaults = {
48         'display_groups_suggestions': True,
49     }
50
51     def __init__(self, pool, cr):
52         """ Override of __init__ to add access rights on notification_email_send
53             and alias fields. Access rights are disabled by default, but allowed
54             on some specific fields defined in self.SELF_{READ/WRITE}ABLE_FIELDS.
55         """
56         init_res = super(res_users, self).__init__(pool, cr)
57         # duplicate list to avoid modifying the original reference
58         self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
59         self.SELF_WRITEABLE_FIELDS.extend(['notify_email', 'display_groups_suggestions'])
60         # duplicate list to avoid modifying the original reference
61         self.SELF_READABLE_FIELDS = list(self.SELF_READABLE_FIELDS)
62         self.SELF_READABLE_FIELDS.extend(['notify_email', 'alias_domain', 'alias_name', 'display_groups_suggestions'])
63         return init_res
64
65     def _auto_init(self, cr, context=None):
66         """ Installation hook: aliases, partner following themselves """
67         # create aliases for all users and avoid constraint errors
68         return self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(res_users, self)._auto_init,
69             self._name, self._columns['alias_id'], 'login', alias_force_key='id', context=context)
70
71     def create(self, cr, uid, data, context=None):
72         if not data.get('login', False):
73             model, action_id = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'action_res_users')
74             msg = _("You cannot create a new user from here.\n To create new user please go to configuration panel.")
75             raise openerp.exceptions.RedirectWarning(msg, action_id, _('Go to the configuration panel'))
76         if context is None:
77             context = {}
78
79         create_context = dict(context, alias_model_name=self._name, alias_parent_model_name=self._name)
80         user_id = super(res_users, self).create(cr, uid, data, context=create_context)
81         user = self.browse(cr, uid, user_id, context=context)
82         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)
83
84         # create a welcome message
85         self._create_welcome_message(cr, uid, user, context=context)
86         return user_id
87
88     def copy_data(self, *args, **kwargs):
89         data = super(res_users, self).copy_data(*args, **kwargs)
90         if data and data.get('alias_name'):
91             data['alias_name'] = data['login']
92         return data
93
94     def _create_welcome_message(self, cr, uid, user, context=None):
95         if not self.has_group(cr, uid, 'base.group_user'):
96             return False
97         company_name = user.company_id.name if user.company_id else ''
98         body = _('%s has joined the %s network.') % (user.name, company_name)
99         # TODO change SUPERUSER_ID into user.id but catch errors
100         return self.pool.get('res.partner').message_post(cr, SUPERUSER_ID, [user.partner_id.id],
101             body=body, context=context)
102
103     def unlink(self, cr, uid, ids, context=None):
104         # Cascade-delete mail aliases as well, as they should not exist without the user.
105         alias_pool = self.pool.get('mail.alias')
106         alias_ids = [user.alias_id.id for user in self.browse(cr, uid, ids, context=context) if user.alias_id]
107         res = super(res_users, self).unlink(cr, uid, ids, context=context)
108         alias_pool.unlink(cr, uid, alias_ids, context=context)
109         return res
110
111     def _message_post_get_pid(self, cr, uid, thread_id, context=None):
112         assert thread_id, "res.users does not support posting global messages"
113         if context and 'thread_model' in context:
114             context['thread_model'] = 'res.users'
115         if isinstance(thread_id, (list, tuple)):
116             thread_id = thread_id[0]
117         return self.browse(cr, SUPERUSER_ID, thread_id).partner_id.id
118
119     @api.cr_uid_ids_context
120     def message_post(self, cr, uid, thread_id, context=None, **kwargs):
121         """ Redirect the posting of message on res.users as a private discussion.
122             This is done because when giving the context of Chatter on the
123             various mailboxes, we do not have access to the current partner_id. """
124         if isinstance(thread_id, (list, tuple)):
125             thread_id = thread_id[0]
126         current_pids = []
127         partner_ids = kwargs.get('partner_ids', [])
128         user_pid = self._message_post_get_pid(cr, uid, thread_id, context=context)
129         for partner_id in partner_ids:
130             if isinstance(partner_id, (list, tuple)) and partner_id[0] == 4 and len(partner_id) == 2:
131                 current_pids.append(partner_id[1])
132             elif isinstance(partner_id, (list, tuple)) and partner_id[0] == 6 and len(partner_id) == 3:
133                 current_pids.append(partner_id[2])
134             elif isinstance(partner_id, (int, long)):
135                 current_pids.append(partner_id)
136         if user_pid not in current_pids:
137             partner_ids.append(user_pid)
138         kwargs['partner_ids'] = partner_ids
139         if context and context.get('thread_model') == 'res.partner':
140             return self.pool['res.partner'].message_post(cr, uid, user_pid, **kwargs)
141         return self.pool['mail.thread'].message_post(cr, uid, uid, **kwargs)
142
143     def message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None):
144         return True
145
146     def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
147         return True
148
149     def message_get_partner_info_from_emails(self, cr, uid, emails, link_mail=False, context=None):
150         return self.pool.get('mail.thread').message_get_partner_info_from_emails(cr, uid, emails, link_mail=link_mail, context=context)
151
152     def message_get_suggested_recipients(self, cr, uid, ids, context=None):
153         return dict((res_id, list()) for res_id in ids)
154
155     def stop_showing_groups_suggestions(self, cr, uid, user_id, context=None):
156         """Update display_groups_suggestions value to False"""
157         if context is None:
158             context = {}
159         self.write(cr, uid, user_id, {"display_groups_suggestions": False}, context)
160
161
162 class res_users_mail_group(osv.Model):
163     """ Update of res.users class
164         - if adding groups to an user, check mail.groups linked to this user
165           group, and the user. This is done by overriding the write method.
166     """
167     _name = 'res.users'
168     _inherit = ['res.users']
169
170     # FP Note: to improve, post processing may be better ?
171     def write(self, cr, uid, ids, vals, context=None):
172         write_res = super(res_users_mail_group, self).write(cr, uid, ids, vals, context=context)
173         if vals.get('groups_id'):
174             # form: {'group_ids': [(3, 10), (3, 3), (4, 10), (4, 3)]} or {'group_ids': [(6, 0, [ids]}
175             user_group_ids = [command[1] for command in vals['groups_id'] if command[0] == 4]
176             user_group_ids += [id for command in vals['groups_id'] if command[0] == 6 for id in command[2]]
177             mail_group_obj = self.pool.get('mail.group')
178             mail_group_ids = mail_group_obj.search(cr, uid, [('group_ids', 'in', user_group_ids)], context=context)
179             mail_group_obj.message_subscribe_users(cr, uid, mail_group_ids, ids, context=context)
180         return write_res
181
182 class res_groups_mail_group(osv.Model):
183     """ Update of res.groups class
184         - if adding users from a group, check mail.groups linked to this user
185           group and subscribe them. This is done by overriding the write method.
186     """
187     _name = 'res.groups'
188     _inherit = 'res.groups'
189
190     # FP Note: to improve, post processeing, after the super may be better
191     def write(self, cr, uid, ids, vals, context=None):
192         write_res = super(res_groups_mail_group, self).write(cr, uid, ids, vals, context=context)
193         if vals.get('users'):
194             # form: {'group_ids': [(3, 10), (3, 3), (4, 10), (4, 3)]} or {'group_ids': [(6, 0, [ids]}
195             user_ids = [command[1] for command in vals['users'] if command[0] == 4]
196             user_ids += [id for command in vals['users'] if command[0] == 6 for id in command[2]]
197             mail_group_obj = self.pool.get('mail.group')
198             mail_group_ids = mail_group_obj.search(cr, uid, [('group_ids', 'in', ids)], context=context)
199             mail_group_obj.message_subscribe_users(cr, uid, mail_group_ids, user_ids, context=context)
200         return write_res