From 5ece0924a62ae3cd7f18bc9377b82e794b86ffaa Mon Sep 17 00:00:00 2001 From: Github Actions Date: Tue, 10 Mar 2020 10:38:53 +0000 Subject: [PATCH 1/9] :construction_worker_man: sync DINAR Pushed from https://github.com/itpp-labs/DINAR/.github/workflows/fork2repos.yml --- .github/workflows/DINAR-pr.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/DINAR-pr.yml b/.github/workflows/DINAR-pr.yml index e0a365677..9464fb9e7 100644 --- a/.github/workflows/DINAR-pr.yml +++ b/.github/workflows/DINAR-pr.yml @@ -178,14 +178,18 @@ jobs: run: | # TODO https://github.com/itpp-labs/DINAR/issues/42 exit 1 + - name: Prepare Artifact Folder + run: | + mkdir new-deps/ + # create dummy file to be sure that Artifact will be uploaded + echo ok > new-deps/.empty - name: Prepare DINAR with additional dependencies if: env.PR_MODULES_DEPS != '' || env.PR_DEPS != '' run: | # Save artifacts for local run and for integrations Tests bash DINAR/workflow-files/save-docker-layers.sh new-deps/ - echo $MODULES > new-deps/modules.txt + echo "${{ env.PR_MODULES_DEPS }}" > new-deps/modules.txt - name: Save DINAR with dependencies - if: env.PR_MODULES_DEPS != '' || env.PR_DEPS != '' uses: actions/upload-artifact@v1 with: name: new-deps @@ -227,9 +231,10 @@ jobs: name: new-deps path: new-deps/ - name: Check artifact - if: failure() run: | - echo "::set-env name=ARTIFACT::failure" + if [ ! -f new-deps/modules.txt ]; then + echo "::set-env name=ARTIFACT::empty" + fi - name: Configure Docker run: | bash DINAR/workflow-files/configure-docker.sh ${{ secrets.DINAR_TOKEN || secrets.GITHUB_TOKEN }} @@ -245,7 +250,7 @@ jobs: docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml pull docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml up --no-start - name: Apply new-deps artifact - if: env.ARTIFACT != 'failure' + if: env.ARTIFACT != 'empty' run: | bash DINAR/workflow-files/load-docker-layers.sh new-deps/ From 36ee27b9d0a2e58f99054207b4ae44a470a3e3ee Mon Sep 17 00:00:00 2001 From: Github Actions Date: Wed, 11 Mar 2020 13:06:08 +0000 Subject: [PATCH 2/9] :construction_worker_man: sync DINAR Pushed from https://github.com/itpp-labs/DINAR/.github/workflows/fork2repos.yml --- .github/workflows/repo2store.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/repo2store.yml b/.github/workflows/repo2store.yml index ea918a922..5fe3fc977 100644 --- a/.github/workflows/repo2store.yml +++ b/.github/workflows/repo2store.yml @@ -6,7 +6,7 @@ on: jobs: repo2store: runs-on: ubuntu-latest - if: "! endsWith(github.repository, '-store')" + if: "! endsWith(github.repository, '-store') && startsWith(github.repository, 'itpp-labs/')" steps: - name: Checkout REPO uses: actions/checkout@v2-beta From 5eacafceee633ed29cc04094541d726b4248642b Mon Sep 17 00:00:00 2001 From: Github Actions Date: Wed, 11 Mar 2020 13:15:45 +0000 Subject: [PATCH 3/9] :construction_worker_man: sync DINAR Pushed from https://github.com/itpp-labs/DINAR/.github/workflows/fork2repos.yml --- .github/workflows/repo2store.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/repo2store.yml b/.github/workflows/repo2store.yml index 5fe3fc977..39116651c 100644 --- a/.github/workflows/repo2store.yml +++ b/.github/workflows/repo2store.yml @@ -6,7 +6,9 @@ on: jobs: repo2store: runs-on: ubuntu-latest - if: "! endsWith(github.repository, '-store') && startsWith(github.repository, 'itpp-labs/')" + if: + "! endsWith(github.repository, '-store') && startsWith(github.repository, + 'itpp-labs/')" steps: - name: Checkout REPO uses: actions/checkout@v2-beta From 4a4d0e112812fb721ef1891f166172ec089aafb6 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Wed, 11 Mar 2020 13:49:58 +0000 Subject: [PATCH 4/9] :construction_worker_man: sync DINAR Pushed from https://github.com/itpp-labs/DINAR/.github/workflows/fork2repos.yml --- .DINAR/build-date.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 .DINAR/build-date.txt diff --git a/.DINAR/build-date.txt b/.DINAR/build-date.txt new file mode 100644 index 000000000..d0fa445ef --- /dev/null +++ b/.DINAR/build-date.txt @@ -0,0 +1 @@ +March 11, 2020 From 3b7e45a5a7fb9a2bab9bafb6d5de53bc773b2bfa Mon Sep 17 00:00:00 2001 From: Github Actions Date: Wed, 11 Mar 2020 14:30:41 +0000 Subject: [PATCH 5/9] :construction_worker_man: sync DINAR Pushed from https://github.com/itpp-labs/DINAR/.github/workflows/fork2repos.yml --- .github/workflows/DINAR-pr.yml | 3 +++ .github/workflows/DINAR.yml | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/DINAR-pr.yml b/.github/workflows/DINAR-pr.yml index 9464fb9e7..d595c2a43 100644 --- a/.github/workflows/DINAR-pr.yml +++ b/.github/workflows/DINAR-pr.yml @@ -144,6 +144,7 @@ jobs: - name: Configure docker run: | bash DINAR/workflow-files/configure-docker.sh ${{ secrets.DINAR_TOKEN || secrets.GITHUB_TOKEN }} + echo "::set-env name=PR_FILES::../../REPO" - name: Install python tools run: | pip install plumbum PyGithub pyyaml @@ -158,6 +159,7 @@ jobs: ODOO_BASE_MODULES=$(docker inspect \ --format '{{ index .Config.Labels "dinar.odoo.modules"}}' \ dinar_odoo_1) + echo "ODOO_BASE_MODULES=$ODOO_BASE_MODULES" # sets environment variables that available in next steps via $ {{ env.PR_... }} notation cd REPO @@ -238,6 +240,7 @@ jobs: - name: Configure Docker run: | bash DINAR/workflow-files/configure-docker.sh ${{ secrets.DINAR_TOKEN || secrets.GITHUB_TOKEN }} + echo "::set-env name=PR_FILES::../../REPO" - name: Analyze PR run: | # sets environment variables that available in next steps via $ {{ env.PR_... }} notation diff --git a/.github/workflows/DINAR.yml b/.github/workflows/DINAR.yml index c18943a0d..089d610a2 100644 --- a/.github/workflows/DINAR.yml +++ b/.github/workflows/DINAR.yml @@ -63,7 +63,6 @@ jobs: password: ${{ env.REGISTRY_PASSWORD }} buildargs: ODOO_VERSION,AGGREGATE,PIP_INSTALL_ODOO,CLEAN,COMPILE,LOCAL_CUSTOM_DIR workdir: REPO/.DINAR/ - cache: ${{ github.event_name != 'schedule' }} - name: Install python tools run: | pip install plumbum pyyaml From 848e0295e5d99a1011b387a0368dfc9a3824a6a4 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Wed, 11 Mar 2020 14:31:37 +0000 Subject: [PATCH 6/9] :construction_worker_man: sync DINAR Pushed from https://github.com/itpp-labs/DINAR/.github/workflows/fork2repos.yml --- .DINAR/build-date.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.DINAR/build-date.txt b/.DINAR/build-date.txt index d0fa445ef..d818938fa 100644 --- a/.DINAR/build-date.txt +++ b/.DINAR/build-date.txt @@ -1 +1 @@ -March 11, 2020 +March 11, 2020 -- 19:31 From 6213f7fb0964fd9b276338085f7ff3214093a4db Mon Sep 17 00:00:00 2001 From: Ivan Yelizariev Date: Tue, 10 Mar 2020 11:44:46 +0500 Subject: [PATCH 7/9] :book: Distribute under MIT license If you made a contribution and don't agree with this change please open an issue --- hr_public_holidays_ics_import/__manifest__.py | 2 +- ir_attachment_force_storage/__manifest__.py | 2 +- ir_attachment_s3/__manifest__.py | 2 +- ir_attachment_url/__manifest__.py | 2 +- project_task_subtask/__manifest__.py | 2 +- reminder_crm_next_action_time/__manifest__.py | 2 +- theme_kit/__manifest__.py | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hr_public_holidays_ics_import/__manifest__.py b/hr_public_holidays_ics_import/__manifest__.py index e2521c9d5..80bf0d2d0 100644 --- a/hr_public_holidays_ics_import/__manifest__.py +++ b/hr_public_holidays_ics_import/__manifest__.py @@ -7,7 +7,7 @@ "vesion": "11.0.1.0.0", "author": "IT-Projects LLC, Ildar Nasyrov", "website": "https://it-projects.info", - "license": "AGPL-3", + "license": "Other OSI approved licence", # MIT "price": 9.00, "currency": "EUR", "depends": ["hr_public_holidays"], diff --git a/ir_attachment_force_storage/__manifest__.py b/ir_attachment_force_storage/__manifest__.py index d4dfedea3..6f0f9b807 100644 --- a/ir_attachment_force_storage/__manifest__.py +++ b/ir_attachment_force_storage/__manifest__.py @@ -2,7 +2,7 @@ "name": "Force move attachments to DB storage", "version": "11.0.1.0.0", "author": "IT-Projects LLC, Ivan Yelizariev", - "license": "AGPL-3", + "license": "Other OSI approved licence", # MIT "category": "Tools", "website": "https://yelizariev.github.io", "depends": ["attachment_large_object"], diff --git a/ir_attachment_s3/__manifest__.py b/ir_attachment_s3/__manifest__.py index d85ace5eb..355e5072b 100644 --- a/ir_attachment_s3/__manifest__.py +++ b/ir_attachment_s3/__manifest__.py @@ -7,7 +7,7 @@ "application": False, "author": "IT-Projects LLC, Ildar Nasyrov", "website": "https://it-projects.info", - "license": "AGPL-3", + "license": "Other OSI approved licence", # MIT "price": 200.00, "currency": "EUR", "depends": ["base_setup", "ir_attachment_url"], diff --git a/ir_attachment_url/__manifest__.py b/ir_attachment_url/__manifest__.py index 1a4b91a02..6ce7905d9 100644 --- a/ir_attachment_url/__manifest__.py +++ b/ir_attachment_url/__manifest__.py @@ -7,7 +7,7 @@ "application": False, "author": "IT-Projects LLC, Ildar Nasyrov", "website": "https://it-projects.info", - "license": "AGPL-3", + "license": "Other OSI approved licence", # MIT "price": 30.00, "currency": "EUR", "depends": ["web"], diff --git a/project_task_subtask/__manifest__.py b/project_task_subtask/__manifest__.py index b32344084..88e0ff20d 100644 --- a/project_task_subtask/__manifest__.py +++ b/project_task_subtask/__manifest__.py @@ -14,7 +14,7 @@ "author": "IT-Projects LLC, Manaev Rafael", "support": "apps@itpp.dev", "website": "https://it-projects.info", - "license": "GPL-3", + "license": "Other OSI approved licence", # MIT "price": 69.00, "currency": "EUR", "depends": ["base", "project"], diff --git a/reminder_crm_next_action_time/__manifest__.py b/reminder_crm_next_action_time/__manifest__.py index 7e5f28f15..9af1a1c01 100644 --- a/reminder_crm_next_action_time/__manifest__.py +++ b/reminder_crm_next_action_time/__manifest__.py @@ -8,7 +8,7 @@ "author": "IT-Projects LLC, Dinar Gabbasov", "support": "apps@itpp.dev", "website": "https://twitter.com/gabbasov_dinar", - "license": "GPL-3", + "license": "Other OSI approved licence", # MIT "price": 21.00, "currency": "EUR", "depends": ["reminder_base", "crm"], diff --git a/theme_kit/__manifest__.py b/theme_kit/__manifest__.py index df9192139..70353abae 100644 --- a/theme_kit/__manifest__.py +++ b/theme_kit/__manifest__.py @@ -11,7 +11,7 @@ "application": False, "author": "IT-Projects LLC, Ivan Yelizariev", "website": "https://it-projects.info", - "license": "GPL-3", + "license": "Other OSI approved licence", # MIT "price": 50.00, "currency": "EUR", "depends": ["web_debranding", "web_login_background", "web_widget_color"], From 3c4a509d6b4a80ee88c3523793265d701be93424 Mon Sep 17 00:00:00 2001 From: Ivan Yelizariev Date: Tue, 10 Mar 2020 13:53:50 +0500 Subject: [PATCH 8/9] :shield: add server_wide_mod --- .DINAR/config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.DINAR/config.yaml b/.DINAR/config.yaml index 24e4c0f3a..36d06cf94 100644 --- a/.DINAR/config.yaml +++ b/.DINAR/config.yaml @@ -9,3 +9,5 @@ addons: server_wide_modules: - web + - ir_attachment_url + - ir_config_parameter_multi_company From 98e39889eda6217de3ce531f1010ef43340074f3 Mon Sep 17 00:00:00 2001 From: Eugene Molotov Date: Tue, 10 Mar 2020 18:14:28 +0500 Subject: [PATCH 9/9] :tada: ir_attachment_google_drive --- ir_attachment_google_drive/README.rst | 51 ++++++ ir_attachment_google_drive/__init__.py | 3 + ir_attachment_google_drive/__manifest__.py | 39 ++++ ir_attachment_google_drive/doc/changelog.rst | 4 + ir_attachment_google_drive/doc/index.rst | 35 ++++ ir_attachment_google_drive/models/__init__.py | 4 + .../models/ir_attachment.py | 173 ++++++++++++++++++ .../models/res_config_settings.py | 37 ++++ .../static/description/icon.png | Bin 0 -> 3035 bytes .../views/res_config_settings_views.xml | 18 ++ 10 files changed, 364 insertions(+) create mode 100644 ir_attachment_google_drive/README.rst create mode 100644 ir_attachment_google_drive/__init__.py create mode 100644 ir_attachment_google_drive/__manifest__.py create mode 100644 ir_attachment_google_drive/doc/changelog.rst create mode 100644 ir_attachment_google_drive/doc/index.rst create mode 100644 ir_attachment_google_drive/models/__init__.py create mode 100644 ir_attachment_google_drive/models/ir_attachment.py create mode 100644 ir_attachment_google_drive/models/res_config_settings.py create mode 100644 ir_attachment_google_drive/static/description/icon.png create mode 100644 ir_attachment_google_drive/views/res_config_settings_views.xml diff --git a/ir_attachment_google_drive/README.rst b/ir_attachment_google_drive/README.rst new file mode 100644 index 000000000..5ccb2c999 --- /dev/null +++ b/ir_attachment_google_drive/README.rst @@ -0,0 +1,51 @@ +.. image:: https://img.shields.io/badge/license-MIT-blue.svg + :target: https://opensource.org/licenses/MIT + :alt: License: MIT + +================================= + Google Drive Attachment Storage +================================= + +TODO description intro + +TODO detailed description + +Credits +======= + +Contributors +------------ +* `Eugene Molotov `__: + + * :one::zero: init version of the module + +Sponsors +-------- +* `IT-Projects LLC `__ + +Maintainers +----------- +* `IT-Projects LLC `__ + + To get a guaranteed support + you are kindly requested to purchase the module + at `odoo apps store `__. + + Thank you for understanding! + + `IT-Projects Team `__ + +Further information +=================== + +Demo: http://runbot.it-projects.info/demo/misc-addons/11.0 + +HTML Description: https://apps.odoo.com/apps/modules/11.0/ir_attachment_google_drive/ + +Usage instructions: ``_ + +Changelog: ``_ + +Notifications on updates: `via Atom `_, `by Email `_ + +Tested on Odoo 11.0 a827d3015c6994bc3c779f9ba5cd270d8bdd8edd diff --git a/ir_attachment_google_drive/__init__.py b/ir_attachment_google_drive/__init__.py new file mode 100644 index 000000000..1d99e04b6 --- /dev/null +++ b/ir_attachment_google_drive/__init__.py @@ -0,0 +1,3 @@ +# License MIT (https://opensource.org/licenses/MIT). + +from . import models diff --git a/ir_attachment_google_drive/__manifest__.py b/ir_attachment_google_drive/__manifest__.py new file mode 100644 index 000000000..5a61de218 --- /dev/null +++ b/ir_attachment_google_drive/__manifest__.py @@ -0,0 +1,39 @@ +# Copyright 2020 Eugene Molotov +# License MIT (https://opensource.org/licenses/MIT). + +{ + "name": """Google Drive Attachment Storage""", + "summary": """TODO description intro""", + "category": "Extra Tools", + # "live_test_url": "http://apps.it-projects.info/shop/product/DEMO-URL?version=12.0", + "images": [], + "version": "11.0.1.0.0", + "application": False, + "author": "IT-Projects LLC, Eugene Molotov", + "support": "apps@it-projects.info", + "website": "https://apps.odoo.com/apps/modules/11.0/ir_attachment_google_drive/", + "license": "Other OSI approved licence", # MIT + # "price": 9.00, + # "currency": "EUR", + "depends": ["base", "google_drive"], + "external_dependencies": {"python": [], "bin": []}, + "data": ["views/res_config_settings_views.xml"], + "demo": [], + "qweb": [], + "post_load": None, + "pre_init_hook": None, + "post_init_hook": None, + "uninstall_hook": None, + "auto_install": False, + "installable": True, + # "demo_title": "Google Drive Attachment Storage", + # "demo_addons": [ + # ], + # "demo_addons_hidden": [ + # ], + # "demo_url": "DEMO-URL", + # "demo_summary": "TODO description intro", + # "demo_images": [ + # "images/MAIN_IMAGE", + # ] +} diff --git a/ir_attachment_google_drive/doc/changelog.rst b/ir_attachment_google_drive/doc/changelog.rst new file mode 100644 index 000000000..5583eb326 --- /dev/null +++ b/ir_attachment_google_drive/doc/changelog.rst @@ -0,0 +1,4 @@ +`1.0.0` +------- + +- **Init version** diff --git a/ir_attachment_google_drive/doc/index.rst b/ir_attachment_google_drive/doc/index.rst new file mode 100644 index 000000000..d3870a75f --- /dev/null +++ b/ir_attachment_google_drive/doc/index.rst @@ -0,0 +1,35 @@ +================================= + Google Drive Attachment Storage +================================= + +Installation +============ +{Instruction about things to do before actual installation} + +* {OPTIONAL }`Activate longpolling `__ +* {Additional notes if any} +* `Install `__ this module in a usual way + +Configuration +============= + +{Instruction how to configure the module before start to use it} + +* `Log in as SUPERUSER `__ +* `Activate Developer Mode `__ +* Open menu ``[[ {Menu} ]] >> {Submenu} >> {Subsubmenu}`` +* Click ``[{Button Name}]`` + +Usage +===== + +{Instruction for daily usage. It should describe how to check that module works. What shall user do and what would user get.} + +* Open menu ``[[ {Menu} ]]>> {Submenu} >> {Subsubmenu}`` +* Click ``[{Button Name}]`` +* RESULT: {what user gets, how the modules changes default behaviour} + +Uninstallation +============== + +{Optional section for uninstallation notes. Delete it if you don't have notes for uninstallation.} diff --git a/ir_attachment_google_drive/models/__init__.py b/ir_attachment_google_drive/models/__init__.py new file mode 100644 index 000000000..fcf9596c4 --- /dev/null +++ b/ir_attachment_google_drive/models/__init__.py @@ -0,0 +1,4 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +from . import ir_attachment +from . import res_config_settings diff --git a/ir_attachment_google_drive/models/ir_attachment.py b/ir_attachment_google_drive/models/ir_attachment.py new file mode 100644 index 000000000..46a64ce2d --- /dev/null +++ b/ir_attachment_google_drive/models/ir_attachment.py @@ -0,0 +1,173 @@ +# Copyright 2020 Eugene Molotov +# License MIT (https://opensource.org/licenses/MIT). + +import base64 +import json +import logging + +import requests +from urllib3.fields import RequestField +from urllib3.filepost import choose_boundary, encode_multipart_formdata + +from odoo import api, models +from odoo.tools import human_size +from odoo.tools.safe_eval import safe_eval + +from odoo.addons.google_account.models.google_service import TIMEOUT + +_logger = logging.getLogger(__name__) +_logger.setLevel(logging.DEBUG) + +PREFIX = "google_drive://" + + +# https://stackoverflow.com/a/47682897 +def encode_multipart_related(fields, boundary=None): + if boundary is None: + boundary = choose_boundary() + + body, _ = encode_multipart_formdata(fields, boundary) + content_type = str("multipart/related; boundary=%s" % boundary) + + return body, content_type + + +def encode_media_related(metadata, media, media_content_type): + rf1 = RequestField( + name="placeholder", + data=json.dumps(metadata), + headers={"Content-Type": "application/json; charset=UTF-8"}, + ) + rf2 = RequestField( + name="placeholder2", data=media, headers={"Content-Type": media_content_type}, + ) + return encode_multipart_related([rf1, rf2]) + + +class IrAttachment(models.Model): + + _inherit = "ir.attachment" + + def _get_google_drive_auth_header(self): + access_token = self.env.context.get("google_drive_access_token") + if not access_token: + access_token = self.env["google.drive.config"].get_access_token() + return {"Authorization": "Bearer " + access_token} + + # это нагло скопировано с ir_attachment_url + @api.multi + def _filter_protected_attachments(self): + return self.filtered( + lambda r: r.res_model not in ["ir.ui.view", "ir.ui.menu"] + or not r.name.startswith("/web/content/") + or not r.name.startswith("/web/static/") + ) + + def _inverse_datas(self): + condition = ( + self.env["ir.config_parameter"] + .sudo() + .get_param("google_drive.attachment_condition") + ) + + if condition: + condition = safe_eval(condition, mode="eval") + our_records = self.sudo().search([("id", "in", self.ids)] + condition) + else: + our_records = self + + our_records = our_records._filter_protected_attachments() + + if our_records: + # make sure, you can use google drive + # otherwise - use default behaviour + try: + google_drive_access_token = self.env[ + "google.drive.config" + ].get_access_token() + except Exception: + _logger.exception( + "Google Drive is not configured properly. Keeping attachments as usual" + ) + return super(IrAttachment, self)._inverse_datas() + + self = self.with_context( + google_drive_access_token=google_drive_access_token + ) + + for attach in our_records: + bin_value = base64.b64decode(attach.datas) + fname = self._file_write_google_drive(bin_value, attach.datas_fname) + vals = { + "file_size": len(bin_value), + "checksum": self._compute_checksum(bin_value), + "index_content": self._index( + bin_value, attach.datas_fname, attach.mimetype + ), + "store_fname": fname, + "db_datas": False, + "type": "binary", + "datas_fname": attach.datas_fname, + } + super(IrAttachment, attach.sudo()).write(vals) + + return super(IrAttachment, self - our_records)._inverse_datas() + + def _file_read(self, fname, bin_size=False): + if not fname.startswith(PREFIX): + return super(IrAttachment, self)._file_read(fname, bin_size) + + file_id = fname[len(PREFIX) :] + _logger.debug("reading file with id {}".format(file_id)) + + if bin_size: + request_url = "https://www.googleapis.com/drive/v2/files/{}".format(file_id) + else: + request_url = "https://www.googleapis.com/drive/v2/files/{}?alt=media".format( + file_id + ) + + r = requests.get( + request_url, headers=self._get_google_drive_auth_header(), timeout=TIMEOUT + ) + r.raise_for_status() + + if bin_size: + return human_size(int(r.json()["fileSize"])) + else: + return base64.b64encode(r.content) + + def _file_write_google_drive(self, bin_value, original_filename): + metadata = {} + if original_filename: + metadata["title"] = original_filename + + data, content_type = encode_media_related( + metadata, bin_value, "application/octet-stream" + ) + + headers = self._get_google_drive_auth_header() + headers["Content-Type"] = content_type + + r = requests.post( + "https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart", + headers=headers, + data=data, + ) + r.raise_for_status() + file_id = r.json()["id"] + _logger.debug("uploaded file with id {}".format(file_id)) + return PREFIX + file_id + + def _file_delete(self, fname): + if not fname.startswith(PREFIX): + return super(IrAttachment, self)._file_delete(fname) + + file_id = fname[len(PREFIX) :] + + r = requests.delete( + "https://www.googleapis.com/drive/v2/files/{}".format(file_id), + headers=self._get_google_drive_auth_header(), + timeout=TIMEOUT, + ) + r.raise_for_status() diff --git a/ir_attachment_google_drive/models/res_config_settings.py b/ir_attachment_google_drive/models/res_config_settings.py new file mode 100644 index 000000000..028e69dcf --- /dev/null +++ b/ir_attachment_google_drive/models/res_config_settings.py @@ -0,0 +1,37 @@ +# Copyright 2020 Eugene Molotov +# License MIT (https://opensource.org/licenses/MIT). + +from odoo import api, fields, models + + +class ResConfigSettings(models.TransientModel): + + _inherit = "res.config.settings" + + google_drive_attachment_condition = fields.Char( + string="Google Drive Condition", + help="""Specify valid odoo search domain here, + e.g. [('res_model', 'in', ['product.image'])] -- store data of product.image only. + Empty condition means all models""", + config_parameter="google_drive.attachment_condition", + ) + + @api.model + def get_values(self): + res = super(ResConfigSettings, self).get_values() + icp = self.env["ir.config_parameter"].sudo() + + res.update( + google_drive_attachment_condition=icp.get_param( + "google_drive.attachment_condition", "" + ), + ) + return res + + def set_values(self): + super(ResConfigSettings, self).set_values() + icp = self.env["ir.config_parameter"].sudo() + icp.set_param( + "google_drive.attachment_condition", + self.google_drive_attachment_condition or "", + ) diff --git a/ir_attachment_google_drive/static/description/icon.png b/ir_attachment_google_drive/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b43a0a135f903a4c0c401f03a8690fbbd021a2ab GIT binary patch literal 3035 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 + + + + res.config.settings.view.form.inherit.google.drive + res.config.settings + + + +
+
+
+
+
+