Add the NSFW mode

This commit is contained in:
Rodolphe Breard 2018-05-27 18:45:52 +02:00
parent f0a3ce06fa
commit 5b6609a46f
10 changed files with 239 additions and 12 deletions

View file

@ -55,3 +55,5 @@ You can set the following variables in the `.env` file:
* `KHAGANAT_FORCE_HTTPS`: If True, enable the use of `KHAGANAT_HTTPS_HEADER_NAME` and `KHAGANAT_HTTPS_HEADER_VALUE` to set the `SECURE_PROXY_SSL_HEADER` configuration option. Default is `False`. * `KHAGANAT_FORCE_HTTPS`: If True, enable the use of `KHAGANAT_HTTPS_HEADER_NAME` and `KHAGANAT_HTTPS_HEADER_VALUE` to set the `SECURE_PROXY_SSL_HEADER` configuration option. Default is `False`.
* `KHAGANAT_HTTPS_HEADER_NAME`: Header name for `SECURE_PROXY_SSL_HEADER`, default is `HTTP_X_FORWARDED_PROTO`. * `KHAGANAT_HTTPS_HEADER_NAME`: Header name for `SECURE_PROXY_SSL_HEADER`, default is `HTTP_X_FORWARDED_PROTO`.
* `KHAGANAT_HTTPS_HEADER_VALUE`: Header value for `SECURE_PROXY_SSL_HEADER`, default is `https`. * `KHAGANAT_HTTPS_HEADER_VALUE`: Header value for `SECURE_PROXY_SSL_HEADER`, default is `https`.
* `KHAGANAT_NSFW_TAGS`: Coma-separated list of words that triggers the content warning in logs, default is `\#nsfw`.
* `KHAGANAT_NSFW_NAME`: Name of the cookie holding the NSFW allowance, default is `nsfw_allowed`.

View file

@ -183,3 +183,10 @@ if config('KHAGANAT_FORCE_HTTPS', default=False, cast=bool):
config('KHAGANAT_HTTPS_HEADER_NAME', default='HTTP_X_FORWARDED_PROTO'), config('KHAGANAT_HTTPS_HEADER_NAME', default='HTTP_X_FORWARDED_PROTO'),
config('KHAGANAT_HTTPS_HEADER_VALUE', default='https') config('KHAGANAT_HTTPS_HEADER_VALUE', default='https')
) )
# NSFW
KHAGANAT_NSFW_TAGS = config('KHAGANAT_NSFW_TAGS', default='\\#nsfw', cast=Csv())
KHAGANAT_NSFW_NAME = config('KHAGANAT_NSFW_NAME', default='nsfw_allowed')
KHAGANAT_NSFW_OK = ('y', 'yes', 't', 'true', '1')

View file

@ -6,6 +6,7 @@ from django.views import generic
from django.conf import settings from django.conf import settings
from django.urls import reverse from django.urls import reverse
from django.http import Http404 from django.http import Http404
from neluser import nsfw
from .models import Source, Entry from .models import Source, Entry
from .forms import SearchForm from .forms import SearchForm
import datetime import datetime
@ -102,6 +103,19 @@ class EntriesView(generic.ListView):
template_name = 'logs/entries.html' template_name = 'logs/entries.html'
allow_empty = False allow_empty = False
def is_nsfw(self):
for e in self.get_queryset():
for tag in settings.KHAGANAT_NSFW_TAGS:
if tag.lower() in e.content.lower():
return True
return False
def dispatch(self, request, *args, **kwargs):
if not nsfw.is_nsfw_allowed(request):
if self.is_nsfw():
return nsfw.redirect(request)
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context['date'] = datetime.date( context['date'] = datetime.date(

View file

@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 1.0\n" "Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-04 15:56+0100\n" "POT-Creation-Date: 2018-05-27 18:28+0200\n"
"PO-Revision-Date: 2018-02-04 01:03+0100\n" "PO-Revision-Date: 2018-02-04 01:03+0100\n"
"Last-Translator: Khaganat <assoc@khaganat.net>\n" "Last-Translator: Khaganat <assoc@khaganat.net>\n"
"Language-Team: Khaganat <assoc@khaganat.net>\n" "Language-Team: Khaganat <assoc@khaganat.net>\n"
@ -38,11 +38,19 @@ msgstr ""
msgid "date joined" msgid "date joined"
msgstr "" msgstr ""
#: models.py:65 #: models.py:58
msgid "NSFW flag"
msgstr ""
#: models.py:61
msgid "Indicate whether or not adult or sensitive content should be displayed."
msgstr ""
#: models.py:73
msgid "user" msgid "user"
msgstr "" msgstr ""
#: models.py:66 #: models.py:74
msgid "users" msgid "users"
msgstr "" msgstr ""
@ -58,6 +66,7 @@ msgstr "Your account has been activated."
#: templates/neluser/activate_done.html:10 templates/neluser/login.html:4 #: templates/neluser/activate_done.html:10 templates/neluser/login.html:4
#: templates/neluser/login.html:12 #: templates/neluser/login.html:12
#: templates/neluser/password_reset_done.html:10
msgid "login" msgid "login"
msgstr "" msgstr ""
@ -97,6 +106,40 @@ msgstr ""
msgid "forgotten_password" msgid "forgotten_password"
msgstr "forgotten password" msgstr "forgotten password"
#: templates/neluser/nsfw.html:4 templates/neluser/nsfw.html:8
msgid "NSFW content"
msgstr ""
#: templates/neluser/nsfw.html:9
msgid ""
"The content you were about to see is flagged as sensitive and therefore "
"cannot be seen while the safe mode is activated."
msgstr ""
#: templates/neluser/nsfw.html:11
msgid "Go back home"
msgstr ""
#: templates/neluser/nsfw.html:12
msgid "Permanently disable safe mode"
msgstr ""
#: templates/neluser/nsfw.html:14
msgid "Or disable safe mode for:"
msgstr ""
#: templates/neluser/nsfw.html:15
msgid "5 minutes"
msgstr ""
#: templates/neluser/nsfw.html:16
msgid "1 hour"
msgstr ""
#: templates/neluser/nsfw.html:17
msgid "1 day"
msgstr ""
#: templates/neluser/password_reset.html:4 #: templates/neluser/password_reset.html:4
#: templates/neluser/password_reset_confirm.html:4 #: templates/neluser/password_reset_confirm.html:4
#: templates/neluser/password_reset_done.html:4 #: templates/neluser/password_reset_done.html:4
@ -120,7 +163,7 @@ msgstr "change my password"
msgid "reset_password_invalid_link" msgid "reset_password_invalid_link"
msgstr "Sorry, we are unable to reset your password." msgstr "Sorry, we are unable to reset your password."
#: templates/neluser/password_reset_done.html:8 #: templates/neluser/password_reset_done.html:9
msgid "password_reset_success" msgid "password_reset_success"
msgstr "Your password has been changed." msgstr "Your password has been changed."
@ -139,8 +182,9 @@ msgstr ""
#: templates/neluser/password_reset_email_sent.html:8 #: templates/neluser/password_reset_email_sent.html:8
msgid "password_reset_success_email" msgid "password_reset_success_email"
msgstr "An email has been sent to your address. Please follow the link given " msgstr ""
"in this email to reset your password." "An email has been sent to your address. Please follow the link given in this "
"email to reset your password."
#: templates/neluser/password_reset_email_subject.txt:2 #: templates/neluser/password_reset_email_subject.txt:2
#, python-format #, python-format

View file

@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 1.0\n" "Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-04 15:56+0100\n" "POT-Creation-Date: 2018-05-27 18:28+0200\n"
"PO-Revision-Date: 2018-02-04 01:03+0100\n" "PO-Revision-Date: 2018-02-04 01:03+0100\n"
"Last-Translator: Khaganat <assoc@khaganat.net>\n" "Last-Translator: Khaganat <assoc@khaganat.net>\n"
"Language-Team: Khaganat <assoc@khaganat.net>\n" "Language-Team: Khaganat <assoc@khaganat.net>\n"
@ -40,11 +40,19 @@ msgstr ""
msgid "date joined" msgid "date joined"
msgstr "date d'inscription" msgstr "date d'inscription"
#: models.py:65 #: models.py:58
msgid "NSFW flag"
msgstr "Affichage du contenu sensible"
#: models.py:61
msgid "Indicate whether or not adult or sensitive content should be displayed."
msgstr "Indique si le contenu adulte ou choquant doit être ou non affiché."
#: models.py:73
msgid "user" msgid "user"
msgstr "utilisateur" msgstr "utilisateur"
#: models.py:66 #: models.py:74
msgid "users" msgid "users"
msgstr "utilisateurs" msgstr "utilisateurs"
@ -60,6 +68,7 @@ msgstr "compte activé"
#: templates/neluser/activate_done.html:10 templates/neluser/login.html:4 #: templates/neluser/activate_done.html:10 templates/neluser/login.html:4
#: templates/neluser/login.html:12 #: templates/neluser/login.html:12
#: templates/neluser/password_reset_done.html:10
msgid "login" msgid "login"
msgstr "connexion" msgstr "connexion"
@ -99,6 +108,43 @@ msgstr "Activation de compte sur %(site_name)s"
msgid "forgotten_password" msgid "forgotten_password"
msgstr "mot de passe oublié" msgstr "mot de passe oublié"
#: templates/neluser/nsfw.html:4 templates/neluser/nsfw.html:8
msgid "NSFW content"
msgstr "Contenu sensible"
#: templates/neluser/nsfw.html:9
msgid ""
"The content you were about to see is flagged as sensitive and therefore "
"cannot be seen while the safe mode is activated."
msgstr ""
"Le contenu que vous vous apprêtiez à consulter est indiqué comme pouvant "
"choquer la sensibilité et ne peut donc pas être affiché tant que la "
"navigation filtrée est activée."
#: templates/neluser/nsfw.html:11
msgid "Go back home"
msgstr "Retourner à l'accueil"
#: templates/neluser/nsfw.html:12
msgid "Permanently disable safe mode"
msgstr "Définitivement désactiver la navigation filtrée"
#: templates/neluser/nsfw.html:14
msgid "Or disable safe mode for:"
msgstr "Ou désactiver la navigation filtrée pour :"
#: templates/neluser/nsfw.html:15
msgid "5 minutes"
msgstr "5 minutes"
#: templates/neluser/nsfw.html:16
msgid "1 hour"
msgstr "1 heure"
#: templates/neluser/nsfw.html:17
msgid "1 day"
msgstr "1 jour"
#: templates/neluser/password_reset.html:4 #: templates/neluser/password_reset.html:4
#: templates/neluser/password_reset_confirm.html:4 #: templates/neluser/password_reset_confirm.html:4
#: templates/neluser/password_reset_done.html:4 #: templates/neluser/password_reset_done.html:4
@ -122,7 +168,7 @@ msgstr "Modifier mon mot de passe"
msgid "reset_password_invalid_link" msgid "reset_password_invalid_link"
msgstr "Désolé, nous ne sommes pas en mesure de modifier votre mot de passe." msgstr "Désolé, nous ne sommes pas en mesure de modifier votre mot de passe."
#: templates/neluser/password_reset_done.html:8 #: templates/neluser/password_reset_done.html:9
msgid "password_reset_success" msgid "password_reset_success"
msgstr "Votre mot de passe a été modifié." msgstr "Votre mot de passe a été modifié."
@ -144,8 +190,9 @@ msgstr ""
#: templates/neluser/password_reset_email_sent.html:8 #: templates/neluser/password_reset_email_sent.html:8
msgid "password_reset_success_email" msgid "password_reset_success_email"
msgstr "Un message a été envoyé sur votre messagerie électronique. Veuillez " msgstr ""
"suivre le lien donné dans ce message afin de réinitialiser votre mot de passe." "Un message a été envoyé sur votre messagerie électronique. Veuillez suivre "
"le lien donné dans ce message afin de réinitialiser votre mot de passe."
#: templates/neluser/password_reset_email_subject.txt:2 #: templates/neluser/password_reset_email_subject.txt:2
#, python-format #, python-format

View file

@ -0,0 +1,18 @@
# Generated by Django 2.0.2 on 2018-05-27 10:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('neluser', '0002_auto_20180204_2035'),
]
operations = [
migrations.AddField(
model_name='neluser',
name='nsfw_allowed',
field=models.BooleanField(default=False, help_text='Indicate whether or not adult or sensitive content should be displayed.', verbose_name='NSFW flag'),
),
]

View file

@ -54,6 +54,14 @@ class NelUser(AbstractBaseUser, PermissionsMixin):
), ),
) )
date_joined = models.DateTimeField(_('date joined'), default=timezone.now) date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
nsfw_allowed = models.BooleanField(
_('NSFW flag'),
default=False,
help_text=_(
'Indicate whether or not adult or sensitive content should '
'be displayed.'
)
)
objects = NelUserManager() objects = NelUserManager()

62
neluser/nsfw.py Normal file
View file

@ -0,0 +1,62 @@
from django.http import HttpResponseRedirect, QueryDict
from django.urls.exceptions import Resolver404
from django.shortcuts import render
from neluser.models import NelUser
from django.urls import reverse, resolve
from django.conf import settings
def is_link_legit(url):
try:
resolve(url)
except Resolver404:
return False
return True
def is_nsfw_allowed(request):
if isinstance(request.user, NelUser):
if request.user.nsfw_allowed:
return True
s = request.COOKIES.get(settings.KHAGANAT_NSFW_NAME) or ''
return s.lower() in settings.KHAGANAT_NSFW_OK
def disable_view(request, max_age):
try:
max_age = int(max_age) or None
except ValueError:
max_age = None
next_url = QueryDict(request.META.get('QUERY_STRING')).get('next') or '/'
if not is_link_legit(next_url):
next_url = '/'
response = HttpResponseRedirect(next_url)
if isinstance(request.user, NelUser) and not max_age:
request.user.nsfw_allowed = True
request.user.save()
else:
response.set_cookie(
settings.KHAGANAT_NSFW_NAME,
'true',
max_age=max_age
)
return response
def warn_view(request):
next_url = QueryDict(request.META.get('QUERY_STRING')).get('next') or '/'
if not is_link_legit(next_url):
next_url = '/'
context = {
'next_url': next_url,
'is_authenticated': request.user.is_authenticated,
}
return render(request, 'neluser/nsfw.html', context=context)
def redirect(request):
dest = '{to_url}?next={next_url}'.format(
to_url=reverse(warn_view),
next_url=request.get_full_path()
)
return HttpResponseRedirect(dest)

View file

@ -0,0 +1,20 @@
{% extends "khaganat/base.html" %}
{% load i18n %}
{% block title %}{% trans "NSFW content" %}{% endblock %}
{% block content %}
<div class="content-bloc">
<h2>{% trans "NSFW content" %}</h2>
<p>{% trans "The content you were about to see is flagged as sensitive and therefore cannot be seen while the safe mode is activated." %}</p>
<div>
<a class="btn btn-primary" href="{% url "index" %}" role="button">{% trans "Go back home" %}</a>
<a class="btn btn-danger" href="{% url "disable_nsfw" "0" %}?next={{ next_url }}" role="button">{% trans "Permanently disable safe mode" %}</a>
<br>
{% trans "Or disable safe mode for:" %}
<a class="badge badge-warning" href="{% url "disable_nsfw" "300" %}?next={{ next_url }}">{% trans "5 minutes" %}</a>
<a class="badge badge-warning" href="{% url "disable_nsfw" "3600" %}?next={{ next_url }}">{% trans "1 hour" %}</a>
<a class="badge badge-warning" href="{% url "disable_nsfw" "86400" %}?next={{ next_url }}">{% trans "1 day" %}</a>
</div>
</div>
{% endblock %}

View file

@ -1,6 +1,7 @@
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
from django.urls import reverse_lazy, path from django.urls import reverse_lazy, path
from . import views from . import views
from . import nsfw
urlpatterns = [ urlpatterns = [
@ -61,4 +62,8 @@ urlpatterns = [
), ),
name='password_reset_complete' name='password_reset_complete'
), ),
# NSFW
path('nsfw/', nsfw.warn_view, name='nsfw'),
path('nsfw/disable/<max_age>/', nsfw.disable_view, name='disable_nsfw'),
] ]