diff --git a/atdb/atdb/settings/base.py b/atdb/atdb/settings/base.py index 52dcb06fd829093025ad6f689324e43f02ceaa72..d50d1746a64ba3f36c017bc0861f2b7454ac51fd 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 eb0a0d4579cf06624aab550489ea092d78035b9a..0e41549469a72781ded8b68c1e4170c5fa0e62d7 100644 --- a/atdb/taskdatabase/services/algorithms.py +++ b/atdb/taskdatabase/services/algorithms.py @@ -8,7 +8,7 @@ from datetime import datetime, timedelta from django.db.models import Q, Sum import logging from .common import timeit - +from django.urls import reverse from ..models import Task, LogEntry, Workflow, Configuration from django.conf import settings @@ -251,13 +251,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')) + '?' + 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 +449,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')) + 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') + query link = '<a href="' + url + '" target="_blank">' + str(count) + "</a>" except: pass @@ -467,13 +467,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/templates/taskdatabase/index.html b/atdb/taskdatabase/templates/taskdatabase/index.html index 0f0f743101d9f767d7bfad3be6e815a82a27ca93..55ba5dde0dbe3250425f0f89094702fa5129e0b0 100644 --- a/atdb/taskdatabase/templates/taskdatabase/index.html +++ b/atdb/taskdatabase/templates/taskdatabase/index.html @@ -34,7 +34,7 @@ {% include 'taskdatabase/pagination.html' %} </div> </div> - <p class="footer"> Version 1.0.0 (17 may 2022 - 9:00) + <p class="footer"> Version 1.0.0 (11 jul 2022 - 9:00) </div> diff --git a/atdb/taskdatabase/views.py b/atdb/taskdatabase/views.py index 689a241c5815891540bd90dddee0ba80f0f7e84d..ea2984755e4993479cc2568e8b61b4bbd49d7bb7 100644 --- a/atdb/taskdatabase/views.py +++ b/atdb/taskdatabase/views.py @@ -19,7 +19,7 @@ from django_filters.views import FilterView from django_tables2.views import SingleTableMixin from django_tables2 import SingleTableView -from django.shortcuts import render, redirect +from django.shortcuts import render, redirect, reverse from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from rest_framework.request import Request @@ -45,6 +45,10 @@ from .services import algorithms logger = logging.getLogger(__name__) +def redirect_with_params(view_name, params): + return redirect(reverse(view_name) + params) + + # ---------- filters (in the REST API) --------- class TaskFilter(filters.FilterSet): class Meta: @@ -143,6 +147,7 @@ class PostProcessingFilter(filters.FilterSet): 'workflow_to_apply__id': ['exact'], } + class MonitorFilter(filters.FilterSet): class Meta: model = Monitor @@ -155,6 +160,7 @@ class MonitorFilter(filters.FilterSet): 'status': ['exact', 'icontains', 'in'], } + class LatestMonitorFilter(filters.FilterSet): class Meta: model = LatestMonitor @@ -164,6 +170,7 @@ class LatestMonitorFilter(filters.FilterSet): 'hostname': ['exact', 'icontains', 'in'], } + # ---------- Tables2 Views (experimental) ----------- class QueryView(SingleTableMixin, FilterView): table_class = TaskTable @@ -293,7 +300,7 @@ class ShowQualityPage(ListView): # exclude the tasks without quality information tasks = tasks.exclude(outputs__quality__isnull=True) - #tasks = tasks.exclude(outputs__0__quality__isnull=True) + # tasks = tasks.exclude(outputs__0__quality__isnull=True) paginator = Paginator(tasks, config.TASKS_PER_PAGE) # Show 50 tasks per page page = self.request.GET.get('page') @@ -401,7 +408,7 @@ class ShowFailuresPage(ListView): # this provides a broad range of filters for the search_box in the GUI def get_filtered_tasks(request, pre_filtered_tasks=None): - filtered_tasks=[] + filtered_tasks = [] filtered_tasks_as_list = None try: @@ -456,7 +463,6 @@ def get_filtered_tasks(request, pre_filtered_tasks=None): Q(status__in=search) | Q(project__icontains=search)) - if (Task.objects.all().count() == filtered_tasks.count()): request.session['filtered'] = False else: @@ -523,7 +529,6 @@ def ShowTaskQuality(request, id=0, page=0): def AnnotateQuality(request, id=0, page=0, new_remark=""): - # a POST means that the form is filled in and should be stored in the database if request.method == "POST": @@ -532,13 +537,13 @@ def AnnotateQuality(request, id=0, page=0, new_remark=""): if form.is_valid(): task = Task.objects.get(id=id) try: - task.remarks['quality'] = request.POST.get("annotation","") + task.remarks['quality'] = request.POST.get("annotation", "") except: task.remarks = {} - task.remarks['quality'] = request.POST.get("annotation","") + task.remarks['quality'] = request.POST.get("annotation", "") task.save() - return redirect('/atdb/validation?page='+request.POST.get("return_to_page",1)) + return redirect_with_params('validation', '?page=' + request.POST.get("return_to_page", 1)) else: # a GET means that the form should be presented to be filled in @@ -549,12 +554,11 @@ 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}) def ShowInspectionPlots(request, id=0, page=0): - # a GET means that the form should be presented to be filled in task = Task.objects.get(id=id) @@ -611,8 +615,9 @@ def WorkflowDetails(request, id): def ShowMonitoring(request): # get the latest value of each unique combination of service name and hostname. - #distinct_services_per_host = Monitor.objects.all().order_by('name', 'hostname', '-timestamp').distinct('name', 'hostname') - distinct_services_per_host = LatestMonitor.objects.all().order_by('name', 'hostname', '-timestamp').distinct('name', 'hostname') + # distinct_services_per_host = Monitor.objects.all().order_by('name', 'hostname', '-timestamp').distinct('name', 'hostname') + distinct_services_per_host = LatestMonitor.objects.all().order_by('name', 'hostname', '-timestamp').distinct('name', + 'hostname') monitor_results = algorithms.convert_monitor_to_html(request, distinct_services_per_host) return render(request, "taskdatabase/monitoring_page.html", {'monitor_results': monitor_results}) @@ -852,7 +857,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 +878,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_with_params('index', '?page=' + page) def HoldQuery(request, pk, hold_it, query_params): @@ -886,13 +891,13 @@ 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_with_params('query', '?' + current_query_params) @login_required def ServiceHoldResume(request, name, hostname, enabled): model = LatestMonitor - service = LatestMonitor.objects.get(name=name,hostname=hostname) + service = LatestMonitor.objects.get(name=name, hostname=hostname) metadata = service.metadata if not metadata: metadata = {} @@ -900,7 +905,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 +917,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_with_params('index', '?page=' + page) @login_required @@ -929,10 +934,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_with_params('validation', '?page=' + page) @login_required @@ -944,10 +949,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_with_params('failures', '?page=' + page) # set a filter value in the session, used later by the 'get_searched_tasks' mechanism @@ -959,9 +964,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_with_params('index', '?page=1') # set the defined list of ACTIVE_STATUSSES on the session, used later by the 'get_searched_tasks' mechanism @@ -970,16 +975,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_with_params('index', '?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_with_params('index', '?page=1') def TaskClearFilter(request, redirect_to_page): @@ -990,10 +995,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_with_params('index', '?page=1') @login_required @@ -1010,17 +1015,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_with_params('index', '?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') + if redirect_to_page == 'atdb': + return redirect('index') else: return redirect(redirect_to_page) @@ -1058,7 +1063,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_with_params('query', '?' + current_query_params) @login_required @@ -1075,7 +1080,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_with_params('query', '?' + 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 +1104,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_with_params('query', '?' + 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) @@ -1161,15 +1166,18 @@ class GetMinMaxTimeView(generics.ListAPIView): 'error': str(error) }) + from rest_framework.serializers import ListSerializer + + # /atdb/get_unique_values_for_key/{key} class GetUniqueValuesForKey(generics.ListAPIView): queryset = Task.objects.all() model = Task filter_backends = (filters.DjangoFilterBackend,) filter_class = TaskFilter - # override list and generate a custom response + # override list and generate a custom response def list(self, request: Request, *args, **kwargs): try: @@ -1187,12 +1195,14 @@ class GetUniqueValuesForKey(generics.ListAPIView): 'error': str(error) }) + # 4 mar 2022 # this is a test class to test token authentication # can be removed if it all also works in production class HelloView(APIView): permission_classes = (IsAuthenticated,) queryset = Task.objects.all() + def get(self, request): content = {'message': 'Hello, World!'} - return Response(content) \ No newline at end of file + return Response(content)