diff options
| author | Harry (Open ERP) <hmo@tinyerp.com> | 2010-05-31 21:20:04 +0530 |
|---|---|---|
| committer | Harry (Open ERP) <hmo@tinyerp.com> | 2010-05-31 21:20:04 +0530 |
| commit | d9b0ffb2e14c02b3e797232c4d4a7ac0039405ca (patch) | |
| tree | 615ec70cd2fc4006afb0018e2caae91db78ee12c /bin | |
| parent | 1929575d8ed1933b61f3e07b8f7d19e5441fcac4 (diff) | |
[REC] base: share_wizard
bzr revid: hmo@tinyerp.com-20100531155004-ol4rgnt9unfb9ade
Diffstat (limited to 'bin')
| -rw-r--r-- | bin/addons/base/base_update.xml | 5 | ||||
| -rw-r--r-- | bin/addons/base/res/partner/wizard/wizard_share.py | 466 | ||||
| -rw-r--r-- | bin/addons/base/res/partner/wizard/wizard_share_view.xml | 111 | ||||
| -rw-r--r-- | bin/addons/base/res/res_user.py | 2 |
4 files changed, 551 insertions, 33 deletions
diff --git a/bin/addons/base/base_update.xml b/bin/addons/base/base_update.xml index 185be1eabdb..319c8a8d0d6 100644 --- a/bin/addons/base/base_update.xml +++ b/bin/addons/base/base_update.xml @@ -19,7 +19,8 @@ <field name="type">form</field> <field name="arch" type="xml"> <form string="Groups"> - <field colspan="4" name="name" select="1"/> + <field name="name" select="1"/> + <field name="share_group"/> <notebook colspan="4"> <page string="Users"> <field colspan="4" name="users" nolabel="1"/> @@ -106,6 +107,8 @@ <field name="active"/> <field name="login" select="1"/> <field name="password" password="True"/> + <field name="share_user"/> + <newline/> <notebook colspan="4"> <page string="User"> <field name="address_id" select="1"/> diff --git a/bin/addons/base/res/partner/wizard/wizard_share.py b/bin/addons/base/res/partner/wizard/wizard_share.py index 573a1faa287..4e5f33295b7 100644 --- a/bin/addons/base/res/partner/wizard/wizard_share.py +++ b/bin/addons/base/res/partner/wizard/wizard_share.py @@ -2,29 +2,471 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved -# $Id$ +# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## from osv import osv, fields +from tools.translate import _ +import tools -class partner_share_create(osv.osv_memory): - _name = 'partner.share.create' - _description = 'Create parner share' +def _generate_random_number(): + import random + RANDOM_PASS_CHARACTERS = [chr(x) for x in range(48,58) + range(97,123) + range(65,91)] + RANDOM_PASS_CHARACTERS.remove('l') #lowercase l, easily mistaken as one or capital i + RANDOM_PASS_CHARACTERS.remove('I') #uppercase i, easily mistaken as one or lowercase l + RANDOM_PASS_CHARACTERS.remove('O') #uppercase o, mistaken with zero + RANDOM_PASS_CHARACTERS.remove('o') #lowercase o, mistaken with zero + RANDOM_PASS_CHARACTERS.remove('0') #zero, mistaken with o-letter + def generate_random_pass(): + pass_chars = RANDOM_PASS_CHARACTERS[:] + random.shuffle(pass_chars) + return ''.join(pass_chars[0:10]) + +class share_create(osv.osv_memory): + _name = 'share.create' + _description = 'Create share' _columns = { - 'user_ids': fields.many2many('res.users', 'share_patner_rel', 'partner_id','user_id', 'Share Users'), + 'action_id': fields.many2one('ir.actions.actions', 'Home Action'), + 'domain': fields.char('Domain', size=64), + 'user_type': fields.selection( [ ('existing','Existing'),('new','New')],'User Type'), + 'user_ids': fields.many2many('res.users', 'share_user_rel', 'share_id','user_id', 'Share Users'), + 'new_user': fields.text("New user"), + 'access_mode': fields.selection( [ ('readonly','READ ONLY'),('readwrite','READ & WRITE')],'Access Mode'), + } + _defaults = { + 'user_type' : 'existing' } -partner_share_create()
\ No newline at end of file + + + + def do_step_1(self, cr, uid, ids, context=None): + """ + This action to excute step 1 + + """ + if not context: + context = {} + + data_obj = self.pool.get('ir.model.data') + + step1_form_view = data_obj._get_id(cr, uid, 'base', 'share_step1_form') + + if step1_form_view: + step1_form_view_id = data_obj.browse(cr, uid, step1_form_view, context=context).res_id + + step1_id = False + for this in self.browse(cr, uid, ids, context=context): + vals ={ + 'domain': this.domain, + 'action_id': this.action_id and this.action_id.id or False, + } + + context.update(vals) + value = { + 'name': _('Step:2 Sharing Wizard'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'share.create', + 'view_id': False, + 'views': [(step1_form_view_id, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')], + 'type': 'ir.actions.act_window', + 'context': context, + 'target': 'new' + } + return value + + + def do_step_2(self, cr, uid, ids, context=None): + """ + This action to excute step 2 + + """ + if not context: + context = {} + + data_obj = self.pool.get('ir.model.data') + + step2_form_view = data_obj._get_id(cr, uid, 'base', 'share_step2_form') + + if step2_form_view: + step2_form_view_id = data_obj.browse(cr, uid, step2_form_view, context=context).res_id + + step1_id = False + for this in self.browse(cr, uid, ids, context=context): + vals ={ + 'user_type': this.user_type, + 'existing_user_ids': map(lambda x:x.id, this.user_ids), + 'new_user': this.new_user + } + + context.update(vals) + value = { + 'name': _('Step:3 Sharing Wizard'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'share.create', + 'view_id': False, + 'views': [(step2_form_view_id, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')], + 'type': 'ir.actions.act_window', + 'context': context, + 'target': 'new' + } + return value + + + def do_step_3(self, cr, uid, ids, context=None): + """ + This action to excute step 3 + + """ + if not context: + context = {} + + group_obj = self.pool.get('res.groups') + user_obj = self.pool.get('res.users') + fields_obj = self.pool.get('ir.model.fields') + model_access_obj = self.pool.get('ir.model.access') + model_obj = self.pool.get('ir.model') + rule_obj = self.pool.get('ir.rule') + + new_users = context.get('new_user', False) + action_id = context.get('action_id', False) + user_type = context.get('user_type', False) + access_mode = context.get('access_mode', False) + active_model = context.get('active_model', False) + active_id = context.get('active_id', False) + existing_user_ids = context.get('existing_user_ids', False) + + # Create Share Group + share_group_name = '%s:[%d]%s' %(_('Sharing'), active_id, active_model) + group_id = group_obj.create(cr, uid, {'name': share_group_name, 'share_group': True}) + + # Create new user + current_user = user_obj.browse(cr, uid, uid) + user_ids = [] + if user_type == 'new' and new_users: + for new_user in new_users.split('\n'): + user_id = user_obj.create(cr, uid, { + 'login': new_user, + 'password': _generate_random_number(), + 'name': new_user, + 'user_email': new_user, + 'groups_id': [(6,0,[group_id])], + 'action_id': action_id, + 'company_id': current_user.company_id and current_user.company_id.id}) + user_ids.append(user_id) + context['new_user_ids'] = user_ids + + # Modify existing user + if user_type == 'existing': + user_obj.write(cr, uid, existing_user_ids , { + 'groups_id': [(4,group_id)], + 'action_id': action_id + }) + + + #ACCESS RIGHTS / IR.RULES COMPUTATION + #TODO: TO Resolve Recurrent Problems + active_model_ids = model_obj.search(cr, uid, [('model','=',active_model)]) + active_model_id = active_model_ids and active_model_ids[0] or False + obj0 = model_obj.browse(cr, uid, active_model_id, context=context) + def _get_relation(model, ttypes): + obj = [] + field_ids = fields_obj.search(cr, uid, [('model','=',model),('ttype','in', ttypes)]) + for field in fields_obj.browse(cr, uid, field_ids, context=context): + for ttype in ttypes: + if ttype in ('one2many', 'many2many'): + obj += _get_relation(field.relation, [ttype]) + if field.model_id.model != active_model and field.model_id.id not in obj: + obj.append((field.relation_field, field.model_id)) + return obj + + obj1 = _get_relation(active_model, ['one2many']) + obj2 = _get_relation(active_model, ['one2many', 'many2many']) + obj3 = _get_relation(active_model, ['many2one']) + for rel_field, model in obj1: + obj3 += _get_relation(model.model, ['many2one']) + + if access_mode == 'readonly': + for rel_field, model in obj1+obj2: + model_access_obj.create(cr, uid, { + 'name': 'Read Access of group %s on %s model'%(share_group_name, model.name), + 'model_id' : model.id, + 'group_id' : group_id, + 'perm_read' : True + }) + if access_mode == 'readwrite': + for rel_field, model in obj1: + model_access_obj.create(cr, uid, { + 'name': 'Read Access of group %s on %s model'%(share_group_name, model.name), + 'model_id' : model.id, + 'group_id' : group_id, + 'perm_read' : True, + 'perm_write' : True + }) + for rel_field, model in obj2+obj3: + model_access_obj.create(cr, uid, { + 'name': 'Read Access of group %s on %s model'%(share_group_name, model.name), + 'model_id' : model.id, + 'group_id' : group_id, + 'perm_read' : True + }) + + rule_obj.create(cr, uid, { + 'name': '%s-%s'%(group_name, obj0.model), + 'model_id': obj0.id, + 'domain': domain, + 'group_ids': [(6,0,[group_id])] + }) + for rel_field, model in obj1: + obj1_domain = [] + for opr1, opt, opr2 in domain: + new_opr1 = '%s.%s'%(rel_field, opr1) + obj1_domain.append((new_opr1, opt, opr2)) + + rule_obj.create(cr, uid, { + 'name': '%s-%s'%(group_name, model.model), + 'model_id': model.id, + 'domain': obj1_domain, + 'group_ids': [(6,0,[group_id])] + }) + # TODO: + # And on OBJ0, OBJ1, OBJ2, OBJ3: add all rules from groups of the user + # that is sharing in the many2many of the rules on the new group + # (rule must be copied instead of adding it if it contains a reference to uid + # or user.xxx so it can be replaced correctly) + value = { + 'name': _('Step:4 Sharing Wizard'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'share.result', + 'view_id': False, + 'views': [(False, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')], + 'type': 'ir.actions.act_window', + 'context': context, + 'target': 'new' + } + return value +share_create() + + +class share_result(osv.osv_memory): + _name = "share.result" + _columns = { + } + + def view_init(self, cr, uid, fields_list, context=None): + res = super(share_result, self).view_init(cr, uid, fields_list, context=context) + user_obj = self.pool.get('res.users') + if not context: + context={} + moveids = [] + user_ids = context.get('existing_user_ids', []) + context.get('new_user_ids', []) + for user in user_obj.browse(cr, uid, user_ids): + if 'user%s_login'%(user.id) not in self._columns: + self._columns['user%s_log_id'%(user.id)] = fields.char('Login', size=64) + if 'user%s_password'%(user.id) not in self._columns: + self._columns['user%s_password'%(user.id)] = fields.char('Password', size=64) + if 'user%s_url'%(user.id) not in self._columns: + self._columns['user%s_url'%(user.id)] = fields.char('URL', size=64) + return res + + def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False): + result = super(share_result, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu) + user_obj = self.pool.get('res.users') + data_obj = self.pool.get('ir.model.data') + existing_user_ids = context.get('existing_user_ids', []) + new_user_ids = context.get('new_user_ids', []) + _arch_lst = """<form string="Share Users"> + <separator colspan="4" string="Step 4: Share User Details"/> + """ + _fields = result['fields'] + + + send_email_act = data_obj._get_id(cr, uid, 'base', 'share_email_act') + + + send_email_act_id = data_obj.browse(cr, uid, send_email_act, context=context).res_id + + if new_user_ids and view_type in ['form']: + for user in user_obj.browse(cr, uid, new_user_ids, context): + _fields.update({ + 'user%s_login'%(user.id) : { + 'string': _('Login'), + 'type' : 'char', + 'size': '64', + 'readonly' : True, + }, + 'user%s_password'%(user.id) : { + 'string': _('Password'), + 'type' : 'char', + 'readonly': True, + }, + 'user%s_url'%(user.id) : { + 'string': _('URL'), + 'type' : 'char', + 'readonly' : True, + } + }) + + _arch_lst += """ + <group colspan="4" col="10"> + <field name="user%s_login"/> + <field name="user%s_password"/> + <field name="user%s_url" widget="url" /> + <button name="%s" string="send_email" type="action" icon="gtk-apply" context="{'user_id':%s, 'user_type':'new', 'share_url': user%s_url}"/> + """%(user.id, user.id, user.id, send_email_act_id, user.id, user.id) + + _arch_lst += """ + </group>""" + + if existing_user_ids and view_type in ['form']: + for user in user_obj.browse(cr, uid, existing_user_ids, context): + _fields.update({ + 'user%s_login'%(user.id) : { + 'string': _('Login'), + 'type' : 'char', + 'size': '64', + 'readonly' : True, + }, + 'user%s_url'%(user.id) : { + 'string': _('URL'), + 'type' : 'char', + 'readonly' : True, + } + }) + + _arch_lst += """ + <group colspan="4" col="10"> + <field name="user%s_login" /> + <field name="user%s_url" widget="url" /> + <button name="%s" string="send_email" type="action" icon="gtk-apply" context="{'user_id':%s, 'user_type':'existing', 'share_url': user%s_url}"/> + """%(user.id, user.id, user.id, send_email_act_id, user.id, user.id) + + _arch_lst += """ + </group>""" + _arch_lst += """ + </form>""" + result['arch'] = _arch_lst + result['fields'] = _fields + return result + + def default_get(self, cr, uid, fields, context=None): + """ + To get default values for the object. + + @param self: The object pointer. + @param cr: A database cursor + @param uid: ID of the user currently logged in + @param fields: List of fields for which we want default values + @param context: A standard dictionary + + @return: A dictionary which of fields with values. + + """ + + res = super(share_result, self).default_get(cr, uid, fields, context=context) + user_obj = self.pool.get('res.users') + if not context: + context={} + existing_user_ids = context.get('existing_user_ids', []) + new_user_ids = context.get('new_user_ids', []) + + for user in user_obj.browse(cr, uid, new_user_ids): + if 'user%s_login'%(user.id) in fields: + res['user%s_login'%(user.id)] = user.login + if 'user%s_password'%(user.id) in fields: + res['user%s_password'%(user.id)] = user.password + if 'user%s_url'%(user.id) in fields: + res['user%s_url'%(user.id)] = tools.config('share_root_url', False) + + for user in user_obj.browse(cr, uid, existing_user_ids): + if 'user%s_login'%(user.id) in fields: + res['user%s_login'%(user.id)] = user.login + if 'user%s_url'%(user.id) in fields: + res['user%s_url'%(user.id)] = tools.config('share_root_url', False) + return res + +share_result() + +class share_email(osv.osv_memory): + _name = 'share.email' + _description = 'share email' + _columns = { + 'email_to': fields.char('To', size=64, readonly=True), + 'subject': fields.char('Subject', size=64, required=True), + 'body': fields.text('Body', required=True), + } + def default_get(self, cr, uid, fields, context=None): + """ + To get default values for the object. + + @param self: The object pointer. + @param cr: A database cursor + @param uid: ID of the user currently logged in + @param fields: List of fields for which we want default values + @param context: A standard dictionary + + @return: A dictionary which of fields with values. + + """ + + res = super(share_email, self).default_get(cr, uid, fields, context=context) + user_obj = self.pool.get('res.users') + if not context: + context={} + user_id = context.get('user_id', False) + user_type = context.get('user_type', False) + share_url = context.get('share_url', False) + + user = user_obj.browse(cr, uid, user_id) + if 'email_to' in fields: + res['email_to'] = user.user_email + if 'subject' in fields: + res['subject'] = '%s wants to share private data with you' %(user.name) + if 'body' in fields: + res['body'] = """ +Dear, + + %s wants to share private data from OpenERP with you! + To view it, you can access the following URL: + %s +"""%(user.name, share_url) + if user_type == 'new': + res['body'] += """ + You may use the following login and password to get access to this + protected area: + login: %s + password: %s +"""%(user.login, user.password) + elif user_type == 'existing': + res['body'] += """ + You may use your existing login and password to get access to this + additional data. As a reminder, your login is %s. +"""%(user.name) + return res + + def do_send_email(cr, uid, ids, context=None): + user = user_obj.browse(cr, uid, uid) + for this in self.browse(cr, uid, ids, context=context): + flag = tools.email_send( + user.user_email, + this.email_to, + this.subject, + this.body + ) +share_email() + diff --git a/bin/addons/base/res/partner/wizard/wizard_share_view.xml b/bin/addons/base/res/partner/wizard/wizard_share_view.xml index 6485d6307fb..55628b9cfec 100644 --- a/bin/addons/base/res/partner/wizard/wizard_share_view.xml +++ b/bin/addons/base/res/partner/wizard/wizard_share_view.xml @@ -1,41 +1,112 @@ <?xml version="1.0" encoding="utf-8"?> <openerp> <data> - <record id="res_partner_share" model="ir.ui.view"> - <field name="name">partner.share.create.form</field> - <field name="model">partner.share.create</field> + <record id="share_email_form" model="ir.ui.view"> + <field name="name">share.email</field> + <field name="model">share.email</field> <field name="type">form</field> <field name="arch" type="xml"> - <form string="Share"> - <separator colspan="4" string="Users"/> - <field name="user_ids" colspan="4" nolabel="1"/> + <form string="Send Email"> + <separator colspan="4" string="Step 5: Send Email"/> + <field name="email_to" string="To" colspan="4"/> + <field name="subject" string="Subject" colspan="4"/> + <field name="body" nolabel="True" colspan="4"/> <separator colspan="4"/> <group col="2" colspan="4"> <button special="cancel" string="Cancel" icon='gtk-cancel'/> - <button name="do_share" string="Share" colspan="1" type="object" icon="gtk-execute"/> + <button name="do_send_email" string="Send Mail" type="object" icon="gtk-apply"/> </group> </form> </field> - </record> + </record> - <record id="res_partner_share_act" model="ir.actions.act_window"> - <field name="name">Share</field> + <record id="share_email_act" model="ir.actions.act_window"> + <field name="name">Step5: Send Email</field> <field name="type">ir.actions.act_window</field> - <field name="res_model">partner.share.create</field> + <field name="res_model">share.email</field> <field name="view_type">form</field> <field name="view_mode">form</field> + <field name="view_id" ref="share_email_form"/> <field name="target">new</field> + </record> + + <record id="share_step0_form" model="ir.ui.view"> + <field name="name">share.step0.form</field> + <field name="model">share.create</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Share"> + <separator colspan="4" string="Step 1: Chose the action and the additional domain"/> + <field name="action_id"/> + <field name="domain"/> + <separator colspan="4"/> + <group col="2" colspan="4"> + <button special="cancel" string="Cancel" icon='gtk-cancel'/> + <button name="do_step_1" string="Next" colspan="1" type="object" icon="gtk-next"/> + </group> + </form> + </field> + </record> + + <record id="share_step1_form" model="ir.ui.view"> + <field name="name">share.step1.form</field> + <field name="model">share.create</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Share"> + <separator colspan="4" string="Step 2: Chose the User type"/> + <field name="user_type"/> + <newline/> + <separator colspan="4" string="Exising Users"/> + <field colspan="4" nolabel="1" name="user_ids" attrs="{'readonly':[('user_type','=','new')]}" domain="[('share_user','=',True)]"/> + <separator colspan="4" string="New Users"/> + <field colspan="4" nolabel="1" name="new_user" attrs="{'readonly':[('user_type','=','existing')]}" /> + <separator colspan="4"/> + <group col="3" colspan="4"> + <button special="cancel" string="Cancel" icon='gtk-cancel'/> + <button name="do_step_1" string="Previous" colspan="1" type="object" icon="gtk-previous"/> + <button name="do_step_2" string="Next" colspan="1" type="object" icon="gtk-next"/> + </group> + </form> + </field> </record> - <record model="ir.values" id="res_partner_share_values"> - <field name="model_id" ref="model_res_partner" /> - <field name="object" eval="1" /> - <field name="name">Share</field> - <field name="key2">client_action_multi</field> - <field name="value" eval="'ir.actions.act_window,' + str(ref('res_partner_share_act'))" /> - <field name="key">action</field> - <field name="model">res.partner</field> + <record id="share_step2_form" model="ir.ui.view"> + <field name="name">share.step2.form</field> + <field name="model">share.create</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Share"> + <separator colspan="4" string="Step 3: Chose Access Mode"/> + <field name="access_mode"/> + <separator colspan="4"/> + <group col="3" colspan="4"> + <button special="cancel" string="Cancel" icon='gtk-cancel'/> + <button name="do_step_2" string="Previous" colspan="1" type="object" icon="gtk-previous"/> + <button name="do_step_3" string="Next" colspan="1" type="object" icon="gtk-next"/> + </group> + </form> + </field> </record> + + + <act_window name="Sharing Wizard" + res_model="share.create" + src_model="res.partner" + view_mode="form" + target="new" + view_id="ref('share_step1_form')" + key2="client_action_multi" + id="share_step1_act"/> + + + + + + + + + </data> -</openerp>
\ No newline at end of file +</openerp> diff --git a/bin/addons/base/res/res_user.py b/bin/addons/base/res/res_user.py index 70045acabfc..0f530ac8e0c 100644 --- a/bin/addons/base/res/res_user.py +++ b/bin/addons/base/res/res_user.py @@ -39,6 +39,7 @@ class groups(osv.osv): 'group_id', 'rule_group_id', 'Rules', domain="[('global', '<>', True)]"), 'menu_access': fields.many2many('ir.ui.menu', 'ir_ui_menu_group_rel', 'gid', 'menu_id', 'Access Menu'), 'comment' : fields.text('Comment',size=250), + 'share_group': fields.boolean('Share') } _sql_constraints = [ ('name_uniq', 'unique (name)', 'The name of the group must be unique !') @@ -242,6 +243,7 @@ class users(osv.osv): 'context_tz': fields.selection(_tz_get, 'Timezone', size=64, help="The user's timezone, used to perform timezone conversions " "between the server and the client."), + 'share_user': fields.boolean('Share'), 'view': fields.function(_get_interface_type, method=True, type='selection', fnct_inv=_set_interface_type, selection=[('simple','Simplified'),('extended','Extended')], string='Interface', help="Choose between the simplified interface and the extended one"), |
