Commit a207f10b authored by Remi Rampin's avatar Remi Rampin

Merge branch 'cookies-prompt' into 'master'

parents 9e9b59bb 45e73561
......@@ -82,6 +82,9 @@ MAIL_SERVER = {{
"port": 25,
}}
# Whether users must explicitly accept cookies before using the website
COOKIES_PROMPT = True
# Whether new users can create an account
REGISTRATION_ENABLED = True
......@@ -109,7 +112,7 @@ DEFAULT_CONFIG = {
}
REQUIRED_CONFIG = ['NAME', 'PORT', 'SECRET_KEY', 'DATABASE',
'EMAIL', 'MAIL_SERVER']
'EMAIL', 'MAIL_SERVER', 'COOKIES_PROMPT']
def main():
......@@ -236,6 +239,7 @@ def main():
PORT=int(args.port),
DATABASE=prepare_db(args.database),
SECRET_KEY=secret,
COOKIES_PROMPT=False,
)
if 'PROMETHEUS_LISTEN' in config:
......
{% extends "base.html" %}
{% block contents %}
<h1>Cookie warning</h1>
<p>This website uses cookies to store your identity (if you choose to log in) and as a protection against <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery">cross-site request forgery (CSRF)</a>. Before continuing, you must accept their use by clicking the button below. Those <strong>are not</strong> "third-party" or "tracking" cookies.</p>
<form action="{{ reverse_url('cookies_prompt') }}" method="post">
<input type="hidden" name="accepted" value="yes" />
<input type="hidden" name="next" value="{{ next }}" />
<button type="submit" class="btn btn-primary">{% trans %}Accept cookies{% endtrans %}</button>
</form>
{% endblock %}
......@@ -55,6 +55,7 @@ def make_app(config, debug=False, xsrf_cookies=True):
[
# Basic pages
URLSpec('/', views.Index, name='index'),
URLSpec('/cookies', views.CookiesPrompt, name='cookies_prompt'),
URLSpec('/login', views.Login, name='login'),
URLSpec('/logout', views.Logout, name='logout'),
URLSpec('/register', views.Register, name='register'),
......
......@@ -3,6 +3,8 @@ import hashlib
import hmac
import json
import logging
from urllib.parse import urlencode
import jinja2
import pkg_resources
import smtplib
......@@ -169,6 +171,23 @@ class BaseHandler(RequestHandler):
else:
return None
def set_cookie(self, name, value, domain=None,
expires=None, path='/', expires_days=None,
*, dont_check=False,
**kwargs):
if (dont_check or
not self.application.config['COOKIES_PROMPT'] or
self.get_cookie('cookies_accepted') or
self.get_cookie('user')):
return super(BaseHandler, self).set_cookie(name, value, **kwargs)
else:
self.redirect(
self.reverse_url('cookies_prompt') +
'?' +
urlencode(dict(next=self.request.uri)),
)
raise HTTPError(302)
def get_user_locale(self):
if self.current_user is not None:
user = self.db.query(database.User).get(self.current_user)
......
......@@ -63,6 +63,26 @@ class Index(BaseHandler):
return self.render('welcome.html')
class CookiesPrompt(BaseHandler):
PROM_PAGE.labels('cookies_prompt').inc(0)
def get(self):
PROM_PAGE.labels('cookies_prompt').inc()
return self.render('cookies_prompt.html',
next=self.get_argument('next', ''))
def post(self):
PROM_PAGE.labels('cookies_prompt').inc()
self.set_cookie('cookies_accepted', 'yes', dont_check=True)
next_ = self.get_argument('next', '')
if not next_:
next_ = self.reverse_url('index')
return self.redirect(next_)
def check_xsrf_cookie(self):
pass
class Login(BaseHandler):
PROM_PAGE.labels('login').inc(0)
......
......@@ -218,6 +218,7 @@ class TestMultiuser(MyHTTPTestCase):
DATABASE=DATABASE_URI,
EMAIL='test@example.com',
MAIL_SERVER={'host': 'localhost', 'port': 25},
COOKIES_PROMPT=True,
MULTIUSER=True,
SECRET_KEY='2PbQ/5Rs005G/nTuWfibaZTUAo3Isng3QuRirmBK',
))
......@@ -242,6 +243,17 @@ class TestMultiuser(MyHTTPTestCase):
for user in db.query(database.User).all()],
['admin'])
# Fetch registration page, should hit cookies prompt
response = self.get('/register')
self.assertEqual(response.code, 302)
self.assertEqual(response.headers['Location'],
'/cookies?next=%2Fregister')
# Accept cookies
response = self.post('/cookies', dict(next='/register'))
self.assertEqual(response.code, 302)
self.assertEqual(response.headers['Location'], '/register')
# Fetch registration page
response = self.get('/register')
self.assertEqual(response.code, 200)
......@@ -293,6 +305,11 @@ class TestMultiuser(MyHTTPTestCase):
@gen_test
async def test_projects(self):
# Accept cookies
response = await self.apost('/cookies', dict())
self.assertEqual(response.code, 302)
self.assertEqual(response.headers['Location'], '/')
# Log in
response = await self.aget('/login')
self.assertEqual(response.code, 200)
......@@ -439,6 +456,7 @@ class TestSingleuser(MyHTTPTestCase):
DATABASE=DATABASE_URI,
EMAIL='test@example.com',
MAIL_SERVER={'host': 'localhost', 'port': 25},
COOKIES_PROMPT=False,
MULTIUSER=False,
SECRET_KEY='bq7ZoAtO7LtRJJ4P0iHSdH8yvcmCqynfeGB+x9y1',
),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment