Odoo18-Base/addons/cloud_storage_google/models/ir_attachment.py

84 lines
3.7 KiB
Python
Raw Permalink Normal View History

2025-01-06 10:57:38 +07:00
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import json
import re
from urllib.parse import unquote, quote
try:
from google.oauth2 import service_account
from google.auth.transport.requests import Request
except ImportError:
service_account = Request = None
from odoo import models
from odoo.exceptions import ValidationError
from ..utils.cloud_storage_google_utils import generate_signed_url_v4
CloudStorageGoogleCredentials = {} # {db_name: (account_info, credential)}
def get_cloud_storage_google_credential(env):
""" Get the credentials object of currently used account info.
This method is cached to because from_service_account_info is slow.
"""
cached_account_info, cached_credential = CloudStorageGoogleCredentials.get(env.registry.db_name, (None, None))
account_info = json.loads(env['ir.config_parameter'].sudo().get_param('cloud_storage_google_account_info'))
if cached_account_info == account_info:
return cached_credential
credential = service_account.Credentials.from_service_account_info(account_info)
CloudStorageGoogleCredentials[env.registry.db_name] = (account_info, credential)
return credential
class IrAttachment(models.Model):
_inherit = 'ir.attachment'
_cloud_storage_google_url_pattern = re.compile(r'https://storage\.googleapis\.com/(?P<bucket_name>[\w\-.]+)/(?P<blob_name>[^?]+)')
def _get_cloud_storage_google_info(self):
match = self._cloud_storage_google_url_pattern.match(self.url)
if not match:
raise ValidationError('%s is not a valid Google Cloud Storage URL.', self.url)
return {
'bucket_name': match['bucket_name'],
'blob_name': unquote(match['blob_name']),
}
def _generate_cloud_storage_google_url(self, blob_name):
bucket_name = self.env['ir.config_parameter'].get_param('cloud_storage_google_bucket_name')
return f"https://storage.googleapis.com/{bucket_name}/{quote(blob_name)}"
def _generate_cloud_storage_google_signed_url(self, bucket_name, blob_name, **kwargs):
quote_blob_name = quote(blob_name)
return generate_signed_url_v4(
credentials=get_cloud_storage_google_credential(self.env),
resource=f'/{bucket_name}/{quote_blob_name}',
**kwargs,
)
# OVERRIDES
def _generate_cloud_storage_url(self):
if self.env['ir.config_parameter'].sudo().get_param('cloud_storage_provider') != 'google':
return super()._generate_cloud_storage_url()
blob_name = self._generate_cloud_storage_blob_name()
return self._generate_cloud_storage_google_url(blob_name)
def _generate_cloud_storage_download_info(self):
if self.env['ir.config_parameter'].sudo().get_param('cloud_storage_provider') != 'google':
return super()._generate_cloud_storage_download_info()
info = self._get_cloud_storage_google_info()
return {
'url': self._generate_cloud_storage_google_signed_url(info['bucket_name'], info['blob_name'], method='GET', expiration=self._cloud_storage_download_url_time_to_expiry),
'time_to_expiry': self._cloud_storage_download_url_time_to_expiry,
}
def _generate_cloud_storage_upload_info(self):
if self.env['ir.config_parameter'].sudo().get_param('cloud_storage_provider') != 'google':
return super()._generate_cloud_storage_upload_info()
info = self._get_cloud_storage_google_info()
return {
'url': self._generate_cloud_storage_google_signed_url(info['bucket_name'], info['blob_name'], method='PUT', expiration=self._cloud_storage_upload_url_time_to_expiry),
'method': 'PUT',
'response_status': 200,
}