Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mixins.py 4.5KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. from urllib.parse import urlparse
  2. from django.conf import settings
  3. from django.contrib.auth import REDIRECT_FIELD_NAME
  4. from django.contrib.auth.views import redirect_to_login
  5. from django.core.exceptions import ImproperlyConfigured, PermissionDenied
  6. from django.shortcuts import resolve_url
  7. class AccessMixin:
  8. """
  9. Abstract CBV mixin that gives access mixins the same customizable
  10. functionality.
  11. """
  12. login_url = None
  13. permission_denied_message = ""
  14. raise_exception = False
  15. redirect_field_name = REDIRECT_FIELD_NAME
  16. def get_login_url(self):
  17. """
  18. Override this method to override the login_url attribute.
  19. """
  20. login_url = self.login_url or settings.LOGIN_URL
  21. if not login_url:
  22. raise ImproperlyConfigured(
  23. f"{self.__class__.__name__} is missing the login_url attribute. Define "
  24. f"{self.__class__.__name__}.login_url, settings.LOGIN_URL, or override "
  25. f"{self.__class__.__name__}.get_login_url()."
  26. )
  27. return str(login_url)
  28. def get_permission_denied_message(self):
  29. """
  30. Override this method to override the permission_denied_message attribute.
  31. """
  32. return self.permission_denied_message
  33. def get_redirect_field_name(self):
  34. """
  35. Override this method to override the redirect_field_name attribute.
  36. """
  37. return self.redirect_field_name
  38. def handle_no_permission(self):
  39. if self.raise_exception or self.request.user.is_authenticated:
  40. raise PermissionDenied(self.get_permission_denied_message())
  41. path = self.request.build_absolute_uri()
  42. resolved_login_url = resolve_url(self.get_login_url())
  43. # If the login url is the same scheme and net location then use the
  44. # path as the "next" url.
  45. login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
  46. current_scheme, current_netloc = urlparse(path)[:2]
  47. if (not login_scheme or login_scheme == current_scheme) and (
  48. not login_netloc or login_netloc == current_netloc
  49. ):
  50. path = self.request.get_full_path()
  51. return redirect_to_login(
  52. path,
  53. resolved_login_url,
  54. self.get_redirect_field_name(),
  55. )
  56. class LoginRequiredMixin(AccessMixin):
  57. """Verify that the current user is authenticated."""
  58. def dispatch(self, request, *args, **kwargs):
  59. if not request.user.is_authenticated:
  60. return self.handle_no_permission()
  61. return super().dispatch(request, *args, **kwargs)
  62. class PermissionRequiredMixin(AccessMixin):
  63. """Verify that the current user has all specified permissions."""
  64. permission_required = None
  65. def get_permission_required(self):
  66. """
  67. Override this method to override the permission_required attribute.
  68. Must return an iterable.
  69. """
  70. if self.permission_required is None:
  71. raise ImproperlyConfigured(
  72. f"{self.__class__.__name__} is missing the "
  73. f"permission_required attribute. Define "
  74. f"{self.__class__.__name__}.permission_required, or override "
  75. f"{self.__class__.__name__}.get_permission_required()."
  76. )
  77. if isinstance(self.permission_required, str):
  78. perms = (self.permission_required,)
  79. else:
  80. perms = self.permission_required
  81. return perms
  82. def has_permission(self):
  83. """
  84. Override this method to customize the way permissions are checked.
  85. """
  86. perms = self.get_permission_required()
  87. return self.request.user.has_perms(perms)
  88. def dispatch(self, request, *args, **kwargs):
  89. if not self.has_permission():
  90. return self.handle_no_permission()
  91. return super().dispatch(request, *args, **kwargs)
  92. class UserPassesTestMixin(AccessMixin):
  93. """
  94. Deny a request with a permission error if the test_func() method returns
  95. False.
  96. """
  97. def test_func(self):
  98. raise NotImplementedError(
  99. "{} is missing the implementation of the test_func() method.".format(
  100. self.__class__.__name__
  101. )
  102. )
  103. def get_test_func(self):
  104. """
  105. Override this method to use a different test_func method.
  106. """
  107. return self.test_func
  108. def dispatch(self, request, *args, **kwargs):
  109. user_test_result = self.get_test_func()()
  110. if not user_test_result:
  111. return self.handle_no_permission()
  112. return super().dispatch(request, *args, **kwargs)