# -*- coding: utf-8 -*- """ s3-storage.models ~~~~~~~~~~~~~~~~~ Use s3 as file storage mechanism :copyright: (c) 2017 by Marc Lijour, brolycjw. :license: MIT License, see LICENSE for more details. """ import hashlib import base64 from odoo import models from . import s3_helper class S3Attachment(models.Model): """Extends ir.attachment to implement the S3 storage engine """ _inherit = "ir.attachment" def _connect_to_S3_bucket(self, s3, bucket_name): s3_bucket = s3.Bucket(bucket_name) exists = s3_helper.bucket_exists(s3, bucket_name) if not exists: s3_bucket = s3.create_bucket(Bucket=bucket_name) return s3_bucket def _file_read(self, fname, bin_size=False): storage = self._storage() if storage[:5] == 's3://': access_key_id, secret_key, bucket_name, do_space_url = s3_helper.parse_bucket_url( storage) s3 = s3_helper.get_resource( access_key_id, secret_key, do_space_url) s3_bucket = self._connect_to_S3_bucket(s3, bucket_name) file_exists = s3_helper.object_exists(s3, s3_bucket.name, fname) if not file_exists: # Some old files (prior to the installation of odoo-s3) may # still be stored in the file system even though # ir_attachment.location is configured to use S3 try: read = super(S3Attachment, self)._file_read( fname, bin_size=False) except Exception: # Could not find the file in the file system either. return False else: s3_key = s3.Object(s3_bucket.name, fname) read = base64.b64encode(s3_key.get()['Body'].read()) else: read = super(S3Attachment, self)._file_read(fname, bin_size=False) return read def _file_write(self, value, checksum): storage = self._storage() if storage[:5] == 's3://': access_key_id, secret_key, bucket_name, do_space_url = s3_helper.parse_bucket_url( storage) s3 = s3_helper.get_resource( access_key_id, secret_key, do_space_url) s3_bucket = self._connect_to_S3_bucket(s3, bucket_name) bin_value = base64.b64decode(value) fname = hashlib.sha1(bin_value).hexdigest() if encryption_enabled: s3.Object(s3_bucket.name, fname).put(Body=bin_value, ServerSideEncryption='AES256') else: s3.Object(s3_bucket.name, fname).put(Body=bin_value) else: # falling back on Odoo's local filestore fname = super(S3Attachment, self)._file_write(value, checksum) return fname