diff --git a/shopinvader_cache_purge/__init__.py b/shopinvader_cache_purge/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/shopinvader_cache_purge/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/shopinvader_cache_purge/__manifest__.py b/shopinvader_cache_purge/__manifest__.py new file mode 100644 index 0000000000..bec84e6c50 --- /dev/null +++ b/shopinvader_cache_purge/__manifest__.py @@ -0,0 +1,27 @@ +# Copyright 2023 Akretion (https://www.akretion.com). +# @author Matthieu SAISON +# License AGPL-3.0 or later (https: //www.gnu.org/licenses/agpl). + +{ + "name": "Custom Shopinvader Cache Purge", + "summary": "List url to purge and manage purge", + "version": "14.0.1.0.0", + "category": "Uncategorized", + "website": "www.akretion.com", + "author": " Akretion", + "license": "AGPL-3", + "application": False, + "installable": True, + "external_dependencies": { + "python": [], + "bin": [], + }, + "depends": ["connector_search_engine", "connector", "shopinvader"], + "data": [ + "data/ir_cron.xml", + "security/ir.model.access.csv", + "views/shopinvader_url_purge.xml", + "views/shopinvader_backend.xml", + ], + "demo": [], +} diff --git a/shopinvader_cache_purge/data/ir_cron.xml b/shopinvader_cache_purge/data/ir_cron.xml new file mode 100644 index 0000000000..01a044e1a5 --- /dev/null +++ b/shopinvader_cache_purge/data/ir_cron.xml @@ -0,0 +1,15 @@ + + + + Purge search engine cache from listed urls. + + + 1 + hours + -1 + + + code + model.search([("to_purge", "=", True)])._purge_url() + + diff --git a/shopinvader_cache_purge/models/__init__.py b/shopinvader_cache_purge/models/__init__.py new file mode 100644 index 0000000000..2f6cc20b9d --- /dev/null +++ b/shopinvader_cache_purge/models/__init__.py @@ -0,0 +1,3 @@ +from . import se_binding +from . import shopinvader_url_purge +from . import shopinvader_backend diff --git a/shopinvader_cache_purge/models/se_binding.py b/shopinvader_cache_purge/models/se_binding.py new file mode 100644 index 0000000000..39bb3254cb --- /dev/null +++ b/shopinvader_cache_purge/models/se_binding.py @@ -0,0 +1,32 @@ +# Copyright 2023 Akretion (https://www.akretion.com). +# @author Matthieu SAISON +# License AGPL-3.0 or later (https: //www.gnu.org/licenses/agpl). +# Copyright 2023 Akretion (https://www.akretion.com). +# @author Matthieu SAISON +# License AGPL-3.0 or later (https: //www.gnu.org/licenses/agpl). + +import logging + +from odoo import models + +_logger = logging.getLogger(__name__) + + +class SeBinding(models.AbstractModel): + _inherit = "se.binding" + + def synchronize(self): + res = super().synchronize() + # some fields "url_key" are missing in self.data + url_keys = {binding.data.get("url_key") for binding in self} + + for url_key in url_keys: + for sbackend in self.shopinvader_backend_ids: + if url_key: + self.env["shopinvader.url.purge"]._request_purge( + url_key, + self._name, + self._description, + sbackend.id, + ) + return res diff --git a/shopinvader_cache_purge/models/shopinvader_backend.py b/shopinvader_cache_purge/models/shopinvader_backend.py new file mode 100644 index 0000000000..af876bfc66 --- /dev/null +++ b/shopinvader_cache_purge/models/shopinvader_backend.py @@ -0,0 +1,19 @@ +# Copyright 2023 Akretion (https://www.akretion.com). +# @author Matthieu SAISON +# License AGPL-3.0 or later (https: //www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class ShopinvaderBackend(models.Model): + _inherit = "shopinvader.backend" + + purge_ids = fields.One2many( + "shopinvader.url.purge", "backend_id", string="Urls to purge" + ) + purge_nbr = fields.Integer(compute="_compute_purge_nbr", store=True, readonly=True) + + @api.depends("purge_ids") + def _compute_purge_nbr(self): + for record in self: + record.purge_nbr = len(record.purge_ids) diff --git a/shopinvader_cache_purge/models/shopinvader_url_purge.py b/shopinvader_cache_purge/models/shopinvader_url_purge.py new file mode 100644 index 0000000000..38b3f495df --- /dev/null +++ b/shopinvader_cache_purge/models/shopinvader_url_purge.py @@ -0,0 +1,67 @@ +# Copyright 2023 Akretion (https://www.akretion.com). +# @author Matthieu SAISON +# License AGPL-3.0 or later (https: //www.gnu.org/licenses/agpl). +import requests + +from odoo import fields, models + + +class ShopinvaderUrlPurge(models.Model): + _name = "shopinvader.url.purge" + _description = "List of url to purge from cache" + + url = fields.Char(required=True) + to_purge = fields.Boolean(default=True) + purge_type_id = fields.Many2one("shopinvader.url.purge.type", string="Purge Type") + backend_id = fields.Many2one("shopinvader.backend", string="Backend") + date_last_purge = fields.Datetime("Last Purge Date", readonly=True) + manual = fields.Boolean(default=True, readonly=True) + status = fields.Char(readonly=True) + request_info = fields.Char(readonly=True) + + def _request_purge(self, url_key, model_name, model_description, backend_id): + record = self.search([("url", "=", url_key)]) + if record: + record.to_purge = True + else: + purge_type = self.env["shopinvader.url.purge.type"].get_or_create( + model_name, model_description + ) + + record = self.create( + { + "url": url_key, + "to_purge": True, + "purge_type_id": purge_type.id, + "backend_id": backend_id, + "manual": False, + } + ) + + # use by cron + def _purge_url(self): + for url_key in self: + url = f"{url_key.backend_id.location}/{url_key.url}/" + try: + response = requests.get( + url, + # headers={"TODO"}, + ) + self.last_request_status = response.status_code + except Exception as e: + self.request_info = str(e) + self.status = "Failed" + continue + + +class ShopinvaderUrlPurgeType(models.Model): + _name = "shopinvader.url.purge.type" + + code = fields.Char() + name = fields.Char() + + def get_or_create(self, model_name, model_description): + res = self.search([("code", "=", model_name)]) + if not res: + res = self.create({"code": model_name, "name": model_description}) + return res diff --git a/shopinvader_cache_purge/security/ir.model.access.csv b/shopinvader_cache_purge/security/ir.model.access.csv new file mode 100644 index 0000000000..6cae8f7f66 --- /dev/null +++ b/shopinvader_cache_purge/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_custom_shopinvader_cache_purge,full access cache_purge,model_shopinvader_url_purge,base.group_user,1,1,1,1 +access_custom_shopinvader_cache_purge_type,full access cache_purge_type,model_shopinvader_url_purge_type,base.group_user,1,1,1,1 diff --git a/shopinvader_cache_purge/views/shopinvader_backend.xml b/shopinvader_cache_purge/views/shopinvader_backend.xml new file mode 100644 index 0000000000..20716d36e8 --- /dev/null +++ b/shopinvader_cache_purge/views/shopinvader_backend.xml @@ -0,0 +1,23 @@ + + + + + + shopinvader.backend + + +
+ +
+
+
+ +
diff --git a/shopinvader_cache_purge/views/shopinvader_url_purge.xml b/shopinvader_cache_purge/views/shopinvader_url_purge.xml new file mode 100644 index 0000000000..de611b2e3b --- /dev/null +++ b/shopinvader_cache_purge/views/shopinvader_url_purge.xml @@ -0,0 +1,57 @@ + + + + ir.actions.act_window + Liste des URL + shopinvader.url.purge + tree + [('backend_id', '=', active_id)] + + + + + shopinvader.url.purge.tree.view + shopinvader.url.purge + + + + + + + + + + + + shopinvader.url.purge + tree,form + [] + {} + + + + Purger + + action + + code + + records._purge_url() + + + + + + + + +