[MERGE] catch and display error when there are an error in an attachment upload. Add mail/download_attachment controllers

bzr revid: chm@openerp.com-20121211152219-2hlw1npfq2jfzx88
This commit is contained in:
Christophe Matthieu 2012-12-11 16:22:19 +01:00
commit c70f05cc77
9 changed files with 107 additions and 29 deletions

View File

@ -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:

View File

@ -0,0 +1,3 @@
import main
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -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()

View File

@ -204,6 +204,22 @@ class mail_message(osv.Model):
self.write(cr, SUPERUSER_ID, message.get('id'), {'vote_user_ids': [(3, uid)]}, context=context)
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

View File

@ -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;

View File

@ -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>
@ -179,6 +179,12 @@
<div class="oe_view_nocontent">No messages.</div>
</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

View File

@ -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)

View File

@ -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

View File

@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
7 access_res_partner_title res.partner_title base.model_res_partner_title portal.group_portal 1 0 0 0
8 access_acquirer portal.payment.acquirer portal.model_portal_payment_acquirer 1 0 0 0
9 access_acquirer_all portal.payment.acquirer portal.model_portal_payment_acquirer base.group_system 1 1 1 1
10 access_ir_attachment_group_portal ir.attachment group_portal base.model_ir_attachment portal.group_portal 1 0 1 0