Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
91d2536
apps:comments add comments app add urls und add in settings+ recreate…
Jun 16, 2025
1e70f21
Add relevant guest user changes from roots
partizipation Jun 17, 2025
1ca85a5
Add guest user created on non auth comment
partizipation Jun 24, 2025
b3f1c4a
Add ratings url and viewset
partizipation Jul 1, 2025
f4ae1a4
start addings ar tests
partizipation Jul 1, 2025
db1fef2
Add migration after rebase
partizipation Jul 1, 2025
3c944ac
Add ar test works after rebase
partizipation Jul 1, 2025
d21834a
Clean up and move ar guest test
partizipation Jul 2, 2025
71f1a4d
Fix urls
partizipation Jul 2, 2025
f30edd7
Add changelog
partizipation Jul 2, 2025
8e1da45
Remove comments app
partizipation Jul 2, 2025
f63c90c
Add a4 branch off hash to package.json
partizipation Jul 2, 2025
564e515
Add back package-lock.json (newly generated)
partizipation Jul 2, 2025
c4211f8
Remove extra filter calls, remove http methods, remove comment
partizipation Jul 3, 2025
38f9ba1
Change ar comment test name
partizipation Jul 3, 2025
b1cccfe
Add transaction handling to test
partizipation Jul 3, 2025
0a29f86
Add print statements
partizipation Jul 3, 2025
7d06640
Add clear content type cache
partizipation Jul 3, 2025
1f0c2bd
Add more debugging
partizipation Jul 3, 2025
a7e0686
Add debug github build step
partizipation Jul 3, 2025
e86c34a
Fix debug
partizipation Jul 3, 2025
027dab9
fix debug again
partizipation Jul 3, 2025
9d1f9b3
Revert debug build step
partizipation Jul 3, 2025
af7270c
try using reverse
partizipation Jul 3, 2025
ef4128f
Add url paths print
partizipation Jul 3, 2025
2f0d93e
Move urls to end
partizipation Jul 3, 2025
7e0060b
Wait for apps to load
partizipation Jul 3, 2025
a87693e
Revert urls
partizipation Jul 3, 2025
2798322
string import urls
partizipation Jul 3, 2025
f4c4618
Merge branch 'main' into jp-25-05-guest-user-2-redo
partizipation Jul 3, 2025
03f222a
changed test_ar_topicprio + moved url creation into config/urls.py
Jul 7, 2025
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
13 changes: 13 additions & 0 deletions adhocracy-plus/config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

# Link to a dokuwiki instance containing a manual for aplus
# Leave blank to disable
# For guest users this is hardcoded in indicator.html
APLUS_MANUAL_URL = ""

# Application definition
Expand All @@ -42,6 +43,7 @@
"allauth",
"allauth.account",
"allauth.socialaccount",
"guest_user",
"rules.apps.AutodiscoverRulesConfig",
"easy_thumbnails",
"parler",
Expand Down Expand Up @@ -280,6 +282,7 @@
"rules.permissions.ObjectPermissionBackend",
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend",
"guest_user.backends.GuestBackend",
)

ACCOUNT_ADAPTER = "apps.users.adapters.AccountAdapter"
Expand Down Expand Up @@ -719,3 +722,13 @@
},
},
}

GUEST_USER = {
"NAME_GENERATOR": "guest_user.functions.generate_uuid_username",
}


GUEST_USER_REQUIRED_ANON_URL = "/accounts/guests/login"
# Redirects below when guest user is required but currently regular user.
# Currently only guest dashboard views use this, so redirects to user profile.
GUEST_USER_REQUIRED_USER_URL = "/account/profile/"
9 changes: 9 additions & 0 deletions adhocracy-plus/config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
from adhocracy4.ratings.api import RatingViewSet
from adhocracy4.reports.api import ReportViewSet
from apps.account.api import AccountViewSet
from apps.augmentedreality.api import CombinedCommentViewSet
from apps.augmentedreality.api import CombinedRatingViewSet
from apps.contrib import views as contrib_views
from apps.contrib.sitemaps import static_sitemap_index
from apps.documents.api import DocumentViewSet
Expand Down Expand Up @@ -87,12 +89,18 @@
)
ct_router.register(r"comment-moderate", CommentModerateSet, basename="comment-moderate")

ar_router = a4routers.ContentTypeDefaultRouter()
ar_router.register(r"arpas-comments", CombinedCommentViewSet, basename="arpas-comments")
ar_router.register(r"arpas-ratings", CombinedRatingViewSet, basename="arpas-ratings")


comment_router = a4routers.CommentDefaultRouter()
comment_router.register(
r"moderatorfeedback", ModeratorCommentFeedbackViewSet, basename="moderatorfeedback"
)

urlpatterns = [
path("api/", include(ar_router.urls)),
# General platform urls
re_path(r"^django-admin/", admin.site.urls),
path("admin/", include("wagtail.admin.urls")),
Expand All @@ -112,6 +120,7 @@
path("api/", include(comment_router.urls)),
path("api/", include(moderation_router.urls)),
path("api/", include(router.urls)),
# path("api/", include("apps.augmentedreality.urls")),
re_path(r"^api/account/", AccountViewSet.as_view(), name="api-account"),
# API JWT authentication
re_path(r"^api/login", obtain_auth_token, name="api-login"),
Expand Down
8 changes: 5 additions & 3 deletions apps/account/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@
from apps.users.models import User
from apps.users.utils import set_session_language

from guest_user.functions import is_guest_user
from guest_user.mixins import GuestUserRequiredMixin, RegularUserRequiredMixin

from . import forms
from .emails import AccountDeletionEmail


class AccountView(RedirectView):
class AccountView(RegularUserRequiredMixin, RedirectView):
permanent = False
pattern_name = "account_profile"
# Placeholder View to be replaced if we want to use a custom account
# dashboard function overview.


class ProfileUpdateView(LoginRequiredMixin, SuccessMessageMixin, generic.UpdateView):
class ProfileUpdateView(LoginRequiredMixin, SuccessMessageMixin, RegularUserRequiredMixin, generic.UpdateView):
model = User
template_name = "a4_candy_account/profile.html"
form_class = forms.ProfileForm
Expand Down
9 changes: 8 additions & 1 deletion apps/augmentedreality/api.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
from guest_user.mixins import AllowGuestUserMixin

from adhocracy4.comments_async.api import CommentViewSet
from adhocracy4.ratings.api import RatingViewSet


class CombinedRatingViewSet(AllowGuestUserMixin, RatingViewSet):
http_method_names = ["post", "patch"]


class CombinedCommentViewSet(CommentViewSet):
class CombinedCommentViewSet(AllowGuestUserMixin, CommentViewSet):
def get_queryset(self):
comments = super().get_queryset()
return comments
24 changes: 24 additions & 0 deletions apps/augmentedreality/migrations/0005_alter_scene_content_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 4.2.18 on 2025-07-01 15:42

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
("contenttypes", "0002_remove_content_type_name"),
("arpas_augmentedreality", "0004_alter_arobject_scene"),
]

operations = [
migrations.AlterField(
model_name="scene",
name="content_type",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="scenes",
to="contenttypes.contenttype",
),
),
]
4 changes: 3 additions & 1 deletion apps/augmentedreality/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ def validate_item_content_type(content_type):


class Scene(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
content_type = models.ForeignKey(
ContentType, on_delete=models.CASCADE, related_name="scenes"
)
object_id = models.PositiveIntegerField()
item = GenericForeignKey("content_type", "object_id")

Expand Down
8 changes: 0 additions & 8 deletions apps/augmentedreality/urls.py

This file was deleted.

2 changes: 2 additions & 0 deletions apps/userdashboard/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.views import generic
from guest_user.mixins import RegularUserRequiredMixin

from adhocracy4.actions.models import Action
from adhocracy4.comments.models import Comment
Expand All @@ -18,6 +19,7 @@

class UserDashboardBaseMixin(
LoginRequiredMixin,
RegularUserRequiredMixin,
generic.base.ContextMixin,
generic.base.TemplateResponseMixin,
generic.base.View,
Expand Down
1 change: 1 addition & 0 deletions apps/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class User(auth_models.AbstractBaseUser, auth_models.PermissionsMixin):
objects = auth_models.UserManager()

USERNAME_FIELD = "username"
PASSWORD_FIELD = "username" # for django-guest-user
REQUIRED_FIELDS = ["email"]

def get_projects_follow_list(self, exclude_private_projects=False):
Expand Down
132 changes: 72 additions & 60 deletions apps/users/templates/a4_candy_users/indicator.html
Original file line number Diff line number Diff line change
@@ -1,65 +1,77 @@
{% load i18n static thumbnail settings %}
{% load i18n static thumbnail settings guest_user %}
{% if request.user.is_authenticated %}
<div class="dropdown userindicator__dropdown">
<button title="{% translate 'Menu' %}"
class="d-md-none dropdown-toggle btn btn--secondary-filled btn--attached-top header-upper__mobile-toggle"
data-bs-toggle="dropdown"
data-flip="false"
aria-haspopup="true"
aria-expanded="false"
id="user-actions-mobile">
<span class="d-none d-sm-inline-block pe-1">{% translate 'Menu' %}</span>
</button>
<button title="{% translate 'Menu' %}"
class="d-none d-md-inline-block dropdown-toggle btn btn--secondary-filled btn--attached-top btn--align-left header-upper__toggle"
data-bs-toggle="dropdown"
data-flip="false"
aria-haspopup="true"
aria-expanded="false"
id="user-actions">
<div class="userindicator__btn-img"
style="background-image: {% if request.user.avatar %} url({{ request.user.avatar|thumbnail_url:'avatar' }}) {% else %} url({{ request.user.avatar_fallback }}) {% endif %}">
{% with is_guest=user|is_guest_user %}
<div class="dropdown userindicator__dropdown">
<button title="{% translate 'Menu' %}"
class="d-md-none dropdown-toggle btn btn--secondary-filled btn--attached-top header-upper__mobile-toggle"
data-bs-toggle="dropdown"
data-flip="false"
aria-haspopup="true"
aria-expanded="false"
id="user-actions-mobile">
<span class="d-none d-sm-inline-block pe-1">{% translate 'Menu' %}</span>
</button>
<button title="{% translate 'Menu' %}"
class="d-none d-md-inline-block dropdown-toggle btn btn--secondary-filled btn--attached-top btn--align-left header-upper__toggle"
data-bs-toggle="dropdown"
data-flip="false"
aria-haspopup="true"
aria-expanded="false"
id="user-actions">
{% if not is_guest %}
<div class="userindicator__btn-img"
style="background-image: {% if request.user.avatar %} url({{ request.user.avatar|thumbnail_url:'avatar' }}) {% else %} url({{ request.user.avatar_fallback }}) {% endif %}">
</div>
{% endif %}
<div class="userindicator__btn-text text-start">
<span class="userindicator__hello">{% translate "Hello" %}, </span>
{% if not is_guest %}
<br>
<div class="u-overflow-ellipsis">{{ request.user.username }}</div>
{% else %}
<span>{% translate "Guest" %}</span>
{% endif %}
</div>
<i class="fa fa-chevron-down" aria-hidden="true"></i>
</button>
<div class="dropdown-menu dropdown-menu-end userindicator__dropdown-menu"
aria-labelledby="user-actions user-actions-mobile">
{% if request.user.is_superuser %}
<a class="dropdown-item" href="{% url 'admin:index' %}">{% translate "Admin" %}</a>
{% endif %}
{% if not is_guest %}
<a class="dropdown-item" href="{% url 'userdashboard-overview' %}">{% translate 'My Overview' %}</a>
<a class="dropdown-item" href="{% url 'account' %}">{% translate "Account Settings" %}</a>
{% for organisation in request.user.organisations %}
<a class="dropdown-item"
href="{% url 'a4dashboard:project-list' organisation_slug=organisation.slug %}">
{{ organisation.name }}
</a>
{% endfor %}
{% settings_value "APLUS_MANUAL_URL" as manual_url %}
{% if manual_url %}
<a class="dropdown-item"
href="{{ manual_url }}/{{ LANGUAGE_CODE }}:start"
target="_blank">{% translate 'Help' %}</a>
{% endif %}
{% else %}
<a class="dropdown-item" href="https://manual.adhocracy.plus/de:start" target="_blank">{% translate "Help" %}</a>
{% endif %}
<form class="form--inline"
action="{% url 'account_logout' %}"
method="post"
aria-label="{% translate 'Logout' %}">
{% csrf_token %}
<input type="hidden" name="next" value="{{ redirect_field_value }}">
<button type="submit" class="dropdown-item">{% translate "Logout" %}</button>
</form>
</div>
<div class="userindicator__btn-text text-start">
<span class="userindicator__hello">{% translate "Hello" %}</span>
<br>
<div class="u-overflow-ellipsis">{{ request.user.username }}</div>
{% endwith %}
{% else %}
<div class="btn btn--secondary-filled btn--huge btn--attached-top">
<span class="navi__item"><a href="{% url 'account_login' %}?next={{ redirect_field_value }}">{% translate "Login" %}</a></span>
<span class="d-none d-md-inline">/</span>
<span class="navi__item"><a href="{% url 'account_signup' %}?next={{ redirect_field_value }}">{% translate "Register" %}</a></span>
</div>
<i class="fa fa-chevron-down" aria-hidden="true"></i>
</button>
<div class="dropdown-menu dropdown-menu-end userindicator__dropdown-menu"
aria-labelledby="user-actions user-actions-mobile">
{% if request.user.is_superuser %}
<a class="dropdown-item" href="{% url 'admin:index' %}">{% translate "Admin" %}</a>
{% endif %}
<a class="dropdown-item" href="{% url 'userdashboard-overview' %}">{% translate 'My Overview' %}</a>
<a class="dropdown-item" href="{% url 'account' %}">{% translate "Account Settings" %}</a>
{% for organisation in request.user.organisations %}
<a class="dropdown-item"
href="{% url 'a4dashboard:project-list' organisation_slug=organisation.slug %}">
{{ organisation.name }}
</a>
{% endfor %}
{% settings_value "APLUS_MANUAL_URL" as manual_url %}
{% if manual_url %}
<a class="dropdown-item"
href="{{ manual_url }}/{{ LANGUAGE_CODE }}:start"
target="_blank">{% translate 'Help' %}</a>
{% endif %}
<form class="form--inline"
action="{% url 'account_logout' %}"
method="post"
aria-label="{% translate 'Logout' %}">
{% csrf_token %}
<input type="hidden" name="next" value="{{ redirect_field_value }}">
<button type="submit" class="dropdown-item">{% translate "Logout" %}</button>
</form>
</div>
{% else %}
<div class="btn btn--secondary-filled btn--huge btn--attached-top">
<span class="navi__item"><a href="{% url 'account_login' %}?next={{ redirect_field_value }}">{% translate "Login" %}</a></span>
<span class="d-none d-md-inline">/</span>
<span class="navi__item"><a href="{% url 'account_signup' %}?next={{ redirect_field_value }}">{% translate "Register" %}</a></span>
</div>
</div>
{% endif %}
8 changes: 8 additions & 0 deletions changelog/490.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
### Added

- unauthenticated users can add comments and ratings and a guest user will be created for them
- deps: django-guest-user (liqd fork)

### Changed

- deps: a4 branch-off for AR comment labeling
8 changes: 2 additions & 6 deletions changelog/526.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
### Added
- New Api Endpoint for the ARC Part of this Project
- Passing Variant Content Type to ARC App
- Adding propertys to Variant so it works with Comments and Ratings

### Changed
- Comments and Variants on Desktop are bound to Variant instead of Topics

### Added
- Passing Variant Content Type to ARC App

### Added
- Adding propertys to Variant so it works with Comments and Ratings

Loading