-
-
Notifications
You must be signed in to change notification settings - Fork 701
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
313 additions
and
0 deletions.
There are no files selected for viewing
1 change: 1 addition & 0 deletions
1
setup/website_url_sitemap_exclusion/odoo/addons/website_url_sitemap_exclusion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../../../website_url_sitemap_exclusion |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import setuptools | ||
|
||
setuptools.setup( | ||
setup_requires=['setuptools-odoo'], | ||
odoo_addon=True, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Copyright 2023 Simone Rubino - TAKOBI | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
{ | ||
"name": "Website URL Exclusion", | ||
"summary": "Exclude URLs from the website sitemap", | ||
"version": "12.0.1.0.0", | ||
"category": "Website", | ||
"license": "AGPL-3", | ||
"website": "https://github.com/OCA/website" | ||
"/tree/12.0/website_url_sitemap_exclusion", | ||
"author": "TAKOBI, " | ||
"Odoo Community Association (OCA)", | ||
"depends": [ | ||
"website", | ||
], | ||
"data": [ | ||
"security/ir.model.access.csv", | ||
"views/website_views.xml", | ||
], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# Translation of Odoo Server. | ||
# This file contains the translation of the following modules: | ||
# * website_url_sitemap_exclusion | ||
# | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: Odoo Server 12.0\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"POT-Creation-Date: 2023-02-27 13:13+0000\n" | ||
"PO-Revision-Date: 2023-02-27 13:13+0000\n" | ||
"Last-Translator: Simone Rubino <[email protected]>\n" | ||
"Language-Team: \n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: \n" | ||
"Plural-Forms: \n" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: model:ir.model.fields,field_description:website_url_sitemap_exclusion.field_website_forbidden_url__create_uid | ||
msgid "Created by" | ||
msgstr "Creato da" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: model:ir.model.fields,field_description:website_url_sitemap_exclusion.field_website_forbidden_url__create_date | ||
msgid "Created on" | ||
msgstr "Creato il" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: model:ir.model.fields,field_description:website_url_sitemap_exclusion.field_website_forbidden_url__display_name | ||
msgid "Display Name" | ||
msgstr "Nome visualizzato" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: model:ir.model.fields,field_description:website_url_sitemap_exclusion.field_website__forbidden_url_ids | ||
msgid "Forbidden URLs regex" | ||
msgstr "Espressioni regolari per URL vietati" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: model:ir.model.fields,field_description:website_url_sitemap_exclusion.field_website_forbidden_url__id | ||
msgid "ID" | ||
msgstr "" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: model:ir.model.fields,field_description:website_url_sitemap_exclusion.field_website_forbidden_url____last_update | ||
msgid "Last Modified on" | ||
msgstr "Ultima modifica il" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: model:ir.model.fields,field_description:website_url_sitemap_exclusion.field_website_forbidden_url__write_uid | ||
msgid "Last Updated by" | ||
msgstr "Ultimo aggiornamento di" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: model:ir.model.fields,field_description:website_url_sitemap_exclusion.field_website_forbidden_url__write_date | ||
msgid "Last Updated on" | ||
msgstr "Ultimo aggiornamento il" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: model:ir.model.fields,field_description:website_url_sitemap_exclusion.field_website_forbidden_url__regex | ||
msgid "Regex" | ||
msgstr "Espressione regolare" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: code:addons/website_url_sitemap_exclusion/models/website_forbidden_url.py:35 | ||
#, python-format | ||
msgid "Regular Expression `{regex}` is not valid:\n" | ||
"{error}" | ||
msgstr "L'espressione regolare `{regex}` non è valida:\n" | ||
"{error}" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: model:ir.model,name:website_url_sitemap_exclusion.model_website_forbidden_url | ||
msgid "URL not allowed in the sitemap" | ||
msgstr "URL non consentito nella sitemap" | ||
|
||
#. module: website_url_sitemap_exclusion | ||
#: model:ir.model,name:website_url_sitemap_exclusion.model_website | ||
#: model:ir.model.fields,field_description:website_url_sitemap_exclusion.field_website_forbidden_url__website_id | ||
msgid "Website" | ||
msgstr "Sito web" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
from . import website | ||
from . import website_forbidden_url |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Copyright 2023 Simone Rubino - TAKOBI | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
import re | ||
from odoo import api, fields, models | ||
|
||
|
||
class Website(models.Model): | ||
_inherit = 'website' | ||
|
||
forbidden_url_ids = fields.One2many( | ||
comodel_name="website.forbidden.url", | ||
inverse_name="website_id", | ||
string="Forbidden URLs regex", | ||
) | ||
|
||
@api.multi | ||
def enumerate_pages(self, query_string=None, force=False): | ||
pages = super().enumerate_pages(query_string=query_string, force=force) | ||
forbidden_url_regexes = self.mapped("forbidden_url_ids.regex") | ||
forbidden_url_compiled_regexes = list(map(re.compile, forbidden_url_regexes)) | ||
for page in pages: | ||
is_forbidden = \ | ||
self._is_enumerated_page_forbidden_by_regexes( | ||
page, forbidden_url_compiled_regexes, | ||
) | ||
if not is_forbidden: | ||
yield page | ||
|
||
def _is_enumerated_page_forbidden_by_regexes(self, page, compiled_regexes): | ||
page_url = page["loc"] | ||
for forbidden_url_compiled_regex in compiled_regexes: | ||
is_url_forbidden = forbidden_url_compiled_regex.match(page_url) | ||
if is_url_forbidden: | ||
is_forbidden = True | ||
break | ||
else: | ||
is_forbidden = False | ||
return is_forbidden |
41 changes: 41 additions & 0 deletions
41
website_url_sitemap_exclusion/models/website_forbidden_url.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Copyright 2023 Simone Rubino - TAKOBI | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
import re | ||
|
||
from odoo import _, api, fields, models | ||
from odoo.exceptions import ValidationError | ||
|
||
|
||
class WebsiteForbiddenUrls(models.Model): | ||
_name = "website.forbidden.url" | ||
_description = "URL not allowed in the sitemap" | ||
_rec_name = 'regex' | ||
|
||
regex = fields.Char( | ||
string="Regular Expression", | ||
required=True, | ||
) | ||
website_id = fields.Many2one( | ||
comodel_name="website", | ||
ondelete="cascade", | ||
) | ||
|
||
@api.constrains( | ||
'regex', | ||
) | ||
def constrain_regex_valid(self): | ||
"""RegEx must be valid.""" | ||
for forbidden_url in self: | ||
regex = forbidden_url.regex | ||
try: | ||
re.compile(regex) | ||
except re.error as error: | ||
raise ValidationError( | ||
_("Regular Expression `{regex}` is not valid:\n" | ||
"{error}") | ||
.format( | ||
regex=regex, | ||
error=error.msg, | ||
) | ||
) from error |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
In the Website form, add Regular Expressions to the list `Forbidden URLs regex`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
Allow to exclude URLs from the sitemap. | ||
|
||
The URLs can be selected using Regular Expressions. | ||
|
||
This module can be used to exclude URLs that cannot be excluded using page properties; | ||
for instance, this can be used to exclude the URL `/shop` if there are no published products. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Model `website.forbidden.url` can be renamed to `website.blacklisted.url`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
access_website_forbidden_url_all,Everyone can read forbidden URLs,model_website_forbidden_url,,1,0,0,0 | ||
manage_website_forbidden_url_designer,Designers can manage forbidden URLs,model_website_forbidden_url,website.group_website_designer,1,1,1,1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
from . import test_sitemap_exclusion |
80 changes: 80 additions & 0 deletions
80
website_url_sitemap_exclusion/tests/test_sitemap_exclusion.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# Copyright 2023 Simone Rubino - TAKOBI | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
import datetime | ||
from unittest.mock import patch | ||
|
||
from odoo import tests | ||
from odoo.addons.website.controllers.main import Website | ||
from odoo.addons.website.tools import MockRequest | ||
from odoo.exceptions import ValidationError | ||
from odoo.tests import Form | ||
|
||
|
||
class TestSiteMapExclusion (tests.SavepointCase): | ||
|
||
@classmethod | ||
def setUpClass(cls): | ||
super().setUpClass() | ||
cls.controller = Website() | ||
cls.website = cls.env['website'].browse(1) | ||
cls.sitemap = cls._get_sitemap(cls.env) | ||
|
||
@classmethod | ||
def _get_sitemap(cls, env): | ||
"""Get the updated sitemap. | ||
Usually the sitemap is cached for 12 hours, | ||
here we reset the cache so that the sitemap returned is always updated. | ||
""" | ||
base_url = cls.env['ir.config_parameter'].sudo().get_param('web.base.url') | ||
|
||
sitemap_cache_duration_path = 'odoo.addons.website' \ | ||
'.controllers.main.SITEMAP_CACHE_TIME' | ||
no_cache = datetime.timedelta(seconds=-1) | ||
with patch(sitemap_cache_duration_path, new=no_cache), \ | ||
MockRequest(env, website=cls.website) as request: | ||
request.httprequest.url_root = base_url | ||
cls.controller.sitemap_xml_index() | ||
# Sitemap content is the first parameter | ||
# of the first call to `make_response` | ||
sitemap = request.make_response.call_args[0][0] | ||
return sitemap | ||
|
||
def test_url_exclusion(self): | ||
"""URLs defined in the Website are excluded from the sitemap.""" | ||
# Arrange: We want to exclude a URL | ||
url_to_exclude = '/aboutus' | ||
url_regex = '/aboutus' | ||
sitemap = self.sitemap | ||
# pre-condition: The URL is in the sitemap, | ||
# and the regex matches the URL | ||
self.assertRegex(url_to_exclude, url_regex) | ||
self.assertIn(url_to_exclude, sitemap.decode()) | ||
|
||
# Act: Exclude the URL in the website | ||
website_form = Form(self.website) | ||
with website_form.forbidden_url_ids.new() as forbid: | ||
forbid.regex = url_regex | ||
website_form.save() | ||
|
||
# Assert: The sitemap does not contain the URL | ||
new_sitemap = TestSiteMapExclusion._get_sitemap(self.env) | ||
self.assertNotIn(url_to_exclude, new_sitemap.decode()) | ||
|
||
def test_not_valid_regex(self): | ||
"""Only valid Regular Expressions can be used.""" | ||
# Arrange: A Regular Expression is not valid | ||
not_valid_regex = '/abo[utus' | ||
|
||
# Act: Add the Regular Expression to the website forbidden URLs | ||
website_form = Form(self.website) | ||
with website_form.forbidden_url_ids.new() as forbid: | ||
forbid.regex = not_valid_regex | ||
with self.assertRaises(ValidationError) as ve: | ||
website_form.save() | ||
exc_message = ve.exception.args[0] | ||
|
||
# Assert: The validation error mentions the wrong Regular Expression | ||
self.assertIn(not_valid_regex, exc_message) | ||
self.assertIn('not valid', exc_message) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- | ||
~ Copyright 2023 Simone Rubino - TAKOBI | ||
~ License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
--> | ||
|
||
<odoo> | ||
<record id="view_website_form" model="ir.ui.view"> | ||
<field name="name">Add Forbidden URLs to Website Form View</field> | ||
<field name="model">website</field> | ||
<field name="inherit_id" ref="website.view_website_form"/> | ||
<field name="arch" type="xml"> | ||
<div name="other" position="after"> | ||
<group name="forbidden_urls"> | ||
<field name="forbidden_url_ids"> | ||
<tree editable="top"> | ||
<field name="regex"/> | ||
</tree> | ||
</field> | ||
</group> | ||
</div> | ||
</field> | ||
</record> | ||
</odoo> |