perms.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. from django.contrib import messages
  2. from django.shortcuts import redirect
  3. from django.utils.translation import gettext_lazy as _
  4. from ....acl.admin.forms import get_permissions_forms
  5. from ....acl.admin.views import RoleAdmin, RolesList
  6. from ....acl.cache import clear_acl_cache
  7. from ....acl.models import Role
  8. from ....admin.views import generic
  9. from ...models import Category, CategoryRole, RoleCategoryACL
  10. from ..forms import (
  11. CategoryRoleForm,
  12. CategoryRolesACLFormFactory,
  13. RoleCategoryACLFormFactory,
  14. )
  15. from .categories import CategoriesList, CategoryAdmin
  16. class CategoryRoleAdmin(generic.AdminBaseMixin):
  17. root_link = "misago:admin:permissions:categories:index"
  18. model = CategoryRole
  19. templates_dir = "misago/admin/categoryroles"
  20. message_404 = _("Requested role does not exist.")
  21. class CategoryRolesList(CategoryRoleAdmin, generic.ListView):
  22. ordering = (("name", None),)
  23. class RoleFormMixin:
  24. def real_dispatch(self, request, target):
  25. form = CategoryRoleForm(instance=target)
  26. perms_forms = get_permissions_forms(target)
  27. if request.method == "POST":
  28. perms_forms = get_permissions_forms(target, request.POST)
  29. valid_forms = 0
  30. for permissions_form in perms_forms:
  31. if permissions_form.is_valid():
  32. valid_forms += 1
  33. form = CategoryRoleForm(request.POST, instance=target)
  34. if form.is_valid():
  35. if len(perms_forms) == valid_forms:
  36. new_permissions = {}
  37. for permissions_form in perms_forms:
  38. cleaned_data = permissions_form.cleaned_data
  39. new_permissions[permissions_form.prefix] = cleaned_data
  40. form.instance.permissions = new_permissions
  41. form.instance.save()
  42. messages.success(
  43. request, self.message_submit % {"name": target.name}
  44. )
  45. if "stay" in request.POST:
  46. return redirect(request.path)
  47. return redirect(self.root_link)
  48. form.add_error(None, _("Form contains errors."))
  49. template_name = self.get_template_name(request, target)
  50. return self.render(
  51. request,
  52. {"form": form, "target": target, "perms_forms": perms_forms},
  53. template_name,
  54. )
  55. class NewCategoryRole(RoleFormMixin, CategoryRoleAdmin, generic.ModelFormView):
  56. message_submit = _('New role "%(name)s" has been saved.')
  57. class EditCategoryRole(RoleFormMixin, CategoryRoleAdmin, generic.ModelFormView):
  58. message_submit = _('Role "%(name)s" has been changed.')
  59. class DeleteCategoryRole(CategoryRoleAdmin, generic.ButtonView):
  60. def check_permissions(self, request, target):
  61. if target.special_role:
  62. message = _('Role "%(name)s" is special role and can\'t be deleted.')
  63. return message % {"name": target.name}
  64. def button_action(self, request, target):
  65. target.delete()
  66. message = _('Role "%(name)s" has been deleted.')
  67. messages.success(request, message % {"name": target.name})
  68. class CategoryPermissions(CategoryAdmin, generic.ModelFormView):
  69. templates_dir = "misago/admin/categoryroles"
  70. template_name = "categoryroles.html"
  71. def real_dispatch(self, request, target):
  72. category_roles = CategoryRole.objects.order_by("name")
  73. assigned_roles = {}
  74. for acl in target.category_role_set.select_related("category_role"):
  75. assigned_roles[acl.role_id] = acl.category_role
  76. forms = []
  77. forms_are_valid = True
  78. for role in Role.objects.order_by("name"):
  79. FormType = CategoryRolesACLFormFactory(
  80. role, category_roles, assigned_roles.get(role.pk)
  81. )
  82. if request.method == "POST":
  83. forms.append(FormType(request.POST, prefix=role.pk))
  84. if not forms[-1].is_valid():
  85. forms_are_valid = False
  86. else:
  87. forms.append(FormType(prefix=role.pk))
  88. if request.method == "POST" and forms_are_valid:
  89. target.category_role_set.all().delete()
  90. new_permissions = []
  91. for form in forms:
  92. if form.cleaned_data["category_role"]:
  93. new_permissions.append(
  94. RoleCategoryACL(
  95. role=form.role,
  96. category=target,
  97. category_role=form.cleaned_data["category_role"],
  98. )
  99. )
  100. if new_permissions:
  101. RoleCategoryACL.objects.bulk_create(new_permissions)
  102. clear_acl_cache()
  103. message = _("Category %(name)s permissions have been changed.")
  104. messages.success(request, message % {"name": target.name})
  105. if "stay" in request.POST:
  106. return redirect(request.path)
  107. return redirect(self.root_link)
  108. template_name = self.get_template_name(request, target)
  109. return self.render(request, {"forms": forms, "target": target}, template_name)
  110. CategoriesList.add_item_action(
  111. name=_("Change permissions"), link="misago:admin:categories:permissions"
  112. )
  113. class RoleCategoriesACL(RoleAdmin, generic.ModelFormView):
  114. templates_dir = "misago/admin/categoryroles"
  115. template_name = "rolecategories.html"
  116. def real_dispatch(self, request, target):
  117. categories = Category.objects.all_categories()
  118. roles = CategoryRole.objects.order_by("name")
  119. if not categories:
  120. messages.info(request, _("No categories exist."))
  121. return redirect(self.root_link)
  122. choices = {}
  123. for choice in target.categories_acls.select_related("category_role"):
  124. choices[choice.category_id] = choice.category_role
  125. forms = []
  126. forms_are_valid = True
  127. for category in categories:
  128. category.level_range = range(category.level - 1)
  129. FormType = RoleCategoryACLFormFactory(
  130. category, roles, choices.get(category.pk)
  131. )
  132. if request.method == "POST":
  133. forms.append(FormType(request.POST, prefix=category.pk))
  134. if not forms[-1].is_valid():
  135. forms_are_valid = False
  136. else:
  137. forms.append(FormType(prefix=category.pk))
  138. if request.method == "POST" and forms_are_valid:
  139. target.categories_acls.all().delete()
  140. new_permissions = []
  141. for form in forms:
  142. if form.cleaned_data["role"]:
  143. new_permissions.append(
  144. RoleCategoryACL(
  145. role=target,
  146. category=form.category,
  147. category_role=form.cleaned_data["role"],
  148. )
  149. )
  150. if new_permissions:
  151. RoleCategoryACL.objects.bulk_create(new_permissions)
  152. clear_acl_cache()
  153. message = _("Category permissions for role %(name)s have been changed.")
  154. messages.success(request, message % {"name": target.name})
  155. if "stay" in request.POST:
  156. return redirect(request.path)
  157. return redirect(self.root_link)
  158. template_name = self.get_template_name(request, target)
  159. return self.render(request, {"forms": forms, "target": target}, template_name)
  160. RolesList.add_item_action(
  161. name=_("Categories permissions"), link="misago:admin:permissions:categories"
  162. )