diff --git a/document_url_google_drive/README.rst b/document_url_google_drive/README.rst index 38929e87..9c094456 100644 --- a/document_url_google_drive/README.rst +++ b/document_url_google_drive/README.rst @@ -1,35 +1,127 @@ -**This file is going to be generated by oca-gen-addon-readme.** +=========================== +Google Drive URL attachment +=========================== -*Manual changes will be overwritten.* +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:c5d9ab55bc4eea23f037ee922df0021f29e6fe04a6aa716a4a28146b4f75502e + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -Please provide content in the ``readme`` directory: +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fknowledge-lightgray.png?logo=github + :target: https://github.com/OCA/knowledge/tree/16.0/document_url_google_drive + :alt: OCA/knowledge +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/knowledge-16-0/knowledge-16-0-document_url_google_drive + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/knowledge&target_branch=16.0 + :alt: Try me on Runboat -* **DESCRIPTION.rst** (required) -* INSTALL.rst (optional) -* CONFIGURE.rst (optional) -* **USAGE.rst** (optional, highly recommended) -* DEVELOP.rst (optional) -* ROADMAP.rst (optional) -* HISTORY.rst (optional, recommended) -* **CONTRIBUTORS.rst** (optional, highly recommended) -* CREDITS.rst (optional) +|badge1| |badge2| |badge3| |badge4| |badge5| -Content of this README will also be drawn from the addon manifest, -from keys such as name, authors, maintainers, development_status, -and license. +This module extends the functionality of the document_url module and +allows you to attach a link to a file from your Google Drive -A good, one sentence summary in the manifest is also highly recommended. +**Table of contents** +.. contents:: + :local: -Automatic changelog generation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Configuration +============= -`HISTORY.rst` can be auto generated using `towncrier `_. +To configure this module, you need to: -Just put towncrier compatible changelog fragments into `readme/newsfragments` -and the changelog file will be automatically generated and updated when a new fragment is added. +- Go to Settings -> General Settings and scroll down to the + Integrations section. -Please refer to `towncrier` documentation to know more. +- Enable "Google API", save. Setup instructions + https://developers.google.com/drive/picker/guides/overview -NOTE: the changelog will be automatically generated when using `/ocabot merge $option`. -If you need to run it manually, refer to `OCA/maintainer-tools README `_. + - field "Google Client ID" - enter the client ID from the Google API + console. + - field "Google API key" - enter the API key from the Google API + console. + - field "Google App ID" - enter the ID of the Google application. + The default value is ``odoo``. + +- Next, open your user profile and set up personal access credentials + on the "Google API" tab. + + - field "Google Scope" - enter the scope for the Google API. The + default value is + ``https://www.googleapis.com/auth/drive.readonly``. + - field "Google Access Token" - your token will be displayed here. + It is necessary to edit it. + - field "Google Mime Types" - enter the file formats to be filtered + when selecting. Example: + ``application/pdf, image/jpeg, image/png``. By default, all files + are selected + +- You will be asked to authenticate when you add a link for the first + time. + +Usage +===== + +To use this module, you need to: + +#. Open the form view of an object (Example: Customer Invoice +INV/2019/0007). #. Go to the chatter and click on the attached icon. #. +Click **Add GDrive link**. #. Fill the wizard fields and click on Add +button. #. In the open window, select the files you need and press the +select button. #. You will see a new **URL attachment** in the set of +attachments related to the object. #. In order to log in under another +google user, click on the logout icon located after **Add GDrive link** + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Cetmix + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-CetmixGitDrone| image:: https://github.com/CetmixGitDrone.png?size=40px + :target: https://github.com/CetmixGitDrone + :alt: CetmixGitDrone + +Current `maintainer `__: + +|maintainer-CetmixGitDrone| + +This module is part of the `OCA/knowledge `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/document_url_google_drive/models/res_users.py b/document_url_google_drive/models/res_users.py index afbb0c0e..88a33489 100644 --- a/document_url_google_drive/models/res_users.py +++ b/document_url_google_drive/models/res_users.py @@ -12,7 +12,11 @@ class ResUsers(models.Model): default="https://www.googleapis.com/auth/drive.readonly", ) google_picker_access_token = fields.Char(string="Google Access Token") + google_picker_expires_date = fields.Integer(string="Google Expires Date") google_picker_mime_types = fields.Char(string="Google Mime Types") + google_picker_active = fields.Boolean( + compute="_compute_google_picker_active", + ) def get_google_picker_params(self): """ @@ -22,9 +26,8 @@ class ResUsers(models.Model): self.ensure_one() config = self.env["ir.config_parameter"].sudo() google_service = self.env["google.service"] - is_active_google_api = config.get_param("is_active_google_api") - if not is_active_google_api: + if not self.google_picker_active: return {} return { "client_id": google_service._get_client_id("picker"), @@ -32,10 +35,11 @@ class ResUsers(models.Model): "app_id": config.get_param("google_picker_app_id"), "scope": self.google_picker_scope, "access_token": self.google_picker_access_token, + "expires_date": self.google_picker_expires_date, "mime_types": self.google_picker_mime_types, } - def save_google_picker_access_token(self, access_token): + def save_google_picker_access_token(self, access_token, expires_date): """ Save Google Picker access token :param access_token: str @@ -43,3 +47,12 @@ class ResUsers(models.Model): """ self.ensure_one() self.google_picker_access_token = access_token + self.google_picker_expires_date = expires_date + + def _compute_google_picker_active(self): + """ + Compute Google Picker Active + :return: None + """ + conf = self.env["ir.config_parameter"].sudo() + self.google_picker_active = conf.get_param("is_active_google_api") diff --git a/document_url_google_drive/readme/CONFIGURE.md b/document_url_google_drive/readme/CONFIGURE.md index 6daf85ab..2b744770 100644 --- a/document_url_google_drive/readme/CONFIGURE.md +++ b/document_url_google_drive/readme/CONFIGURE.md @@ -2,7 +2,7 @@ To configure this module, you need to: - Go to Settings -> General Settings and scroll down to the Integrations section. -- Enable "Google API", save. +- Enable "Google API", save. Setup instructions https://developers.google.com/drive/picker/guides/overview - field "Google Client ID" - enter the client ID from the Google API console. - field "Google API key" - enter the API key from the Google API console. diff --git a/document_url_google_drive/static/src/js/attachment_google_picker.esm.js b/document_url_google_drive/static/src/js/attachment_google_picker.esm.js index c0cd3f3e..d3f69dc3 100644 --- a/document_url_google_drive/static/src/js/attachment_google_picker.esm.js +++ b/document_url_google_drive/static/src/js/attachment_google_picker.esm.js @@ -25,6 +25,7 @@ export class AttachmentGooglePicker extends Component { client_id: "", app_id: "", accessToken: null, + expiresDate: 0, }); this.tokenClient = null; @@ -48,9 +49,15 @@ export class AttachmentGooglePicker extends Component { // Public // -------------------------------------------------------------------------- - _onAddGooglePickerUrl() { - console.log("Add Google Picker URL"); - this.handleAuthClick(); + async _onAddGooglePickerUrl() { + if ( + this.state.accessToken && + this.state.expiresDate > Math.floor(Date.now() / 1000) + ) { + await this.createPicker(); + } else { + await this.handleAuthClick(); + } } checkActive() { @@ -74,11 +81,15 @@ export class AttachmentGooglePicker extends Component { const res = await this.orm.call("res.users", "get_google_picker_params", [ this.user.userId, ]); + if (!res) { + return; + } this.state.client_id = res.client_id; this.state.api_key = res.api_key; this.state.app_id = res.app_id; this.state.scopes = res.scope; this.state.accessToken = res.access_token; + this.state.expiresDate = res.expires_date; this.state.mime_types = res.mime_types; } @@ -86,6 +97,7 @@ export class AttachmentGooglePicker extends Component { await this.orm.call("res.users", "save_google_picker_access_token", [ this.user.userId, this.state.accessToken, + this.state.expiresDate, ]); } @@ -106,6 +118,8 @@ export class AttachmentGooglePicker extends Component { throw response; } this.state.accessToken = response.access_token; + this.state.expiresDate = + Math.floor(Date.now() / 1000) + response.expires_in; await this.createPicker(); await this.saveUserAuthAccessToken(); }; @@ -113,10 +127,13 @@ export class AttachmentGooglePicker extends Component { if (this.state.accessToken === null) { // Prompt the user to select a Google Account and ask for consent to share their data // when establishing a new session. - this.tokenClient.requestAccessToken({prompt: "consent"}); + this.tokenClient.requestAccessToken({ + prompt: "consent", + access_type: "offline", + }); } else { // Skip display of account chooser and consent dialog for an existing session. - this.tokenClient.requestAccessToken({prompt: ""}); + this.tokenClient.requestAccessToken({prompt: "", access_type: "offline"}); } } diff --git a/document_url_google_drive/tests/test_document_url.py b/document_url_google_drive/tests/test_document_url.py index 79763a58..6af67e2c 100644 --- a/document_url_google_drive/tests/test_document_url.py +++ b/document_url_google_drive/tests/test_document_url.py @@ -33,17 +33,15 @@ class TestDocumentUrl(common.TransactionCase): self.assertEqual(attachment.mimetype, "application/link") def test_get_google_picker_params_is_active(self): - self.config_settings.set_param( - "document_url_google_drive.is_active_google_api", True - ) + self.config_settings.set_param("is_active_google_api", True) + self.config_settings.set_param("google_picker_api_key", "test_api_key") + self.config_settings.set_param("google_picker_app_id", "test_app_id") + self.config_settings.set_param("google_picker_client_id", "test_client_id") user = self.users.with_context(no_reset_password=True).create( { "name": "Test User", "login": "test_user", - "google_picker_client_id": "test_client_id", - "google_picker_api_key": "test_api_key", "google_picker_scope": "test_scope", - "google_picker_app_id": "test_app_id", "google_picker_access_token": "test_access_token", "google_picker_mime_types": "test_mime_types", } @@ -62,9 +60,7 @@ class TestDocumentUrl(common.TransactionCase): ) def test_get_google_picker_params_not_is_active(self): - self.config_settings.set_param( - "document_url_google_drive.is_active_google_api", False - ) + self.config_settings.set_param("is_active_google_api", False) user = self.users.with_context(no_reset_password=True).create( { "name": "Test User", diff --git a/document_url_google_drive/views/res_users_view.xml b/document_url_google_drive/views/res_users_view.xml index ed209db0..22bdab1e 100644 --- a/document_url_google_drive/views/res_users_view.xml +++ b/document_url_google_drive/views/res_users_view.xml @@ -9,7 +9,32 @@ - + + + + + + + + + + + + + + res.users.simple_modif (document_url_google_drive) + res.users + + + + + diff --git a/pandoc-3.1.9-1-amd64.deb b/pandoc-3.1.9-1-amd64.deb new file mode 100644 index 00000000..77ae8bb6 Binary files /dev/null and b/pandoc-3.1.9-1-amd64.deb differ