diff --git a/swh/web/admin/urls.py b/swh/web/admin/urls.py index 3398cf7b..d7c38f17 100644 --- a/swh/web/admin/urls.py +++ b/swh/web/admin/urls.py @@ -1,28 +1,28 @@ # Copyright (C) 2018 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information from django.conf.urls import url from django.contrib.auth.views import LoginView, LogoutView from django.shortcuts import redirect from swh.web.admin.adminurls import AdminUrls import swh.web.admin.origin_save # noqa import swh.web.admin.deposit # noqa -def admin_default_view(request): +def _admin_default_view(request): return redirect('admin-origin-save') -urlpatterns = [url(r'^$', admin_default_view, name='admin'), +urlpatterns = [url(r'^$', _admin_default_view, name='admin'), url(r'^login/$', LoginView.as_view(template_name='login.html'), name='login'), url(r'^logout/$', LogoutView.as_view(template_name='logout.html'), name='logout')] urlpatterns += AdminUrls.get_url_patterns() diff --git a/swh/web/browse/views/origin.py b/swh/web/browse/views/origin.py index b03cb0e2..2e5f926e 100644 --- a/swh/web/browse/views/origin.py +++ b/swh/web/browse/views/origin.py @@ -1,291 +1,241 @@ # Copyright (C) 2017-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import json from distutils.util import strtobool -from django.core.cache import caches from django.http import HttpResponse from django.shortcuts import render, redirect -from django.views.decorators.cache import never_cache from swh.web.common import service from swh.web.common.origin_visits import get_origin_visits from swh.web.common.utils import ( reverse, format_utc_iso_date, parse_timestamp ) from swh.web.common.exc import handle_view_exception from swh.web.browse.utils import ( get_origin_info, get_snapshot_context ) from swh.web.browse.browseurls import browse_route -from swh.web.misc.coverage import code_providers from .utils.snapshot_context import ( browse_snapshot_directory, browse_snapshot_content, browse_snapshot_log, browse_snapshot_branches, browse_snapshot_releases ) @browse_route(r'origin/(?P[a-z]+)/url/(?P.+)' '/visit/(?P.+)/directory/', r'origin/(?P[a-z]+)/url/(?P.+)' '/visit/(?P.+)/directory/(?P.+)/', r'origin/(?P[a-z]+)/url/(?P.+)' '/directory/', r'origin/(?P[a-z]+)/url/(?P.+)' '/directory/(?P.+)/', r'origin/(?P.+)/visit/(?P.+)/directory/', r'origin/(?P.+)/visit/(?P.+)' '/directory/(?P.+)/', r'origin/(?P.+)/directory/', r'origin/(?P.+)/directory/(?P.+)/', view_name='browse-origin-directory') def origin_directory_browse(request, origin_url, origin_type=None, timestamp=None, path=None): """Django view for browsing the content of a directory associated to an origin for a given visit. The url scheme that points to it is the following: * :http:get:`/browse/origin/[(origin_type)/url/](origin_url)/directory/[(path)/]` * :http:get:`/browse/origin/[(origin_type)/url/](origin_url)/visit/(timestamp)/directory/[(path)/]` """ # noqa return browse_snapshot_directory( request, origin_type=origin_type, origin_url=origin_url, timestamp=timestamp, path=path) @browse_route(r'origin/(?P[a-z]+)/url/(?P.+)' '/visit/(?P.+)/content/(?P.+)/', r'origin/(?P[a-z]+)/url/(?P.+)' '/content/(?P.+)/', r'origin/(?P.+)/visit/(?P.+)' '/content/(?P.+)/', r'origin/(?P.+)/content/(?P.+)/', view_name='browse-origin-content') def origin_content_browse(request, origin_url, origin_type=None, path=None, timestamp=None): """Django view that produces an HTML display of a content associated to an origin for a given visit. The url scheme that points to it is the following: * :http:get:`/browse/origin/[(origin_type)/url/](origin_url)/content/(path)/` * :http:get:`/browse/origin/[(origin_type)/url/](origin_url)/visit/(timestamp)/content/(path)/` """ # noqa language = request.GET.get('language', None) return browse_snapshot_content(request, origin_type=origin_type, origin_url=origin_url, timestamp=timestamp, path=path, selected_language=language) PER_PAGE = 20 @browse_route(r'origin/(?P[a-z]+)/url/(?P.+)' '/visit/(?P.+)/log/', r'origin/(?P[a-z]+)/url/(?P.+)/log/', r'origin/(?P.+)/visit/(?P.+)/log/', r'origin/(?P.+)/log/', view_name='browse-origin-log') def origin_log_browse(request, origin_url, origin_type=None, timestamp=None): """Django view that produces an HTML display of revisions history (aka the commit log) associated to a software origin. The url scheme that points to it is the following: * :http:get:`/browse/origin/[(origin_type)/url/](origin_url)/log/` * :http:get:`/browse/origin/[(origin_type)/url/](origin_url)/visit/(timestamp)/log/` """ # noqa return browse_snapshot_log(request, origin_type=origin_type, origin_url=origin_url, timestamp=timestamp) @browse_route(r'origin/(?P[a-z]+)/url/(?P.+)' '/visit/(?P.+)/branches/', r'origin/(?P[a-z]+)/url/(?P.+)' '/branches/', r'origin/(?P.+)/visit/(?P.+)/branches/', r'origin/(?P.+)/branches/', view_name='browse-origin-branches') def origin_branches_browse(request, origin_url, origin_type=None, timestamp=None): """Django view that produces an HTML display of the list of branches associated to an origin for a given visit. The url scheme that points to it is the following: * :http:get:`/browse/origin/[(origin_type)/url/](origin_url)/branches/` * :http:get:`/browse/origin/[(origin_type)/url/](origin_url)/visit/(timestamp)/branches/` """ # noqa return browse_snapshot_branches(request, origin_type=origin_type, origin_url=origin_url, timestamp=timestamp) @browse_route(r'origin/(?P[a-z]+)/url/(?P.+)' '/visit/(?P.+)/releases/', r'origin/(?P[a-z]+)/url/(?P.+)' '/releases/', r'origin/(?P.+)/visit/(?P.+)/releases/', r'origin/(?P.+)/releases/', view_name='browse-origin-releases') def origin_releases_browse(request, origin_url, origin_type=None, timestamp=None): """Django view that produces an HTML display of the list of releases associated to an origin for a given visit. The url scheme that points to it is the following: * :http:get:`/browse/origin/[(origin_type)/url/](origin_url)/releases/` * :http:get:`/browse/origin/[(origin_type)/url/](origin_url)/visit/(timestamp)/releases/` """ # noqa return browse_snapshot_releases(request, origin_type=origin_type, origin_url=origin_url, timestamp=timestamp) @browse_route(r'origin/(?P[a-z]+)/url/(?P.+)/visits/', r'origin/(?P.+)/visits/', view_name='browse-origin-visits') def origin_visits_browse(request, origin_url, origin_type=None): """Django view that produces an HTML display of visits reporting for a swh origin identified by its id or its url. The url that points to it is :http:get:`/browse/origin/[(origin_type)/url/](origin_url)/visits/`. """ try: origin_info = get_origin_info(origin_url, origin_type) origin_visits = get_origin_visits(origin_info) snapshot_context = get_snapshot_context(origin_type=origin_type, origin_url=origin_url) except Exception as exc: return handle_view_exception(request, exc) for i, visit in enumerate(origin_visits): url_date = format_utc_iso_date(visit['date'], '%Y-%m-%dT%H:%M:%SZ') visit['fmt_date'] = format_utc_iso_date(visit['date']) query_params = {} if i < len(origin_visits) - 1: if visit['date'] == origin_visits[i+1]['date']: query_params = {'visit_id': visit['visit']} if i > 0: if visit['date'] == origin_visits[i-1]['date']: query_params = {'visit_id': visit['visit']} snapshot = visit['snapshot'] if visit['snapshot'] else '' visit['browse_url'] = reverse('browse-origin-directory', url_args={'origin_type': origin_type, 'origin_url': origin_url, 'timestamp': url_date}, query_params=query_params) if not snapshot: visit['snapshot'] = '' visit['date'] = parse_timestamp(visit['date']).timestamp() heading = 'Origin visits - %s' % origin_url return render(request, 'browse/origin-visits.html', {'heading': heading, 'swh_object_name': 'Visits', 'swh_object_metadata': origin_info, 'origin_visits': origin_visits, 'origin_info': origin_info, 'snapshot_context': snapshot_context, 'vault_cooking': None, 'show_actions_menu': False}) @browse_route(r'origin/search/(?P.+)/', view_name='browse-origin-search') def _origin_search(request, url_pattern): """Internal browse endpoint to search for origins whose urls contain a provided string pattern or match a provided regular expression. The search is performed in a case insensitive way. """ offset = int(request.GET.get('offset', '0')) limit = int(request.GET.get('limit', '50')) regexp = request.GET.get('regexp', 'false') with_visit = request.GET.get('with_visit', 'false') url_pattern = url_pattern.replace('///', '\\') try: results = service.search_origin(url_pattern, offset, limit, bool(strtobool(regexp)), bool(strtobool(with_visit))) results = json.dumps(list(results), sort_keys=True, indent=4, separators=(',', ': ')) except Exception as exc: return handle_view_exception(request, exc, html_response=False) return HttpResponse(results, content_type='application/json') -@browse_route(r'origin/coverage_count/', - view_name='browse-origin-coverage-count') -@never_cache -def _origin_coverage_count(request): - """Internal browse endpoint to count the number of origins associated - to each code provider declared in the archive coverage list. - As this operation takes some times, we execute it once per day and - cache its results to database. The cached origin counts are then served. - Cache management is handled in the implementation to avoid sending - the same count query twice to the storage database. - """ - try: - cache = caches['db_cache'] - results = [] - for code_provider in code_providers: - provider_id = code_provider['provider_id'] - url_regexp = code_provider['origin_url_regexp'] - cache_key = '%s_origins_count' % provider_id - prev_cache_key = '%s_origins_prev_count' % provider_id - # get cached origin count - origin_count = cache.get(cache_key, -2) - # cache entry has expired or does not exist - if origin_count == -2: - # mark the origin count as processing - cache.set(cache_key, -1, timeout=10*60) - # execute long count query - origin_count = service.storage.origin_count(url_regexp, - regexp=True) - # cache count result - cache.set(cache_key, origin_count, timeout=24*60*60) - cache.set(prev_cache_key, origin_count, timeout=None) - # origin count is currently processing - elif origin_count == -1: - # return previous count if it exists - origin_count = cache.get(prev_cache_key, -1) - results.append({ - 'provider_id': provider_id, - 'origin_count': origin_count, - 'origin_types': code_provider['origin_types'] - }) - results = json.dumps(results) - except Exception as exc: - return handle_view_exception(request, exc, html_response=False) - - return HttpResponse(results, content_type='application/json') - - @browse_route(r'origin/(?P[a-z]+)/url/(?P.+)/', r'origin/(?P.+)/', view_name='browse-origin') def origin_browse(request, origin_url, origin_type=None): """Django view that redirects to the display of the latest archived snapshot for a given software origin. """ last_snapshot_url = reverse('browse-origin-directory', url_args={'origin_type': origin_type, 'origin_url': origin_url}) return redirect(last_snapshot_url) diff --git a/swh/web/misc/coverage.py b/swh/web/misc/coverage.py index 64220611..a0f4b883 100644 --- a/swh/web/misc/coverage.py +++ b/swh/web/misc/coverage.py @@ -1,120 +1,181 @@ # Copyright (C) 2018-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information +import json + +from django.conf.urls import url +from django.core.cache import caches +from django.http import HttpResponse from django.shortcuts import render +from django.views.decorators.cache import never_cache from django.views.decorators.clickjacking import xframe_options_exempt +from swh.web.common import service +from swh.web.common.exc import handle_view_exception from swh.web.config import get_config + # Current coverage list of the archive # TODO: Retrieve that list dynamically instead of hardcoding it -code_providers = [ +_code_providers = [ { 'provider_id': 'debian', 'provider_url': 'https://www.debian.org/', 'provider_logo': 'img/logos/debian.png', 'provider_info': 'source packages from the Debian distribution ' '(continuously archived)', 'origin_url_regexp': '^deb://', 'origin_types': 'packages', }, { 'provider_id': 'framagit', 'provider_url': 'https://framagit.org/', 'provider_logo': 'img/logos/framagit.png', 'provider_info': 'public repositories from Framagit ' '(continuously archived)', 'origin_url_regexp': '^https://framagit.org/', 'origin_types': 'repositories', }, { 'provider_id': 'github', 'provider_url': 'https://github.com', 'provider_logo': 'img/logos/github.png', 'provider_info': 'public repositories from GitHub ' '(continuously archived)', 'origin_url_regexp': '^https://github.com/', 'origin_types': 'repositories', }, { 'provider_id': 'gitlab', 'provider_url': 'https://gitlab.com', 'provider_logo': 'img/logos/gitlab.svg', 'provider_info': 'public repositories from GitLab ' '(continuously archived)', 'origin_url_regexp': '^https://gitlab.com/', 'origin_types': 'repositories', }, { 'provider_id': 'gitorious', 'provider_url': 'https://gitorious.org/', 'provider_logo': 'img/logos/gitorious.png', 'provider_info': 'public repositories from the former Gitorious code ' 'hosting service', 'origin_url_regexp': '^https://gitorious.org/', 'origin_types': 'repositories', }, { 'provider_id': 'googlecode', 'provider_url': 'https://code.google.com/archive/', 'provider_logo': 'img/logos/googlecode.png', 'provider_info': 'public repositories from the former Google Code ' 'project hosting service', 'origin_url_regexp': '^http.*.googlecode.com/', 'origin_types': 'repositories', }, { 'provider_id': 'gnu', 'provider_url': 'https://www.gnu.org', 'provider_logo': 'img/logos/gnu.png', 'provider_info': 'releases from the GNU project (as of August 2015)', 'origin_url_regexp': '^rsync://ftp.gnu.org/', 'origin_types': 'releases', }, { 'provider_id': 'hal', 'provider_url': 'https://hal.archives-ouvertes.fr/', 'provider_logo': 'img/logos/hal.png', 'provider_info': 'scientific software source code deposited in the ' 'open archive HAL', 'origin_url_regexp': '^https://hal.archives-ouvertes.fr/', 'origin_types': 'deposits', }, { 'provider_id': 'inria', 'provider_url': 'https://gitlab.inria.fr', 'provider_logo': 'img/logos/inria.jpg', 'provider_info': 'public repositories from Inria GitLab ' '(continuously archived)', 'origin_url_regexp': '^https://gitlab.inria.fr/', 'origin_types': 'repositories', }, { 'provider_id': 'npm', 'provider_url': 'https://www.npmjs.com/', 'provider_logo': 'img/logos/npm.png', 'provider_info': 'public packages from the package registry for ' 'javascript (continuously archived)', 'origin_url_regexp': '^https://www.npmjs.com/', 'origin_types': 'packages', }, { 'provider_id': 'pypi', 'provider_url': 'https://pypi.org', 'provider_logo': 'img/logos/pypi.svg', 'provider_info': 'source packages from the Python Packaging Index ' '(continuously archived)', 'origin_url_regexp': '^https://pypi.org/', 'origin_types': 'packages', }, ] @xframe_options_exempt -def swh_coverage(request): +def _swh_coverage(request): count_origins = get_config()['coverage_count_origins'] - return render(request, 'coverage.html', {'providers': code_providers, - 'count_origins': count_origins}) + return render(request, 'misc/coverage.html', + {'providers': _code_providers, + 'count_origins': count_origins}) + + +@never_cache +def _swh_coverage_count(request): + """Internal browse endpoint to count the number of origins associated + to each code provider declared in the archive coverage list. + As this operation takes some times, we execute it once per day and + cache its results to database. The cached origin counts are then served. + Cache management is handled in the implementation to avoid sending + the same count query twice to the storage database. + """ + try: + cache = caches['db_cache'] + results = [] + for code_provider in _code_providers: + provider_id = code_provider['provider_id'] + url_regexp = code_provider['origin_url_regexp'] + cache_key = '%s_origins_count' % provider_id + prev_cache_key = '%s_origins_prev_count' % provider_id + # get cached origin count + origin_count = cache.get(cache_key, -2) + # cache entry has expired or does not exist + if origin_count == -2: + # mark the origin count as processing + cache.set(cache_key, -1, timeout=10*60) + # execute long count query + origin_count = service.storage.origin_count(url_regexp, + regexp=True) + # cache count result + cache.set(cache_key, origin_count, timeout=24*60*60) + cache.set(prev_cache_key, origin_count, timeout=None) + # origin count is currently processing + elif origin_count == -1: + # return previous count if it exists + origin_count = cache.get(prev_cache_key, -1) + results.append({ + 'provider_id': provider_id, + 'origin_count': origin_count, + 'origin_types': code_provider['origin_types'] + }) + results = json.dumps(results) + except Exception as exc: + return handle_view_exception(request, exc, html_response=False) + + return HttpResponse(results, content_type='application/json') + + +urlpatterns = [ + url(r'^coverage/$', _swh_coverage, name='swh-coverage'), + url(r'^coverage/count/$', _swh_coverage_count, name='swh-coverage-count'), +] diff --git a/swh/web/urls.py b/swh/web/misc/urls.py similarity index 50% copy from swh/web/urls.py copy to swh/web/misc/urls.py index 0485cbc4..8455da81 100644 --- a/swh/web/urls.py +++ b/swh/web/misc/urls.py @@ -1,103 +1,57 @@ -# Copyright (C) 2017-2019 The Software Heritage developers +# Copyright (C) 2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import json -from django.conf import settings -from django.conf.urls import ( - url, include, handler400, handler403, handler404, handler500 -) +from django.conf.urls import url, include from django.contrib.staticfiles import finders -from django.contrib.staticfiles.views import serve from django.shortcuts import render -from django.views.generic.base import RedirectView -from django_js_reverse.views import urls_js - -from swh.web.browse.identifiers import swh_id_browse from swh.web.config import get_config -from swh.web.common.exc import ( - swh_handle400, swh_handle403, swh_handle404, swh_handle500 -) -from swh.web.misc.coverage import swh_coverage - -swh_web_config = get_config() - -favicon_view = RedirectView.as_view(url='/static/img/icons/swh-logo-32x32.png', - permanent=True) -def default_view(request): - return render(request, "homepage.html") - - -def jslicenses(request): +def _jslicenses(request): jslicenses_file = finders.find('jssources/jslicenses.json') jslicenses_data = json.load(open(jslicenses_file)) jslicenses_data = sorted(jslicenses_data.items(), key=lambda item: item[0].split('/')[-1]) - return render(request, "jslicenses.html", + return render(request, "misc/jslicenses.html", {'jslicenses_data': jslicenses_data}) urlpatterns = [ - url(r'^admin/', include('swh.web.admin.urls')), - url(r'^favicon\.ico$', favicon_view), - url(r'^api/', include('swh.web.api.urls')), - url(r'^browse/', include('swh.web.browse.urls')), - url(r'^$', default_view, name='swh-web-homepage'), - url(r'^jsreverse/$', urls_js, name='js_reverse'), - url(r'^(?Pswh:[0-9]+:[a-z]+:[0-9a-f]+.*)/$', - swh_id_browse, name='browse-swh-id'), - url(r'^coverage/$', swh_coverage, name='swh-coverage'), - url(r'^jslicenses/$', jslicenses, name='jslicenses'), + url(r'^', include('swh.web.misc.coverage')), + url(r'^jslicenses/$', _jslicenses, name='jslicenses'), ] + # when running end to end tests trough cypress, declare some extra # endpoints to provide input data for some of those tests -if swh_web_config['e2e_tests_mode']: +if get_config()['e2e_tests_mode']: from swh.web.tests.data import ( get_content_code_data_by_ext, get_content_other_data_by_ext, get_content_code_data_all_exts, get_content_code_data_by_filename, get_content_code_data_all_filenames, ) # noqa urlpatterns.append( url(r'^tests/data/content/code/extension/(?P.+)/$', get_content_code_data_by_ext, name='tests-content-code-extension')) urlpatterns.append( url(r'^tests/data/content/other/extension/(?P.+)/$', get_content_other_data_by_ext, name='tests-content-other-extension')) urlpatterns.append(url(r'^tests/data/content/code/extensions/$', get_content_code_data_all_exts, name='tests-content-code-extensions')) urlpatterns.append( url(r'^tests/data/content/code/filename/(?P.+)/$', get_content_code_data_by_filename, name='tests-content-code-filename')) urlpatterns.append(url(r'^tests/data/content/code/filenames/$', get_content_code_data_all_filenames, name='tests-content-code-filenames')) - - -# allow to serve assets through django staticfiles -# even if settings.DEBUG is False -def insecure_serve(request, path, **kwargs): - return serve(request, path, insecure=True, **kwargs) - - -# enable to serve compressed assets through django development server -if swh_web_config['serve_assets']: - static_pattern = r'^%s(?P.*)$' % settings.STATIC_URL[1:] - urlpatterns.append(url(static_pattern, insecure_serve)) - - -handler400 = swh_handle400 # noqa -handler403 = swh_handle403 # noqa -handler404 = swh_handle404 # noqa -handler500 = swh_handle500 # noqa diff --git a/swh/web/templates/coverage.html b/swh/web/templates/misc/coverage.html similarity index 98% rename from swh/web/templates/coverage.html rename to swh/web/templates/misc/coverage.html index 54c7d1d0..e1fcd248 100644 --- a/swh/web/templates/coverage.html +++ b/swh/web/templates/misc/coverage.html @@ -1,91 +1,91 @@ {% comment %} Copyright (C) 2015-2019 The Software Heritage developers See the AUTHORS file at the top-level directory of this distribution License: GNU Affero General Public License version 3, or any later version See top-level LICENSE file for more information {% endcomment %} {% load js_reverse %} {% load static %} {% load render_bundle from webpack_loader %} Software Heritage archive coverage {% render_bundle 'vendors' %} {% render_bundle 'webapp' %}
{% for provider in providers %} {% endfor %}
JavaScript license information {% if count_origins %} {% endif %} diff --git a/swh/web/templates/jslicenses.html b/swh/web/templates/misc/jslicenses.html similarity index 98% rename from swh/web/templates/jslicenses.html rename to swh/web/templates/misc/jslicenses.html index 40f114a6..3a343ff3 100644 --- a/swh/web/templates/jslicenses.html +++ b/swh/web/templates/misc/jslicenses.html @@ -1,77 +1,77 @@ -{% extends "layout.html" %} +{% extends "../layout.html" %} {% comment %} Copyright (C) 2019 The Software Heritage developers See the AUTHORS file at the top-level directory of this distribution License: GNU Affero General Public License version 3, or any later version See top-level LICENSE file for more information {% endcomment %} {% load swh_templatetags %} {% block title %}JavaScript license information{% endblock %} {% block navbar-content %}

JavaScript license information

{% endblock %} {% block content %}

This page states the licenses of all the JavaScript files loaded by that web application. The loaded JavaScript files correspond to bundles concatenating multiple source files. You can find the details of the content of each bundle in the Web Labels table below.

{% for jsasset, bundled_js_srcs in jslicenses_data %} {% endfor %}
Script Licenses Sources
{% if jsasset|split:"/"|last %} {{ jsasset | split:"/" | last }} {% else %} {{ jsasset }} {% endif %} {% for js_src in bundled_js_srcs %} {% for js_license in js_src.licenses %} {{ js_license.name }} {% if js_license.copy_url %} (view) {% endif %} {% if not forloop.last %}
{% endif %} {% endfor %} {% if not forloop.last %}

{% endif %} {% endfor %}
{% for js_src in bundled_js_srcs %} {{ js_src.id }} {% for js_license in js_src.licenses %} {% if not forloop.last %}
{% endif %} {% endfor %} {% if not forloop.last %}

{% endif %} {% endfor %}
{% endblock %} diff --git a/swh/web/urls.py b/swh/web/urls.py index 0485cbc4..f6ecfb7f 100644 --- a/swh/web/urls.py +++ b/swh/web/urls.py @@ -1,103 +1,61 @@ # Copyright (C) 2017-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information -import json from django.conf import settings from django.conf.urls import ( url, include, handler400, handler403, handler404, handler500 ) -from django.contrib.staticfiles import finders from django.contrib.staticfiles.views import serve from django.shortcuts import render from django.views.generic.base import RedirectView from django_js_reverse.views import urls_js from swh.web.browse.identifiers import swh_id_browse from swh.web.config import get_config from swh.web.common.exc import ( swh_handle400, swh_handle403, swh_handle404, swh_handle500 ) -from swh.web.misc.coverage import swh_coverage swh_web_config = get_config() favicon_view = RedirectView.as_view(url='/static/img/icons/swh-logo-32x32.png', permanent=True) -def default_view(request): +def _default_view(request): return render(request, "homepage.html") -def jslicenses(request): - jslicenses_file = finders.find('jssources/jslicenses.json') - jslicenses_data = json.load(open(jslicenses_file)) - jslicenses_data = sorted(jslicenses_data.items(), - key=lambda item: item[0].split('/')[-1]) - return render(request, "jslicenses.html", - {'jslicenses_data': jslicenses_data}) - - urlpatterns = [ url(r'^admin/', include('swh.web.admin.urls')), url(r'^favicon\.ico$', favicon_view), url(r'^api/', include('swh.web.api.urls')), url(r'^browse/', include('swh.web.browse.urls')), - url(r'^$', default_view, name='swh-web-homepage'), + url(r'^$', _default_view, name='swh-web-homepage'), url(r'^jsreverse/$', urls_js, name='js_reverse'), url(r'^(?Pswh:[0-9]+:[a-z]+:[0-9a-f]+.*)/$', swh_id_browse, name='browse-swh-id'), - url(r'^coverage/$', swh_coverage, name='swh-coverage'), - url(r'^jslicenses/$', jslicenses, name='jslicenses'), + url(r'^', include('swh.web.misc.urls')), ] -# when running end to end tests trough cypress, declare some extra -# endpoints to provide input data for some of those tests -if swh_web_config['e2e_tests_mode']: - from swh.web.tests.data import ( - get_content_code_data_by_ext, - get_content_other_data_by_ext, - get_content_code_data_all_exts, - get_content_code_data_by_filename, - get_content_code_data_all_filenames, - ) # noqa - urlpatterns.append( - url(r'^tests/data/content/code/extension/(?P.+)/$', - get_content_code_data_by_ext, - name='tests-content-code-extension')) - urlpatterns.append( - url(r'^tests/data/content/other/extension/(?P.+)/$', - get_content_other_data_by_ext, - name='tests-content-other-extension')) - urlpatterns.append(url(r'^tests/data/content/code/extensions/$', - get_content_code_data_all_exts, - name='tests-content-code-extensions')) - urlpatterns.append( - url(r'^tests/data/content/code/filename/(?P.+)/$', - get_content_code_data_by_filename, - name='tests-content-code-filename')) - urlpatterns.append(url(r'^tests/data/content/code/filenames/$', - get_content_code_data_all_filenames, - name='tests-content-code-filenames')) - # allow to serve assets through django staticfiles # even if settings.DEBUG is False def insecure_serve(request, path, **kwargs): return serve(request, path, insecure=True, **kwargs) # enable to serve compressed assets through django development server if swh_web_config['serve_assets']: static_pattern = r'^%s(?P.*)$' % settings.STATIC_URL[1:] urlpatterns.append(url(static_pattern, insecure_serve)) handler400 = swh_handle400 # noqa handler403 = swh_handle403 # noqa handler404 = swh_handle404 # noqa handler500 = swh_handle500 # noqa