From d9353edbe77d2283bbc8d4dce142e1d5ea17eb72 Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Tue, 7 Apr 2020 18:38:16 +0200
Subject: [PATCH 1/3] seo: add middleware for /robots.txt url (#20263)

---
 debian/debian_config_common.py |  4 ++++
 hobo/middleware/__init__.py    |  1 +
 hobo/middleware/seo.py         | 28 ++++++++++++++++++++++++++++
 tests/settings.py              |  2 ++
 tests/test_seo.py              | 30 ++++++++++++++++++++++++++++++
 5 files changed, 65 insertions(+)
 create mode 100644 hobo/middleware/seo.py
 create mode 100644 tests/test_seo.py

diff --git a/debian/debian_config_common.py b/debian/debian_config_common.py
index 8d92ebe..1be5679 100644
--- a/debian/debian_config_common.py
+++ b/debian/debian_config_common.py
@@ -240,16 +240,17 @@ SESSION_ENGINE = 'mellon.sessions_backends.cached_db'
 # make it easier to use runserver behind nginx as reverse proxy
 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
 
 if 'MIDDLEWARE' not in globals():
     MIDDLEWARE = global_settings.MIDDLEWARE
 
 if 'MIDDLEWARE_CLASSES' in globals():
     MIDDLEWARE_CLASSES = (
+        'hobo.middleware.RobotsTxtMiddleware',
         'hobo.middleware.VersionMiddleware',  # /__version__
         'hobo.middleware.cors.CORSMiddleware',
     ) + MIDDLEWARE_CLASSES
 
     if PROJECT_NAME != 'wcs' and 'authentic2' not in INSTALLED_APPS:
         MIDDLEWARE_CLASSES = MIDDLEWARE_CLASSES + (
             'mellon.middleware.PassiveAuthenticationMiddleware',
         )
@@ -259,16 +260,19 @@ if 'MIDDLEWARE_CLASSES' in globals():
             'hobo.agent.authentic2.middleware.ProvisionningMiddleware',
         )
 else:
     MIDDLEWARE = (
         'hobo.middleware.VersionMiddleware',  # /__version__
         'hobo.middleware.cors.CORSMiddleware',
     ) + MIDDLEWARE
 
+    if PROJECT_NAME != 'wcs':
+        MIDDLEWARE = ('hobo.middleware.RobotsTxtMiddleware',) + MIDDLEWARE
+
     if PROJECT_NAME != 'wcs' and 'authentic2' not in INSTALLED_APPS:
         MIDDLEWARE = MIDDLEWARE + (
             'mellon.middleware.PassiveAuthenticationMiddleware',
         )
 
     if 'authentic2' in INSTALLED_APPS:
         MIDDLEWARE = MIDDLEWARE + (
             'hobo.agent.authentic2.middleware.ProvisionningMiddleware',
diff --git a/hobo/middleware/__init__.py b/hobo/middleware/__init__.py
index 5e4b3a2..84b1ce7 100644
--- a/hobo/middleware/__init__.py
+++ b/hobo/middleware/__init__.py
@@ -1,3 +1,4 @@
 from .version import VersionMiddleware
 from .cors import CORSMiddleware
+from .seo import RobotsTxtMiddleware
 from .stats import PrometheusStatsMiddleware
diff --git a/hobo/middleware/seo.py b/hobo/middleware/seo.py
new file mode 100644
index 0000000..e5f473a
--- /dev/null
+++ b/hobo/middleware/seo.py
@@ -0,0 +1,28 @@
+# hobo - portal to configure and deploy applications
+# Copyright (C) 2020  Entr'ouvert
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from django.conf import settings
+from django.http import HttpResponse
+from django.utils.deprecation import MiddlewareMixin
+
+
+class RobotsTxtMiddleware(MiddlewareMixin):
+    def process_request(self, request):
+        if request.method == 'GET' and request.path == '/robots.txt' and hasattr(settings, 'TEMPLATE_VARS'):
+            return HttpResponse(
+                settings.TEMPLATE_VARS.get('robots_txt', ''),
+                content_type='text/plain')
+        return None
diff --git a/tests/settings.py b/tests/settings.py
index 1daffcb..98d6fc8 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -3,9 +3,11 @@ BROKER_URL = 'memory://'
 OZWILLO_SECRET = 'secret'
 
 INSTALLED_APPS += ('hobo.contrib.ozwillo',)
 
 ALLOWED_HOSTS.append('localhost')
 
 TEMPLATES[0]['OPTIONS']['debug'] = True
 
+MIDDLEWARE_CLASSES = ('hobo.middleware.RobotsTxtMiddleware', ) + MIDDLEWARE_CLASSES
+
 HOBO_MANAGER_HOMEPAGE_URL_VAR = 'portal_agent_url'
diff --git a/tests/test_seo.py b/tests/test_seo.py
new file mode 100644
index 0000000..f0e0530
--- /dev/null
+++ b/tests/test_seo.py
@@ -0,0 +1,30 @@
+# hobo - portal to configure and deploy applications
+# Copyright (C) 2020  Entr'ouvert
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.import pytest
+
+import pytest
+
+from django.test import override_settings
+
+
+pytestmark = pytest.mark.django_db
+
+def test_middleware(app):
+    with override_settings(TEMPLATE_VARS={'robots_txt': 'xxx'}):
+        resp = app.get('/robots.txt', status=200)
+        assert resp.text == 'xxx'
+
+    with override_settings():
+        resp = app.get('/robots.txt', status=404)
-- 
2.25.1

