Skip to content
Snippets Groups Projects
Commit 05f90d17 authored by Antoine Lambert's avatar Antoine Lambert Committed by Antoine Lambert
Browse files

Add swh.web.admin django application wrapping django admin site

Enable to use django administration site in swh-web by including "swh.web.admin"
application in swh_extra_django_apps list from swh-web configuration.

When enabled, the admin site is available through the new /manage/ endpoint.

It allows an user to modify some django models of interest (adding, deleting or
modifying rows) if he/she has adequate permissions to do so.

Currently, only the add forge now request and save code now request models can
be managed with the admin site through the use of the following permissions:

- swh_web_add_forge_now.add_request
- swh_web_add_forge_now.change_request
- swh_web_add_forge_now.delete_request
- swh_web_add_forge_now.view_request
- swh_web_save_code_now.add_saveoriginrequest
- swh_web_save_code_now.change_saveoriginrequest
- swh_web_save_code_now.delete_saveoriginrequest
- swh_web_save_code_now.view_saveoriginrequest

When swh-web is using the default django authentication backend, the admin site
also enables and administrator to manage user accounts and their permissions.

When swh-web is using Keycloak as the authentication backend, the permissions
listed above must be added as swh-web client roles and these roles can then be
set for an user through the Keycloak admin console in order to use the features
offered by the admin site.
parent 03ce950a
No related branches found
No related tags found
No related merge requests found
# Copyright (C) 2024 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
default_app_config = "swh.web.admin.apps.AdminConfig"
# Copyright (C) 2024 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.apps import AppConfig
class AdminConfig(AppConfig):
name = "swh.web.admin"
label = "swh_web_admin"
{% extends "admin/base.html" %}
{% comment %}
Copyright (C) 2024 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 %}
{% comment %}
Override base_site.html template from django.contrib.admin application
to include SWH logo in admin site header.
{% endcomment %}
{% load static %}
{% block title %}
{% if subtitle %}{{ subtitle }} |{% endif %}
{{ title }} | {{ site_title|default:_("Django site admin") }}
{% endblock title %}
{% block extrastyle %}
{{ block.super }}
<style>
#header {
padding-bottom: 0 !important;
}
{% if "/login/" in request.get_full_path or "/logout/" in request.get_full_path %}
#swh-admin-header {
position: relative;
top: -16px;
left: 4px;
}
{% else %}
#swh-admin-header {
position: absolute;
top: 13px;
left: 95px;
}
{% endif %}
</style>
{% endblock extrastyle %}
{% block branding %}
<div id="site-name">
<img src="{% static 'img/swh-logo.png' %}"
alt="Software Heritage logo"
height="45px" />
<a href="{% url 'admin:index' %}" id="swh-admin-header">
{{ site_header|default:_("Django administration") }}
</a>
</div>
{% if user.is_anonymous %}
{% include "admin/color_theme_toggle.html" %}
{% endif %}
{% endblock branding %}
{% block nav-global %}
{% endblock nav-global %}
# Copyright (C) 2024 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 pytest
from django.urls.exceptions import NoReverseMatch
from swh.web.utils import reverse
@pytest.mark.django_db
def test_admin_deactivate(client, staff_user, django_settings):
"""Check admin site feature is deactivated when the swh.web.admin django
application is not in installed apps."""
assert reverse("admin:index") is not None
django_settings.SWH_DJANGO_APPS = [
app for app in django_settings.SWH_DJANGO_APPS if app != "swh.web.admin"
]
with pytest.raises(NoReverseMatch, match="'admin' is not a registered namespace"):
reverse("admin:index")
# Copyright (C) 2024 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 import settings
from django.contrib import admin
from django.urls import path as url
from swh.web.config import get_config
config = get_config()
oidc_enabled = bool(config["keycloak"]["server_url"])
if oidc_enabled:
# use swh-auth views in admin site for login/logout when webapp
# uses Keycloak for authentication
from swh.auth.django.views import oidc_login, oidc_logout
admin.site.login = oidc_login # type: ignore[assignment]
admin.site.logout = oidc_logout # type: ignore[assignment]
if "swh.web.add_forge_now" in settings.SWH_DJANGO_APPS:
# register add forge now request model as manageable by admin site
from swh.web.add_forge_now.models import Request
if not admin.site.is_registered(Request):
admin.site.register(Request)
if "swh.web.save_code_now" in settings.SWH_DJANGO_APPS:
# register save code now request model as manageable by admin site
from swh.web.save_code_now.models import SaveOriginRequest
if not admin.site.is_registered(SaveOriginRequest):
admin.site.register(SaveOriginRequest)
admin.site.site_header = "swh-web management"
admin.site.site_title = "Software Heritage Web Application management"
urlpatterns = [
url("manage/", admin.site.urls),
]
......@@ -172,6 +172,7 @@ DEFAULT_CONFIG = {
"list",
[
"swh.web.add_forge_now",
"swh.web.admin",
"swh.web.archive_coverage",
"swh.web.badges",
"swh.web.banners",
......
# Copyright (C) 2022 The Software Heritage developers
# Copyright (C) 2022-2024 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
......@@ -12,7 +12,7 @@ def test_swh_web_urls_have_trailing_slash():
urls = set(
value[1]
for key, value in get_resolver().reverse_dict.items()
if key != "browse-swhid" # (see T3234)
if type(key) is str and key not in ("browse-swhid", "favicon-no-trailing-slash")
)
for url in urls:
if url != "$":
......
# Copyright (C) 2017-2022 The Software Heritage developers
# Copyright (C) 2017-2024 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
......@@ -38,8 +38,8 @@ def insecure_serve(request, path, **kwargs):
# enable to serve compressed assets through django development server
if swh_web_config["serve_assets"]:
static_pattern = r"^%s(?P<path>.*)/$" % settings.STATIC_URL[1:]
urlpatterns.append(url(static_pattern, insecure_serve))
static_pattern = r"^%s(?P<path>.*)$" % settings.STATIC_URL[1:]
urlpatterns.append(url(static_pattern, insecure_serve, name="insecure-serve"))
handler400 = swh_handle400 # noqa
......
# Copyright (C) 2022 The Software Heritage developers
# Copyright (C) 2022-2024 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
......@@ -57,6 +57,9 @@ def stat_counters(request):
urlpatterns = [
url(r"^favicon\.ico/$", favicon_view, name="favicon"),
# to prevent django.template.base.VariableDoesNotExist exception when
# browsing django admin site
url(r"^favicon\.ico$", favicon_view, name="favicon-no-trailing-slash"),
url(r"^$", default_view, name="swh-web-homepage"),
url(r"^jsreverse/$", urls_js, name="js-reverse"),
url(r"^stat_counters/$", stat_counters, name="stat-counters"),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment