Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for managing and deleting attachments.
Modified substantially by tabbott to fix tons of issues. Fixes #454.
- Loading branch information
Showing
18 changed files
with
238 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
var attachments_ui = (function () { | ||
|
||
var exports = {}; | ||
|
||
function delete_attachments(attachment) { | ||
channel.del({url: '/json/attachments/' + attachment, idempotent: true}); | ||
} | ||
|
||
exports.set_up_attachments = function () { | ||
// The settings page must be rendered before this function gets called. | ||
|
||
var attachment_list = $('#attachments_list'); | ||
_.each(page_params.attachments, function (attachment) { | ||
var li = templates.render('attachment-item', {attachment: attachment}); | ||
attachment_list.append(li); | ||
}); | ||
|
||
$('#attachments_list').on('click', '.remove-attachment', function (event) { | ||
var li = $(event.currentTarget).parents('li'); | ||
li.remove(); | ||
delete_attachments($(this).data('attachment')); | ||
}); | ||
}; | ||
|
||
return exports; | ||
}()); | ||
|
||
if (typeof module !== 'undefined') { | ||
module.exports = attachments_ui; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
|
||
<li class="attachment-item" data-attachment='{{attachment.id}}'> | ||
<div class="attachment-information-box list-container"> | ||
<div class="attachment_listing"> | ||
<strong>{{attachment.name}}</strong> | ||
</div> | ||
<div class="edit-attachment-buttons"> | ||
<button type="submit" | ||
class="button small btn-small btn-danger remove-attachment" | ||
title="{{t 'Delete file' }}" data-attachment="{{attachment.id}}"> | ||
<i class="icon-vector-trash"></i> | ||
</button> | ||
</div> | ||
{{#if attachment.messages }} | ||
<ul class="attachment-messages"> | ||
{{#each attachment.messages}} | ||
<li> | ||
<a href="/#narrow/id/{{ this.id }}">{{ this.name }}</a> | ||
</li> | ||
{{/each}} | ||
</ul> | ||
{{/if}} | ||
</div> | ||
</li> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<div id="attachments-settings" class="settings-section" data-name="uploaded-files"> | ||
<div class="settings-section-title"> | ||
<i class="icon-vector-paper-clip settings-section-icon"></i> | ||
{{t "Uploaded files" }} | ||
</div> | ||
<div class="side-padded-container"> | ||
<p class="alert-word-settings-note"> | ||
{{t 'For each file, we list any messages that link to it.' }} | ||
</p> | ||
</div> | ||
<ul id="attachments_list"></ul> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,5 +11,7 @@ | |
|
||
{{ partial "alert-word-settings" }} | ||
|
||
{{ partial "attachments-settings" }} | ||
|
||
{{ partial "ui-settings" }} | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from __future__ import absolute_import | ||
|
||
from django.utils.translation import ugettext as _ | ||
from typing import Any, Dict, List | ||
|
||
from zerver.lib.request import JsonableError | ||
from zerver.lib.upload import delete_message_image | ||
from zerver.models import Attachment, UserProfile | ||
|
||
def user_attachments(user_profile): | ||
# type: (UserProfile) -> List[Dict[str, Any]] | ||
attachments = Attachment.objects.filter(owner=user_profile).prefetch_related('messages') | ||
return [a.to_dict() for a in attachments] | ||
|
||
def access_attachment_by_id(user_profile, attachment_id, needs_owner=False): | ||
# type: (UserProfile, int, bool) -> Attachment | ||
query = Attachment.objects.filter(id=attachment_id) | ||
if needs_owner: | ||
query = query.filter(owner=user_profile) | ||
|
||
attachment = query.first() | ||
if attachment is None: | ||
raise JsonableError(_("Invalid attachment")) | ||
return attachment | ||
|
||
def remove_attachment(user_profile, attachment): | ||
# type: (UserProfile, Attachment) -> None | ||
delete_message_image(attachment.path_id) | ||
attachment.delete() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# -*- coding: utf-8 -*- | ||
from __future__ import absolute_import | ||
from __future__ import print_function | ||
|
||
import mock | ||
import ujson | ||
|
||
from typing import Any | ||
|
||
from zerver.lib.attachments import user_attachments | ||
from zerver.lib.test_helpers import get_user_profile_by_email | ||
from zerver.lib.test_classes import ZulipTestCase | ||
from zerver.models import Attachment | ||
|
||
|
||
class AttachmentsTests(ZulipTestCase): | ||
def setUp(self): | ||
# type: () -> None | ||
user = get_user_profile_by_email("cordelia@zulip.com") | ||
self.attachment = Attachment.objects.create( | ||
file_name='test.txt', path_id='foo/bar/test.txt', owner=user) | ||
|
||
def test_list_by_user(self): | ||
# type: () -> None | ||
self.login("cordelia@zulip.com") | ||
result = self.client_get('/json/attachments') | ||
self.assert_json_success(result) | ||
user = get_user_profile_by_email("cordelia@zulip.com") | ||
attachments = user_attachments(user) | ||
data = ujson.loads(result.content) | ||
self.assertEqual(data['attachments'], attachments) | ||
|
||
@mock.patch('zerver.lib.attachments.delete_message_image') | ||
def test_remove_attachment(self, ignored): | ||
# type: (Any) -> None | ||
self.login("cordelia@zulip.com") | ||
result = self.client_delete('/json/attachments/{pk}'.format(pk=self.attachment.pk)) | ||
self.assert_json_success(result) | ||
user = get_user_profile_by_email("cordelia@zulip.com") | ||
attachments = user_attachments(user) | ||
self.assertEqual(attachments, []) | ||
|
||
def test_list_another_user(self): | ||
# type: () -> None | ||
self.login("iago@zulip.com") | ||
result = self.client_get('/json/attachments') | ||
self.assert_json_success(result) | ||
data = ujson.loads(result.content) | ||
self.assertEqual(data['attachments'], []) | ||
|
||
def test_remove_another_user(self): | ||
# type: () -> None | ||
self.login("iago@zulip.com") | ||
result = self.client_delete('/json/attachments/{pk}'.format(pk=self.attachment.pk)) | ||
self.assert_json_error(result, 'Invalid attachment') | ||
user = get_user_profile_by_email("cordelia@zulip.com") | ||
attachments = user_attachments(user) | ||
self.assertEqual(attachments, [self.attachment.to_dict()]) | ||
|
||
def test_list_unauthenticated(self): | ||
# type: () -> None | ||
result = self.client_get('/json/attachments') | ||
self.assert_json_error(result, 'Not logged in: API authentication or user session required', status_code=401) | ||
|
||
def test_delete_unauthenticated(self): | ||
# type: () -> None | ||
result = self.client_delete('/json/attachments/{pk}'.format(pk=self.attachment.pk)) | ||
self.assert_json_error(result, 'Not logged in: API authentication or user session required', status_code=401) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from __future__ import absolute_import | ||
from django.http import HttpRequest, HttpResponse | ||
|
||
from zerver.decorator import REQ | ||
from zerver.models import UserProfile | ||
from zerver.lib.validator import check_int | ||
from zerver.lib.response import json_success | ||
from zerver.lib.attachments import user_attachments, remove_attachment, \ | ||
access_attachment_by_id | ||
|
||
|
||
def list_by_user(request, user_profile): | ||
# type: (HttpRequest, UserProfile) -> HttpResponse | ||
return json_success({"attachments": user_attachments(user_profile)}) | ||
|
||
|
||
def remove(request, user_profile, attachment_id=REQ(validator=check_int)): | ||
# type: (HttpRequest, UserProfile, int) -> HttpResponse | ||
attachment = access_attachment_by_id(user_profile, attachment_id, | ||
needs_owner=True) | ||
remove_attachment(user_profile, attachment) | ||
return json_success() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters