mirror of
https://github.com/sissbruecker/linkding
synced 2024-11-10 06:04:15 +00:00
Allow configuring guest user profile (#809)
This commit is contained in:
parent
79bf4b38c6
commit
aad62f61c9
7 changed files with 127 additions and 8 deletions
|
@ -1,13 +1,17 @@
|
|||
from django.conf import settings
|
||||
from django.contrib.auth.middleware import RemoteUserMiddleware
|
||||
|
||||
from bookmarks.models import UserProfile
|
||||
from bookmarks.models import UserProfile, GlobalSettings
|
||||
|
||||
|
||||
class CustomRemoteUserMiddleware(RemoteUserMiddleware):
|
||||
header = settings.LD_AUTH_PROXY_USERNAME_HEADER
|
||||
|
||||
|
||||
standard_profile = UserProfile()
|
||||
standard_profile.enable_favicons = True
|
||||
|
||||
|
||||
class UserProfileMiddleware:
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
@ -16,8 +20,16 @@ class UserProfileMiddleware:
|
|||
if request.user.is_authenticated:
|
||||
request.user_profile = request.user.profile
|
||||
else:
|
||||
request.user_profile = UserProfile()
|
||||
request.user_profile.enable_favicons = True
|
||||
# check if a custom profile for guests exists, otherwise use standard profile
|
||||
guest_profile = None
|
||||
try:
|
||||
global_settings = GlobalSettings.get()
|
||||
if global_settings.guest_profile_user:
|
||||
guest_profile = global_settings.guest_profile_user.profile
|
||||
except:
|
||||
pass
|
||||
|
||||
request.user_profile = guest_profile or standard_profile
|
||||
|
||||
response = self.get_response(request)
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# Generated by Django 5.0.8 on 2024-08-31 17:54
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("bookmarks", "0037_globalsettings"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="globalsettings",
|
||||
name="guest_profile_user",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
]
|
|
@ -508,6 +508,9 @@ class GlobalSettings(models.Model):
|
|||
blank=False,
|
||||
default=LANDING_PAGE_LOGIN,
|
||||
)
|
||||
guest_profile_user = models.ForeignKey(
|
||||
get_user_model(), on_delete=models.SET_NULL, null=True, blank=True
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get(cls):
|
||||
|
@ -526,6 +529,8 @@ class GlobalSettings(models.Model):
|
|||
class GlobalSettingsForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = GlobalSettings
|
||||
fields = [
|
||||
"landing_page",
|
||||
]
|
||||
fields = ["landing_page", "guest_profile_user"]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GlobalSettingsForm, self).__init__(*args, **kwargs)
|
||||
self.fields["guest_profile_user"].empty_label = "Standard profile"
|
||||
|
|
|
@ -249,7 +249,17 @@ reddit.com/r/Music music reddit</pre>
|
|||
<label for="{{ global_settings_form.landing_page.id_for_label }}" class="form-label">Landing page</label>
|
||||
{{ global_settings_form.landing_page|add_class:"form-select width-25 width-sm-100" }}
|
||||
<div class="form-input-hint">
|
||||
The page that unauthorized users are redirected to when accessing the root URL.
|
||||
The page that unauthenticated users are redirected to when accessing the root URL.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="{{ global_settings_form.guest_profile_user.id_for_label }}" class="form-label">Guest user
|
||||
profile</label>
|
||||
{{ global_settings_form.guest_profile_user|add_class:"form-select width-25 width-sm-100" }}
|
||||
<div class="form-input-hint">
|
||||
The user profile to use for users that are not logged in. This will affect how publicly shared bookmarks
|
||||
are displayed regarding theme, bookmark list settings, etc. You can either use your own profile or create
|
||||
a dedicated user for this purpose. By default, a standard profile with fixed settings is used.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ from bookmarks.models import GlobalSettings
|
|||
from bookmarks.tests.helpers import BookmarkFactoryMixin
|
||||
|
||||
|
||||
class AnonymousViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
class RootViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
def test_unauthenticated_user_redirect_to_login_by_default(self):
|
||||
response = self.client.get(reverse("bookmarks:root"))
|
||||
self.assertRedirects(response, reverse("login"))
|
||||
|
|
|
@ -469,10 +469,13 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
|||
def test_update_global_settings(self):
|
||||
superuser = self.setup_superuser()
|
||||
self.client.force_login(superuser)
|
||||
selectable_user = self.setup_user()
|
||||
|
||||
# Update global settings
|
||||
form_data = {
|
||||
"update_global_settings": "",
|
||||
"landing_page": GlobalSettings.LANDING_PAGE_SHARED_BOOKMARKS,
|
||||
"guest_profile_user": selectable_user.id,
|
||||
}
|
||||
response = self.client.post(reverse("bookmarks:settings.general"), form_data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
@ -480,6 +483,22 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
|||
|
||||
global_settings = GlobalSettings.get()
|
||||
self.assertEqual(global_settings.landing_page, form_data["landing_page"])
|
||||
self.assertEqual(global_settings.guest_profile_user, selectable_user)
|
||||
|
||||
# Revert settings
|
||||
form_data = {
|
||||
"update_global_settings": "",
|
||||
"landing_page": GlobalSettings.LANDING_PAGE_LOGIN,
|
||||
"guest_profile_user": "",
|
||||
}
|
||||
response = self.client.post(reverse("bookmarks:settings.general"), form_data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertSuccessMessage(response.content.decode(), "Global settings updated")
|
||||
|
||||
global_settings = GlobalSettings.get()
|
||||
global_settings.refresh_from_db()
|
||||
self.assertEqual(global_settings.landing_page, form_data["landing_page"])
|
||||
self.assertIsNone(global_settings.guest_profile_user)
|
||||
|
||||
def test_update_global_settings_should_not_be_called_without_respective_form_action(
|
||||
self,
|
||||
|
|
47
bookmarks/tests/test_user_profile_middleware.py
Normal file
47
bookmarks/tests/test_user_profile_middleware.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from bookmarks.models import UserProfile, GlobalSettings
|
||||
from bookmarks.tests.helpers import BookmarkFactoryMixin
|
||||
from bookmarks.middlewares import standard_profile
|
||||
|
||||
|
||||
class UserProfileMiddlewareTestCase(TestCase, BookmarkFactoryMixin):
|
||||
def test_unauthenticated_user_should_use_standard_profile_by_default(self):
|
||||
response = self.client.get(reverse("login"))
|
||||
|
||||
self.assertEqual(standard_profile, response.wsgi_request.user_profile)
|
||||
|
||||
def test_unauthenticated_user_should_use_custom_configured_profile(self):
|
||||
guest_user = self.setup_user()
|
||||
guest_user_profile = guest_user.profile
|
||||
guest_user_profile.theme = UserProfile.THEME_DARK
|
||||
guest_user_profile.save()
|
||||
|
||||
global_settings = GlobalSettings.get()
|
||||
global_settings.guest_profile_user = guest_user
|
||||
global_settings.save()
|
||||
|
||||
response = self.client.get(reverse("login"))
|
||||
|
||||
self.assertEqual(guest_user_profile, response.wsgi_request.user_profile)
|
||||
|
||||
def test_authenticated_user_should_use_own_profile(self):
|
||||
guest_user = self.setup_user()
|
||||
guest_user_profile = guest_user.profile
|
||||
guest_user_profile.theme = UserProfile.THEME_DARK
|
||||
guest_user_profile.save()
|
||||
|
||||
global_settings = GlobalSettings.get()
|
||||
global_settings.guest_profile_user = guest_user
|
||||
global_settings.save()
|
||||
|
||||
user = self.get_or_create_test_user()
|
||||
user_profile = user.profile
|
||||
user_profile.theme = UserProfile.THEME_LIGHT
|
||||
user_profile.save()
|
||||
self.client.force_login(user)
|
||||
|
||||
response = self.client.get(reverse("login"), follow=True)
|
||||
|
||||
self.assertEqual(user_profile, response.wsgi_request.user_profile)
|
Loading…
Reference in a new issue