Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ name: "CodeQL"

on:
push:
branches: [ master, dev ]
branches: [ main, dev ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master, dev ]
branches: [ main, dev ]
schedule:
# Runs at 03:45 UTC every day
- cron: '45 3 * * *'
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# web

[![build](https://github.com/MAKENTNU/web/workflows/build/badge.svg)](https://github.com/MAKENTNU/web/actions)
[![codecov](https://codecov.io/gh/MAKENTNU/web/branch/master/graph/badge.svg)](https://codecov.io/gh/MAKENTNU/web)
[![codecov](https://codecov.io/gh/MAKENTNU/web/branch/main/graph/badge.svg)](https://codecov.io/gh/MAKENTNU/web)

## Contribution guidelines
See [CONTRIBUTING.md](CONTRIBUTING.md) for the following topics:
Expand Down
4 changes: 2 additions & 2 deletions announcements/templates/announcements/announcement_admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ <h1>
<div class="ui header">
{{ announcement.get_classification_display }}
{% if perms.announcements.change_announcement %}
<a href="{% url 'edit_announcement' pk=announcement.pk %}">
<a href="{% url 'edit_announcement' announcement.pk %}">
<i class="make-col-yellow pencil icon"></i>
</a>
{% endif %}
{% if perms.announcements.delete_announcement %}
<a class="delete-modal-button"
data-url="{% url 'delete_announcement' pk=announcement.pk %}"
data-url="{% url 'delete_announcement' announcement.pk %}"
data-obj-name="{{ announcement }}">
<i class="red trash icon"></i>
</a>
Expand Down
2 changes: 1 addition & 1 deletion announcements/tests/test_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def test_all_get_request_paths_succeed(self):
path_predicates = [
Get(reverse('announcement_admin'), public=False),
Get(reverse('create_announcement'), public=False),
Get(reverse('edit_announcement', kwargs={'pk': self.announcement1.pk}), public=False),
Get(reverse('edit_announcement', args=[self.announcement1.pk]), public=False),
]
assert_requesting_paths_succeeds(self, path_predicates)

Expand Down
4 changes: 2 additions & 2 deletions contentbox/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ def setUp(self):
self.public_content_box = ContentBox.objects.get(url_name=TEST_URL_NAME)
self.internal_content_box = ContentBox.objects.get(url_name=INTERNAL_TEST_URL_NAME)

self.public_edit_url = reverse('contentbox_edit', kwargs={'pk': self.public_content_box.pk})
self.public_edit_url = reverse('contentbox_edit', args=[self.public_content_box.pk])
self.public_admin_edit_url = reverse('admin:contentbox_contentbox_change', args=[self.public_content_box.pk], host='admin')
self.internal_edit_url = reverse('contentbox_edit', kwargs={'pk': self.internal_content_box.pk}, host='test_internal')
self.internal_edit_url = reverse('contentbox_edit', args=[self.internal_content_box.pk], host='test_internal')
self.internal_admin_edit_url = reverse('admin:contentbox_contentbox_change', args=[self.internal_content_box.pk], host='admin')

def test_content_box_edit_urls_are_only_accessible_with_required_permissions(self):
Expand Down
25 changes: 23 additions & 2 deletions dataporten/ldap_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,36 @@ def get_user_details_from_LDAP(search_field: str, search_value: str) -> Dict[str


def _get_user_details_from_user_field(field_name: str, field_value: str, use_cached: bool) -> Dict[str, str]:
user_details = {}
if use_cached:
user = User.objects.filter(**{field_name: field_value}).first()
if user:
return {
user_details = {
'username': user.username,
'email': user.email,
'full_name': user.get_full_name(),
}
return get_user_details_from_LDAP(field_name, field_value)

if (user_details
# If `user_details` contains values for all dict keys:
and all(value for value in user_details.values())):
return user_details

try:
LDAP_user_details = get_user_details_from_LDAP(field_name, field_value)
except ldap.LDAPError:
return user_details

if not LDAP_user_details:
return user_details
if not user_details:
return LDAP_user_details

# Update missing values with data from LDAP
for key, value in user_details.items():
if not value:
user_details[key] = LDAP_user_details[key]
return user_details


def get_user_details_from_username(username: str, use_cached=True) -> Dict[str, str]:
Expand Down
16 changes: 4 additions & 12 deletions docs/converters.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
from util.url_utils import SpecificObjectConverter
from .models import Content, Page
from .models import Page
from .validators import page_title_regex


class SpecificPageByTitle:
regex = page_title_regex.strip(r"^$")

def to_python(self, value):
try:
return Page.objects.get(title=value).pk
except Page.DoesNotExist:
raise ValueError("No page exists with that title")
return str(value)

def to_url(self, page: Page):
return page.title


class SpecificContent(SpecificObjectConverter):
model = Content
def to_url(self, page_pk: int):
return Page.objects.get(pk=page_pk).title
7 changes: 7 additions & 0 deletions docs/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django import forms
from django.utils.translation import gettext_lazy as _

from web.widgets import CKEditorUploadingWidget
from .models import Content, Page


Expand All @@ -25,6 +26,12 @@ class Meta:
'content': {'required': _("The page is currently empty; please add some content.")},
}

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Have to set the widget here instead of in `Meta.widgets` above,
# as the `widget` kwarg is always overwritten in `RichTextUploadingFormField`
self.fields['content'].widget = CKEditorUploadingWidget()

def clean(self):
cleaned_data = super().clean()
page: Page = cleaned_data.get('page')
Expand Down
9 changes: 6 additions & 3 deletions docs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

class Page(models.Model):
"""Model for each individual documentation page."""

title = models.CharField(max_length=64, unique=True, verbose_name=_("title"), validators=[page_title_validator])
created_by = models.ForeignKey(
to=User,
Expand All @@ -21,7 +20,7 @@ class Page(models.Model):
related_name='doc_pages_created',
)
current_content = models.OneToOneField(
to="Content",
to='Content',
on_delete=models.SET_NULL,
null=True,
blank=True,
Expand All @@ -32,10 +31,14 @@ class Page(models.Model):
def __str__(self):
return self.title

@classmethod
def get_main_page(cls) -> 'Page':
main_page, _created = Page.objects.get_or_create(title=MAIN_PAGE_TITLE)
return main_page


class Content(models.Model):
"""The content of a documentation page. All versions are kept for editing history."""

page = models.ForeignKey(
to=Page,
on_delete=models.CASCADE,
Expand Down
12 changes: 6 additions & 6 deletions docs/templates/docs/documentation_page_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,29 @@
on {{ date }} at {{ time }}.
{% endblocktrans %}
{% trans "To view the current version, click" %}
<a href="{% url 'page_detail' pk=page %}">{% trans "here" %}</a>.
<a href="{% url 'page_detail' page.pk %}">{% trans "here" %}</a>.
{% if perms.docs.change_page %}
{% trans "To change the current version to this one, click" %}
<a id="change-current-version" href="">{% trans "here" %}</a>.
{% endif %}
</div>
{% endif %}
<h3 class="edit tools">
<a class="explanation-popup" href="{% url 'page_history' pk=page %}" data-title="{% trans "History" %}"
<a class="explanation-popup" href="{% url 'page_history' page.pk %}" data-title="{% trans "History" %}"
data-content="{% trans "Click to view the content history of the page" %}">
<i class="blue archive icon"></i>
</a>
{% if not old %}
{% if perms.docs.change_page %}
<a class="explanation-popup" href="{% url 'edit_page' pk=page %}" data-title="{% trans "Edit" %}"
<a class="explanation-popup" href="{% url 'edit_page' page.pk %}" data-title="{% trans "Edit" %}"
data-content="{% trans "Click to edit the content of the page" %}">
<i class="make-col-yellow edit icon"></i>
</a>
{% endif %}
{% if perms.docs.delete_page and page.title != MAIN_PAGE_TITLE %}
<a class="delete-modal-button explanation-popup"
data-title="{% trans "Delete" %}" data-content="{% trans "Click to delete the page" %}"
data-url="{% url 'delete_page' pk=page %}" data-obj-name="{{ page }}">
data-url="{% url 'delete_page' page.pk %}" data-obj-name="{{ page }}">
<i class="red trash icon"></i>
</a>
{% endif %}
Expand All @@ -59,7 +59,7 @@ <h1>{{ page.title }}</h1>
{% else %}
<i>
{% if perms.docs.change_page %}
{% url 'edit_page' pk=page as edit_page_url %}
{% url 'edit_page' page.pk as edit_page_url %}
{% blocktrans trimmed with link_start='<a href="'|add:edit_page_url|safe|add:'">' link_end='</a>' %}
No content exists for this page. Do you wish to {{ link_start }}create{{ link_end }} some?
{% endblocktrans %}
Expand All @@ -72,7 +72,7 @@ <h1>{{ page.title }}</h1>

{% if form and old and perms.docs.change_page %}
<form id="change-version-form" class="dont-prevent-leaving hidden form" method="POST"
action="{% url 'change_page_version' pk=page %}">
action="{% url 'change_page_version' page.pk %}">
{% csrf_token %}
{{ form }}
</form>
Expand Down
4 changes: 2 additions & 2 deletions docs/templates/docs/documentation_page_history.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ <h1>
<div class="ui relaxed divided list">
{% for content in page.content_history.all reversed %}
{% if content == page.current_content %}
{% url 'page_detail' pk=page as content_url %}
{% url 'page_detail' page.pk as content_url %}
{% else %}
{% url 'old_page_content' pk=page content=content as content_url %}
{% url 'old_page_content' page.pk content.pk as content_url %}
{% endif %}
<div class="item">
{% if forloop.last %}
Expand Down
2 changes: 1 addition & 1 deletion docs/templates/docs/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ <h1>{% trans "Search" %}</h1>
<div class="ui item">
<div class="content">
<div class="header">
<a href="{% url 'page_detail' pk=page %}">{{ page.title }}</a>
<a href="{% url 'page_detail' page.pk %}">{{ page.title }}</a>
</div>
<div class="description">
{% if page.current_content %}
Expand Down
14 changes: 7 additions & 7 deletions docs/tests/test_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ def setUp(self):
def test_all_get_request_paths_succeed(self):
path_predicates = [
Get(self.reverse('home'), public=False),
Get(self.reverse('page_detail', pk=self.page1), public=False),
Get(self.reverse('page_history', pk=self.page1), public=False),
Get(self.reverse('old_page_content', pk=self.page1, content=self.content1), public=False),
Get(self.reverse('old_page_content', pk=self.page1, content=self.content2), public=False),
Get(self.reverse('page_detail', self.page1.pk), public=False),
Get(self.reverse('page_history', self.page1.pk), public=False),
Get(self.reverse('old_page_content', self.page1.pk, self.content1.pk), public=False),
Get(self.reverse('old_page_content', self.page1.pk, self.content2.pk), public=False),
Get(self.reverse('create_page'), public=False),
Get(self.reverse('edit_page', pk=self.page1), public=False),
Get(self.reverse('edit_page', self.page1.pk), public=False),
Get(self.reverse('search_pages'), public=False),
Get('/robots.txt', public=True, translated=False),
Get('/.well-known/security.txt', public=True, translated=False),
Expand All @@ -59,5 +59,5 @@ def test_all_admin_get_request_paths_succeed(self):
assert_requesting_paths_succeeds(self, path_predicates, 'admin')

@staticmethod
def reverse(viewname: str, **kwargs):
return reverse(viewname, kwargs=kwargs, host='docs')
def reverse(viewname: str, *args):
return reverse(viewname, args=args, host='docs')
31 changes: 16 additions & 15 deletions docs/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,35 @@
from django.urls import path, register_converter
from django.views.generic import TemplateView

from util.url_utils import debug_toolbar_urls
from . import converters, views
from .models import MAIN_PAGE_TITLE, Page


register_converter(converters.SpecificPageByTitle, 'Page')
register_converter(converters.SpecificContent, 'Content')

unsafe_urlpatterns = [
path("", views.DocumentationPageDetailView.as_view(), {'pk': Page.objects.get_or_create(title=MAIN_PAGE_TITLE)[0].pk}, name='home'),
path("page/<Page:pk>/", views.DocumentationPageDetailView.as_view(), name='page_detail'),
path("page/<Page:pk>/history/", views.HistoryDocumentationPageView.as_view(), name='page_history'),
path("page/<Page:pk>/history/change/", views.ChangeDocumentationPageVersionView.as_view(), name='change_page_version'),
path("page/<Page:pk>/history/<Content:content>/", views.OldDocumentationPageContentView.as_view(), name='old_page_content'),
path("page/create/", views.CreateDocumentationPageView.as_view(), name='create_page'),
path("page/<Page:pk>/edit/", views.EditDocumentationPageView.as_view(), name='edit_page'),
path("page/<Page:pk>/delete/", views.DeleteDocumentationPageView.as_view(), name='delete_page'),
path("search/", views.SearchPagesView.as_view(), name='search_pages'),
]
register_converter(converters.SpecificPageByTitle, 'PageTitle')

urlpatterns = [
path("robots.txt", TemplateView.as_view(template_name='docs/robots.txt', content_type='text/plain')),
path(".well-known/security.txt", TemplateView.as_view(template_name='web/security.txt', content_type='text/plain')),

*debug_toolbar_urls(),
path("i18n/", decorator_include(
permission_required('docs.view_page'),
'django.conf.urls.i18n'
)),
]

unsafe_urlpatterns = [
path("", views.DocumentationPageDetailView.as_view(is_main_page=True), name='home'),
path("page/create/", views.CreateDocumentationPageView.as_view(), name='create_page'),
path("page/<PageTitle:title>/", views.DocumentationPageDetailView.as_view(), name='page_detail'),
path("page/<PageTitle:title>/history/", views.HistoryDocumentationPageView.as_view(), name='page_history'),
path("page/<PageTitle:title>/history/change/", views.ChangeDocumentationPageVersionView.as_view(), name='change_page_version'),
path("page/<PageTitle:title>/history/<int:content_pk>/", views.OldDocumentationPageContentView.as_view(), name='old_page_content'),
path("page/<PageTitle:title>/edit/", views.EditDocumentationPageView.as_view(), name='edit_page'),
path("page/<PageTitle:title>/delete/", views.DeleteDocumentationPageView.as_view(), name='delete_page'),
path("search/", views.SearchPagesView.as_view(), name='search_pages'),
]

urlpatterns += i18n_patterns(
path("", decorator_include(
permission_required('docs.view_page'),
Expand Down
Loading