From eebf4c27f5da1c76cec63d383dc4c10f300afb9e Mon Sep 17 00:00:00 2001
From: mancini <mancini@astron.nl>
Date: Tue, 5 Jul 2022 12:03:30 +0200
Subject: [PATCH] Make url redirect generic

To make ATDB being able to be deployed behind a proxy on different address
direct links to address have to be converted in local urls

To deploy on a different url also an environment variable should be set.
Such environment variable is called ATDB_PATH.
For instance if you want to deploy ATDB on https://sdc.astron.nl/asw/atdb
you have to define the environment as ATDB_PATH='/asw/'.
---
 atdb/atdb/settings/base.py               |  9 ++--
 atdb/taskdatabase/services/algorithms.py | 15 ++++---
 atdb/taskdatabase/views.py               | 57 ++++++++++++------------
 3 files changed, 42 insertions(+), 39 deletions(-)

diff --git a/atdb/atdb/settings/base.py b/atdb/atdb/settings/base.py
index 52dcb06f..d50d1746 100644
--- a/atdb/atdb/settings/base.py
+++ b/atdb/atdb/settings/base.py
@@ -183,14 +183,15 @@ MESSAGE_TAGS = {
         messages.ERROR: 'alert-danger',
 }
 
-LOGIN_REDIRECT_URL = '/atdb'
-LOGOUT_REDIRECT_URL = '/atdb'
+FORCE_SCRIPT_NAME = os.environ.get('ATDB_PATH', '/')
+LOGIN_REDIRECT_URL = FORCE_SCRIPT_NAME + 'atdb'
+LOGOUT_REDIRECT_URL = FORCE_SCRIPT_NAME + 'atdb'
 
 # Static files (CSS, JavaScript, Images)
 # https://docs.djangoproject.com/en/2.0/howto/static-files/
 
 #STATIC_URL = '/static_atdb/'
-STATIC_URL = '/atdb/static/'
+STATIC_URL = FORCE_SCRIPT_NAME + 'atdb/static/'
 STATIC_ROOT = os.path.join(BASE_DIR, 'static')
 
 ALL_STATUSSES = ['defining','defined','staging','staged','processing','processed','storing','stored','validated', 'archiving','archived','finished']
@@ -200,4 +201,4 @@ AGGREGATES = ['failed','active','total']
 
 QUERY_LIMIT_MULTI_CHANGE = 1000
 MAX_MONITORING_HISTORY_HOURS = 7 * 24
-SERVICES_LATE_WARNING_SECONDS = 1800
\ No newline at end of file
+SERVICES_LATE_WARNING_SECONDS = 1800
diff --git a/atdb/taskdatabase/services/algorithms.py b/atdb/taskdatabase/services/algorithms.py
index eb0a0d45..70ac69f1 100644
--- a/atdb/taskdatabase/services/algorithms.py
+++ b/atdb/taskdatabase/services/algorithms.py
@@ -8,7 +8,8 @@ from datetime import datetime, timedelta
 from django.db.models import Q, Sum
 import logging
 from .common import timeit
-
+from django.urls import reverse
+from django.utils.http import urlencode
 from ..models import Task, LogEntry, Workflow, Configuration
 from django.conf import settings
 
@@ -251,13 +252,13 @@ def construct_link_to_monitor_history(request, title, name, hostname):
     try:
 
         if settings.DEV == True:
-            url = request.build_absolute_uri('/atdb/monitor/?') + query
+            url = request.build_absolute_uri(reverse('monitor')) + urlencode('?' + query)
         else:
             # Unclear why 'build_absolute_uri' doesn't return 'https' in production.
             # Probably because the https is handled fully outside the container by Traefik
             # and ATDB is not aware of that.
 
-            url = "https://" + request.get_host() + '/atdb/monitor/?' + query
+            url = "https://" + request.get_host() + reverse('monitor') + '?' + query
         link = '<a href="' + url + '" target="_blank">' + title + "</a>"
     except:
         pass
@@ -449,13 +450,13 @@ def construct_link_to_tasks_api(request, status, workflow_id, count):
                 query = "?workflow__id=" + str(workflow_id)
 
         if settings.DEV == True:
-            url = request.build_absolute_uri('/atdb/tasks') + query
+            url = request.build_absolute_uri(reverse('tasks')) + urlencode(query)
         else:
             # Unclear why 'build_absolute_uri' doesn't return 'https' in production.
             # Probably because the https is handled fully outside the container by Traefik
             # and ATDB is not aware of that.
 
-            url = "https://" + request.get_host() + '/atdb/tasks' + query
+            url = "https://" + request.get_host() + reverse('tasks') + urlencode(query)
         link = '<a href="' + url + '" target="_blank">' + str(count) + "</a>"
     except:
         pass
@@ -467,13 +468,13 @@ def construct_link_to_workflow_api(request, workflow_result):
     link = str(title)
     try:
         if settings.DEV == True:
-            url = request.build_absolute_uri('/atdb/workflows/') + str(workflow_result['id'])
+            url = request.build_absolute_uri(reverse('workflows')) + '/' + str(workflow_result['id'])
         else:
             # Unclear why 'build_absolute_uri' doesn't return 'https' in production.
             # Probably because the https is handled fully outside the container by Traefik
             # and ATDB is not aware of that.
 
-            url = "https://" + request.get_host() + '/atdb/workflows/' + str(workflow_result['id'])
+            url = "https://" + request.get_host() + reverse('workflows') + '/' + str(workflow_result['id'])
 
         link = '<a href="' + url + '" target="_blank">' + title + "</a>"
     except:
diff --git a/atdb/taskdatabase/views.py b/atdb/taskdatabase/views.py
index 689a241c..31c1859b 100644
--- a/atdb/taskdatabase/views.py
+++ b/atdb/taskdatabase/views.py
@@ -20,6 +20,7 @@ from django_tables2.views import SingleTableMixin
 from django_tables2 import SingleTableView
 
 from django.shortcuts import render, redirect
+from django.utils.http import urlencode
 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
 from rest_framework.request import Request
 
@@ -538,7 +539,7 @@ def AnnotateQuality(request, id=0, page=0, new_remark=""):
                 task.remarks['quality'] = request.POST.get("annotation","")
 
             task.save()
-            return redirect('/atdb/validation?page='+request.POST.get("return_to_page",1))
+            return redirect('validation') + urlencode('?page='+request.POST.get("return_to_page", 1))
 
     else:
         # a GET means that the form should be presented to be filled in
@@ -549,7 +550,7 @@ def AnnotateQuality(request, id=0, page=0, new_remark=""):
             quality_remarks = ""
 
         form = QualityAnnotationForm(initial={'annotation': quality_remarks, 'return_to_page': page})
-        return render(request, "taskdatabase/validation/annotate_quality.html", {'task': task, 'page': page, 'form':form})
+        return render(request, "taskdatabase/validation/annotate_quality.html", {'task': task, 'page': page, 'form': form})
 
 
 
@@ -852,7 +853,7 @@ class LatestMonitorListViewAPI(generics.ListCreateAPIView):
 @login_required
 def ClearInactiveServices(request):
     LatestMonitor.objects.all().delete()
-    return redirect("/atdb/monitoring")
+    return redirect("monitoring")
 
 
 # example: /atdb/job/5/
@@ -873,10 +874,10 @@ def Hold(request, pk, hold_it, page=0):
     task.save()
     if page == 0:
         # redirect to details screen
-        return redirect('/atdb/query')
+        return redirect('query')
     else:
         # redirect to tasks list
-        return redirect('/atdb/?page=' + page)
+        return redirect('index') + urlencode('?page=' + page)
 
 
 def HoldQuery(request, pk, hold_it, query_params):
@@ -886,7 +887,7 @@ def HoldQuery(request, pk, hold_it, query_params):
     task.save()
 
     current_query_params = convert_query_params_to_url(query_params)
-    return redirect('/atdb/query/?' + current_query_params)
+    return redirect('query') + '?' + urlencode(current_query_params)
 
 
 @login_required
@@ -900,7 +901,7 @@ def ServiceHoldResume(request, name, hostname, enabled):
     metadata['enabled'] = enabled
     service.metadata = metadata
     service.save()
-    return redirect('/atdb/monitoring')
+    return redirect('monitoring')
 
 
 @login_required
@@ -912,10 +913,10 @@ def TaskSetStatus(request, pk, new_status, page=0):
 
     if page == 0:
         # redirect to details screen
-        return redirect('/atdb/task_details')
+        return redirect('task-details')
     else:
         # redirect to tasks list
-        return redirect('/atdb/?page=' + page)
+        return redirect('index') + urlencode('?page=' + page)
 
 
 @login_required
@@ -929,10 +930,10 @@ def TaskValidate(request, pk, quality, new_status, page=0):
 
     if page == 0:
         # redirect to details screen
-        return redirect('/atdb/validation')
+        return redirect('validation')
     else:
         # redirect to tasks list
-        return redirect('/atdb/validation?page=' + page)
+        return redirect('validation') + urlencode('?page=' + page)
 
 
 @login_required
@@ -944,10 +945,10 @@ def TaskRetry(request, pk, new_status, page=0):
 
     if page == 0:
         # redirect to details screen
-        return redirect('/atdb/task_details')
+        return redirect('task-details')
     else:
         # redirect to tasks list
-        return redirect('/atdb/failures?page=' + page)
+        return redirect('failures') + urlencode('?page=' + page)
 
 
 # set a filter value in the session, used later by the 'get_searched_tasks' mechanism
@@ -959,9 +960,9 @@ def TaskSetFilter(request, filter, redirect_to_page):
         request.session['task_onhold_filter'] = None
 
     if redirect_to_page == 'quality':
-        return redirect('/atdb/quality')
+        return redirect('quality')
 
-    return redirect('/atdb/?page=1')
+    return redirect('index') + urlencode('?page=1')
 
 
 # set the defined list of ACTIVE_STATUSSES on the session, used later by the 'get_searched_tasks' mechanism
@@ -970,16 +971,16 @@ def TaskSetActiveFilter(request, redirect_to_page):
     request.session['task_onhold_filter'] = None
 
     if redirect_to_page == 'quality':
-        return redirect('/atdb/quality')
-    return redirect('/atdb/?page=1')
+        return redirect('quality')
+    return redirect('index') + urlencode('?page=1')
 
 
 def TaskSetOnHoldFilter(request, onhold, redirect_to_page):
     request.session['task_onhold_filter'] = onhold
 
     if redirect_to_page == 'quality':
-        return redirect('/atdb/quality')
-    return redirect('/atdb/?page=1')
+        return redirect('quality')
+    return redirect('index') + urlencode('?page=1')
 
 
 def TaskClearFilter(request, redirect_to_page):
@@ -990,10 +991,10 @@ def TaskClearFilter(request, redirect_to_page):
     request.session['filtered'] = False
 
     if redirect_to_page == 'quality':
-        return redirect('/atdb/quality')
+        return redirect('quality')
     if redirect_to_page == 'query':
-        return redirect('/atdb/query')
-    return redirect('/atdb/?page=1')
+        return redirect('query')
+    return redirect('index') + urlencode('?page=1')
 
 
 @login_required
@@ -1010,17 +1011,17 @@ def ChangePriority(request, pk, priority_change, page=0):
 
     if page == 0:
         # redirect to details screen
-        return redirect('/atdb/task_details')
+        return redirect('task-details')
     else:
         # redirect to tasks list
-        return redirect('/atdb/?page=' + page)
+        return redirect('index') + urlencode('?page=' + page)
 
 
 def SortTasks(request, sort, redirect_to_page):
     # store the sort field on the session
     request.session['sort'] = sort
     if redirect_to_page=='atdb':
-        return redirect('/atdb')
+        return redirect('index')
     else:
         return redirect(redirect_to_page)
 
@@ -1058,7 +1059,7 @@ def TaskSetStatusTables2(request, pk, new_status, query_params):
 
     current_query_params = convert_query_params_to_url(query_params)
     # current_query_params = "id=&id__gte=&id__lte=&workflow__id=&filter=%09test&filter__icontains=&priority=&priority__gte=&priority__lte=&status__icontains=&status__in=&project=&project__icontains=&sas_id=&sas_id__icontains=&resume=unknown"
-    return redirect('/atdb/query/?' + current_query_params)
+    return redirect('query') + urlencode('?' + current_query_params)
 
 
 @login_required
@@ -1075,7 +1076,7 @@ def TaskMultiStatus(request, new_status, query_params):
             task.save()
 
         current_query_params = request.session['current_query_params']
-        return redirect('/atdb/query?' + current_query_params)
+        return redirect('query') + urlencode('?' + current_query_params)
 
     # add the current query parameters to the session so that they survive
     # the request/response to the confirmation page (which has other query parameters)
@@ -1099,7 +1100,7 @@ def TaskMultiHold(request, onhold, query_params):
             task.save()
 
         current_query_params = request.session['current_query_params']
-        return redirect('/atdb/query?' + current_query_params)
+        return redirect('query') + urlencode('?' + current_query_params)
 
     # add the current query parameters to the session so that they survive
     # the request/response to the confirmation page (which has other query parameters)
-- 
GitLab