1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
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.
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.
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/>.
20 ##############################################################################
21 from osv import osv, fields
22 from tools.translate import _
25 def _generate_random_number():
27 RANDOM_PASS_CHARACTERS = [chr(x) for x in range(48,58) + range(97,123) + range(65,91)]
28 RANDOM_PASS_CHARACTERS.remove('l') #lowercase l, easily mistaken as one or capital i
29 RANDOM_PASS_CHARACTERS.remove('I') #uppercase i, easily mistaken as one or lowercase l
30 RANDOM_PASS_CHARACTERS.remove('O') #uppercase o, mistaken with zero
31 RANDOM_PASS_CHARACTERS.remove('o') #lowercase o, mistaken with zero
32 RANDOM_PASS_CHARACTERS.remove('0') #zero, mistaken with o-letter
33 def generate_random_pass():
34 pass_chars = RANDOM_PASS_CHARACTERS[:]
35 random.shuffle(pass_chars)
36 return ''.join(pass_chars[0:10])
37 return generate_random_pass()
39 class share_create(osv.osv_memory):
40 _name = 'share.create'
41 _description = 'Create share'
43 def _access(self, cr, uid, ids, field_name, arg, context=None):
47 action_id = context.get('action_id', False)
48 access_obj = self.pool.get('ir.model.access')
49 action_obj = self.pool.get('ir.actions.act_window')
50 model_obj = self.pool.get('ir.model')
51 user_obj = self.pool.get('res.users')
52 current_user = user_obj.browse(cr, uid, uid)
55 action = action_obj.browse(cr, uid, action_id, context=context)
56 active_model_ids = model_obj.search(cr, uid, [('model','=',action.res_model)])
57 active_model_id = active_model_ids and active_model_ids[0] or False
58 access_ids = access_obj.search(cr, uid, [
59 ('group_id','in',map(lambda x:x.id, current_user.groups_id)),
60 ('model_id','',active_model_id)])
64 for access in access_obj.browse(cr, uid, access_ids, context=context):
69 res[rec_id]['write_access'] = write_access
70 res[rec_id]['read_access'] = read_access
74 'action_id': fields.many2one('ir.actions.act_window', 'Action', required=True),
75 'domain': fields.char('Domain', size=64),
76 'user_type': fields.selection( [ ('existing','Existing'),('new','New')],'User Type'),
77 'user_ids': fields.many2many('res.users', 'share_user_rel', 'share_id','user_id', 'Share Users'),
78 'new_user': fields.text("New user"),
79 'access_mode': fields.selection([('readwrite','READ & WRITE'),('readonly','READ ONLY')],'Access Mode'),
80 'write_access': fields.function(_access, method=True, string='Write Access',type='boolean', multi='write_access'),
81 'read_access': fields.function(_access, method=True, string='Write Access',type='boolean', multi='read_access'),
84 'user_type' : 'existing',
86 'access_mode': 'readonly'
90 def default_get(self, cr, uid, fields, context=None):
92 To get default values for the object.
95 res = super(share_create, self).default_get(cr, uid, fields, context=context)
98 action_id = context.get('action_id', False)
99 domain = context.get('domain', '[]')
102 if 'action_id' in fields:
103 res['action_id'] = action_id
104 if 'domain' in fields:
105 res['domain'] = domain
108 def do_step_1(self, cr, uid, ids, context=None):
110 This action to excute step 1
116 data_obj = self.pool.get('ir.model.data')
118 step1_form_view = data_obj._get_id(cr, uid, 'share', 'share_step1_form')
121 step1_form_view_id = data_obj.browse(cr, uid, step1_form_view, context=context).res_id
124 for this in self.browse(cr, uid, ids, context=context):
126 'domain': this.domain,
127 'action_id': this.action_id and this.action_id.id or False,
133 'name': _('Step:2 Sharing Wizard'),
136 'res_model': 'share.create',
139 'views': [(step1_form_view_id, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')],
140 'type': 'ir.actions.act_window',
147 def do_step_2(self, cr, uid, ids, context=None):
149 This action to excute step 2
155 data_obj = self.pool.get('ir.model.data')
157 step2_form_view = data_obj._get_id(cr, uid, 'share', 'share_step2_form')
160 step2_form_view_id = data_obj.browse(cr, uid, step2_form_view, context=context).res_id
163 for this in self.browse(cr, uid, ids, context=context):
165 'user_type': this.user_type,
166 'existing_user_ids': map(lambda x:x.id, this.user_ids),
167 'new_user': this.new_user,
172 'name': _('Step:3 Sharing Wizard'),
175 'res_model': 'share.create',
177 'views': [(step2_form_view_id, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')],
178 'type': 'ir.actions.act_window',
185 def do_step_3(self, cr, uid, ids, context=None):
187 This action to excute step 3
193 for this in self.browse(cr, uid, ids, context=context):
195 'access_mode': this.access_mode,
200 group_obj = self.pool.get('res.groups')
201 user_obj = self.pool.get('res.users')
202 fields_obj = self.pool.get('ir.model.fields')
203 model_access_obj = self.pool.get('ir.model.access')
204 model_obj = self.pool.get('ir.model')
205 rule_obj = self.pool.get('ir.rule')
206 action_obj = self.pool.get('ir.actions.act_window')
208 new_users = context.get('new_user', False)
209 action_id = context.get('action_id', False)
210 user_type = context.get('user_type', False)
211 access_mode = context.get('access_mode', False)
212 action = action_obj.browse(cr, uid, action_id, context=context)
213 active_model = action.res_model
215 active_id = False #TODO: Pass record id of res_model of action
216 existing_user_ids = context.get('existing_user_ids', False)
217 domain = eval(context.get('domain', '[]'))
220 share_group_name = '%s: %s' %('Sharing', active_model)
221 group_ids = group_obj.search(cr, uid, [('name','=',share_group_name)])
222 group_id = group_ids and group_ids[0] or False
224 group_id = group_obj.create(cr, uid, {'name': share_group_name, 'share': True})
226 group = group_obj.browse(cr, uid, group_id, context=context)
228 raise osv.except_osv(_('Error'), _("Share Group is exits without sharing !"))
232 current_user = user_obj.browse(cr, uid, uid)
234 if user_type == 'new' and new_users:
235 for new_user in new_users.split('\n'):
236 password = _generate_random_number()
237 user_id = user_obj.create(cr, uid, {
239 'password': password,
241 'user_email': new_user,
242 'groups_id': [(6,0,[group_id])],
243 'action_id': action_id,
245 'company_id': current_user.company_id and current_user.company_id.id})
246 user_ids.append(user_id)
247 context['new_user_ids'] = user_ids
249 # Modify existing user
250 if user_type == 'existing':
251 user_obj.write(cr, uid, existing_user_ids , {
252 'groups_id': [(4,group_id)],
253 'action_id': action_id
257 #ACCESS RIGHTS / IR.RULES COMPUTATION
259 active_model_ids = model_obj.search(cr, uid, [('model','=',active_model)])
260 active_model_id = active_model_ids and active_model_ids[0] or False
262 def _get_relation(model_id, ttypes, new_obj=[]):
264 models = map(lambda x:x[1].model, new_obj)
265 field_ids = fields_obj.search(cr, uid, [('model_id','=',model_id),('ttype','in', ttypes)])
266 for field in fields_obj.browse(cr, uid, field_ids, context=context):
267 if field.relation not in models:
268 relation_model_ids = model_obj.search(cr, uid, [('model','=',field.relation)])
269 relation_model_id = relation_model_ids and relation_model_ids[0] or False
270 relation_model = model_obj.browse(cr, uid, relation_model_id, context=context)
271 obj.append((field.relation_field, relation_model))
273 if relation_model_id != model_id and field.ttype in ['one2many', 'many2many']:
274 obj += _get_relation(relation_model_id, [field.ttype], obj)
278 active_model = model_obj.browse(cr, uid, active_model_id, context=context)
279 obj0 = [(None, active_model)]
280 obj1 = _get_relation(active_model_id, ['one2many'])
281 obj2 = _get_relation(active_model_id, ['one2many', 'many2many'])
282 obj3 = _get_relation(active_model_id, ['many2one'])
283 for rel_field, model in obj1:
284 obj3 += _get_relation(model.id, ['many2one'])
286 current_user = user_obj.browse(cr, uid, uid, context=context)
287 if access_mode == 'readonly':
289 # intersect with read access rights of user running the
290 # wizard, to avoid adding more access than current
291 for group in current_user.groups_id:
292 for access_control in group.model_access:
293 if access_control.model_id.id in res:
295 if access_control.perm_read:
296 res.append(access_control.model_id.id)
297 model_access_obj.create(cr, uid, {
298 'name': 'Read Access of group %s on %s model'%(share_group_name, access_control.model_id.name),
299 'model_id' : access_control.model_id.id,
300 'group_id' : group_id,
304 for rel_field, model in obj0+obj1+obj2+obj3:
308 model_access_obj.create(cr, uid, {
309 'name': 'Read Access of group %s on %s model'%(share_group_name, model.name),
310 'model_id' : model.id,
311 'group_id' : group_id,
314 if access_mode == 'readwrite':
316 for rel_field, model in obj0+obj1:
320 model_access_obj.create(cr, uid, {
321 'name': 'Write Access of group %s on %s model'%(share_group_name, model.name),
322 'model_id' : model.id,
323 'group_id' : group_id,
326 'perm_unlink' : True,
327 'perm_create' : True,
329 # intersect with access rights of user
330 # running the wizard, to avoid adding more access than current
332 for group in current_user.groups_id:
333 for access_control in group.model_access:
334 if access_control.model_id.id in res:
336 if access_control.perm_read:
337 res.append(access_control.model_id.id)
338 model_access_obj.create(cr, uid, {
339 'name': 'Read Access of group %s on %s model'%(share_group_name, access_control.model_id.name),
340 'model_id' : access_control.model_id.id,
341 'group_id' : group_id,
344 for rel_field, model in obj2+obj3:
348 model_access_obj.create(cr, uid, {
349 'name': 'Read Access of group %s on %s model'%(share_group_name, model.name),
350 'model_id' : model.id,
351 'group_id' : group_id,
355 # And on OBJ0, OBJ1, OBJ2, OBJ3: add all rules from groups of the user
356 # that is sharing in the many2many of the rules on the new group
357 # (rule must be copied instead of adding it if it contains a reference to uid
358 # or user.xxx so it can be replaced correctly)
360 for group in current_user.groups_id:
362 for rel_field, model in obj0+obj1+obj2+obj3:
366 for rule in group.rule_groups:
367 if rule.model_id == model.id:
368 rule_obj.copy(cr, uid, rule.id, default={
369 'name': '%s-%s'%(share_group_name, model.model),
370 'groups': [(6,0,[group_id])]}, context=context)
372 rule_obj.create(cr, uid, {
373 'name': '%s-%s'%(share_group_name, active_model.model),
374 'model_id': active_model.id,
375 'domain_force': domain,
376 'groups': [(6,0,[group_id])]
378 for rel_field, model in obj1:
380 for opr1, opt, opr2 in domain:
381 new_opr1 = '%s.%s'%(rel_field, opr1)
382 obj1_domain.append((new_opr1, opt, opr2))
384 rule_obj.create(cr, uid, {
385 'name': '%s-%s'%(share_group_name, model.model),
386 'model_id': model.id,
387 'domain_force': obj1_domain,
388 'groups': [(6,0,[group_id])]
390 context['share_model'] = active_model.model
391 context['share_rec_id'] = active_id
394 data_obj = self.pool.get('ir.model.data')
396 form_view = data_obj._get_id(cr, uid, 'share', 'share_result_form')
399 form_view_id = data_obj.browse(cr, uid, form_view, context=context).res_id
403 'name': _('Step:4 Share Users Detail'),
406 'res_model': 'share.result',
408 'views': [(form_view_id, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')],
409 'type': 'ir.actions.act_window',
417 class share_result(osv.osv_memory):
418 _name = "share.result"
420 'users': fields.text("Users", readonly=True),
425 def do_send_email(self, cr, uid, ids, context=None):
426 user_obj = self.pool.get('res.users')
429 existing_user_ids = context.get('existing_user_ids', [])
430 new_user_ids = context.get('new_user_ids', [])
431 share_url = tools.config.get('share_root_url', False)
432 user = user_obj.browse(cr, uid, uid, context=context)
433 for share_user in user_obj.browse(cr, uid, new_user_ids+existing_user_ids, context=context):
434 email_to = share_user.user_email
435 subject = '%s wants to share private data with you' %(user.name)
439 %s wants to share private data from OpenERP with you!
443 To view it, you can access the following URL:
445 """%(user.name, share_url)
446 if share_user.id in new_user_ids:
448 You may use the following login and password to get access to this
452 """%(user.login, user.password)
453 elif share_user.id in existing_user_ids:
455 You may use your existing login and password to get access to this
456 additional data. As a reminder, your login is %s.
459 flag = tools.email_send(
468 def default_get(self, cr, uid, fields, context=None):
470 To get default values for the object.
473 res = super(share_result, self).default_get(cr, uid, fields, context=context)
474 user_obj = self.pool.get('res.users')
477 existing_user_ids = context.get('existing_user_ids', [])
478 new_user_ids = context.get('new_user_ids', [])
479 share_url = tools.config.get('share_root_url', False)
480 if 'users' in fields:
482 for user in user_obj.browse(cr, uid, new_user_ids):
483 txt = 'Login: %s Password: %s' %(user.login, user.password)
485 txt += ' Share URL: %s' %(share_url)
487 for user in user_obj.browse(cr, uid, existing_user_ids):
488 txt = 'Login: %s' %(user.login)
490 txt += ' Share URL: %s' %(share_url)
492 res['users'] = '\n'.join(users)