Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

decorators.py 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import urlparse
  2. from functools import wraps
  3. from django.contrib.auth import REDIRECT_FIELD_NAME
  4. from django.contrib.auth.decorators import user_passes_test
  5. from django.shortcuts import render
  6. from django.contrib import messages
  7. from django.contrib.auth.views import redirect_to_login
  8. from django.core.exceptions import PermissionDenied
  9. from django.core.urlresolvers import reverse_lazy
  10. from django.utils.translation import ugettext_lazy as _
  11. def staff_member_required(view_func, login_url=None):
  12. """
  13. Ensure that the user is a logged-in staff member.
  14. * If not authenticated, redirect to a specified login URL.
  15. * If not staff, show a 403 page
  16. This decorator is based on the decorator with the same name from
  17. django.contrib.admin.views.decorators. This one is superior as it allows a
  18. redirect URL to be specified.
  19. """
  20. if login_url is None:
  21. login_url = reverse_lazy('customer:login')
  22. @wraps(view_func)
  23. def _checklogin(request, *args, **kwargs):
  24. if request.user.is_active and request.user.is_staff:
  25. return view_func(request, *args, **kwargs)
  26. # If user is not logged in, redirect to login page
  27. if not request.user.is_authenticated():
  28. # If the login url is the same scheme and net location then just
  29. # use the path as the "next" url.
  30. path = request.build_absolute_uri()
  31. login_scheme, login_netloc = urlparse.urlparse(login_url)[:2]
  32. current_scheme, current_netloc = urlparse.urlparse(path)[:2]
  33. if ((not login_scheme or login_scheme == current_scheme) and
  34. (not login_netloc or login_netloc == current_netloc)):
  35. path = request.get_full_path()
  36. messages.warning(request, _("You must log in to access this page"))
  37. return redirect_to_login(path, login_url, REDIRECT_FIELD_NAME)
  38. else:
  39. # User does not have permission to view this page
  40. raise PermissionDenied
  41. return _checklogin
  42. def check_permissions(user, permissions):
  43. """
  44. Permissions can be a list or a two-tuple of lists. If it is a two-tuple,
  45. both permission lists will be evaluated and the outcome will be or'ed.
  46. Each item of the list(s) must be either a valid Django permission name
  47. (model.codename) or an attribute on the User model
  48. (e.g. 'is_active', 'is_superuser').
  49. Example usage:
  50. - permissions_required(['is_staff', ])
  51. would replace staff_member_required
  52. - permissions_required(['is_anonymous', ])
  53. would replace login_forbidden
  54. - permissions_required((['is_staff',], ['partner.dashboard_access']))
  55. allows both staff users and users with the above permission
  56. """
  57. def _check_one_permission_list(perms):
  58. regular_permissions = [perm for perm in perms if '.' in perm]
  59. conditions = [perm for perm in perms if '.' not in perm]
  60. if conditions and ['is_active', 'is_anonymous'] not in conditions:
  61. # always check for is_active where appropriate
  62. conditions.append('is_active')
  63. passes_conditions = all([getattr(user, perm) for perm in conditions])
  64. return passes_conditions and user.has_perms(regular_permissions)
  65. if permissions is None:
  66. return True
  67. elif isinstance(permissions, list):
  68. return _check_one_permission_list(permissions)
  69. else:
  70. return (_check_one_permission_list(permissions[0]) or
  71. _check_one_permission_list(permissions[1]))
  72. def permissions_required(permissions, login_url=None):
  73. """
  74. Decorator that checks if a user has the given permissions.
  75. Accepts a list or two-tuple of lists of permissions (see check_permissions
  76. documentation).
  77. If the user is not logged in and the test fails, she is redirected to a
  78. login page. If the user is logged in, she gets a HTTP 403 Permission Denied
  79. message, analogous to Django's permission_required decorator.
  80. """
  81. if login_url is None:
  82. login_url = reverse_lazy('customer:login')
  83. def _check_permissions(user):
  84. outcome = check_permissions(user, permissions)
  85. if not outcome and user.is_authenticated():
  86. raise PermissionDenied
  87. else:
  88. return outcome
  89. return user_passes_test(_check_permissions, login_url=login_url)
  90. def login_forbidden(view_func, template_name='login_forbidden.html',
  91. status=403):
  92. """
  93. Only allow anonymous users to access this view.
  94. """
  95. @wraps(view_func)
  96. def _checklogin(request, *args, **kwargs):
  97. if not request.user.is_authenticated():
  98. return view_func(request, *args, **kwargs)
  99. return render(request, template_name, status=status)
  100. return _checklogin