models.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. # -*- coding: utf-8 -*-
  2. """
  3. s3-storage.models
  4. ~~~~~~~~~~~~~~~~~
  5. Use s3 as file storage mechanism
  6. :copyright: (c) 2017 by Marc Lijour, brolycjw.
  7. :license: MIT License, see LICENSE for more details.
  8. """
  9. import hashlib
  10. import base64
  11. from odoo import models
  12. from . import s3_helper
  13. class S3Attachment(models.Model):
  14. """Extends ir.attachment to implement the S3 storage engine
  15. """
  16. _inherit = "ir.attachment"
  17. def _connect_to_S3_bucket(self, s3, bucket_name):
  18. s3_bucket = s3.Bucket(bucket_name)
  19. exists = s3_helper.bucket_exists(s3, bucket_name)
  20. if not exists:
  21. s3_bucket = s3.create_bucket(Bucket=bucket_name)
  22. return s3_bucket
  23. def _file_read(self, fname, bin_size=False):
  24. storage = self._storage()
  25. if storage[:5] == 's3://':
  26. access_key_id, secret_key, bucket_name, do_space_url = s3_helper.parse_bucket_url(
  27. storage)
  28. s3 = s3_helper.get_resource(
  29. access_key_id, secret_key, do_space_url)
  30. s3_bucket = self._connect_to_S3_bucket(s3, bucket_name)
  31. file_exists = s3_helper.object_exists(s3, s3_bucket.name, fname)
  32. if not file_exists:
  33. # Some old files (prior to the installation of odoo-s3) may
  34. # still be stored in the file system even though
  35. # ir_attachment.location is configured to use S3
  36. try:
  37. read = super(S3Attachment, self)._file_read(
  38. fname, bin_size=False)
  39. except Exception:
  40. # Could not find the file in the file system either.
  41. return False
  42. else:
  43. s3_key = s3.Object(s3_bucket.name, fname)
  44. read = base64.b64encode(s3_key.get()['Body'].read())
  45. else:
  46. read = super(S3Attachment, self)._file_read(fname, bin_size=False)
  47. return read
  48. def _file_write(self, value, checksum):
  49. storage = self._storage()
  50. if storage[:5] == 's3://':
  51. access_key_id, secret_key, bucket_name, do_space_url = s3_helper.parse_bucket_url(
  52. storage)
  53. s3 = s3_helper.get_resource(
  54. access_key_id, secret_key, do_space_url)
  55. s3_bucket = self._connect_to_S3_bucket(s3, bucket_name)
  56. bin_value = base64.b64decode(value)
  57. fname = hashlib.sha1(bin_value).hexdigest()
  58. if encryption_enabled:
  59. s3.Object(s3_bucket.name, fname).put(Body=bin_value, ServerSideEncryption='AES256')
  60. else:
  61. s3.Object(s3_bucket.name, fname).put(Body=bin_value)
  62. else: # falling back on Odoo's local filestore
  63. fname = super(S3Attachment, self)._file_write(value, checksum)
  64. return fname