diff options
| author | Arnaud Pineux <api@openerp.com> | 2012-12-11 16:33:52 +0100 |
|---|---|---|
| committer | Arnaud Pineux <api@openerp.com> | 2012-12-11 16:33:52 +0100 |
| commit | d288b45bb3e192146dfd2fe40d840c8c23a79f74 (patch) | |
| tree | 55f0fed474aee380ecd2d6a544024763bd533a20 /addons | |
| parent | dd94a6b00a129c506299ec7e0b5739f5e9668a24 (diff) | |
| parent | c70f05cc778435a069d258a82b8b2870e8565922 (diff) | |
[MERGE] with trunk
bzr revid: api@openerp.com-20121211153352-l1ikpqgz8cxmuuu0
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/analytic/analytic.py | 2 | ||||
| -rw-r--r-- | addons/mail/__init__.py | 1 | ||||
| -rw-r--r-- | addons/mail/controllers/__init__.py | 3 | ||||
| -rw-r--r-- | addons/mail/controllers/main.py | 22 | ||||
| -rw-r--r-- | addons/mail/mail_message.py | 18 | ||||
| -rw-r--r-- | addons/mail/static/src/js/mail.js | 65 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/mail.xml | 10 | ||||
| -rw-r--r-- | addons/mail/tests/test_mail.py | 4 | ||||
| -rw-r--r-- | addons/mail/tests/test_mail_access_rights.py | 12 | ||||
| -rw-r--r-- | addons/portal/security/ir.model.access.csv | 1 |
10 files changed, 108 insertions, 30 deletions
diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py index 782fbc4f3ee..420c6516b38 100644 --- a/addons/analytic/analytic.py +++ b/addons/analytic/analytic.py @@ -166,7 +166,7 @@ class account_analytic_account(osv.osv): _columns = { 'name': fields.char('Account/Contract Name', size=128, required=True), 'complete_name': fields.function(_get_full_name, type='char', string='Full Account Name'), - 'code': fields.char('Reference', size=24, select=True), + 'code': fields.char('Reference', select=True), 'type': fields.selection([('view','Analytic View'), ('normal','Analytic Account'),('contract','Contract or Project'),('template','Template of Contract')], 'Type of Account', required=True, help="If you select the View Type, it means you won\'t allow to create journal entries using that account.\n"\ "The type 'Analytic account' stands for usual accounts that you only want to use in accounting.\n"\ diff --git a/addons/mail/__init__.py b/addons/mail/__init__.py index b34993ffd32..b759a08d778 100644 --- a/addons/mail/__init__.py +++ b/addons/mail/__init__.py @@ -35,5 +35,6 @@ import wizard import res_config import mail_group_menu import update +import controllers # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mail/controllers/__init__.py b/addons/mail/controllers/__init__.py new file mode 100644 index 00000000000..e11f9ba81bb --- /dev/null +++ b/addons/mail/controllers/__init__.py @@ -0,0 +1,3 @@ +import main + +# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mail/controllers/main.py b/addons/mail/controllers/main.py new file mode 100644 index 00000000000..4c6f6e56064 --- /dev/null +++ b/addons/mail/controllers/main.py @@ -0,0 +1,22 @@ +import base64 +import openerp.addons.web.http as oeweb +from openerp.addons.web.controllers.main import content_disposition + +#---------------------------------------------------------- +# Controller +#---------------------------------------------------------- +class MailController(oeweb.Controller): + _cp_path = '/mail' + + @oeweb.httprequest + def download_attachment(self, req, model, id, method, attachment_id, **kw): + Model = req.session.model(model) + res = getattr(Model, method)(int(id), int(attachment_id)) + if res: + filecontent = base64.b64decode(res.get('base64')) + filename = res.get('filename') + if filecontent and filename: + return req.make_response(filecontent, + headers=[('Content-Type', 'application/octet-stream'), + ('Content-Disposition', content_disposition(filename, req))]) + return req.not_found() diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index a5080e48373..069e0118ec4 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -205,6 +205,22 @@ class mail_message(osv.Model): return new_has_voted or False #------------------------------------------------------ + # download an attachment + #------------------------------------------------------ + + def download_attachment(self, cr, uid, id_message, attachment_id, context=None): + """ Return the content of linked attachments. """ + message = self.browse(cr, uid, id_message, context=context) + if attachment_id in [attachment.id for attachment in message.attachment_ids]: + attachment = self.pool.get('ir.attachment').browse(cr, SUPERUSER_ID, attachment_id, context=context) + if attachment.datas and attachment.datas_fname: + return { + 'base64': attachment.datas, + 'filename': attachment.datas_fname, + } + return False + + #------------------------------------------------------ # Notification API #------------------------------------------------------ @@ -294,7 +310,7 @@ class mail_message(osv.Model): partner_tree = dict((partner[0], partner) for partner in partners) # 2. Attachments - attachments = ir_attachment_obj.read(cr, uid, list(attachment_ids), ['id', 'datas_fname'], context=context) + attachments = ir_attachment_obj.read(cr, SUPERUSER_ID, list(attachment_ids), ['id', 'datas_fname'], context=context) attachments_tree = dict((attachment['id'], {'id': attachment['id'], 'filename': attachment['datas_fname']}) for attachment in attachments) # 3. Update message dictionaries diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 7181367cf85..b86aad91658 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -29,8 +29,13 @@ openerp.mail = function (session) { }, /* Get the url of an attachment {'id': id} */ - get_attachment_url: function (session, attachment) { - return session.url('/web/binary/saveas', {model: 'ir.attachment', field: 'datas', filename_field: 'datas_fname', id: attachment['id']}); + get_attachment_url: function (session, message_id, attachment_id) { + return session.url('/mail/download_attachment', { + 'model': 'mail.message', + 'id': message_id, + 'method': 'download_attachment', + 'attachment_id': attachment_id + }); }, /** @@ -258,7 +263,7 @@ openerp.mail = function (session) { for (var l in this.attachment_ids) { var attach = this.attachment_ids[l]; if (!attach.formating) { - attach.url = mail.ChatterUtils.get_attachment_url(this.session, attach); + attach.url = mail.ChatterUtils.get_attachment_url(this.session, this.id, attach.id); attach.filetype = mail.ChatterUtils.filetype(attach.filename); attach.name = mail.ChatterUtils.breakword(attach.name || attach.filename); attach.formating = true; @@ -420,18 +425,23 @@ openerp.mail = function (session) { /* when the file is uploaded */ on_attachment_loaded: function (event, result) { - for (var i in this.attachment_ids) { - if (this.attachment_ids[i].filename == result.filename && this.attachment_ids[i].upload) { - this.attachment_ids[i]={ - 'id': result.id, - 'name': result.name, - 'filename': result.filename, - 'url': mail.ChatterUtils.get_attachment_url(this.session, result) - }; + + if (result.erorr || !result.id ) { + this.do_warn( session.web.qweb.render('mail.error_upload'), result.error); + this.attachment_ids = _.filter(this.attachment_ids, function (val) { return !val.upload; }); + } else { + for (var i in this.attachment_ids) { + if (this.attachment_ids[i].filename == result.filename && this.attachment_ids[i].upload) { + this.attachment_ids[i]={ + 'id': result.id, + 'name': result.name, + 'filename': result.filename, + 'url': mail.ChatterUtils.get_attachment_url(this.session, this.id, result.id) + }; + } } } this.display_attachments(); - var $input = this.$('input.oe_form_binary_file'); $input.after($input.clone(true)).remove(); this.$(".oe_attachment_file").show(); @@ -484,6 +494,11 @@ openerp.mail = function (session) { }, on_compose_fullmail: function (default_composition_mode) { + + if(!this.do_check_attachment_upload()) { + return false; + } + if (default_composition_mode == 'reply') { var context = { 'default_composition_mode': default_composition_mode, @@ -534,31 +549,31 @@ openerp.mail = function (session) { this.reinit(); }, + /* return true if all file are complete else return false and make an alert */ + do_check_attachment_upload: function () { + if (_.find(this.attachment_ids, function (file) {return file.upload;})) { + this.do_warn(session.web.qweb.render('mail.error_upload'), session.web.qweb.render('mail.error_upload_please_wait')); + return false; + } else { + return true; + } + }, + /*post a message and fetch the message*/ on_message_post: function (event) { var self = this; var comment_node = this.$('textarea'); var body = comment_node.val(); - comment_node.val(''); - - var attachments=[]; - for (var i in this.attachment_ids) { - if (this.attachment_ids[i].upload) { - session.web.dialog($('<div>' + session.web.qweb.render('CrashManager.warning', {message: 'Please, wait while the file is uploading.'}) + '</div>')); - return false; - } - attachments.push(this.attachment_ids[i].id); - } - if (body.match(/\S+/)) { + if (this.do_check_attachment_upload() && (this.attachment_ids.length || body.match(/\S+/))) { //session.web.blockUI(); this.parent_thread.ds_thread.call('message_post_user_api', [ this.context.default_res_id, body, false, this.context.default_parent_id, - attachments, + _.map(this.attachment_ids, function (file) {return file.id;}), this.parent_thread.context ]).done(function (record) { var thread = self.parent_thread; @@ -571,8 +586,8 @@ openerp.mail = function (session) { var message = thread.create_message_object( data[0] ); // insert the message on dom thread.insert_message( message, root ? undefined : self.$el, root ); - self.on_cancel(); }); + self.on_cancel(); //session.web.unblockUI(); }); return true; diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index cca908a5d98..67449cca0ba 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -75,7 +75,7 @@ <t t-foreach='widget.attachment_ids' t-as='attachment'> <t t-if="attachment.filetype !== 'webimage'"> <div t-attf-class="oe_attachment #{attachment.upload ? 'oe_uploading' : ''}"> - <a t-att-href='attachment.url'> + <a t-att-href='attachment.url' target="_blank"> <img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.filetype + '.png'"></img> <div class='oe_name'><t t-raw='attachment.name' /></div> </a> @@ -87,7 +87,7 @@ </t> <t t-if="attachment.filetype === 'webimage'"> <div t-attf-class="oe_attachment oe_preview #{attachment.upload ? 'oe_uploading' : ''}"> - <a t-att-href='attachment.url'> + <a t-att-href='attachment.url' target="_blank"> <img t-att-src="widget.attachments_resize_image(attachment.id, [100,80])"></img> <div class='oe_name'><t t-raw='attachment.name' /></div> </a> @@ -180,6 +180,12 @@ </t> <!-- + error message for uploading + --> + <t t-name="mail.error_upload">Uploading error</t> + <t t-name="mail.error_upload_please_wait">Please, wait while the file is uploading.</t> + + <!-- record_thread main template Template used to display the communication history in documents form view. diff --git a/addons/mail/tests/test_mail.py b/addons/mail/tests/test_mail.py index c18dea46452..6db6a8d6c71 100644 --- a/addons/mail/tests/test_mail.py +++ b/addons/mail/tests/test_mail.py @@ -421,6 +421,10 @@ class test_mail(test_mail_mockup.TestMailMockups): self.assertEqual(attach.res_id, self.group_pigs_id, 'mail.message attachment res_id incorrect') self.assertIn((attach.name, attach.datas.decode('base64')), _attachments, 'mail.message attachment name / data incorrect') + # Test: download attachments + for attach in message.attachment_ids: + dl_attach = self.mail_message.download_attachment(cr, uid, id_message=message.id, attachment_id=attach.id) + self.assertIn(( dl_attach['filename'], dl_attach['base64'].decode('base64') ), _attachments, 'mail.message download_attachment is incorrect') # 3. Reply to the last message, check that its parent will be the first message msg_id3 = self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Test', parent_id=msg_id2) diff --git a/addons/mail/tests/test_mail_access_rights.py b/addons/mail/tests/test_mail_access_rights.py index 1b2f7f85d71..15003ca9b87 100644 --- a/addons/mail/tests/test_mail_access_rights.py +++ b/addons/mail/tests/test_mail_access_rights.py @@ -31,6 +31,7 @@ class test_mail_access_rights(test_mail_mockup.TestMailMockups): cr, uid = self.cr, self.uid self.mail_group = self.registry('mail.group') self.mail_message = self.registry('mail.message') + self.attachment = self.registry('ir.attachment') self.mail_notification = self.registry('mail.notification') self.res_users = self.registry('res.users') self.res_groups = self.registry('res.groups') @@ -97,12 +98,16 @@ class test_mail_access_rights(test_mail_mockup.TestMailMockups): self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Message') self.group_jobs_id = self.mail_group.create(cr, uid, {'name': 'Jobs', 'public': 'public'}) + # prepare an attachment + attachment_id = self.attachment.create(cr, uid, {'datas': 'My attachment'.encode('base64'), 'name': 'doc.txt', 'datas_fname': 'doc.txt' }) + # ---------------------------------------- # CASE1: Bert, basic mail.message read access # ---------------------------------------- # Do: create a new mail.message - message_id = self.mail_message.create(cr, uid, {'body': 'My Body'}) + message_id = self.mail_message.create(cr, uid, {'body': 'My Body', 'attachment_ids': [4, attachment_id] }) + # Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc self.assertRaises(except_orm, self.mail_message.read, cr, user_bert_id, message_id) @@ -110,11 +115,16 @@ class test_mail_access_rights(test_mail_mockup.TestMailMockups): notif_id = self.mail_notification.create(cr, uid, {'message_id': message_id, 'partner_id': partner_bert_id}) # Test: Bert reads the message, ok because notification pushed self.mail_message.read(cr, user_bert_id, message_id) + # Test: Bert download attachment, ok because he can read message + self.mail_message.download_attachment(cr, user_bert_id, message_id, attachment_id) # Do: remove notification self.mail_notification.unlink(cr, uid, notif_id) # Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc self.assertRaises(except_orm, self.mail_message.read, cr, self.user_bert_id, message_id) + # Test: Bert download attachment, crash because he can't read message + self.assertRaises(except_orm, self.mail_message.download_attachment, + cr, user_bert_id, message_id, attachment_id) # Do: Bert is now the author self.mail_message.write(cr, uid, [message_id], {'author_id': partner_bert_id}) # Test: Bert reads the message, ok because Bert is the author diff --git a/addons/portal/security/ir.model.access.csv b/addons/portal/security/ir.model.access.csv index b9f98f81fd7..59ca37e213d 100644 --- a/addons/portal/security/ir.model.access.csv +++ b/addons/portal/security/ir.model.access.csv @@ -7,3 +7,4 @@ access_res_partner_category,res.partner_category,base.model_res_partner_category access_res_partner_title,res.partner_title,base.model_res_partner_title,portal.group_portal,1,0,0,0 access_acquirer,portal.payment.acquirer,portal.model_portal_payment_acquirer,,1,0,0,0 access_acquirer_all,portal.payment.acquirer,portal.model_portal_payment_acquirer,base.group_system,1,1,1,1 +access_ir_attachment_group_portal,ir.attachment group_portal,base.model_ir_attachment,portal.group_portal,1,0,1,0
\ No newline at end of file |
