Django - django-cookie-consent not working - python

https://github.com/haricot/django-cookie-consent
https://django-cookie-consent.readthedocs.io/en/latest/index.html
I found a fork of the django-cookie-consent github project for managing cookies on your website and I got it to work most of the time but it is not 100% perfect.
Here is how I got it to run (either install via pip from that fork link or):
Do not use pip3 install django-cookie-consent from the default PyPi. Download the zip file from github and copy the cookie_consent folder to your site packages folder. For example for me it was - /home/user/.local/share/virtualenvs/project_name/lib/python3.7/site-packages/cookie_consent. Then pip3 install django-appconf. Then follow the documentation instructions.
Links:
http://127.0.0.1:8000/cookies/
http://127.0.0.1:8000/cookies/accept/
http://127.0.0.1:8000/cookies/accept/variable_name/
http://127.0.0.1:8000/cookies/decline/
http://127.0.0.1:8000/cookies/decline/variable_name/
I found some code for the consent banner https://github.com/haricot/django-cookie-consent/tree/master/tests/core/templates but was having problems with it. I copied the test_page.html template code to my own project's base.html but this entire script tag did not work for me -> <script type="{% cc_receipts "social" %}" data-varname="social">. I got django.template.exceptions.TemplateSyntaxError: 'cc_receipts' did not receive value(s) for the argument(s): 'request'. Copying the rest of the code from that file and not including that one script tag did cause the banner to show up on my project's base.html file.
Accepting a cookie from clicking accept on the banner code found from the tests directory just redirects me to a blank /cookies/accept/social/ page. This acceptance does not get logged either.
Accepting a cookie from /cookies/ does get logged but it gave me this error:
TypeError: cannot use a string pattern on a bytes-like object
[20/Jan/2020 16:00:43] "POST /cookies/accept/social/ HTTP/1.1" 500 121416
Method Not Allowed (GET): /cookies/accept/social/
Method Not Allowed: /cookies/accept/social/
[20/Jan/2020 16:00:44] "GET /cookies/accept/social/ HTTP/1.1" 405 0
Is this error a possible python3 incompatibility issue?
How would I configure, for example, where a group variable name called social and a cookie named 1P_JAR (this is an example of a recaptcha v3 cookie on my site).
Noticed that the username is not being logged or the the user's IP address. It would be nice to include these once they accept or decline.
I am not sure if this fork automatically blocks cookies until the user accepts. Can someone verify this? If this feature is or is not included, how do you implement it?
When accepting cookies or declining cookies, an actual cookie called cookie_consent gets created in your browser and it tells you which cookies are accepted or declined.
Can someone please help me get this to work? It seems very close to being GDPR compliant.

Check your runserver log. You have to set up COOKIE_CONSENT_NAME setting. Because there is no default value for this setting.
Then you have to go to django admin panel and create the cookies with their respective names and domains which you can find in the browser inspector.

how does it works: in creates a cookie labelled cookie_consent, this stores all the data necessary for this package to work. to make it work properly, several tweaks are required:
1)into setting.py you must indicate COOKIE_CONSENT_NAME = "cookie_consent" (or whatever you like probably works too)
into TEMPLATE_CONTEXT_PROCESSORS copy: 'django.template.context_processors.request' --OR-- copy into:
TEMPLATES = [
{
...
'OPTIONS': {
'context_processors': [
"django.template.context_processors.request",
...
3)[NOT MANDATORY BUT HELPFUL, see instuctions on django documentation] i have also indicated into setting COOKIE_CONSENT_CACHE_BACKEND = "default" plus
setted the whole website cache to: django.core.cache.backends.db.DatabaseCache
then you create on the admin page firstly a cookie group into cookie groups window, WITHOUT checking the Is required checkbox (otherwise you are not able to manage the cookie group because the checkbox implies that these cookies are always on and thus the user cannot decide or not to eliminate them); then you must also add at least 1 cookie for cookie group
(otherwise the get_version will not work for cookie groups and its mandatory to the correct use of the library)
consensus is gathered for groups and not for each cookie (As GDPR suggests), meaning that the accept_cookies(request, response, varname="your_cookie_group") will only works if you use cookie groups.
this is an exaple of the functions (not perfect) telling to accept the cookie from view, to work it requires obviously two refresh, the first to set the cookie, the second to see it:
---views.py
def homepage(request):
#to render the page
response = render(request = request,
...
#to accept a cookie group
accept_cookies(request, response, varname="cookie_group")#probabilmente solo per cookie groups
#to check the cookie group
cc = get_cookie_value_from_request(request, varname='cookie_group')
print("cookie value from request: ",cc)
if cc == True:
print("Consensus given", cc)
elif cc==False:
print("Consensus not given",cc)
else:
print("probable error in getting cookie value from request: ", cc) # problem with cookie group
return response
---urls.py
path('', views.homepage, name ="home")

Related

Setting HttpReferrer In Unit Tests

In my view.py I have the following check on several consecutive pages:
if(request.META.get('HTTP_REFERER') != request.build_absolute_uri(reverse('page1'))):
return redirect('page1')
This is performed on every page, checking that the user was redirected from the previous page, so (for example), if a user tries to enter the url for page4 in the address bar, the test will fail and he will be sent to page3, then that pages test will fail and he will fall back to page2, and so on.
Im doing this because I have several pages linked together which users must visit consecutively.
The problem comes when I want to unit test. The following test would throw an error because it fails the redirect test and therefore cannot test the logic of the page which im trying to test:
def test_user_information_updated_on_validation_success(self):
user = User.objects.create_superuser('username')
self.client.force_login(user)
self.client.post(reverse('page_4'), {
'exampleQuestion': 'exampleAnswer'
})
user.refresh_from_db()
self.assertEqual(user.exampleform.somefield, 'exampleAnswer')
How can I access the page within a unit test as if it had been redirected.
Thank you.
A request in the test client accepts keywords that are mapped to WSGI environment variables. Environment variables that start with HTTP and are all uppercase, with dashes mapped to underscores - are Http headers, so the short version is that we can set HTTP headers as such:
# Wrong: Generates absolute paths without hosts
self.client.post(
reverse('page_4'), {'exampleQuestion': 'exampleAnswer'},
HTTP_REFERER=reverse('page_3')
)
Edit:
It's a little too simple, because HTTP referrers are fully qualified, so we need:
referer = 'http://testserver{}'.format(reverse('page_3'))
self.client.post(
reverse('page_4'), {'exampleQuestion': 'exampleAnswer'},
HTTP_REFERER=referer
)
FYI: The protocol (wsgi.scheme) and host name (HTTP_SERVER) come from djang.test.client.RequestFactory._base_environ(). If you use a modified client that changes servername and/or protocol, you should adjust accordingly. In that case it would be wise to override _base_environ in your modified test client and derive values from that.

flask: hashes "#" in the routing

I'm working with google API lately and use simple flask method to retrieve some id_token.
here is my code with explanations in comment:
#app.route('/afterlogin/id_token')
def afterlogin(id): # get the id
print(id) # print it
return render_template(r'creds_view.html', data=id) # and render the template with 'id' in it (for test purposes)
So what happens is that after the user logins, the api redirects the id_token to http://localhost:8000/afterlogin/#id_token=some_id_token.
but for some reason it is showing me 404 error.
i think it is because of the '#' in the url , i want the id_token. i know that '#' in html means for path linking or routing in 'href'.
so for that i tried.
#app.route('/afterlogin/<path:id>')
but the error still persists.
any guesses?
Everything after # is processed locally by the browser, it's not sent to the server, so you can't use it in routing. Leave out the #:
http://localhost:8000/afterlogin/some_id_token

Praw: API Login Fails with Client Error

I couldn't log into my own Reddit account using the code below.
Error message:
raise HTTPError(http_error_msg, response=self) HTTPError: 403 Client Error: Forbidden
Is there a way to get around this error?
class PrawTest(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Yo, imma redit bot!')
get_login= ConfigParser.ConfigParser()
get_login.read("logins.ini")
r = praw.Reddit(user_agent='Captain Reddit!')
r.login(get_login.get("login1", "username"),get_login.get("login1","password"))
app = webapp2.WSGIApplication([('/hype_shit_up', PrawTest)], debug=True)
Your code is very needlessly over-complicated just to login with PRAW. The way reccomended in the documentation is to have reddit = praw.Reddit('SOME-NAME-HERE') to login. Then, in your praw.ini file, set it up to look like this:
[DEFAULT]
# A boolean to indicate whether or not to check for package updates.
check_for_updates=True
# Object to kind mappings
comment_kind=t1
message_kind=t4
redditor_kind=t2
submission_kind=t3
subreddit_kind=t5
# The URL prefix for OAuth-related requests.
oauth_url=https://oauth.reddit.com
# The URL prefix for regular requests.
reddit_url=https://www.reddit.com
# The URL prefix for short URLs.
short_url=https://redd.it
[SOME-NAME-HERE]
user_agent=USER-AGENT-HERE
username=REDDIT-ACCOUNT-USERNAME
password=REDDIT-ACCOUNT-PASSWORD
client_id=REDDIT-APP-CLIENT-ID
client_secret=REDDIT-APP-CLIENT-SECRET
Requirements for the user agent are found here:
Change your client's User-Agent string to something unique and descriptive, including the target platform, a unique application identifier, a version string, and your username as contact information, in the following format:
<platform>:<app ID>:<version string> (by /u/<reddit username>)
-Example: User-Agent: android:com.example.myredditapp:v1.2.3 (by /u/kemitche)
Many default User-Agents (like "Python/urllib" or "Java") are drastically limited to encourage unique and descriptive user-agent strings.
Including the version number and updating it as you build your application allows us to safely block old buggy/broken versions of your app.
NEVER lie about your user-agent. This includes spoofing popular browsers and spoofing other bots. We will ban liars with extreme prejudice.
If you have any future questions dont hesitate to ask them as a comment to this answer!

Facebook Graph API key error

I am working on a python AppEngine application with Facebook login. I want to be able to access a logged-in user's friends' bios (their "about me" information).
Having requested/saved changes for all of the permissions I need on the Facebook developer's dashboard, I can successfully make calls like this:
friends = graph.get_connections("me", "friends", fields="name")
for friend in friends["data"]:
print friend["name"]
But trying to access the about me, as specified by the "bio" field in the docs, results in a key error:
friends = graph.get_connections("me", "friends", fields="name,bio")
for friend in friends["data"]:
print friend["bio"]
AppEngine log when running on local host:
File "/Users/nicole/aggie-harmony/main.py", line 154, in get
user = self.current_user
File "/Users/nicole/aggie-harmony/main.py", line 108, in current_user
bio = friend["bio"]
KeyError: 'bio'
INFO 2013-11-16 02:59:27,243 module.py:608] default: "GET / HTTP/1.1" 500 -
I have experimented with other fields, and it seems like anything that requires an access token will generate a key error (although the docs actually seem to have been updated mere HOURS before this question was posted...and they now suggest that "Other fields that have been explicitly set to public visibility can also be retrieved without an access token"...in my test user, the bio is indeed public!)
Unless I am just missing something syntax-wise, is this indeed a token issue? My app is based on the example here and basically obtains/uses the access token like this (auth stuff was generated previously and stored in its own file):
...
cookie = facebook.get_user_from_cookie(self.request.cookies, auth.FACEBOOK_APP_ID,
auth.FACEBOOK_APP_SECRET)
...
graph = facebook.GraphAPI(cookie["access_token"])
...
Interestingly enough, the app doesn't pop up a permission box for the user after the log-in area, which might support my hunch...
SOLVED: It was indeed an issue of permissions. In my adapted example html file, I just needed to change this:
function doLogin() {
FB.login(function(response) {} , {perms:''});
}
...to this:
function doLogin() {
FB.login(function(response) {} , {perms:'user_about_me,friends_about_me,user_likes,friends_likes,user_relationship_details,friends _relationship_details,user_relationships,friends_relationships, user_education_history, friends_education_history'});
}
Facebook takes care of the rest with the proper oauth dialog, etc.

Pylons - Redirects will drop from HTTPS to HTTP unless I specify the protocol... Is there a way to fix this?

On my Pylons website, I have my login form sending it's data to 'https://mysite.com'. Upon a successful login, a redirect takes place to send them to their profile page.
redirect(url(controller='profile'))
This sends the user to http://mysite.com/profile instead of https://mysite.com/profile. The only way I've found to fix this is to change the redirect to:
redirect(url(controller='profile', protocol='https'))
The problem I have with this is "what if, for whatever reason, my cert goes away and I have to drop SSL" I don't want to have to go through my entire code looking for all redirects I specify the 'https' protocol in. I want my login to send the user to HTTPS and that's it...
Is there a reason the redirect drops to HTTP? Is there a way to stop it? :/
Since I spent a couple of hours wading through the pylons/routes/beaker/etc. source I thought I'd share my solution.
First a bit of context. I'm using an elastic load balancer (ELB) on AWS with SSL termination. The application is built to run solely over https; this is a post-firesheep world after all. It's layered like so:
ELB -> nginx -> pasteWSGI -> pylons
ELB is jolly good in terms of simplicity but any call to pylons.controllers.util.redirect would trigger a 302 Redirect to "http://mysite/". The ELB would not change that on the way back (no reason to) and so my browser would be sent back to port 80 and there is no ELB listening on that port.
I've tried updating the Mapper as suggested above.
it did not work,
I wanted my redirects to be relative. Switching to https in pylons means that the URL generator goes and fetches the host to create a new URL (https://localhost/....)
Note that Mapper.redirect_to works out of the box and uses relative redirects so there is no need to mess with that. The fundamental problem is that controllers.redirect uses a slightly different code path. In particular, in Routes, the controllers.util.redirect is not a redirect (there's an "if routes and routes.redirect" which evals to False).
My solution: replace all calls to redirect by a new controller method (called redirect too) to change redirects from absolute to relative redirects.
The code is as follows:
lib/helpers.py
def relative_redirect(to_url, start_response):
"""Returns a redirect that is compatible with AWS ELB (no absolute http responses)
Using pylons.controllers.util.redirect triggers an exception that'll be turned into a 302
But with an absolute path so the response does not contains https but simple http
"""
start_response("302 Found", [("Content-Type", "text/plain; charset=utf-8"), ("Location", url(to_url))])
return ["You are being redirected to {0}".format(url(to_url))]
With that bit called from the base class of my controllers:
class BaseController(WSGIController):
...
def redirect(self, to_url):
"""Force a relative redirection, to work with AWS ELB"""
return relative_redirect(to_url, self.start_response)
I'd customize the Mapper so that every call to "url" would force the correct protocol...
Inside routing.py:
class CustomMapper(Mapper):
def generate(self, *args, **kwargs):
kwargs["protocol"] = "https"
return Mapper.generate(self, *args, **kwargs)
def make_map(config):
"""Create, configure and return the routes Mapper"""
map = CustomMapper(directory=config['pylons.paths']['controllers'],
always_scan=config['debug'])

Categories

Resources