Skip to content

Commit

Permalink
Merge pull request #674 from RafiZz/12.0-port-ir_attachment_url
Browse files Browse the repository at this point in the history
⬆️1️⃣2️⃣ ir_attachment_url
  • Loading branch information
Ivan Yelizariev committed Dec 6, 2018
2 parents 3d496f3 + daa5206 commit 65ab335
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 32 deletions.
4 changes: 2 additions & 2 deletions ir_attachment_url/README.rst
Expand Up @@ -18,10 +18,10 @@ Sponsors
Further information
===================

HTML Description: https://apps.odoo.com/apps/modules/10.0/ir_attachment_url/
HTML Description: https://apps.odoo.com/apps/modules/12.0/ir_attachment_url/

Usage instructions: `<doc/index.rst>`_

Changelog: `<doc/changelog.rst>`_

Tested on Odoo 10.0 f05e8655ee4ee7205c67006ca5a8cb30ed445c81
Tested on Odoo 12.0 e774b2cb1c29fdd407aedc1f5c959d9725d2b514
6 changes: 3 additions & 3 deletions ir_attachment_url/__manifest__.py
Expand Up @@ -3,11 +3,11 @@
"summary": """Use attachment URL and upload data to external storage""",
"category": "Tools",
"images": [],
"version": "11.0.1.1.6",
"version": "12.0.1.1.6",
"application": False,

"author": "IT-Projects LLC, Ildar Nasyrov",
"website": "https://it-projects.info",
"website": "https://apps.odoo.com/apps/modules/12.0/ir_attachment_url/",
"license": "AGPL-3",
"price": 30.00,
"currency": "EUR",
Expand All @@ -31,5 +31,5 @@
"post_init_hook": None,

"auto_install": False,
"installable": False,
"installable": True,
}
4 changes: 2 additions & 2 deletions ir_attachment_url/doc/index.rst
Expand Up @@ -27,9 +27,9 @@ Odoo parameters
Usage
=====

* Go to Sales >> Products menu
* Go to Sales >> Products >> Products
* Open a product
* Upload image to this product or specify image URL
* Save the changes
* Go to Settings >> Database Structure >> Attachments menu
* Go to Settings >> Technical >> Database Structure >> Attachments
* See related attachment form that contains URL of the image
4 changes: 2 additions & 2 deletions ir_attachment_url/models/binary_fields.py
Expand Up @@ -5,7 +5,7 @@

class Binary(fields.Binary):

def write(self, records, value, create=False):
def write(self, records, value):
domain = [
('res_model', '=', records._name),
('res_field', '=', self.name),
Expand Down Expand Up @@ -40,7 +40,7 @@ def write(self, records, value, create=False):
else:
atts.unlink()
else:
super(Binary, self).write(records, value, create=create)
super(Binary, self).write(records, value)


fields.Binary = Binary
24 changes: 16 additions & 8 deletions ir_attachment_url/models/image.py
Expand Up @@ -5,8 +5,11 @@
super_image_resize_images = tools.image_resize_images


def updated_image_resize_images(vals, big_name='image', medium_name='image_medium', small_name='image_small'):
def updated_image_resize_images(vals, big_name='image', medium_name='image_medium', small_name='image_small', sizes=None):
""" Update ``vals`` with image fields resized as expected. """
if not sizes:
sizes = {}

url = None
if big_name in vals and is_url(vals[big_name]):
url = vals[big_name]
Expand All @@ -20,7 +23,7 @@ def updated_image_resize_images(vals, big_name='image', medium_name='image_mediu
vals.update({medium_name: url})
vals.update({small_name: url})
else:
super_image_resize_images(vals, big_name, medium_name, small_name)
super_image_resize_images(vals, big_name, medium_name, small_name, sizes=sizes)


def is_url(value):
Expand All @@ -31,11 +34,11 @@ def is_url(value):
super_image_resize_image = tools.image_resize_image


def updated_image_resize_image(base64_source, size=(1024, 1024), encoding='base64', filetype=None, avoid_if_small=False):
def updated_image_resize_image(base64_source, size=(1024, 1024), encoding='base64', filetype=None, avoid_if_small=False, upper_limit=False):
source_for_check = base64_source.decode("utf-8") if isinstance(base64_source, bytes) else base64_source
if is_url(source_for_check):
return source_for_check
return super_image_resize_image(base64_source, size=size, encoding=encoding, filetype=filetype, avoid_if_small=avoid_if_small)
return super_image_resize_image(base64_source, size=size, encoding=encoding, filetype=filetype, avoid_if_small=avoid_if_small, upper_limit=upper_limit)


def updated_image_resize_image_big(base64_source, size=(1024, 1024), encoding='base64', filetype=None, avoid_if_small=True):
Expand All @@ -61,19 +64,24 @@ def updated_image_resize_image_small(base64_source, size=(64, 64), encoding='bas

def updated_image_get_resized_images(base64_source, return_big=False, return_medium=True, return_small=True,
big_name='image', medium_name='image_medium', small_name='image_small',
avoid_resize_big=True, avoid_resize_medium=False, avoid_resize_small=False):
avoid_resize_big=True, avoid_resize_medium=False, avoid_resize_small=False, sizes=None):
""" copy-pasted from odoo/tools/image.py::image_get_resized_images
because we rewrite image_resize_image function.
"""
if not sizes:
sizes = {}
return_dict = dict()
size_big = sizes.get(big_name, (1024, 1024))
size_medium = sizes.get(medium_name, (128, 128))
size_small = sizes.get(small_name, (64, 64))
if isinstance(base64_source, tools.pycompat.text_type):
base64_source = base64_source.encode('ascii')
if return_big:
return_dict[big_name] = updated_image_resize_image_big(base64_source, avoid_if_small=avoid_resize_big)
return_dict[big_name] = updated_image_resize_image_big(base64_source, avoid_if_small=avoid_resize_big, size=size_big)
if return_medium:
return_dict[medium_name] = updated_image_resize_image_medium(base64_source, avoid_if_small=avoid_resize_medium)
return_dict[medium_name] = updated_image_resize_image_medium(base64_source, avoid_if_small=avoid_resize_medium, size=size_medium)
if return_small:
return_dict[small_name] = updated_image_resize_image_small(base64_source, avoid_if_small=avoid_resize_small)
return_dict[small_name] = updated_image_resize_image_small(base64_source, avoid_if_small=avoid_resize_small, size=size_small)
return return_dict


Expand Down
29 changes: 17 additions & 12 deletions ir_attachment_url/models/ir_http.py
Expand Up @@ -19,13 +19,11 @@ class IrHttp(models.AbstractModel):
def binary_content(cls, xmlid=None, model='ir.attachment', id=None, field='datas',
unique=False, filename=None, filename_field='datas_fname', download=False,
mimetype=None, default_mimetype='application/octet-stream',
access_token=None, env=None):
access_token=None, related_id=None, access_mode=None, env=None):
""" Get file, attachment or downloadable content
If the ``xmlid`` and ``id`` parameter is omitted, fetches the default value for the
binary field (via ``default_get``), otherwise fetches the field for
that precise record.
:param str xmlid: xmlid of the record
:param str model: name of the model to fetch the binary from
:param int id: id of the record from which to fetch the binary
Expand All @@ -35,6 +33,8 @@ def binary_content(cls, xmlid=None, model='ir.attachment', id=None, field='datas
:param str filename_field: if not create an filename with model-id-field
:param bool download: apply headers to download the file
:param str mimetype: mintype of the field (for headers)
:param related_id: the id of another record used for custom_check
:param access_mode: if truthy, will call custom_check to fetch the object that contains the binary.
:param str default_mimetype: default mintype if no mintype found
:param str access_token: optional token for unauthenticated access
only available for ir.attachment
Expand All @@ -45,21 +45,25 @@ def binary_content(cls, xmlid=None, model='ir.attachment', id=None, field='datas
# get object and content
obj = None
if xmlid:
obj = env.ref(xmlid, False)
elif id and model == 'ir.attachment' and access_token:
obj = env[model].sudo().browse(int(id))
if not consteq(obj.access_token, access_token):
return (403, [], None)
obj = cls._xmlid_to_obj(env, xmlid)
elif id and model in env.registry:
obj = env[model].browse(int(id))

# obj exists
if not obj or not obj.exists() or field not in obj:
return (404, [], None)

# access token grant access
if model == 'ir.attachment' and access_token:
obj = obj.sudo()
if access_mode:
if not cls._check_access_mode(env, id, access_mode, model, access_token=access_token, related_id=related_id):
return (403, [], None)
elif not consteq(obj.access_token or u'', access_token):
return (403, [], None)

# check read access
try:
last_update = obj['__last_update']
obj['__last_update']
except AccessError:
return (403, [], None)

Expand All @@ -79,7 +83,8 @@ def binary_content(cls, xmlid=None, model='ir.attachment', id=None, field='datas
if module_resource_path.startswith(module_path):
with open(module_resource_path, 'rb') as f:
content = base64.b64encode(f.read())
last_update = pycompat.text_type(os.path.getmtime(module_resource_path))
# lint error fix (unused variable)
# last_update = pycompat.text_type(os.path.getmtime(module_resource_path))

if not module_resource_path:
module_resource_path = obj.url
Expand Down Expand Up @@ -130,7 +135,7 @@ def binary_content(cls, xmlid=None, model='ir.attachment', id=None, field='datas

# cache
etag = bool(request) and request.httprequest.headers.get('If-None-Match')
retag = '"%s"' % hashlib.md5(last_update.encode('utf-8')).hexdigest()
retag = '"%s"' % hashlib.md5(pycompat.to_text(content).encode('utf-8')).hexdigest()
status = status or (304 if etag == retag else 200)
headers.append(('ETag', retag))
headers.append(('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0)))
Expand Down
5 changes: 2 additions & 3 deletions ir_attachment_url/tests/test_data_get.py
@@ -1,13 +1,12 @@
import logging

from openerp.tests.common import HttpCase
from odoo.tests.common import HttpCase, tagged

_logger = logging.getLogger(__name__)


@tagged('post_install', '-at_install')
class TestDataGet(HttpCase):
at_install = False
post_install = True

def test_data_get(self):
test_attachment = self.env.ref('ir_attachment_url.test_url_attachment')
Expand Down

0 comments on commit 65ab335

Please sign in to comment.