odoo-addon-fs-attachment-s3 19.0.1.1.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,178 @@
1
+ .. image:: https://odoo-community.org/readme-banner-image
2
+ :target: https://odoo-community.org/get-involved?utm_source=readme
3
+ :alt: Odoo Community Association
4
+
5
+ ================
6
+ Fs Attachment S3
7
+ ================
8
+
9
+ ..
10
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
11
+ !! This file is generated by oca-gen-addon-readme !!
12
+ !! changes will be overwritten. !!
13
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
14
+ !! source digest: sha256:fa6cd8ca3c6ea2e5d68db8c84d27f352c43b8082fc09986d14a15a7adbbc1050
15
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
16
+
17
+ .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
18
+ :target: https://odoo-community.org/page/development-status
19
+ :alt: Beta
20
+ .. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
21
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
22
+ :alt: License: AGPL-3
23
+ .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github
24
+ :target: https://github.com/OCA/storage/tree/19.0/fs_attachment_s3
25
+ :alt: OCA/storage
26
+ .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
27
+ :target: https://translation.odoo-community.org/projects/storage-19-0/storage-19-0-fs_attachment_s3
28
+ :alt: Translate me on Weblate
29
+ .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
30
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/storage&target_branch=19.0
31
+ :alt: Try me on Runboat
32
+
33
+ |badge1| |badge2| |badge3| |badge4| |badge5|
34
+
35
+ This module extends the functionality of
36
+ `fs_attachment <https://github.com/OCA/storage/tree/16.0/fs_attachment>`__
37
+ to better support Amazon S3 storage. It includes features such as:
38
+
39
+ - Special handling of X-Accel-Redirect headers for S3 storages.
40
+ - Options for using signed URLs in X-Accel-Redirect. (This is required
41
+ to be able to serve files from a private S3 bucket using
42
+ X-Accel-Redirect without exposing the files publicly.)
43
+ - Enforcing the mimetype of files stored in S3.
44
+
45
+ **Table of contents**
46
+
47
+ .. contents::
48
+ :local:
49
+
50
+ Configuration
51
+ =============
52
+
53
+ On the Odoo instance, go to *Settings* > *Technical* > *Storage* > *File
54
+ Storage*.
55
+
56
+ When you create a new storage for s3 or modify an existing one, when you
57
+ activate the option "Use X-Sendfile To Serve Internal Url", 2 additional
58
+ fields will appear:
59
+
60
+ - **S3 Uses Signed URL For X-Accel-Redirect**: If checked, the
61
+ X-Accel-Redirect path will be a signed URL, which is useful for S3
62
+ storages that require signed URLs for access.
63
+ - **S3 Signed URL Expiration**: The expiration time for the signed URL
64
+ in seconds. This field is only relevant if the previous option is
65
+ checked. By default, it is set to 30 seconds but it could be less
66
+ since the url generated into the X-Accel-Redirect process is directly
67
+ used by the web server to serve the file.
68
+
69
+ The value of these fields can also be set in the server environment
70
+ variables using the keys:
71
+
72
+ - *s3_uses_signed_url_for_x_sendfile*
73
+ - *s3_signed_url_expiration*
74
+
75
+ When the option "Use X-Sendfile To Serve Internal Url" is enabled, the
76
+ system will generate an X-Accel-Redirect header in the response to a
77
+ request to get a file. In the case of S3 storages, it will follow the
78
+ format:
79
+
80
+ .. code:: text
81
+
82
+ X-Accel-Redirect: /fs_x_sendfile/{scheme}/{host}/{path with query if any}
83
+
84
+ Where:
85
+
86
+ - ``{scheme}``: The URL scheme (http or https).
87
+ - ``{host}``: The host of the S3 storage.
88
+ - ``{path with query if any}``: The path to the file in the S3 storage,
89
+ including any query parameters. (Query parameters are set when the
90
+ ``s3_uses_signed_url_for_x_sendfile`` option is enabled.)
91
+
92
+ In order to serve files using X-Accel-Redirect, you must ensure that
93
+ your web server is configured to handle these headers correctly. This
94
+ typically involves setting up a location block in your web server
95
+ configuration that matches the X-Accel-Redirect path and proxies the
96
+ request to the S3 storage.
97
+
98
+ For example, if you are using Nginx, you would add a location block like
99
+ this:
100
+
101
+ .. code:: nginx
102
+
103
+
104
+ location ~ ^/fs_x_sendfile/(.*?)/(.*?)/(.*) {
105
+ internal;
106
+ set $url_scheme $1;
107
+ set $url_host $2;
108
+ set $url_path $3;
109
+ set $url $url_scheme://$url_host/$url_path;
110
+
111
+ proxy_pass $url$is_args$args;
112
+ proxy_set_header Host $url_host;
113
+ proxy_ssl_server_name on;
114
+
115
+ }
116
+
117
+ Unlike the standard implementation of X-Accel-Redirect on non S3
118
+ storages, the S3 implementation does not require a base URL to be set in
119
+ the storage configuration. The X-Accel-Redirect path is constructed
120
+ directly from the S3 storage's URL defined for the connection, the
121
+ directory name as bucket name, and the file path.
122
+
123
+ Bug Tracker
124
+ ===========
125
+
126
+ Bugs are tracked on `GitHub Issues <https://github.com/OCA/storage/issues>`_.
127
+ In case of trouble, please check there if your issue has already been reported.
128
+ If you spotted it first, help us to smash it by providing a detailed and welcomed
129
+ `feedback <https://github.com/OCA/storage/issues/new?body=module:%20fs_attachment_s3%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
130
+
131
+ Do not contact contributors directly about support or help with technical issues.
132
+
133
+ Credits
134
+ =======
135
+
136
+ Authors
137
+ -------
138
+
139
+ * ACSONE SA/NV
140
+
141
+ Contributors
142
+ ------------
143
+
144
+ - Laurent Mignon laurent.mignon@acsone.eu (https://www.acsone.eu)
145
+ - Stéphane Bidoul stephane.bidoul@acsone.eu (https://www.acsone.eu)
146
+
147
+ Other credits
148
+ -------------
149
+
150
+ The development of this module has been financially supported by:
151
+
152
+ - ACSONE SA/NV (https://www.acsone.eu)
153
+ - Alcyon Belux
154
+
155
+ Maintainers
156
+ -----------
157
+
158
+ This module is maintained by the OCA.
159
+
160
+ .. image:: https://odoo-community.org/logo.png
161
+ :alt: Odoo Community Association
162
+ :target: https://odoo-community.org
163
+
164
+ OCA, or the Odoo Community Association, is a nonprofit organization whose
165
+ mission is to support the collaborative development of Odoo features and
166
+ promote its widespread use.
167
+
168
+ .. |maintainer-lmignon| image:: https://github.com/lmignon.png?size=40px
169
+ :target: https://github.com/lmignon
170
+ :alt: lmignon
171
+
172
+ Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
173
+
174
+ |maintainer-lmignon|
175
+
176
+ This module is part of the `OCA/storage <https://github.com/OCA/storage/tree/19.0/fs_attachment_s3>`_ project on GitHub.
177
+
178
+ You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
@@ -0,0 +1 @@
1
+ from . import models
@@ -0,0 +1,22 @@
1
+ # Copyright 2025 ACSONE SA/NV
2
+ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3
+
4
+ {
5
+ "name": "Fs Attachment S3",
6
+ "summary": """Store attachments into S3 complient filesystem""",
7
+ "version": "19.0.1.1.0",
8
+ "license": "AGPL-3",
9
+ "author": "ACSONE SA/NV,Odoo Community Association (OCA)",
10
+ "website": "https://github.com/OCA/storage",
11
+ "depends": ["fs_attachment"],
12
+ "external_dependencies": {
13
+ "python": [
14
+ "fsspec[s3]",
15
+ ],
16
+ },
17
+ "data": [
18
+ "views/fs_storage.xml",
19
+ ],
20
+ "maintainers": ["lmignon"],
21
+ "installable": True,
22
+ }
@@ -0,0 +1,60 @@
1
+ # Translation of Odoo Server.
2
+ # This file contains the translation of the following modules:
3
+ # * fs_attachment_s3
4
+ #
5
+ msgid ""
6
+ msgstr ""
7
+ "Project-Id-Version: Odoo Server 19.0\n"
8
+ "Report-Msgid-Bugs-To: \n"
9
+ "Last-Translator: \n"
10
+ "Language-Team: \n"
11
+ "MIME-Version: 1.0\n"
12
+ "Content-Type: text/plain; charset=UTF-8\n"
13
+ "Content-Transfer-Encoding: \n"
14
+ "Plural-Forms: \n"
15
+
16
+ #. module: fs_attachment_s3
17
+ #: model:ir.model,name:fs_attachment_s3.model_ir_attachment
18
+ msgid "Attachment"
19
+ msgstr ""
20
+
21
+ #. module: fs_attachment_s3
22
+ #: model:ir.model.fields,field_description:fs_attachment_s3.field_fs_storage__display_name
23
+ #: model:ir.model.fields,field_description:fs_attachment_s3.field_ir_attachment__display_name
24
+ msgid "Display Name"
25
+ msgstr ""
26
+
27
+ #. module: fs_attachment_s3
28
+ #: model:ir.model,name:fs_attachment_s3.model_fs_storage
29
+ msgid "FS Storage"
30
+ msgstr ""
31
+
32
+ #. module: fs_attachment_s3
33
+ #: model:ir.model.fields,field_description:fs_attachment_s3.field_fs_storage__id
34
+ #: model:ir.model.fields,field_description:fs_attachment_s3.field_ir_attachment__id
35
+ msgid "ID"
36
+ msgstr ""
37
+
38
+ #. module: fs_attachment_s3
39
+ #: model:ir.model.fields,help:fs_attachment_s3.field_fs_storage__s3_uses_signed_url_for_x_sendfile
40
+ msgid ""
41
+ "If checked, the storage will use signed URLs for attachments when using "
42
+ "X-Accel-Redirect. This is useful for S3 storage where the file path is not "
43
+ "directly accessible without authentication."
44
+ msgstr ""
45
+
46
+ #. module: fs_attachment_s3
47
+ #: model:ir.model.fields,field_description:fs_attachment_s3.field_fs_storage__s3_signed_url_expiration
48
+ msgid "Signed URL Expiration (seconds)"
49
+ msgstr ""
50
+
51
+ #. module: fs_attachment_s3
52
+ #: model:ir.model.fields,help:fs_attachment_s3.field_fs_storage__s3_signed_url_expiration
53
+ msgid ""
54
+ "The expiration time for the signed URL in seconds. Default is 30 seconds."
55
+ msgstr ""
56
+
57
+ #. module: fs_attachment_s3
58
+ #: model:ir.model.fields,field_description:fs_attachment_s3.field_fs_storage__s3_uses_signed_url_for_x_sendfile
59
+ msgid "Use signed URL for X-Accel-Redirect"
60
+ msgstr ""
@@ -0,0 +1,49 @@
1
+ # Translation of Odoo Server.
2
+ # This file contains the translation of the following modules:
3
+ # * fs_attachment_s3
4
+ #
5
+ msgid ""
6
+ msgstr ""
7
+ "Project-Id-Version: Odoo Server 18.0\n"
8
+ "Report-Msgid-Bugs-To: \n"
9
+ "Last-Translator: Automatically generated\n"
10
+ "Language-Team: none\n"
11
+ "Language: it\n"
12
+ "MIME-Version: 1.0\n"
13
+ "Content-Type: text/plain; charset=UTF-8\n"
14
+ "Content-Transfer-Encoding: \n"
15
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
16
+
17
+ #. module: fs_attachment_s3
18
+ #: model:ir.model,name:fs_attachment_s3.model_ir_attachment
19
+ msgid "Attachment"
20
+ msgstr ""
21
+
22
+ #. module: fs_attachment_s3
23
+ #: model:ir.model,name:fs_attachment_s3.model_fs_storage
24
+ msgid "FS Storage"
25
+ msgstr ""
26
+
27
+ #. module: fs_attachment_s3
28
+ #: model:ir.model.fields,help:fs_attachment_s3.field_fs_storage__s3_uses_signed_url_for_x_sendfile
29
+ msgid ""
30
+ "If checked, the storage will use signed URLs for attachments when using "
31
+ "X-Accel-Redirect. This is useful for S3 storage where the file path is not "
32
+ "directly accessible without authentication."
33
+ msgstr ""
34
+
35
+ #. module: fs_attachment_s3
36
+ #: model:ir.model.fields,field_description:fs_attachment_s3.field_fs_storage__s3_signed_url_expiration
37
+ msgid "Signed URL Expiration (seconds)"
38
+ msgstr ""
39
+
40
+ #. module: fs_attachment_s3
41
+ #: model:ir.model.fields,help:fs_attachment_s3.field_fs_storage__s3_signed_url_expiration
42
+ msgid ""
43
+ "The expiration time for the signed URL in seconds. Default is 30 seconds."
44
+ msgstr ""
45
+
46
+ #. module: fs_attachment_s3
47
+ #: model:ir.model.fields,field_description:fs_attachment_s3.field_fs_storage__s3_uses_signed_url_for_x_sendfile
48
+ msgid "Use signed URL for X-Accel-Redirect"
49
+ msgstr ""
@@ -0,0 +1,2 @@
1
+ from . import fs_storage
2
+ from . import ir_attachment
@@ -0,0 +1,54 @@
1
+ # Copyright 2025 ACSONE SA/NV
2
+ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3
+
4
+ import fsspec.asyn
5
+
6
+ from odoo import api, fields, models
7
+
8
+
9
+ class FsStorage(models.Model):
10
+ _inherit = "fs.storage"
11
+
12
+ s3_uses_signed_url_for_x_sendfile = fields.Boolean(
13
+ string="Use signed URL for X-Accel-Redirect",
14
+ help="If checked, the storage will use signed URLs for attachments "
15
+ "when using X-Accel-Redirect. This is useful for S3 storage where the "
16
+ "file path is not directly accessible without authentication.",
17
+ )
18
+ s3_signed_url_expiration = fields.Integer(
19
+ string="Signed URL Expiration (seconds)",
20
+ default=30,
21
+ help="The expiration time for the signed URL in seconds. "
22
+ "Default is 30 seconds.",
23
+ )
24
+
25
+ @property
26
+ def _server_env_fields(self):
27
+ """Override to include S3 specific fields."""
28
+ fields = super()._server_env_fields
29
+ fields.update(
30
+ {
31
+ "s3_uses_signed_url_for_x_sendfile": {},
32
+ "s3_signed_url_expiration": {},
33
+ }
34
+ )
35
+ return fields
36
+
37
+ @property
38
+ def is_s3_storage(self):
39
+ """Check if the storage is an S3 storage."""
40
+ self.ensure_one()
41
+ return hasattr(self._get_root_filesystem(self.fs), "s3")
42
+
43
+ @api.model
44
+ def _s3_call_generate_presigned_url(self, s3_client, *args, **kwargs):
45
+ """Generate a presigned URL for S3 operations."""
46
+ # s3fs uses aiobotocore as s3 client, which is asynchronous.
47
+ # We need to run the async function in a synchronous context.
48
+ return fsspec.asyn.sync(
49
+ fsspec.asyn.get_loop(),
50
+ s3_client.generate_presigned_url,
51
+ *args,
52
+ timeout=None,
53
+ **kwargs,
54
+ )
@@ -0,0 +1,81 @@
1
+ # Copyright 2025 ACSONE SA/NV
2
+ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3
+ from urllib.parse import urlparse
4
+
5
+ from odoo import models
6
+
7
+
8
+ class IrAttachment(models.Model):
9
+ _inherit = "ir.attachment"
10
+
11
+ def _storage_write_option(self, fs):
12
+ option = super()._storage_write_option(fs)
13
+ mimetype = self.env.context.get("mimetype")
14
+ if mimetype:
15
+ root_fs = self.env["fs.storage"]._get_root_filesystem(fs)
16
+ if hasattr(root_fs, "s3"):
17
+ option["ContentType"] = mimetype
18
+ return option
19
+
20
+ def _get_x_sendfile_path(self):
21
+ self.ensure_one()
22
+ storage = self.fs_storage_id
23
+ if storage.is_s3_storage:
24
+ return self._get_s3_x_sendfile_path()
25
+ return super()._get_x_sendfile_path()
26
+
27
+ def _fs_use_x_sendfile(self):
28
+ self.ensure_one()
29
+ storage = self.fs_storage_id
30
+ if storage.is_s3_storage:
31
+ return storage.use_x_sendfile_to_serve_internal_url
32
+ return super()._fs_use_x_sendfile()
33
+
34
+ def _get_s3_x_sendfile_path(self):
35
+ """Generate the X-Accel-Redirect path for S3 storage.
36
+
37
+ This method is used to generate the path for S3 storage when using
38
+ X-Accel-Redirect. It constructs the path based on the S3 bucket and
39
+ file path, ensuring that it is compatible with the S3 storage
40
+ configuration and the Odoo file storage system.
41
+
42
+ Args:
43
+ attachment (IrAttachment): The attachment record for which the
44
+ X-Accel-Redirect path is being generated.
45
+ Returns:
46
+ str: The X-Accel-Redirect path for the S3 storage.
47
+
48
+ The path is formatted as:
49
+ /fs_x_sendfile/<scheme>/<netloc>/<path>
50
+
51
+ where:
52
+ - `<scheme>` is the scheme of the base URL (e.g., 'https').
53
+ - `<netloc>` is the netloc of the base URL (e.g., 's3.amazonaws.com').
54
+ - `<path>` is the path to the file in the S3 bucket, including the
55
+ bucket name
56
+ """
57
+ fs, storage_code, file_path = self._get_fs_parts()
58
+ storage = self.env["fs.storage"].sudo().get_by_code(storage_code)
59
+ root_fs = storage._get_root_filesystem(fs)
60
+ s3_client = root_fs.s3
61
+ bucket_name = storage.directory_path.strip("/").rstrip("/")
62
+ if storage.s3_uses_signed_url_for_x_sendfile:
63
+ file_url = storage._s3_call_generate_presigned_url(
64
+ s3_client,
65
+ "get_object",
66
+ Params={"Bucket": bucket_name, "Key": file_path},
67
+ ExpiresIn=storage.s3_signed_url_expiration,
68
+ )
69
+ else:
70
+ file_url = (
71
+ f"{s3_client.meta.endpoint_url.rstrip('/')}/"
72
+ f"{bucket_name}/{file_path.lstrip('/')}"
73
+ )
74
+
75
+ parsed_url = urlparse(file_url)
76
+ path = parsed_url.path.strip("/")
77
+ query = parsed_url.query
78
+ redirect_path = f"/fs_x_sendfile/{parsed_url.scheme}/{parsed_url.netloc}/{path}"
79
+ if query:
80
+ redirect_path += f"?{query}"
81
+ return redirect_path
@@ -0,0 +1,64 @@
1
+ On the Odoo instance, go to *Settings* > *Technical* > *Storage* > *File Storage*.
2
+
3
+ When you create a new storage for s3 or modify an existing one, when you activate
4
+ the option "Use X-Sendfile To Serve Internal Url", 2 additional fields will appear:
5
+
6
+ - **S3 Uses Signed URL For X-Accel-Redirect**: If checked, the X-Accel-Redirect
7
+ path will be a signed URL, which is useful for S3 storages that require
8
+ signed URLs for access.
9
+ - **S3 Signed URL Expiration**: The expiration time for the signed URL in seconds.
10
+ This field is only relevant if the previous option is checked. By default,
11
+ it is set to 30 seconds but it could be less since the url generated into
12
+ the X-Accel-Redirect process is directly used by the web server to serve the file.
13
+
14
+ The value of these fields can also be set in the server environment variables using
15
+ the keys:
16
+
17
+ - *s3_uses_signed_url_for_x_sendfile*
18
+ - *s3_signed_url_expiration*
19
+
20
+ When the option "Use X-Sendfile To Serve Internal Url" is enabled, the system will
21
+ generate an X-Accel-Redirect header in the response to a request to get a file.
22
+ In the case of S3 storages, it will follow the format:
23
+
24
+ ```text
25
+ X-Accel-Redirect: /fs_x_sendfile/{scheme}/{host}/{path with query if any}
26
+ ```
27
+
28
+ Where:
29
+
30
+ - `{scheme}`: The URL scheme (http or https).
31
+ - `{host}`: The host of the S3 storage.
32
+ - `{path with query if any}`: The path to the file in the S3 storage,
33
+ including any query parameters. (Query parameters are set when the
34
+ `s3_uses_signed_url_for_x_sendfile` option is enabled.)
35
+
36
+ In order to serve files using X-Accel-Redirect, you must ensure that your
37
+ web server is configured to handle these headers correctly. This typically
38
+ involves setting up a location block in your web server configuration that
39
+ matches the X-Accel-Redirect path and proxies the request to the S3 storage.
40
+
41
+ For example, if you are using Nginx, you would add a location block like this:
42
+
43
+ ```nginx
44
+
45
+ location ~ ^/fs_x_sendfile/(.*?)/(.*?)/(.*) {
46
+ internal;
47
+ set $url_scheme $1;
48
+ set $url_host $2;
49
+ set $url_path $3;
50
+ set $url $url_scheme://$url_host/$url_path;
51
+
52
+ proxy_pass $url$is_args$args;
53
+ proxy_set_header Host $url_host;
54
+ proxy_ssl_server_name on;
55
+
56
+ }
57
+ ```
58
+
59
+
60
+ Unlike the standard implementation of X-Accel-Redirect on non S3 storages,
61
+ the S3 implementation does not require a base URL to be set in the storage
62
+ configuration. The X-Accel-Redirect path is constructed directly from the
63
+ S3 storage's URL defined for the connection, the directory name as
64
+ bucket name, and the file path.
@@ -0,0 +1,2 @@
1
+ - Laurent Mignon <laurent.mignon@acsone.eu> (https://www.acsone.eu)
2
+ - Stéphane Bidoul <stephane.bidoul@acsone.eu> (https://www.acsone.eu)
@@ -0,0 +1,4 @@
1
+ The development of this module has been financially supported by:
2
+
3
+ - ACSONE SA/NV (https://www.acsone.eu)
4
+ - Alcyon Belux
@@ -0,0 +1,7 @@
1
+ This module extends the functionality of [fs_attachment](https://github.com/OCA/storage/tree/16.0/fs_attachment)
2
+ to better support Amazon S3 storage. It includes features such as:
3
+
4
+ - Special handling of X-Accel-Redirect headers for S3 storages.
5
+ - Options for using signed URLs in X-Accel-Redirect. (This is required to be able to serve files from a private S3 bucket
6
+ using X-Accel-Redirect without exposing the files publicly.)
7
+ - Enforcing the mimetype of files stored in S3.