django-cookie-consent 0.9.0__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cookie_consent/__init__.py +1 -1
- cookie_consent/admin.py +5 -4
- cookie_consent/cache.py +13 -7
- cookie_consent/conf.py +20 -14
- cookie_consent/forms.py +50 -0
- cookie_consent/middleware.py +7 -3
- cookie_consent/models.py +24 -14
- cookie_consent/processor.py +77 -0
- cookie_consent/py.typed +0 -0
- cookie_consent/static/cookie_consent/cookiebar.module.js +8 -3
- cookie_consent/static/cookie_consent/cookiebar.module.js.map +2 -2
- cookie_consent/templates/cookie_consent/_cookie_group.html +4 -2
- cookie_consent/templatetags/cookie_consent_tags.py +25 -126
- cookie_consent/urls.py +3 -24
- cookie_consent/util.py +42 -113
- cookie_consent/views.py +45 -39
- {django_cookie_consent-0.9.0.dist-info → django_cookie_consent-1.0.0.dist-info}/METADATA +7 -6
- django_cookie_consent-1.0.0.dist-info/RECORD +31 -0
- {django_cookie_consent-0.9.0.dist-info → django_cookie_consent-1.0.0.dist-info}/WHEEL +1 -1
- cookie_consent/static/cookie_consent/cookiebar.js +0 -67
- django_cookie_consent-0.9.0.dist-info/RECORD +0 -29
- {django_cookie_consent-0.9.0.dist-info → django_cookie_consent-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {django_cookie_consent-0.9.0.dist-info → django_cookie_consent-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
from collections.abc import Collection
|
|
2
2
|
|
|
3
3
|
from django import template
|
|
4
|
-
from django.
|
|
4
|
+
from django.http import HttpRequest
|
|
5
5
|
from django.utils.html import json_script
|
|
6
6
|
|
|
7
7
|
from ..cache import all_cookie_groups as get_all_cookie_groups
|
|
8
|
-
from ..
|
|
8
|
+
from ..models import CookieGroup
|
|
9
9
|
from ..util import (
|
|
10
10
|
are_all_cookies_accepted,
|
|
11
|
-
get_accepted_cookies,
|
|
12
|
-
get_cookie_dict_from_request,
|
|
13
|
-
get_cookie_string,
|
|
14
11
|
get_cookie_value_from_request,
|
|
15
12
|
get_not_accepted_or_declined_cookie_groups,
|
|
16
13
|
is_cookie_consent_enabled,
|
|
@@ -20,31 +17,39 @@ register = template.Library()
|
|
|
20
17
|
|
|
21
18
|
|
|
22
19
|
@register.filter
|
|
23
|
-
def cookie_group_accepted(request,
|
|
20
|
+
def cookie_group_accepted(request: HttpRequest, group_or_cookie: str) -> bool:
|
|
24
21
|
"""
|
|
25
|
-
|
|
22
|
+
Return ``True`` if the cookie group/cookie is accepted.
|
|
26
23
|
|
|
27
24
|
Examples:
|
|
28
|
-
|
|
25
|
+
|
|
26
|
+
.. code-block:: django
|
|
29
27
|
|
|
30
28
|
{{ request|cookie_group_accepted:"analytics" }}
|
|
31
29
|
{{ request|cookie_group_accepted:"analytics=*:.google.com" }}
|
|
32
30
|
"""
|
|
33
|
-
value = get_cookie_value_from_request(request, *
|
|
31
|
+
value = get_cookie_value_from_request(request, *group_or_cookie.split("="))
|
|
34
32
|
return value is True
|
|
35
33
|
|
|
36
34
|
|
|
37
35
|
@register.filter
|
|
38
|
-
def cookie_group_declined(request,
|
|
36
|
+
def cookie_group_declined(request: HttpRequest, group_or_cookie: str) -> bool:
|
|
39
37
|
"""
|
|
40
|
-
|
|
38
|
+
Return ``True`` if the cookie group/cookie is declined.
|
|
39
|
+
|
|
40
|
+
Examples:
|
|
41
|
+
|
|
42
|
+
.. code-block:: django
|
|
43
|
+
|
|
44
|
+
{{ request|cookie_group_declined:"analytics" }}
|
|
45
|
+
{{ request|cookie_group_declined:"analytics=*:.google.com" }}
|
|
41
46
|
"""
|
|
42
|
-
value = get_cookie_value_from_request(request, *
|
|
47
|
+
value = get_cookie_value_from_request(request, *group_or_cookie.split("="))
|
|
43
48
|
return value is False
|
|
44
49
|
|
|
45
50
|
|
|
46
51
|
@register.filter
|
|
47
|
-
def all_cookies_accepted(request):
|
|
52
|
+
def all_cookies_accepted(request: HttpRequest) -> bool:
|
|
48
53
|
"""
|
|
49
54
|
Filter returns if all cookies are accepted.
|
|
50
55
|
"""
|
|
@@ -52,129 +57,23 @@ def all_cookies_accepted(request):
|
|
|
52
57
|
|
|
53
58
|
|
|
54
59
|
@register.simple_tag
|
|
55
|
-
def not_accepted_or_declined_cookie_groups(
|
|
60
|
+
def not_accepted_or_declined_cookie_groups(
|
|
61
|
+
request: HttpRequest,
|
|
62
|
+
) -> Collection[CookieGroup]:
|
|
56
63
|
"""
|
|
57
|
-
|
|
58
|
-
or decline.
|
|
64
|
+
Return the cookie groups for which no explicit accept or decline has been given.
|
|
59
65
|
"""
|
|
60
66
|
return get_not_accepted_or_declined_cookie_groups(request)
|
|
61
67
|
|
|
62
68
|
|
|
63
69
|
@register.filter
|
|
64
|
-
def cookie_consent_enabled(request):
|
|
70
|
+
def cookie_consent_enabled(request: HttpRequest) -> bool:
|
|
65
71
|
"""
|
|
66
|
-
|
|
72
|
+
Indicate whether the cookie-consent app is enabled or not.
|
|
67
73
|
"""
|
|
68
74
|
return is_cookie_consent_enabled(request)
|
|
69
75
|
|
|
70
76
|
|
|
71
|
-
@register.simple_tag
|
|
72
|
-
def cookie_consent_accept_url(cookie_groups):
|
|
73
|
-
"""
|
|
74
|
-
Assignement tag returns url for accepting given concept groups.
|
|
75
|
-
"""
|
|
76
|
-
varnames = ",".join([g.varname for g in cookie_groups])
|
|
77
|
-
url = reverse("cookie_consent_accept", kwargs={"varname": varnames})
|
|
78
|
-
return url
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
@register.simple_tag
|
|
82
|
-
def cookie_consent_decline_url(cookie_groups):
|
|
83
|
-
"""
|
|
84
|
-
Assignement tag returns url for declining given concept groups.
|
|
85
|
-
"""
|
|
86
|
-
varnames = ",".join([g.varname for g in cookie_groups])
|
|
87
|
-
url = reverse("cookie_consent_decline", kwargs={"varname": varnames})
|
|
88
|
-
return url
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
@register.simple_tag
|
|
92
|
-
def get_accept_cookie_groups_cookie_string(request, cookie_groups): # pragma: no cover
|
|
93
|
-
"""
|
|
94
|
-
Tag returns accept cookie string suitable to use in javascript.
|
|
95
|
-
"""
|
|
96
|
-
warnings.warn(
|
|
97
|
-
"Cookie string template tags for JS are deprecated and will be removed "
|
|
98
|
-
"in django-cookie-consent 1.0",
|
|
99
|
-
DeprecationWarning,
|
|
100
|
-
stacklevel=1,
|
|
101
|
-
)
|
|
102
|
-
cookie_dic = get_cookie_dict_from_request(request)
|
|
103
|
-
for cookie_group in cookie_groups:
|
|
104
|
-
cookie_dic[cookie_group.varname] = cookie_group.get_version()
|
|
105
|
-
return get_cookie_string(cookie_dic)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
@register.simple_tag
|
|
109
|
-
def get_decline_cookie_groups_cookie_string(request, cookie_groups):
|
|
110
|
-
"""
|
|
111
|
-
Tag returns decline cookie string suitable to use in javascript.
|
|
112
|
-
"""
|
|
113
|
-
warnings.warn(
|
|
114
|
-
"Cookie string template tags for JS are deprecated and will be removed "
|
|
115
|
-
"in django-cookie-consent 1.0",
|
|
116
|
-
DeprecationWarning,
|
|
117
|
-
stacklevel=1,
|
|
118
|
-
)
|
|
119
|
-
cookie_dic = get_cookie_dict_from_request(request)
|
|
120
|
-
for cookie_group in cookie_groups:
|
|
121
|
-
cookie_dic[cookie_group.varname] = settings.COOKIE_CONSENT_DECLINE
|
|
122
|
-
return get_cookie_string(cookie_dic)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
@register.simple_tag
|
|
126
|
-
def js_type_for_cookie_consent(request, varname, cookie=None):
|
|
127
|
-
"""
|
|
128
|
-
Tag returns "x/cookie_consent" when processing javascript
|
|
129
|
-
will create an cookie and consent does not exists yet.
|
|
130
|
-
|
|
131
|
-
Example::
|
|
132
|
-
|
|
133
|
-
<script type="{% js_type_for_cookie_consent request "social" %}"
|
|
134
|
-
data-varname="social">
|
|
135
|
-
alert("Social cookie accepted");
|
|
136
|
-
</script>
|
|
137
|
-
"""
|
|
138
|
-
# This approach doesn't work with page caches and/or strict
|
|
139
|
-
# Content-Security-Policies (unless you use nonces, which again doesn't work with
|
|
140
|
-
# aggressive page caching).
|
|
141
|
-
warnings.warn(
|
|
142
|
-
"Template tags for use in/with JS are deprecated and will be removed "
|
|
143
|
-
"in django-cookie-consent 1.0",
|
|
144
|
-
DeprecationWarning,
|
|
145
|
-
stacklevel=1,
|
|
146
|
-
)
|
|
147
|
-
enabled = is_cookie_consent_enabled(request)
|
|
148
|
-
if not enabled:
|
|
149
|
-
res = True
|
|
150
|
-
else:
|
|
151
|
-
value = get_cookie_value_from_request(request, varname, cookie)
|
|
152
|
-
if value is None:
|
|
153
|
-
res = settings.COOKIE_CONSENT_OPT_OUT
|
|
154
|
-
else:
|
|
155
|
-
res = value
|
|
156
|
-
return "text/javascript" if res else "x/cookie_consent"
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
@register.filter
|
|
160
|
-
def accepted_cookies(request):
|
|
161
|
-
"""
|
|
162
|
-
Filter returns accepted cookies varnames.
|
|
163
|
-
|
|
164
|
-
.. code-block:: django
|
|
165
|
-
|
|
166
|
-
{{ request|accepted_cookies }}
|
|
167
|
-
|
|
168
|
-
"""
|
|
169
|
-
warnings.warn(
|
|
170
|
-
"The 'accepted_cookies' template filter is deprecated and will be removed"
|
|
171
|
-
"in django-cookie-consent 1.0.",
|
|
172
|
-
DeprecationWarning,
|
|
173
|
-
stacklevel=1,
|
|
174
|
-
)
|
|
175
|
-
return [c.varname for c in get_accepted_cookies(request)]
|
|
176
|
-
|
|
177
|
-
|
|
178
77
|
@register.simple_tag
|
|
179
78
|
def all_cookie_groups(element_id: str):
|
|
180
79
|
"""
|
cookie_consent/urls.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
from django.urls import path
|
|
2
|
-
from django.views.decorators.csrf import csrf_exempt
|
|
1
|
+
from django.urls import path
|
|
3
2
|
|
|
4
3
|
from .views import (
|
|
5
4
|
CookieGroupAcceptView,
|
|
@@ -9,28 +8,8 @@ from .views import (
|
|
|
9
8
|
)
|
|
10
9
|
|
|
11
10
|
urlpatterns = [
|
|
12
|
-
path(
|
|
13
|
-
|
|
14
|
-
csrf_exempt(CookieGroupAcceptView.as_view()),
|
|
15
|
-
name="cookie_consent_accept_all",
|
|
16
|
-
),
|
|
17
|
-
# TODO: use form or query string params for this instead?
|
|
18
|
-
re_path(
|
|
19
|
-
r"^accept/(?P<varname>.*)/$",
|
|
20
|
-
csrf_exempt(CookieGroupAcceptView.as_view()),
|
|
21
|
-
name="cookie_consent_accept",
|
|
22
|
-
),
|
|
23
|
-
# TODO: use form or query string params for this instead?
|
|
24
|
-
re_path(
|
|
25
|
-
r"^decline/(?P<varname>.*)/$",
|
|
26
|
-
csrf_exempt(CookieGroupDeclineView.as_view()),
|
|
27
|
-
name="cookie_consent_decline",
|
|
28
|
-
),
|
|
29
|
-
path(
|
|
30
|
-
"decline/",
|
|
31
|
-
csrf_exempt(CookieGroupDeclineView.as_view()),
|
|
32
|
-
name="cookie_consent_decline_all",
|
|
33
|
-
),
|
|
11
|
+
path("accept/", CookieGroupAcceptView.as_view(), name="cookie_consent_accept"),
|
|
12
|
+
path("decline/", CookieGroupDeclineView.as_view(), name="cookie_consent_decline"),
|
|
34
13
|
path("status/", CookieStatusView.as_view(), name="cookie_consent_status"),
|
|
35
14
|
path("", CookieGroupListView.as_view(), name="cookie_consent_cookie_group_list"),
|
|
36
15
|
]
|
cookie_consent/util.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import datetime
|
|
2
1
|
import logging
|
|
2
|
+
from collections.abc import Callable, Collection, Iterator
|
|
3
|
+
|
|
4
|
+
from django.http import HttpRequest, HttpResponseBase
|
|
3
5
|
|
|
4
6
|
from .cache import all_cookie_groups, get_cookie, get_cookie_group
|
|
5
7
|
from .conf import settings
|
|
6
|
-
from .models import
|
|
8
|
+
from .models import Cookie, CookieGroup
|
|
7
9
|
|
|
8
10
|
logger = logging.getLogger(__name__)
|
|
9
11
|
|
|
@@ -17,11 +19,12 @@ def parse_cookie_str(cookie: str) -> dict[str, str]:
|
|
|
17
19
|
|
|
18
20
|
bits = cookie.split(COOKIE_GROUP_SEP)
|
|
19
21
|
|
|
20
|
-
def _gen_pairs():
|
|
22
|
+
def _gen_pairs() -> Iterator[tuple[str, str]]:
|
|
21
23
|
for possible_pair in bits:
|
|
22
24
|
parts = possible_pair.split(KEY_VALUE_SEP)
|
|
23
25
|
if len(parts) == 2:
|
|
24
|
-
|
|
26
|
+
varname, cookie = parts
|
|
27
|
+
yield varname, cookie
|
|
25
28
|
else:
|
|
26
29
|
logger.debug("cookie_value_discarded", extra={"value": possible_pair})
|
|
27
30
|
|
|
@@ -39,7 +42,7 @@ def _contains_invalid_characters(*inputs: str) -> bool:
|
|
|
39
42
|
return False
|
|
40
43
|
|
|
41
44
|
|
|
42
|
-
def dict_to_cookie_str(dic) -> str:
|
|
45
|
+
def dict_to_cookie_str(dic: dict[str, str]) -> str:
|
|
43
46
|
"""
|
|
44
47
|
Serialize a dictionary of cookie-group metadata to a string.
|
|
45
48
|
|
|
@@ -50,7 +53,7 @@ def dict_to_cookie_str(dic) -> str:
|
|
|
50
53
|
Invalid key/value pairs are dropped.
|
|
51
54
|
"""
|
|
52
55
|
|
|
53
|
-
def _gen_pairs():
|
|
56
|
+
def _gen_pairs() -> Iterator[str]:
|
|
54
57
|
for key, value in dic.items():
|
|
55
58
|
if _contains_invalid_characters(key, value):
|
|
56
59
|
continue
|
|
@@ -59,105 +62,64 @@ def dict_to_cookie_str(dic) -> str:
|
|
|
59
62
|
return "|".join(_gen_pairs())
|
|
60
63
|
|
|
61
64
|
|
|
62
|
-
def get_cookie_dict_from_request(request):
|
|
63
|
-
cookie_str = request.COOKIES.get(settings.COOKIE_CONSENT_NAME)
|
|
65
|
+
def get_cookie_dict_from_request(request: HttpRequest) -> dict[str, str]:
|
|
66
|
+
cookie_str = request.COOKIES.get(settings.COOKIE_CONSENT_NAME, "")
|
|
64
67
|
return parse_cookie_str(cookie_str)
|
|
65
68
|
|
|
66
69
|
|
|
67
|
-
def set_cookie_dict_to_response(
|
|
70
|
+
def set_cookie_dict_to_response(
|
|
71
|
+
response: HttpResponseBase, dic: dict[str, str]
|
|
72
|
+
) -> None:
|
|
68
73
|
response.set_cookie(
|
|
69
74
|
settings.COOKIE_CONSENT_NAME,
|
|
70
75
|
dict_to_cookie_str(dic),
|
|
71
76
|
max_age=settings.COOKIE_CONSENT_MAX_AGE,
|
|
72
77
|
domain=settings.COOKIE_CONSENT_DOMAIN,
|
|
73
|
-
secure=settings.COOKIE_CONSENT_SECURE
|
|
74
|
-
httponly=settings.COOKIE_CONSENT_HTTPONLY
|
|
78
|
+
secure=settings.COOKIE_CONSENT_SECURE,
|
|
79
|
+
httponly=settings.COOKIE_CONSENT_HTTPONLY,
|
|
75
80
|
samesite=settings.COOKIE_CONSENT_SAMESITE,
|
|
76
81
|
)
|
|
77
82
|
|
|
78
83
|
|
|
79
|
-
def get_cookie_value_from_request(
|
|
84
|
+
def get_cookie_value_from_request(
|
|
85
|
+
request: HttpRequest, varname: str, cookie: str = ""
|
|
86
|
+
) -> bool | None:
|
|
80
87
|
"""
|
|
81
88
|
Returns if cookie group or its specific cookie has been accepted.
|
|
82
89
|
|
|
83
90
|
Returns True or False when cookie is accepted or declined or None
|
|
84
91
|
if cookie is not set.
|
|
85
92
|
"""
|
|
86
|
-
cookie_dic
|
|
87
|
-
if not cookie_dic:
|
|
93
|
+
if not (cookie_dic := get_cookie_dict_from_request(request)):
|
|
88
94
|
return None
|
|
89
|
-
|
|
90
|
-
cookie_group = get_cookie_group(varname=varname)
|
|
91
|
-
if not cookie_group:
|
|
95
|
+
if not (cookie_group := get_cookie_group(varname=varname)):
|
|
92
96
|
return None
|
|
97
|
+
|
|
98
|
+
_cookie: Cookie | None = None
|
|
93
99
|
if cookie:
|
|
94
100
|
name, domain = cookie.split(":")
|
|
95
|
-
|
|
96
|
-
else:
|
|
97
|
-
cookie = None
|
|
101
|
+
_cookie = get_cookie(cookie_group, name, domain)
|
|
98
102
|
|
|
99
|
-
version
|
|
103
|
+
match version := cookie_dic.get(varname, None):
|
|
104
|
+
case None:
|
|
105
|
+
return None
|
|
106
|
+
case str() if version == settings.COOKIE_CONSENT_DECLINE:
|
|
107
|
+
return False
|
|
100
108
|
|
|
101
|
-
if
|
|
102
|
-
|
|
103
|
-
if version is None:
|
|
104
|
-
return None
|
|
105
|
-
if not cookie:
|
|
106
|
-
v = cookie_group.get_version()
|
|
107
|
-
else:
|
|
108
|
-
v = cookie.get_version()
|
|
109
|
-
if version >= v:
|
|
109
|
+
reference_version = _cookie.get_version() if _cookie else cookie_group.get_version()
|
|
110
|
+
if version >= reference_version:
|
|
110
111
|
return True
|
|
111
112
|
return None
|
|
112
113
|
|
|
113
114
|
|
|
114
|
-
def get_cookie_groups(varname=
|
|
115
|
+
def get_cookie_groups(varname: str = "") -> Collection[CookieGroup]:
|
|
115
116
|
if not varname:
|
|
116
117
|
return all_cookie_groups().values()
|
|
117
118
|
keys = varname.split(",")
|
|
118
119
|
return [g for k, g in all_cookie_groups().items() if k in keys]
|
|
119
120
|
|
|
120
121
|
|
|
121
|
-
def
|
|
122
|
-
"""
|
|
123
|
-
Accept cookies in Cookie Group specified by ``varname``.
|
|
124
|
-
"""
|
|
125
|
-
cookie_dic = get_cookie_dict_from_request(request)
|
|
126
|
-
for cookie_group in get_cookie_groups(varname):
|
|
127
|
-
cookie_dic[cookie_group.varname] = cookie_group.get_version()
|
|
128
|
-
if settings.COOKIE_CONSENT_LOG_ENABLED:
|
|
129
|
-
LogItem.objects.create(
|
|
130
|
-
action=ACTION_ACCEPTED,
|
|
131
|
-
cookiegroup=cookie_group,
|
|
132
|
-
version=cookie_group.get_version(),
|
|
133
|
-
)
|
|
134
|
-
set_cookie_dict_to_response(response, cookie_dic)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
def delete_cookies(response, cookie_group):
|
|
138
|
-
if cookie_group.is_deletable:
|
|
139
|
-
for cookie in cookie_group.cookie_set.all():
|
|
140
|
-
response.delete_cookie(cookie.name, cookie.path, cookie.domain)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def decline_cookies(request, response, varname=None):
|
|
144
|
-
"""
|
|
145
|
-
Decline and delete cookies in CookieGroup specified by ``varname``.
|
|
146
|
-
"""
|
|
147
|
-
cookie_dic = get_cookie_dict_from_request(request)
|
|
148
|
-
for cookie_group in get_cookie_groups(varname):
|
|
149
|
-
cookie_dic[cookie_group.varname] = settings.COOKIE_CONSENT_DECLINE
|
|
150
|
-
delete_cookies(response, cookie_group)
|
|
151
|
-
if settings.COOKIE_CONSENT_LOG_ENABLED:
|
|
152
|
-
LogItem.objects.create(
|
|
153
|
-
action=ACTION_DECLINED,
|
|
154
|
-
cookiegroup=cookie_group,
|
|
155
|
-
version=cookie_group.get_version(),
|
|
156
|
-
)
|
|
157
|
-
set_cookie_dict_to_response(response, cookie_dic)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
def are_all_cookies_accepted(request):
|
|
122
|
+
def are_all_cookies_accepted(request: HttpRequest) -> bool:
|
|
161
123
|
"""
|
|
162
124
|
Returns if all cookies are accepted.
|
|
163
125
|
"""
|
|
@@ -169,7 +131,7 @@ def are_all_cookies_accepted(request):
|
|
|
169
131
|
)
|
|
170
132
|
|
|
171
133
|
|
|
172
|
-
def _get_cookie_groups_by_state(request, state: bool | None):
|
|
134
|
+
def _get_cookie_groups_by_state(request, state: bool | None) -> Collection[CookieGroup]:
|
|
173
135
|
return [
|
|
174
136
|
cookie_group
|
|
175
137
|
for cookie_group in get_cookie_groups()
|
|
@@ -177,65 +139,32 @@ def _get_cookie_groups_by_state(request, state: bool | None):
|
|
|
177
139
|
]
|
|
178
140
|
|
|
179
141
|
|
|
180
|
-
def get_not_accepted_or_declined_cookie_groups(
|
|
142
|
+
def get_not_accepted_or_declined_cookie_groups(
|
|
143
|
+
request: HttpRequest,
|
|
144
|
+
) -> Collection[CookieGroup]:
|
|
181
145
|
"""
|
|
182
146
|
Returns all cookie groups that are neither accepted or declined.
|
|
183
147
|
"""
|
|
184
148
|
return _get_cookie_groups_by_state(request, state=None)
|
|
185
149
|
|
|
186
150
|
|
|
187
|
-
def get_accepted_cookie_groups(request):
|
|
151
|
+
def get_accepted_cookie_groups(request: HttpRequest) -> Collection[CookieGroup]:
|
|
188
152
|
"""
|
|
189
153
|
Returns all cookie groups that are accepted.
|
|
190
154
|
"""
|
|
191
155
|
return _get_cookie_groups_by_state(request, state=True)
|
|
192
156
|
|
|
193
157
|
|
|
194
|
-
def get_declined_cookie_groups(request):
|
|
158
|
+
def get_declined_cookie_groups(request: HttpRequest) -> Collection[CookieGroup]:
|
|
195
159
|
"""
|
|
196
160
|
Returns all cookie groups that are declined.
|
|
197
161
|
"""
|
|
198
162
|
return _get_cookie_groups_by_state(request, state=False)
|
|
199
163
|
|
|
200
164
|
|
|
201
|
-
def is_cookie_consent_enabled(request):
|
|
165
|
+
def is_cookie_consent_enabled(request: HttpRequest) -> bool:
|
|
202
166
|
"""
|
|
203
167
|
Returns if django-cookie-consent is enabled for given request.
|
|
204
168
|
"""
|
|
205
|
-
enabled = settings.COOKIE_CONSENT_ENABLED
|
|
206
|
-
if callable(enabled)
|
|
207
|
-
return enabled(request)
|
|
208
|
-
else:
|
|
209
|
-
return enabled
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
# Deprecated
|
|
213
|
-
def get_cookie_string(cookie_dic):
|
|
214
|
-
"""
|
|
215
|
-
Returns cookie in format suitable for use in javascript.
|
|
216
|
-
"""
|
|
217
|
-
expires = datetime.datetime.now() + datetime.timedelta(
|
|
218
|
-
seconds=settings.COOKIE_CONSENT_MAX_AGE
|
|
219
|
-
)
|
|
220
|
-
cookie_str = "{}={}; expires={}; path=/".format(
|
|
221
|
-
settings.COOKIE_CONSENT_NAME,
|
|
222
|
-
dict_to_cookie_str(cookie_dic),
|
|
223
|
-
expires.strftime("%a, %d %b %Y %H:%M:%S GMT"),
|
|
224
|
-
)
|
|
225
|
-
return cookie_str
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
def get_accepted_cookies(request):
|
|
229
|
-
"""
|
|
230
|
-
Returns all accepted cookies.
|
|
231
|
-
"""
|
|
232
|
-
cookie_dic = get_cookie_dict_from_request(request)
|
|
233
|
-
accepted_cookies = []
|
|
234
|
-
for cookie_group in all_cookie_groups().values():
|
|
235
|
-
version = cookie_dic.get(cookie_group.varname, None)
|
|
236
|
-
if not version or version == settings.COOKIE_CONSENT_DECLINE:
|
|
237
|
-
continue
|
|
238
|
-
for cookie in cookie_group.cookie_set.all():
|
|
239
|
-
if version >= cookie.get_version():
|
|
240
|
-
accepted_cookies.append(cookie) # noqa: PERF401
|
|
241
|
-
return accepted_cookies
|
|
169
|
+
enabled: bool | Callable[[HttpRequest], bool] = settings.COOKIE_CONSENT_ENABLED
|
|
170
|
+
return enabled(request) if callable(enabled) else enabled
|
cookie_consent/views.py
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
1
3
|
from django.contrib.auth.views import RedirectURLMixin
|
|
2
|
-
from django.
|
|
3
|
-
|
|
4
|
+
from django.http import (
|
|
5
|
+
HttpRequest,
|
|
6
|
+
HttpResponse,
|
|
7
|
+
HttpResponseBase,
|
|
8
|
+
HttpResponseRedirect,
|
|
9
|
+
JsonResponse,
|
|
10
|
+
)
|
|
4
11
|
from django.middleware.csrf import get_token as get_csrf_token
|
|
5
12
|
from django.urls import reverse
|
|
6
|
-
from django.utils.http import url_has_allowed_host_and_scheme
|
|
7
13
|
from django.views.generic import ListView, View
|
|
8
14
|
|
|
9
15
|
from .conf import settings
|
|
16
|
+
from .forms import ProcessCookiesForm
|
|
10
17
|
from .models import CookieGroup
|
|
18
|
+
from .processor import CookiesProcessor
|
|
11
19
|
from .util import (
|
|
12
|
-
accept_cookies,
|
|
13
|
-
decline_cookies,
|
|
14
20
|
get_accepted_cookie_groups,
|
|
15
21
|
get_declined_cookie_groups,
|
|
16
22
|
get_not_accepted_or_declined_cookie_groups,
|
|
@@ -36,31 +42,40 @@ class CookieGroupListView(ListView):
|
|
|
36
42
|
|
|
37
43
|
|
|
38
44
|
class CookieGroupBaseProcessView(RedirectURLMixin, View):
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
45
|
+
"""
|
|
46
|
+
Process the cookie groups submitted in the POST request (or URL parameters).
|
|
47
|
+
|
|
48
|
+
:class:`RedirectURLMixin` takes care of the hardening against open redirects.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
cookie_process_action: Literal["accept", "decline"]
|
|
52
|
+
"""
|
|
53
|
+
Processing action to apply, must be set on the subclasses.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
def get_default_redirect_url(self) -> str:
|
|
57
|
+
return settings.COOKIE_CONSENT_SUCCESS_URL
|
|
58
|
+
|
|
59
|
+
def post(self, request: HttpRequest, *args, **kwargs):
|
|
60
|
+
form = ProcessCookiesForm(data=request.POST)
|
|
61
|
+
|
|
62
|
+
if not form.is_valid():
|
|
63
|
+
if is_ajax_like(request):
|
|
64
|
+
return JsonResponse(form.errors.get_json_data())
|
|
65
|
+
else:
|
|
66
|
+
return HttpResponse(form.errors.render())
|
|
67
|
+
|
|
68
|
+
cookie_groups = form.get_cookie_groups()
|
|
69
|
+
|
|
70
|
+
response: HttpResponseBase
|
|
59
71
|
if is_ajax_like(request):
|
|
60
72
|
response = HttpResponse()
|
|
61
73
|
else:
|
|
62
74
|
response = HttpResponseRedirect(self.get_success_url())
|
|
63
|
-
|
|
75
|
+
|
|
76
|
+
processor = CookiesProcessor(request, response)
|
|
77
|
+
processor.process(cookie_groups, action=self.cookie_process_action)
|
|
78
|
+
|
|
64
79
|
return response
|
|
65
80
|
|
|
66
81
|
|
|
@@ -69,8 +84,7 @@ class CookieGroupAcceptView(CookieGroupBaseProcessView):
|
|
|
69
84
|
View to accept CookieGroup.
|
|
70
85
|
"""
|
|
71
86
|
|
|
72
|
-
|
|
73
|
-
accept_cookies(request, response, varname)
|
|
87
|
+
cookie_process_action = "accept"
|
|
74
88
|
|
|
75
89
|
|
|
76
90
|
class CookieGroupDeclineView(CookieGroupBaseProcessView):
|
|
@@ -78,11 +92,7 @@ class CookieGroupDeclineView(CookieGroupBaseProcessView):
|
|
|
78
92
|
View to decline CookieGroup.
|
|
79
93
|
"""
|
|
80
94
|
|
|
81
|
-
|
|
82
|
-
decline_cookies(request, response, varname)
|
|
83
|
-
|
|
84
|
-
def delete(self, request, *args, **kwargs):
|
|
85
|
-
return self.post(request, *args, **kwargs)
|
|
95
|
+
cookie_process_action = "decline"
|
|
86
96
|
|
|
87
97
|
|
|
88
98
|
class CookieStatusView(View):
|
|
@@ -100,14 +110,10 @@ class CookieStatusView(View):
|
|
|
100
110
|
accepted = get_accepted_cookie_groups(request)
|
|
101
111
|
declined = get_declined_cookie_groups(request)
|
|
102
112
|
not_accepted_or_declined = get_not_accepted_or_declined_cookie_groups(request)
|
|
103
|
-
# TODO: change this csv URL param into proper POST params
|
|
104
|
-
varnames = ",".join([group.varname for group in not_accepted_or_declined])
|
|
105
113
|
data = {
|
|
106
114
|
"csrftoken": get_csrf_token(request),
|
|
107
|
-
"acceptUrl": reverse("cookie_consent_accept"
|
|
108
|
-
"declineUrl": reverse(
|
|
109
|
-
"cookie_consent_decline", kwargs={"varname": varnames}
|
|
110
|
-
),
|
|
115
|
+
"acceptUrl": reverse("cookie_consent_accept"),
|
|
116
|
+
"declineUrl": reverse("cookie_consent_decline"),
|
|
111
117
|
"acceptedCookieGroups": [group.varname for group in accepted],
|
|
112
118
|
"declinedCookieGroups": [group.varname for group in declined],
|
|
113
119
|
"notAcceptedOrDeclinedCookieGroups": [
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-cookie-consent
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: Django cookie consent application
|
|
5
5
|
Author-email: Informatika Mihelac <bmihelac@mihelac.org>
|
|
6
6
|
License-Expression: BSD-2-Clause-first-lines
|
|
7
7
|
Project-URL: Documentation, https://django-cookie-consent.readthedocs.io/en/latest/
|
|
8
|
-
Project-URL: Changelog, https://github.com/django-commons/django-cookie-consent/blob/
|
|
8
|
+
Project-URL: Changelog, https://github.com/django-commons/django-cookie-consent/blob/main/docs/changelog.rst
|
|
9
9
|
Project-URL: Bug Tracker, https://github.com/django-commons/django-cookie-consent/issues
|
|
10
10
|
Project-URL: Source Code, https://github.com/django-commons/django-cookie-consent
|
|
11
11
|
Keywords: cookies,cookie-consent,cookie bar
|
|
12
|
-
Classifier: Development Status ::
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
13
|
Classifier: Framework :: Django
|
|
14
14
|
Classifier: Framework :: Django :: 4.2
|
|
15
|
-
Classifier: Framework :: Django :: 5.1
|
|
16
15
|
Classifier: Framework :: Django :: 5.2
|
|
16
|
+
Classifier: Framework :: Django :: 6.0
|
|
17
17
|
Classifier: Intended Audience :: Developers
|
|
18
18
|
Classifier: Operating System :: Unix
|
|
19
19
|
Classifier: Operating System :: MacOS
|
|
@@ -23,6 +23,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.11
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.12
|
|
25
25
|
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
26
27
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
28
|
Requires-Python: >=3.10
|
|
28
29
|
Description-Content-Type: text/markdown
|
|
@@ -41,7 +42,7 @@ Provides-Extra: docs
|
|
|
41
42
|
Requires-Dist: sphinx; extra == "docs"
|
|
42
43
|
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
|
43
44
|
Provides-Extra: release
|
|
44
|
-
Requires-Dist:
|
|
45
|
+
Requires-Dist: bump-my-version; extra == "release"
|
|
45
46
|
Dynamic: license-file
|
|
46
47
|
|
|
47
48
|
Django cookie consent
|
|
@@ -86,7 +87,7 @@ from the `docs` directory in this repository.
|
|
|
86
87
|
[ruff]: https://github.com/astral-sh/ruff
|
|
87
88
|
[badge:ruff]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
|
|
88
89
|
[codecov]: https://codecov.io/gh/django-commons/django-cookie-consent
|
|
89
|
-
[badge:codecov]: https://codecov.io/gh/django-commons/django-cookie-consent/branch/
|
|
90
|
+
[badge:codecov]: https://codecov.io/gh/django-commons/django-cookie-consent/branch/main/graph/badge.svg
|
|
90
91
|
[docs]: https://django-cookie-consent.readthedocs.io/en/latest/?badge=latest
|
|
91
92
|
[badge:docs]: https://readthedocs.org/projects/django-cookie-consent/badge/?version=latest
|
|
92
93
|
[pypi]: https://pypi.org/project/django-cookie-consent/
|