diff --git a/aleksis/core/rules.py b/aleksis/core/rules.py index e854c3077dd60e2cf7bd22e02dcd0240689876b3..35b00f23770f80e3a5ca821393af3bf0956833f8 100644 --- a/aleksis/core/rules.py +++ b/aleksis/core/rules.py @@ -66,6 +66,12 @@ edit_person_predicate = has_person & ( ) add_perm("core.edit_person", edit_person_predicate) +# Delete person +delete_person_predicate = has_person & ( + has_global_perm("core.delete_person") | has_object_perm("core.delete_person") +) +add_perm("core.delete_person", delete_person_predicate) + # Link persons with accounts link_persons_accounts_predicate = has_person & has_global_perm("core.link_persons_accounts") add_perm("core.link_persons_accounts", link_persons_accounts_predicate) @@ -88,6 +94,12 @@ edit_group_predicate = has_person & ( ) add_perm("core.edit_group", edit_group_predicate) +# Delete group +delete_group_predicate = has_person & ( + has_global_perm("core.delete_group") | has_object_perm("core.delete_group") +) +add_perm("core.delete_group", delete_group_predicate) + # Assign child groups to groups assign_child_groups_to_groups_predicate = has_person & has_global_perm( "core.assign_child_groups_to_groups" @@ -229,6 +241,18 @@ view_group_type_predicate = has_person & ( ) add_perm("core.view_grouptype", view_group_type_predicate) +# Create person +create_person_predicate = has_person & ( + has_global_perm("core.create_person") | has_object_perm("core.create_person") +) +add_perm("core.create_person", create_person_predicate) + +# Create group +create_group_predicate = has_person & ( + has_global_perm("core.create_group") | has_object_perm("core.create_group") +) +add_perm("core.create_group", create_group_predicate) + # School years view_school_term_predicate = has_person & has_global_perm("core.view_schoolterm") add_perm("core.view_schoolterm", view_school_term_predicate) diff --git a/aleksis/core/templates/core/group/full.html b/aleksis/core/templates/core/group/full.html index 2c778f837a785d431300ea57a1a283a05b6bd367..ba5bba0aa1208565331d748d106b4d2e982f7918 100644 --- a/aleksis/core/templates/core/group/full.html +++ b/aleksis/core/templates/core/group/full.html @@ -13,8 +13,9 @@ {% has_perm 'core.edit_group' user group as can_change_group %} {% has_perm 'core.change_group_preferences' user group as can_change_group_preferences %} + {% has_perm 'core.delete_group' user group as can_delete_group %} - {% if can_change_group or can_change_group_preferences %} + {% if can_change_group or can_change_group_preferences or can_delete_group %} <p> {% if can_change_group %} <a href="{% url 'edit_group_by_id' group.id %}" class="btn waves-effect waves-light"> @@ -22,6 +23,14 @@ {% trans "Edit" %} </a> {% endif %} + + {% if can_delete_group %} + <a href="{% url 'delete_group_by_id' group.id %}" class="btn waves-effect waves-light red"> + <i class="material-icons left">delete</i> + {% trans "Delete" %} + </a> + {% endif %} + {% if can_change_group_preferences %} <a href="{% url "preferences_group" group.id %}" class="btn waves-effect waves-light"> <i class="material-icons left">settings</i> diff --git a/aleksis/core/templates/core/person/full.html b/aleksis/core/templates/core/person/full.html index 68119a4b641ecfa67b14befaf0749069d7dd3e4f..73d2a4cf663999b2648e497e25559e83df69bb24 100644 --- a/aleksis/core/templates/core/person/full.html +++ b/aleksis/core/templates/core/person/full.html @@ -12,8 +12,9 @@ {% has_perm 'core.edit_person' user person as can_change_person %} {% has_perm 'core.change_person_preferences' user person as can_change_person_preferences %} + {% has_perm 'core.delete_person' user person as can_delete_person %} - {% if can_change_person or can_change_person_preferences %} + {% if can_change_person or can_change_person_preferences or can_delete_person %} <p> {% if can_change_person %} <a href="{% url 'edit_person_by_id' person.id %}" class="btn waves-effect waves-light"> @@ -22,6 +23,13 @@ </a> {% endif %} + {% if can_delete_person %} + <a href="{% url 'delete_person_by_id' person.id %}" class="btn waves-effect waves-light red"> + <i class="material-icons left">delete</i> + {% trans "Delete" %} + </a> + {% endif %} + {% if can_change_person_preferences %} <a href="{% url "preferences_person" person.id %}" class="btn waves-effect waves-light"> <i class="material-icons left">settings</i> diff --git a/aleksis/core/templates/core/person/list.html b/aleksis/core/templates/core/person/list.html index dfecfb7c52b64cbdf49e70d06d1148e82128577f..1103199e002bda1394b3028df4483c69804268d8 100644 --- a/aleksis/core/templates/core/person/list.html +++ b/aleksis/core/templates/core/person/list.html @@ -2,12 +2,21 @@ {% extends "core/base.html" %} -{% load i18n %} +{% load i18n rules %} {% load render_table from django_tables2 %} {% block browser_title %}{% blocktrans %}Persons{% endblocktrans %}{% endblock %} {% block page_title %}{% blocktrans %}Persons{% endblocktrans %}{% endblock %} {% block content %} + {% has_perm 'core.create_person' user person as can_create_person %} + + {% if can_create_person %} + <a class="btn green waves-effect waves-light" href="{% url 'create_person' %}"> + <i class="material-icons left">add</i> + {% trans "Create person" %} + </a> + {% endif %} + {% render_table persons_table %} {% endblock %} diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py index 5f08e2d4c036184900e36ea3ef163e66b87edfa1..51048e5c83bdb6c540254a36754f32cdc3059591 100644 --- a/aleksis/core/urls.py +++ b/aleksis/core/urls.py @@ -29,8 +29,10 @@ urlpatterns = [ path("persons", views.persons, name="persons"), path("persons/accounts", views.persons_accounts, name="persons_accounts"), path("person", views.person, name="person"), + path("person/create", views.edit_person, name="create_person"), path("person/<int:id_>", views.person, name="person_by_id"), path("person/<int:id_>/edit", views.edit_person, name="edit_person_by_id"), + path("person/<int:id_>/delete", views.delete_person, name="delete_person_by_id"), path("groups", views.groups, name="groups"), path("groups/additional_fields", views.additional_fields, name="additional_fields"), path("groups/child_groups/", views.groups_child_groups, name="groups_child_groups"), @@ -52,6 +54,7 @@ urlpatterns = [ path("group/create", views.edit_group, name="create_group"), path("group/<int:id_>", views.group, name="group_by_id"), path("group/<int:id_>/edit", views.edit_group, name="edit_group_by_id"), + path("group/<int:id_>/delete", views.delete_group, name="delete_group_by_id"), path("", views.index, name="index"), path( "notifications/mark-read/<int:id_>", diff --git a/aleksis/core/views.py b/aleksis/core/views.py index 3a94dc46a04b554aaf6a7b4625aa968abe84a2b4..80ddd946c02d7e051f33cbdb5e4f4157c13384c5 100644 --- a/aleksis/core/views.py +++ b/aleksis/core/views.py @@ -9,6 +9,7 @@ from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ +import reversion from django_tables2 import RequestConfig, SingleTableView from dynamic_preferences.forms import preference_form_builder from guardian.shortcuts import get_objects_for_user @@ -274,21 +275,28 @@ def groups_child_groups(request: HttpRequest) -> HttpResponse: return render(request, "core/group/child_groups.html", context) -@permission_required( - "core.edit_person", fn=objectgetter_optional(Person, "request.user.person", True) -) +@permission_required("core.edit_person", fn=objectgetter_optional(Person)) def edit_person(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse: """Edit view for a single person, defaulting to logged-in person.""" context = {} - person = objectgetter_optional(Person, "request.user.person", True)(request, id_) + person = objectgetter_optional(Person)(request, id_) context["person"] = person - edit_person_form = EditPersonForm(request.POST or None, request.FILES or None, instance=person) + if id_: + # Edit form for existing group + edit_person_form = EditGroupForm(request.POST or None, instance=person) + else: + # Empty form to create a new group + if request.user.has_perm("core.create_person"): + edit_person_form = EditPersonForm(request.POST or None) + else: + raise PermissionDenied() if request.method == "POST": if edit_person_form.is_valid(): - edit_person_form.save(commit=True) + with reversion.create_revision(): + edit_person_form.save(commit=True) messages.success(request, _("The person has been saved.")) # Redirect to self to ensure post-processed data is displayed @@ -319,11 +327,15 @@ def edit_group(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse: edit_group_form = EditGroupForm(request.POST or None, instance=group) else: # Empty form to create a new group - edit_group_form = EditGroupForm(request.POST or None) + if request.user.has_perm("core.create_group"): + edit_group_form = EditGroupForm(request.POST or None) + else: + raise PermissionDenied() if request.method == "POST": if edit_group_form.is_valid(): - group = edit_group_form.save(commit=True) + with reversion.create_revision(): + group = edit_group_form.save(commit=True) messages.success(request, _("The group has been saved.")) @@ -514,6 +526,33 @@ def preferences( return render(request, "dynamic_preferences/form.html", context) +@permission_required("core.delete_person", fn=objectgetter_optional(Person)) +def delete_person(request: HttpRequest, id_: int) -> HttpResponse: + """View to delete an person.""" + person = objectgetter_optional(Person)(request, id_) + + with reversion.create_revision(): + person.save() + + person.delete() + messages.success(request, _("The person has been deleted.")) + + return redirect("persons") + + +@permission_required("core.delete_group", fn=objectgetter_optional(Group)) +def delete_group(request: HttpRequest, id_: int) -> HttpResponse: + """View to delete an group.""" + group = objectgetter_optional(Group)(request, id_) + with reversion.create_revision(): + group.save() + + group.delete() + messages.success(request, _("The group has been deleted.")) + + return redirect("groups") + + @permission_required( "core.change_additionalfield", fn=objectgetter_optional(AdditionalField, None, False) )