Skip to content

Commit

Permalink
Merge 39e0fd3 into c2529a7
Browse files Browse the repository at this point in the history
  • Loading branch information
sasha-kantoriz committed Aug 15, 2017
2 parents c2529a7 + 39e0fd3 commit 6f4695f
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 20 deletions.
2 changes: 1 addition & 1 deletion openregistry/api/models/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
draft_role = whitelist('status')

document_create_role = blacklist('id', 'datePublished', 'dateModified', 'author', 'download_url')
document_edit_role = blacklist('id', 'url', 'datePublished', 'dateModified', 'author', 'hash', 'download_url'),
document_edit_role = blacklist('id', 'url', 'datePublished', 'dateModified', 'author', 'hash', 'download_url')
document_embedded_role = (blacklist('url', 'download_url') + schematics_embedded_role)
document_view_role = (blacklist('revisions') + schematics_default_role)
document_revisions_role = whitelist('url', 'dateModified')
Expand Down
103 changes: 84 additions & 19 deletions openregistry/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,22 @@
from cornice.resource import view
from webob.multidict import NestedMultiDict
from pkg_resources import iter_entry_points
from urlparse import urlparse, parse_qs, urlunsplit
from urlparse import urlparse, parse_qs, urlunsplit, parse_qsl
from time import time as ttime
from urllib import quote, urlencode
from base64 import b64encode
from urllib import quote, unquote, urlencode
from base64 import b64encode, b64decode
from hashlib import sha512
from email.header import decode_header
from rfc6266 import build_header

from schematics.types import StringType
from jsonpatch import make_patch, apply_patch as _apply_patch

from openregistry.api.events import ErrorDesctiptorEvent
from openregistry.api.constants import LOGGER, TZ, ROUTE_PREFIX
from openregistry.api.constants import (
LOGGER, TZ, ROUTE_PREFIX, SESSION,
DOCUMENT_BLACKLISTED_FIELDS, DOCUMENT_WHITELISTED_FIELDS
)
from openregistry.api.interfaces import IContentConfigurator


Expand Down Expand Up @@ -180,22 +185,82 @@ def fix_url(item, app_url):
]


def generate_docservice_url(request, doc_id, temporary=True, prefix=None):
docservice_key = getattr(request.registry, 'docservice_key', None)
parsed_url = urlparse(request.registry.docservice_url)
query = {}
if temporary:
expires = int(ttime()) + 300 # EXPIRES
mess = "{}\0{}".format(doc_id, expires)
query['Expires'] = expires
def upload_file(request, blacklisted_fields=DOCUMENT_BLACKLISTED_FIELDS, whitelisted_fields=DOCUMENT_WHITELISTED_FIELDS):
first_document = request.validated['documents'][-1] if 'documents' in request.validated and request.validated['documents'] else None
if request.content_type == 'multipart/form-data':
data = request.validated['file']
filename = get_filename(data)
content_type = data.type
in_file = data.file
else:
mess = doc_id
if prefix:
mess = '{}/{}'.format(prefix, mess)
query['Prefix'] = prefix
query['Signature'] = quote(b64encode(docservice_key.signature(mess.encode("utf-8"))))
query['KeyID'] = docservice_key.hex_vk()[:8]
return urlunsplit((parsed_url.scheme, parsed_url.netloc, '/get/{}'.format(doc_id), urlencode(query), ''))
filename = first_document.title
content_type = request.content_type
in_file = request.body_file

if hasattr(request.context, "documents"):
# upload new document
model = type(request.context).documents.model_class
else:
# update document
model = type(request.context)
document = model({'title': filename, 'format': content_type})
document.__parent__ = request.context
if 'document_id' in request.validated:
document.id = request.validated['document_id']
if first_document:
for attr_name in type(first_document)._fields:
if attr_name not in blacklisted_fields:
setattr(document, attr_name, getattr(first_document, attr_name))

key = generate_id()
filename = "{}_{}".format(document.id, key)
request.validated['db_doc']['_attachments'][filename] = {
"content_type": document.format,
"data": b64encode(in_file.read())
}

document_route = request.matched_route.name.replace("collection_", "")
document_path = request.current_route_path(_route_name=document_route, document_id=document.id, _query={'download': key})
document.url = '/' + '/'.join(document_path.split('/')[3:])
update_logging_context(request, {'file_size': in_file.tell()})
return document


def update_file_content_type(request):
pass # TODO


def get_filename(data):
try:
pairs = decode_header(data.filename)
except Exception:
pairs = None
if not pairs:
return data.filename
header = pairs[0]
if header[1]:
return header[0].decode(header[1])
else:
return header[0]


def get_file(request):
db_doc_id = request.validated['db_doc'].id
document = request.validated['document']
key = request.params.get('download')
if not any([key in i.url for i in request.validated['documents']]):
request.errors.add('url', 'download', 'Not Found')
request.errors.status = 404
return
filename = "{}_{}".format(document.id, key)
data = request.registry.db.get_attachment(db_doc_id, filename)
if data:
request.response.content_type = document.format.encode('utf-8')
request.response.content_disposition = build_header(document.title, filename_compat=quote(document.title.encode('utf-8')))
request.response.body_file = data
return request.response
request.errors.add('url', 'download', 'Not Found')
request.errors.status = 404


def forbidden(request):
Expand Down
21 changes: 21 additions & 0 deletions openregistry/api/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,24 @@ def validate_terminated_statuses(request, error_handler, **kwargs):
msg = 'Can\'t update {} in current ({}) status'.format(resource_type,
model.status)
raise_operation_error(request, error_handler, msg)


# Document validators
def validate_patch_document_data(request, error_handler, **kwargs):
model = type(request.context)
return validate_data(request, model, True)


def validate_file_upload(request, error_handler, **kwargs):
update_logging_context(request, {'document_id': '__new__'})
if 'file' not in request.POST or not hasattr(request.POST['file'], 'filename'):
request.errors.add('body', 'file', 'Not Found')
request.errors.status = 404
raise error_handler(request)
else:
request.validated['file'] = request.POST['file']


def validate_file_update(request, error_handler, **kwargs):
if request.content_type == 'multipart/form-data':
validate_file_upload(request, error_handler, **kwargs)

0 comments on commit 6f4695f

Please sign in to comment.