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
30 changes: 13 additions & 17 deletions docker-app/qfieldcloud/authentication/tests/test_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from datetime import datetime

import django.db.utils
from django.conf import settings
from django.core.files.base import ContentFile
from django.urls import reverse
from django.utils.timezone import now
Expand Down Expand Up @@ -146,10 +147,17 @@ def test_multiple_logins(self):
self.assertGreater(tokens[1].expires_at, now())

def test_login_with_session_case_insensitive(self):
self.login_url = reverse("account_login")
u2 = Person.objects.create_user(username="u2", password="p2", is_staff=True)

self.login_url = reverse(settings.LOGIN_URL)

response = self.client.post(
self.login_url, {"login": "user1", "password": "i_am_wrong"}, follow=True
self.login_url,
{
"login": "U2",
"password": "i_am_wrong",
},
follow=True,
)
# As we use a TemplateResponse we cannot check status_code 302 redirect,
# because it renders a template instead of returning an HTTP redirect response.
Expand All @@ -163,26 +171,14 @@ def test_login_with_session_case_insensitive(self):
response = self.client.post(
self.login_url,
{
"login": "user1",
"password": "abc123",
},
follow=True,
)

self.assertEqual(response.status_code, 200)
self.assertEqual(self.client.session["_auth_user_id"], str(self.user1.id))

response = self.client.post(
self.login_url,
{
"login": "USER1",
"password": "abc123",
"login": "U2",
"password": "p2",
},
follow=True,
)

self.assertEqual(response.status_code, 200)
self.assertEqual(self.client.session["_auth_user_id"], str(self.user1.id))
self.assertEqual(self.client.session["_auth_user_id"], str(u2.id))

def test_case_insensitive_username_uniqueness(self):
with self.assertRaises(django.db.utils.IntegrityError):
Expand Down
56 changes: 37 additions & 19 deletions docker-app/qfieldcloud/core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from django import forms
from django.conf import settings
from django.contrib import admin, messages
from django.contrib.admin.sites import AdminSite
from django.contrib.admin.templatetags.admin_urls import admin_urlname
from django.contrib.admin.views.main import ChangeList
from django.core.exceptions import PermissionDenied, ValidationError
Expand Down Expand Up @@ -62,9 +63,23 @@
from qfieldcloud.core.utils import get_file_storage_choices
from qfieldcloud.core.utils2 import delta_utils, jobs, pg_service_file

admin.site.unregister(LogEntry)

Invitation = get_invitation_model()
class QfcAdminSite(AdminSite):
site_header = _("QFieldCloud Admin")
site_title = _("QFieldCloud Admin")
index_title = _("QFieldCloud Admin")

def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

# a little trick, to ensure that the `qfc_admin_site` has all the models registered on the Django's default admin site
self._registry.update(admin.site._registry)

for _model, model_admin in self._registry.items():
model_admin.admin_site = self


qfc_admin_site = QfcAdminSite(name="qfc_admin_site")


class NoPkOrderChangeList(ChangeList):
Expand Down Expand Up @@ -146,11 +161,6 @@ def admin_urlname_by_obj(value, arg):
return admin_urlname(value._meta, arg)


# Unregister admins from other Django apps
admin.site.unregister(Invitation)
admin.site.unregister(TokenProxy)
admin.site.unregister(EmailAddress)

UserEmailDetails = namedtuple(
"UserEmailDetails",
[
Expand Down Expand Up @@ -1596,17 +1606,25 @@ class LogEntryAdmin(
list_filter = ("action", QFieldCloudResourceTypeFilter)


admin.site.register(Invitation, InvitationAdmin)
admin.site.register(Person, PersonAdmin)
admin.site.register(Organization, OrganizationAdmin)
admin.site.register(Team, TeamAdmin)
admin.site.register(Project, ProjectAdmin)
admin.site.register(Secret, SecretAdmin)
admin.site.register(Delta, DeltaAdmin)
admin.site.register(Job, JobAdmin)
admin.site.register(LogEntry, LogEntryAdmin)
Invitation = get_invitation_model()

# Unregister admins from other Django apps
qfc_admin_site.unregister(Invitation)
qfc_admin_site.unregister(TokenProxy)
qfc_admin_site.unregister(EmailAddress)
qfc_admin_site.unregister(LogEntry)

qfc_admin_site.register(Invitation, InvitationAdmin)
qfc_admin_site.register(Person, PersonAdmin)
qfc_admin_site.register(Organization, OrganizationAdmin)
qfc_admin_site.register(Team, TeamAdmin)
qfc_admin_site.register(Project, ProjectAdmin)
qfc_admin_site.register(Secret, SecretAdmin)
qfc_admin_site.register(Delta, DeltaAdmin)
qfc_admin_site.register(Job, JobAdmin)
qfc_admin_site.register(LogEntry, LogEntryAdmin)

# The sole purpose of the `User` and `UserAccount` admin modules is only to support autocomplete fields in Django admin
admin.site.register(User, UserAdmin)
admin.site.register(UserAccount, UserAccountAdmin)
admin.site.register(EmailAddress, EmailAddressAdmin)
qfc_admin_site.register(User, UserAdmin)
qfc_admin_site.register(UserAccount, UserAccountAdmin)
qfc_admin_site.register(EmailAddress, EmailAddressAdmin)
6 changes: 4 additions & 2 deletions docker-app/qfieldcloud/filestorage/admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from django.contrib import admin

from qfieldcloud.core.admin import qfc_admin_site

from .models import File, FileVersion


Expand Down Expand Up @@ -36,5 +38,5 @@ class FileVersionAdmin(admin.ModelAdmin):
]


admin.site.register(File, FileAdmin)
admin.site.register(FileVersion, FileVersionAdmin)
qfc_admin_site.register(File, FileAdmin)
qfc_admin_site.register(FileVersion, FileVersionAdmin)
5 changes: 2 additions & 3 deletions docker-app/qfieldcloud/notifs/admin.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from django.contrib import admin
from notifications.admin import NotificationAdmin as NotificationAdminBase
from notifications.models import Notification

admin.site.unregister(Notification)
from qfieldcloud.core.admin import qfc_admin_site


class NotificationAdmin(NotificationAdminBase):
Expand All @@ -23,4 +22,4 @@ class NotificationAdmin(NotificationAdminBase):
search_fields = ("recipient__username__icontains",)


admin.site.register(Notification, NotificationAdmin)
qfc_admin_site.register(Notification, NotificationAdmin)
15 changes: 9 additions & 6 deletions docker-app/qfieldcloud/subscription/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
from django.utils import timezone
from django.utils.translation import gettext as _

from qfieldcloud.core.admin import QFieldCloudModelAdmin, model_admin_url

from .models import PackageType, Plan, Subscription
from qfieldcloud.core.admin import (
QFieldCloudModelAdmin,
model_admin_url,
qfc_admin_site,
)
from qfieldcloud.subscription.models import PackageType, Plan, Subscription


class PlanAdmin(admin.ModelAdmin):
Expand Down Expand Up @@ -227,6 +230,6 @@ def save_model(self, request, obj, form, change):
return super().save_model(request, obj, form, change)


admin.site.register(Plan, PlanAdmin)
admin.site.register(PackageType, PackageTypeAdmin)
admin.site.register(Subscription, SubscriptionAdmin)
qfc_admin_site.register(Plan, PlanAdmin)
qfc_admin_site.register(PackageType, PackageTypeAdmin)
qfc_admin_site.register(Subscription, SubscriptionAdmin)
3 changes: 2 additions & 1 deletion docker-app/qfieldcloud/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from rest_framework import permissions

from qfieldcloud.authentication import views as auth_views
from qfieldcloud.core.admin import qfc_admin_site
from qfieldcloud.core.views.redirect_views import redirect_to_admin_project_view
from qfieldcloud.filestorage.views import (
compatibility_file_crud_view,
Expand Down Expand Up @@ -92,7 +93,7 @@ def wrapper(request, *args, **kwargs):
),
name="project_file_download",
),
path(settings.QFIELDCLOUD_ADMIN_URI, admin.site.urls),
path(settings.QFIELDCLOUD_ADMIN_URI, qfc_admin_site.urls),
path("api/v1/auth/login/", auth_views.LoginView.as_view()),
path("api/v1/auth/token/", auth_views.LoginView.as_view()),
path("api/v1/auth/user/", auth_views.UserView.as_view()),
Expand Down
Loading