forked from madre/devops
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.py
108 lines (92 loc) · 3.83 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
from __future__ import unicode_literals
import functools
try:
from urllib.parse import urlparse, urlunparse
except ImportError: # python 2
from urlparse import urlparse, urlunparse
from django.core import urlresolvers
from django.core.exceptions import SuspiciousOperation
from django.http import HttpResponseRedirect, QueryDict
from django.contrib.auth import get_user_model
from account.conf import settings
def get_user_lookup_kwargs(kwargs):
result = {}
username_field = getattr(get_user_model(), "USERNAME_FIELD", "username")
for key, value in kwargs.items():
result[key.format(username=username_field)] = value
return result
def default_redirect(request, fallback_url, **kwargs):
redirect_field_name = kwargs.get("redirect_field_name", "next")
next_url = request.POST.get(redirect_field_name, request.GET.get(redirect_field_name))
if not next_url:
# try the session if available
if hasattr(request, "session"):
session_key_value = kwargs.get("session_key_value", "redirect_to")
if session_key_value in request.session:
next_url = request.session[session_key_value]
del request.session[session_key_value]
is_safe = functools.partial(
ensure_safe_url,
allowed_protocols=kwargs.get("allowed_protocols"),
allowed_host=request.get_host()
)
if next_url and is_safe(next_url):
return next_url
else:
try:
fallback_url = urlresolvers.reverse(fallback_url)
except urlresolvers.NoReverseMatch:
if callable(fallback_url):
raise
if "/" not in fallback_url and "." not in fallback_url:
raise
# assert the fallback URL is safe to return to caller. if it is
# determined unsafe then raise an exception as the fallback value comes
# from the a source the developer choose.
is_safe(fallback_url, raise_on_fail=True)
return fallback_url
def user_display(user):
return settings.ACCOUNT_USER_DISPLAY(user)
def ensure_safe_url(url, allowed_protocols=None, allowed_host=None, raise_on_fail=False):
if allowed_protocols is None:
allowed_protocols = ["http", "https"]
parsed = urlparse(url)
# perform security checks to ensure no malicious intent
# (i.e., an XSS attack with a data URL)
safe = True
if parsed.scheme and parsed.scheme not in allowed_protocols:
if raise_on_fail:
raise SuspiciousOperation("Unsafe redirect to URL with protocol '{0}'".format(parsed.scheme))
safe = False
if allowed_host and parsed.netloc and parsed.netloc != allowed_host:
if raise_on_fail:
raise SuspiciousOperation("Unsafe redirect to URL not matching host '{0}'".format(allowed_host))
safe = False
return safe
def handle_redirect_to_login(request, **kwargs):
login_url = kwargs.get("login_url")
redirect_field_name = kwargs.get("redirect_field_name")
next_url = kwargs.get("next_url")
if login_url is None:
login_url = settings.ACCOUNT_LOGIN_URL
if next_url is None:
next_url = request.get_full_path()
try:
login_url = urlresolvers.reverse(login_url)
except urlresolvers.NoReverseMatch:
if callable(login_url):
raise
if "/" not in login_url and "." not in login_url:
raise
url_bits = list(urlparse(login_url))
if redirect_field_name:
querystring = QueryDict(url_bits[4], mutable=True)
querystring[redirect_field_name] = next_url
url_bits[4] = querystring.urlencode(safe="/")
return HttpResponseRedirect(urlunparse(url_bits))
def get_form_data(form, field_name, default=None):
if form.prefix:
key = "-".join([form.prefix, field_name])
else:
key = field_name
return form.data.get(key, default)