[85ab89]: / Allura / allura / controllers / attachments.py  Maximize  Restore  History

Download this file

133 lines (111 with data), 4.5 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import six
from urllib.parse import unquote
from webob import exc
from tg import expose, request, redirect
from ming.utils import LazyProperty
from allura.lib.security import require_access
from allura.lib.utils import is_ajax
from allura import model as M
from .base import BaseController
# text/html, script, flash, image/svg+xml, etc are NOT secure to display directly in the browser
SAFE_CONTENT_TYPES = (
'image/png', 'image/x-png',
'image/jpeg', 'image/pjpeg', 'image/jpg',
'image/gif',
'image/bmp',
'image/tiff',
'image/x-icon',
)
class AttachmentsController(BaseController):
AttachmentControllerClass = None
def __init__(self, artifact):
self.artifact = artifact
@expose()
def _lookup(self, filename=None, *args):
if filename:
if not args:
filename = request.path.rsplit('/', 1)[-1]
filename = unquote(filename)
return self.AttachmentControllerClass(filename, self.artifact), args
else:
raise exc.HTTPNotFound
class AttachmentController(BaseController):
AttachmentClass = None
edit_perm = 'edit'
def _check_security(self):
require_access(self.artifact, 'read')
if isinstance(self.artifact, M.Post):
status = getattr(self.artifact, 'status', None)
if status == 'pending':
require_access(self.artifact, 'moderate')
def __init__(self, filename, artifact):
self.filename = filename
self.artifact = artifact
@property
def attachments_query(self):
metadata = self.AttachmentClass.metadata_for(self.artifact)
metadata['type'] = 'attachment'
return dict(filename=self.filename, **metadata)
@property
def thumbnails_query(self):
metadata = self.AttachmentClass.metadata_for(self.artifact)
metadata['type'] = 'thumbnail'
return dict(filename=self.filename, **metadata)
@LazyProperty
def attachment(self):
attachment = self.AttachmentClass.query.find(
self.attachments_query
).sort('_id', -1).limit(1).first()
if attachment is None:
raise exc.HTTPNotFound
return attachment
@LazyProperty
def thumbnail(self):
attachment = self.AttachmentClass.query.find(
self.thumbnails_query
).sort('_id', -1).limit(1).first()
if attachment is None:
raise exc.HTTPNotFound
return attachment
def handle_post(self, delete, **kw):
require_access(self.artifact, self.edit_perm)
if delete:
# Remove all attachments with such filename. Since we're showing
# only the most recent one we don't want previous attachments
# with such filename (if there was any) to show up after delete
self.AttachmentClass.query.remove(self.attachments_query)
self.AttachmentClass.query.remove(self.thumbnails_query)
@expose()
def index(self, delete=False, **kw):
if request.method == 'POST':
self.handle_post(delete, **kw)
if is_ajax(request):
return
redirect(six.ensure_text(request.referer or '/'))
if self.artifact.deleted:
raise exc.HTTPNotFound
embed = False
if self.attachment.content_type and self.attachment.content_type in SAFE_CONTENT_TYPES:
embed = True
return self.attachment.serve(embed=embed)
@expose()
def thumb(self, **kwargs):
if self.artifact.deleted:
raise exc.HTTPNotFound
return self.thumbnail.serve(embed=True)