Format code using black
This commit is contained in:
parent
7f1e07503a
commit
c15512e799
29 changed files with 412 additions and 475 deletions
|
@ -1,7 +1,9 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import LogSource
|
from .models import LogSource
|
||||||
|
|
||||||
|
|
||||||
class LogSourceAdmin(admin.ModelAdmin):
|
class LogSourceAdmin(admin.ModelAdmin):
|
||||||
list_display = ('name', 'slug', 'hidden')
|
list_display = ("name", "slug", "hidden")
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(LogSource, LogSourceAdmin)
|
admin.site.register(LogSource, LogSourceAdmin)
|
||||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class LogsConfig(AppConfig):
|
class LogsConfig(AppConfig):
|
||||||
name = 'chat'
|
name = "chat"
|
||||||
|
|
|
@ -7,8 +7,8 @@ import datetime
|
||||||
class SearchForm(forms.Form):
|
class SearchForm(forms.Form):
|
||||||
source = forms.CharField(max_length=128)
|
source = forms.CharField(max_length=128)
|
||||||
date = forms.DateField(
|
date = forms.DateField(
|
||||||
label=_('date'),
|
label=_("date"),
|
||||||
initial=datetime.date.today(),
|
initial=datetime.date.today(),
|
||||||
widget=DateInput(format='%Y-%m-%d'),
|
widget=DateInput(format="%Y-%m-%d"),
|
||||||
input_formats=['%Y-%m-%d'],
|
input_formats=["%Y-%m-%d"],
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,7 +3,7 @@ from chat.models import Entry
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = 'Generates the CSS files used by Pygments'
|
help = "Generates the CSS files used by Pygments"
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
for e in Entry.objects.all():
|
for e in Entry.objects.all():
|
||||||
|
|
18
chat/urls.py
18
chat/urls.py
|
@ -3,22 +3,20 @@ from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', views.chat_view, name='chat'),
|
path("", views.chat_view, name="chat"),
|
||||||
path('logs/', views.LogEntriesView.as_view(), name='log_index'),
|
path("logs/", views.LogEntriesView.as_view(), name="log_index"),
|
||||||
path(
|
path(
|
||||||
'logs/<slug:source>/<int:year>/<int:month>/<int:day>/',
|
"logs/<slug:source>/<int:year>/<int:month>/<int:day>/",
|
||||||
views.LogEntriesView.as_view(),
|
views.LogEntriesView.as_view(),
|
||||||
name='log_day'
|
name="log_day",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'logs/switch/source/<int:pk>/',
|
"logs/switch/source/<int:pk>/",
|
||||||
views.switch_log_source,
|
views.switch_log_source,
|
||||||
name='log_switch_source'
|
name="log_switch_source",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'logs/switch/entry/<int:pk>/',
|
"logs/switch/entry/<int:pk>/", views.switch_log_entry, name="log_switch_entry"
|
||||||
views.switch_log_entry,
|
|
||||||
name='log_switch_entry'
|
|
||||||
),
|
),
|
||||||
path('logs/search/', views.log_search_view, name='log_search'),
|
path("logs/search/", views.log_search_view, name="log_search"),
|
||||||
]
|
]
|
||||||
|
|
144
chat/views.py
144
chat/views.py
|
@ -15,22 +15,19 @@ import datetime
|
||||||
|
|
||||||
def chat_view(request):
|
def chat_view(request):
|
||||||
ctx = {
|
ctx = {
|
||||||
'debug': settings.DEBUG,
|
"debug": settings.DEBUG,
|
||||||
'bosh_url': settings.KHAGANAT_XMPP_BOSH_URL,
|
"bosh_url": settings.KHAGANAT_XMPP_BOSH_URL,
|
||||||
'jid': settings.KHAGANAT_XMPP_JID,
|
"jid": settings.KHAGANAT_XMPP_JID,
|
||||||
'rooms': settings.KHAGANAT_XMPP_ROOMS,
|
"rooms": settings.KHAGANAT_XMPP_ROOMS,
|
||||||
'websocket_url': settings.KHAGANAT_XMPP_WEBSOCKET_URL,
|
"websocket_url": settings.KHAGANAT_XMPP_WEBSOCKET_URL,
|
||||||
}
|
}
|
||||||
return render(request, 'chat/chat_conversejs.html', ctx)
|
return render(request, "chat/chat_conversejs.html", ctx)
|
||||||
|
|
||||||
|
|
||||||
def _get_dates():
|
def _get_dates():
|
||||||
now = datetime.date.today()
|
now = datetime.date.today()
|
||||||
start_date = now - datetime.timedelta(
|
start_date = now - datetime.timedelta(days=settings.KHAGANAT_LOGS_MAX_DAYS)
|
||||||
days=settings.KHAGANAT_LOGS_MAX_DAYS
|
end_date = now - datetime.timedelta(days=settings.KHAGANAT_LOGS_MIN_DAYS - 1)
|
||||||
)
|
|
||||||
end_date = now - datetime.timedelta(
|
|
||||||
days=settings.KHAGANAT_LOGS_MIN_DAYS - 1
|
|
||||||
)
|
|
||||||
return (now, start_date, end_date)
|
return (now, start_date, end_date)
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,9 +36,9 @@ def _switch_hidden(request, obj, pk):
|
||||||
e.hidden = not e.hidden
|
e.hidden = not e.hidden
|
||||||
e.save()
|
e.save()
|
||||||
|
|
||||||
next_page = request.GET.get('next', '/')
|
next_page = request.GET.get("next", "/")
|
||||||
if not is_link_legit(next_page):
|
if not is_link_legit(next_page):
|
||||||
next_page = reverse('log_index')
|
next_page = reverse("log_index")
|
||||||
return redirect(next_page)
|
return redirect(next_page)
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,22 +53,27 @@ def switch_log_entry(request, pk):
|
||||||
|
|
||||||
|
|
||||||
def log_search_view(request):
|
def log_search_view(request):
|
||||||
if request.method == 'POST':
|
if request.method == "POST":
|
||||||
form = SearchForm(request.POST)
|
form = SearchForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
date = form.cleaned_data['date']
|
date = form.cleaned_data["date"]
|
||||||
return redirect(reverse('log_day', kwargs={
|
return redirect(
|
||||||
'source': form.cleaned_data['source'],
|
reverse(
|
||||||
'year': date.year,
|
"log_day",
|
||||||
'month': date.month,
|
kwargs={
|
||||||
'day': date.day,
|
"source": form.cleaned_data["source"],
|
||||||
}))
|
"year": date.year,
|
||||||
raise Http404('No search parameters.')
|
"month": date.month,
|
||||||
|
"day": date.day,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
raise Http404("No search parameters.")
|
||||||
|
|
||||||
|
|
||||||
class LogEntriesView(generic.ListView):
|
class LogEntriesView(generic.ListView):
|
||||||
template_name = 'chat/entries.html'
|
template_name = "chat/entries.html"
|
||||||
context_object_name = 'entries'
|
context_object_name = "entries"
|
||||||
filter_nsfw = False
|
filter_nsfw = False
|
||||||
|
|
||||||
def is_nsfw(self):
|
def is_nsfw(self):
|
||||||
|
@ -93,17 +95,17 @@ class LogEntriesView(generic.ListView):
|
||||||
"""Return the date object corresponding to the URL parameters
|
"""Return the date object corresponding to the URL parameters
|
||||||
or None if missing.
|
or None if missing.
|
||||||
"""
|
"""
|
||||||
has_date = all([
|
has_date = all(
|
||||||
self.kwargs.get('year') is not None,
|
[
|
||||||
self.kwargs.get('month') is not None,
|
self.kwargs.get("year") is not None,
|
||||||
self.kwargs.get('day') is not None,
|
self.kwargs.get("month") is not None,
|
||||||
])
|
self.kwargs.get("day") is not None,
|
||||||
|
]
|
||||||
|
)
|
||||||
if not has_date:
|
if not has_date:
|
||||||
return None
|
return None
|
||||||
return datetime.date(
|
return datetime.date(
|
||||||
self.kwargs['year'],
|
self.kwargs["year"], self.kwargs["month"], self.kwargs["day"]
|
||||||
self.kwargs['month'],
|
|
||||||
self.kwargs['day']
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_dates(self, source):
|
def get_dates(self, source):
|
||||||
|
@ -114,26 +116,22 @@ class LogEntriesView(generic.ListView):
|
||||||
|
|
||||||
nb_max = settings.KHAGANAT_LOGS_MAX_DAYS
|
nb_max = settings.KHAGANAT_LOGS_MAX_DAYS
|
||||||
nb_max -= settings.KHAGANAT_LOGS_MIN_DAYS
|
nb_max -= settings.KHAGANAT_LOGS_MIN_DAYS
|
||||||
lst = LogEntry.objects.filter(
|
lst = LogEntry.objects.filter(source=source)
|
||||||
source=source,
|
|
||||||
)
|
|
||||||
if not self.request.user.is_staff:
|
if not self.request.user.is_staff:
|
||||||
lst = lst.filter(
|
lst = lst.filter(hidden=False, created__range=(start_date, end_date))
|
||||||
hidden=False,
|
lst = (
|
||||||
created__range=(start_date, end_date)
|
lst.annotate(date=TruncDate("created"))
|
||||||
)
|
.values("date")
|
||||||
lst = lst.annotate(
|
.annotate(nb=Count("date"))
|
||||||
date=TruncDate('created')
|
.order_by("-date")[:nb_max]
|
||||||
).values('date').annotate(
|
)
|
||||||
nb=Count('date')
|
return [o["date"] for o in lst]
|
||||||
).order_by('-date')[:nb_max]
|
|
||||||
return [o['date'] for o in lst]
|
|
||||||
|
|
||||||
def get_source(self):
|
def get_source(self):
|
||||||
"""Return the current source."""
|
"""Return the current source."""
|
||||||
if self.kwargs.get('source') is None:
|
if self.kwargs.get("source") is None:
|
||||||
return None
|
return None
|
||||||
return LogSource.objects.get(slug=self.kwargs['source'])
|
return LogSource.objects.get(slug=self.kwargs["source"])
|
||||||
|
|
||||||
def get_sources(self):
|
def get_sources(self):
|
||||||
"""Return available sources."""
|
"""Return available sources."""
|
||||||
|
@ -144,32 +142,29 @@ class LogEntriesView(generic.ListView):
|
||||||
qs = qs.filter(
|
qs = qs.filter(
|
||||||
hidden=False,
|
hidden=False,
|
||||||
source__hidden=False,
|
source__hidden=False,
|
||||||
created__range=(start_date, end_date)
|
created__range=(start_date, end_date),
|
||||||
)
|
)
|
||||||
qs = qs.values(
|
qs = qs.values(
|
||||||
'source', 'source__name', 'source__slug',
|
"source", "source__name", "source__slug", "source__id", "source__hidden"
|
||||||
'source__id', 'source__hidden'
|
).annotate(nb=Count("id"))
|
||||||
).annotate(
|
|
||||||
nb=Count('id')
|
|
||||||
)
|
|
||||||
|
|
||||||
out = []
|
out = []
|
||||||
for src in qs:
|
for src in qs:
|
||||||
dts = self.get_dates(src['source'])
|
dts = self.get_dates(src["source"])
|
||||||
src['first_date'] = dts[0] if dts else None
|
src["first_date"] = dts[0] if dts else None
|
||||||
out.append(src)
|
out.append(src)
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
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['form'] = SearchForm()
|
context["form"] = SearchForm()
|
||||||
context['sources'] = self.get_sources()
|
context["sources"] = self.get_sources()
|
||||||
context['current_source'] = self.get_source()
|
context["current_source"] = self.get_source()
|
||||||
context['dates'] = self.get_dates(context['current_source'])
|
context["dates"] = self.get_dates(context["current_source"])
|
||||||
context['current_date'] = self.get_date()
|
context["current_date"] = self.get_date()
|
||||||
context['filter_nsfw'] = self.filter_nsfw
|
context["filter_nsfw"] = self.filter_nsfw
|
||||||
context['current_url'] = self.request.get_full_path()
|
context["current_url"] = self.request.get_full_path()
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
@ -180,10 +175,12 @@ class LogEntriesView(generic.ListView):
|
||||||
|
|
||||||
is_staff = self.request.user.is_staff
|
is_staff = self.request.user.is_staff
|
||||||
now = datetime.date.today()
|
now = datetime.date.today()
|
||||||
out_of_bounds = any((
|
out_of_bounds = any(
|
||||||
(now - dt).days > settings.KHAGANAT_LOGS_MAX_DAYS,
|
(
|
||||||
(now - dt).days < settings.KHAGANAT_LOGS_MIN_DAYS,
|
(now - dt).days > settings.KHAGANAT_LOGS_MAX_DAYS,
|
||||||
))
|
(now - dt).days < settings.KHAGANAT_LOGS_MIN_DAYS,
|
||||||
|
)
|
||||||
|
)
|
||||||
if out_of_bounds and not is_staff:
|
if out_of_bounds and not is_staff:
|
||||||
return LogEntry.objects.none()
|
return LogEntry.objects.none()
|
||||||
src = self.get_source()
|
src = self.get_source()
|
||||||
|
@ -191,14 +188,11 @@ class LogEntriesView(generic.ListView):
|
||||||
return LogEntry.objects.none()
|
return LogEntry.objects.none()
|
||||||
if src.hidden and not is_staff:
|
if src.hidden and not is_staff:
|
||||||
return LogEntry.objects.none()
|
return LogEntry.objects.none()
|
||||||
qs = LogEntry.objects.filter(
|
qs = (
|
||||||
source=src,
|
LogEntry.objects.filter(source=src, created__year=dt.year)
|
||||||
created__year=dt.year
|
.filter(created__month=dt.month)
|
||||||
).filter(
|
.filter(created__day=dt.day)
|
||||||
created__month=dt.month,
|
|
||||||
).filter(
|
|
||||||
created__day=dt.day
|
|
||||||
)
|
)
|
||||||
if not is_staff:
|
if not is_staff:
|
||||||
qs = qs.filter(hidden=False)
|
qs = qs.filter(hidden=False)
|
||||||
return qs.order_by('created')
|
return qs.order_by("created")
|
||||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class KhaganatConfig(AppConfig):
|
class KhaganatConfig(AppConfig):
|
||||||
name = 'khaganat'
|
name = "khaganat"
|
||||||
|
|
|
@ -24,73 +24,73 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = config('KHAGANAT_SECRET_KEY')
|
SECRET_KEY = config("KHAGANAT_SECRET_KEY")
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = config('KHAGANAT_DEBUG', default=False, cast=bool)
|
DEBUG = config("KHAGANAT_DEBUG", default=False, cast=bool)
|
||||||
|
|
||||||
ALLOWED_HOSTS = config('KHAGANAT_HOSTNAMES', default='', cast=Csv())
|
ALLOWED_HOSTS = config("KHAGANAT_HOSTNAMES", default="", cast=Csv())
|
||||||
INTERNAL_IPS = config('KHAGANAT_INTERNAL_IPS', default='127.0.0.1,::1', cast=Csv())
|
INTERNAL_IPS = config("KHAGANAT_INTERNAL_IPS", default="127.0.0.1,::1", cast=Csv())
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'django.contrib.admin',
|
"django.contrib.admin",
|
||||||
'django.contrib.auth',
|
"django.contrib.auth",
|
||||||
'django.contrib.contenttypes',
|
"django.contrib.contenttypes",
|
||||||
'django.contrib.sessions',
|
"django.contrib.sessions",
|
||||||
'django.contrib.messages',
|
"django.contrib.messages",
|
||||||
'bulma',
|
"bulma",
|
||||||
'chat.apps.LogsConfig',
|
"chat.apps.LogsConfig",
|
||||||
'khaganat.apps.KhaganatConfig',
|
"khaganat.apps.KhaganatConfig",
|
||||||
'navbar.apps.NavbarConfig',
|
"navbar.apps.NavbarConfig",
|
||||||
'neluser.apps.NeluserConfig',
|
"neluser.apps.NeluserConfig",
|
||||||
'npb.apps.NpbConfig',
|
"npb.apps.NpbConfig",
|
||||||
'nsfw.apps.NsfwConfig',
|
"nsfw.apps.NsfwConfig",
|
||||||
'pages.apps.PagesConfig',
|
"pages.apps.PagesConfig",
|
||||||
'static_extra.apps.KhaganatStaticFilesConfig',
|
"static_extra.apps.KhaganatStaticFilesConfig",
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
"django.middleware.security.SecurityMiddleware",
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||||
'django.middleware.locale.LocaleMiddleware',
|
"django.middleware.locale.LocaleMiddleware",
|
||||||
'django.middleware.common.CommonMiddleware',
|
"django.middleware.common.CommonMiddleware",
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
"django.middleware.csrf.CsrfViewMiddleware",
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
"django.contrib.messages.middleware.MessageMiddleware",
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'khaganat.urls'
|
ROOT_URLCONF = "khaganat.urls"
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||||
'DIRS': [],
|
"DIRS": [],
|
||||||
'APP_DIRS': True,
|
"APP_DIRS": True,
|
||||||
'OPTIONS': {
|
"OPTIONS": {
|
||||||
'context_processors': [
|
"context_processors": [
|
||||||
'django.template.context_processors.debug',
|
"django.template.context_processors.debug",
|
||||||
'django.template.context_processors.request',
|
"django.template.context_processors.request",
|
||||||
'django.contrib.auth.context_processors.auth',
|
"django.contrib.auth.context_processors.auth",
|
||||||
'django.contrib.messages.context_processors.messages',
|
"django.contrib.messages.context_processors.messages",
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
WSGI_APPLICATION = 'khaganat.wsgi.application'
|
WSGI_APPLICATION = "khaganat.wsgi.application"
|
||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
|
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
"default": {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
"ENGINE": "django.db.backends.sqlite3",
|
||||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,32 +98,27 @@ DATABASES = {
|
||||||
# Emailing
|
# Emailing
|
||||||
# https://docs.djangoproject.com/fr/2.0/topics/email/
|
# https://docs.djangoproject.com/fr/2.0/topics/email/
|
||||||
|
|
||||||
EMAIL_HOST = config('KHAGANAT_EMAIL_HOST', default='localhost')
|
EMAIL_HOST = config("KHAGANAT_EMAIL_HOST", default="localhost")
|
||||||
EMAIL_PORT = config('KHAGANAT_EMAIL_PORT', default=25, cast=int)
|
EMAIL_PORT = config("KHAGANAT_EMAIL_PORT", default=25, cast=int)
|
||||||
EMAIL_HOST_USER = config('KHAGANAT_EMAIL_HOST_USER', default='')
|
EMAIL_HOST_USER = config("KHAGANAT_EMAIL_HOST_USER", default="")
|
||||||
EMAIL_HOST_PASSWORD = config('KHAGANAT_EMAIL_HOST_PASSWORD', default='')
|
EMAIL_HOST_PASSWORD = config("KHAGANAT_EMAIL_HOST_PASSWORD", default="")
|
||||||
EMAIL_USE_TLS = config('KHAGANAT_EMAIL_USE_STARTTLS', default=False, cast=bool)
|
EMAIL_USE_TLS = config("KHAGANAT_EMAIL_USE_STARTTLS", default=False, cast=bool)
|
||||||
EMAIL_USE_SSL = config('KHAGANAT_EMAIL_USE_TLS', default=False, cast=bool)
|
EMAIL_USE_SSL = config("KHAGANAT_EMAIL_USE_TLS", default=False, cast=bool)
|
||||||
|
|
||||||
EMAIL_SUBJECT_PREFIX = config('KHAGANAT_EMAIL_SUBJECT_PREFIX', default='')
|
EMAIL_SUBJECT_PREFIX = config("KHAGANAT_EMAIL_SUBJECT_PREFIX", default="")
|
||||||
DEFAULT_FROM_EMAIL = config(
|
DEFAULT_FROM_EMAIL = config("KHAGANAT_DEFAULT_FROM_EMAIL", default="no-reply@localhost")
|
||||||
'KHAGANAT_DEFAULT_FROM_EMAIL',
|
|
||||||
default='no-reply@localhost'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# User model
|
# User model
|
||||||
# https://docs.djangoproject.com/en/2.0/topics/auth/customizing/
|
# https://docs.djangoproject.com/en/2.0/topics/auth/customizing/
|
||||||
|
|
||||||
AUTH_USER_MODEL = 'neluser.NelUser'
|
AUTH_USER_MODEL = "neluser.NelUser"
|
||||||
LOGIN_URL = reverse_lazy('login')
|
LOGIN_URL = reverse_lazy("login")
|
||||||
LOGIN_REDIRECT_URL = reverse_lazy(
|
LOGIN_REDIRECT_URL = reverse_lazy(
|
||||||
config('KHAGANAT_LOGIN_REDIRECT_URL', default='index')
|
config("KHAGANAT_LOGIN_REDIRECT_URL", default="index")
|
||||||
)
|
)
|
||||||
REGISTER_REQUIRE_VALIDATION = config(
|
REGISTER_REQUIRE_VALIDATION = config(
|
||||||
'KHAGANAT_REGISTER_REQUIRE_VALIDATION',
|
"KHAGANAT_REGISTER_REQUIRE_VALIDATION", default=True, cast=bool
|
||||||
default=True,
|
|
||||||
cast=bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,33 +127,24 @@ REGISTER_REQUIRE_VALIDATION = config(
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
|
||||||
},
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
|
||||||
},
|
},
|
||||||
|
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
|
||||||
|
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
|
||||||
|
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/2.0/topics/i18n/
|
# https://docs.djangoproject.com/en/2.0/topics/i18n/
|
||||||
|
|
||||||
LANGUAGE_CODE = config('KHAGANAT_LANGUAGE_CODE', default='fr')
|
LANGUAGE_CODE = config("KHAGANAT_LANGUAGE_CODE", default="fr")
|
||||||
|
|
||||||
# https://github.com/django/django/blob/master/django/conf/global_settings.py
|
# https://github.com/django/django/blob/master/django/conf/global_settings.py
|
||||||
|
|
||||||
LANGUAGES = [
|
LANGUAGES = [("en", _("English")), ("fr", _("French"))]
|
||||||
('en', _('English')),
|
|
||||||
('fr', _('French')),
|
|
||||||
]
|
|
||||||
|
|
||||||
TIME_ZONE = config('KHAGANAT_TIME_ZONE', default='Europe/Paris')
|
TIME_ZONE = config("KHAGANAT_TIME_ZONE", default="Europe/Paris")
|
||||||
|
|
||||||
USE_I18N = True
|
USE_I18N = True
|
||||||
|
|
||||||
|
@ -170,36 +156,36 @@ USE_TZ = True
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/2.0/howto/static-files/
|
# https://docs.djangoproject.com/en/2.0/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = config('KHAGANAT_STATIC_URL', default='/static/')
|
STATIC_URL = config("KHAGANAT_STATIC_URL", default="/static/")
|
||||||
STATIC_ROOT = config('KHAGANAT_STATIC_ROOT', default='') or None
|
STATIC_ROOT = config("KHAGANAT_STATIC_ROOT", default="") or None
|
||||||
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static_extra')]
|
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static_extra")]
|
||||||
STATICFILES_DIRS += config('KHAGANAT_STATIC_DIRS', default='', cast=Csv()) or []
|
STATICFILES_DIRS += config("KHAGANAT_STATIC_DIRS", default="", cast=Csv()) or []
|
||||||
|
|
||||||
|
|
||||||
# Logs configuration
|
# Logs configuration
|
||||||
KHAGANAT_LOGS_MIN_DAYS = config('KHAGANAT_LOGS_MIN_DAYS', default=0, cast=int)
|
KHAGANAT_LOGS_MIN_DAYS = config("KHAGANAT_LOGS_MIN_DAYS", default=0, cast=int)
|
||||||
KHAGANAT_LOGS_MAX_DAYS = config('KHAGANAT_LOGS_MAX_DAYS', default=7, cast=int)
|
KHAGANAT_LOGS_MAX_DAYS = config("KHAGANAT_LOGS_MAX_DAYS", default=7, cast=int)
|
||||||
|
|
||||||
|
|
||||||
# TLS
|
# TLS
|
||||||
# https://docs.djangoproject.com/fr/2.0/ref/settings/#std:setting-SECURE_PROXY_SSL_HEADER
|
# https://docs.djangoproject.com/fr/2.0/ref/settings/#std:setting-SECURE_PROXY_SSL_HEADER
|
||||||
|
|
||||||
if config('KHAGANAT_FORCE_HTTPS', default=False, cast=bool):
|
if config("KHAGANAT_FORCE_HTTPS", default=False, cast=bool):
|
||||||
SECURE_PROXY_SSL_HEADER = (
|
SECURE_PROXY_SSL_HEADER = (
|
||||||
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
|
# NSFW
|
||||||
|
|
||||||
KHAGANAT_NSFW_TAGS = config('KHAGANAT_NSFW_TAGS', default='\\#nsfw', cast=Csv())
|
KHAGANAT_NSFW_TAGS = config("KHAGANAT_NSFW_TAGS", default="\\#nsfw", cast=Csv())
|
||||||
KHAGANAT_NSFW_NAME = config('KHAGANAT_NSFW_NAME', default='nsfw_allowed')
|
KHAGANAT_NSFW_NAME = config("KHAGANAT_NSFW_NAME", default="nsfw_allowed")
|
||||||
KHAGANAT_NSFW_OK = ('y', 'yes', 't', 'true', '1')
|
KHAGANAT_NSFW_OK = ("y", "yes", "t", "true", "1")
|
||||||
|
|
||||||
# Converse.js
|
# Converse.js
|
||||||
|
|
||||||
KHAGANAT_XMPP_BOSH_URL = config('KHAGANAT_XMPP_BOSH_URL', default='') or None
|
KHAGANAT_XMPP_BOSH_URL = config("KHAGANAT_XMPP_BOSH_URL", default="") or None
|
||||||
KHAGANAT_XMPP_JID = config('KHAGANAT_XMPP_JID', default='') or None
|
KHAGANAT_XMPP_JID = config("KHAGANAT_XMPP_JID", default="") or None
|
||||||
KHAGANAT_XMPP_ROOMS = config('KHAGANAT_XMPP_ROOMS', default='', cast=Csv()) or []
|
KHAGANAT_XMPP_ROOMS = config("KHAGANAT_XMPP_ROOMS", default="", cast=Csv()) or []
|
||||||
KHAGANAT_XMPP_WEBSOCKET_URL = config('KHAGANAT_XMPP_WEBSOCKET_URL', default='') or None
|
KHAGANAT_XMPP_WEBSOCKET_URL = config("KHAGANAT_XMPP_WEBSOCKET_URL", default="") or None
|
||||||
|
|
|
@ -19,16 +19,14 @@ from django.contrib import admin
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
from pages.views import index
|
from pages.views import index
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [path("", index)]
|
||||||
path('', index),
|
|
||||||
]
|
|
||||||
|
|
||||||
urlpatterns += i18n_patterns(
|
urlpatterns += i18n_patterns(
|
||||||
path('', index),
|
path("", index),
|
||||||
path('admin/', admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
path('account/', include('neluser.urls')),
|
path("account/", include("neluser.urls")),
|
||||||
path('page/', include('pages.urls')),
|
path("page/", include("pages.urls")),
|
||||||
path('paste/', include('npb.urls', namespace='npb')),
|
path("paste/", include("npb.urls", namespace="npb")),
|
||||||
path('chat/', include('chat.urls')),
|
path("chat/", include("chat.urls")),
|
||||||
path('nsfw/', include('nsfw.urls')),
|
path("nsfw/", include("nsfw.urls")),
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,10 +6,8 @@ from .models import Element, ElementDescription, ElementSeparator
|
||||||
class ElementDescriptionAdminForm(forms.ModelForm):
|
class ElementDescriptionAdminForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ElementDescription
|
model = ElementDescription
|
||||||
widgets = {
|
widgets = {"description": forms.widgets.Textarea}
|
||||||
'description': forms.widgets.Textarea,
|
fields = "__all__"
|
||||||
}
|
|
||||||
fields = '__all__'
|
|
||||||
|
|
||||||
|
|
||||||
class ElementDescriptionInline(admin.StackedInline):
|
class ElementDescriptionInline(admin.StackedInline):
|
||||||
|
@ -19,8 +17,8 @@ class ElementDescriptionInline(admin.StackedInline):
|
||||||
|
|
||||||
|
|
||||||
class ElementAdmin(admin.ModelAdmin):
|
class ElementAdmin(admin.ModelAdmin):
|
||||||
list_display = ('__str__', 'parent', 'link', 'weight')
|
list_display = ("__str__", "parent", "link", "weight")
|
||||||
ordering = ('parent', 'weight')
|
ordering = ("parent", "weight")
|
||||||
inlines = [ElementDescriptionInline]
|
inlines = [ElementDescriptionInline]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class NavbarConfig(AppConfig):
|
class NavbarConfig(AppConfig):
|
||||||
name = 'navbar'
|
name = "navbar"
|
||||||
|
|
|
@ -6,72 +6,70 @@ import os
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = 'Generates the CSS files used by Pygments'
|
help = "Generates the CSS files used by Pygments"
|
||||||
|
|
||||||
def export_static(self, curr_lang):
|
def export_static(self, curr_lang):
|
||||||
self.stdout.write('Plain HTML export for language %s…' % curr_lang)
|
self.stdout.write("Plain HTML export for language %s…" % curr_lang)
|
||||||
output_dir = os.path.join(self.export_dir, 'html')
|
output_dir = os.path.join(self.export_dir, "html")
|
||||||
output_file = 'khanav_%s.html' % curr_lang
|
output_file = "khanav_%s.html" % curr_lang
|
||||||
os.makedirs(output_dir, mode=0o755, exist_ok=True)
|
os.makedirs(output_dir, mode=0o755, exist_ok=True)
|
||||||
with open(os.path.join(output_dir, output_file), 'w') as f:
|
with open(os.path.join(output_dir, output_file), "w") as f:
|
||||||
ctx = get_base_context(curr_lang, '/')
|
ctx = get_base_context(curr_lang, "/")
|
||||||
html = render_to_string('navbar/navbar.html', ctx)
|
html = render_to_string("navbar/navbar.html", ctx)
|
||||||
f.write(html)
|
f.write(html)
|
||||||
|
|
||||||
def export_docuwiki(self, langs):
|
def export_docuwiki(self, langs):
|
||||||
self.stdout.write(
|
self.stdout.write("Docuwiki export for languages %s…" % ", ".join(langs))
|
||||||
'Docuwiki export for languages %s…' % ', '.join(langs)
|
|
||||||
)
|
|
||||||
output_langs = []
|
output_langs = []
|
||||||
for lang in langs:
|
for lang in langs:
|
||||||
ctx = get_base_context(lang, '/')
|
ctx = get_base_context(lang, "/")
|
||||||
output_langs.append({
|
output_langs.append(
|
||||||
'name': lang,
|
{"name": lang, "html": render_to_string("navbar/navbar.html", ctx)}
|
||||||
'html': render_to_string('navbar/navbar.html', ctx)
|
)
|
||||||
})
|
output_dir = os.path.join(self.export_dir, "docuwiki")
|
||||||
output_dir = os.path.join(self.export_dir, 'docuwiki')
|
|
||||||
os.makedirs(output_dir, mode=0o755, exist_ok=True)
|
os.makedirs(output_dir, mode=0o755, exist_ok=True)
|
||||||
with open(os.path.join(output_dir, 'khanav.php'), 'w') as f:
|
with open(os.path.join(output_dir, "khanav.php"), "w") as f:
|
||||||
f.write(render_to_string('navbar/export_docuwiki.html', {
|
f.write(
|
||||||
'output_langs': output_langs
|
render_to_string(
|
||||||
}))
|
"navbar/export_docuwiki.html", {"output_langs": output_langs}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--dir', '-d',
|
"--dir",
|
||||||
help='Export directory.',
|
"-d",
|
||||||
default=os.path.join(settings.BASE_DIR, 'build/navbar'),
|
help="Export directory.",
|
||||||
dest='export_dir'
|
default=os.path.join(settings.BASE_DIR, "build/navbar"),
|
||||||
|
dest="export_dir",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--lang', '-l',
|
"--lang", "-l", help="Language to export.", action="append", dest="langs"
|
||||||
help='Language to export.',
|
|
||||||
action='append',
|
|
||||||
dest='langs'
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--plain', '--html',
|
"--plain",
|
||||||
help='Export for plain HTML.',
|
"--html",
|
||||||
action='store_true',
|
help="Export for plain HTML.",
|
||||||
dest='static'
|
action="store_true",
|
||||||
|
dest="static",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--docuwiki',
|
"--docuwiki",
|
||||||
help='Export for docuwiki.',
|
help="Export for docuwiki.",
|
||||||
action='store_true',
|
action="store_true",
|
||||||
dest='docuwiki'
|
dest="docuwiki",
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
if options['langs'] is None:
|
if options["langs"] is None:
|
||||||
raise CommandError('No language specified.')
|
raise CommandError("No language specified.")
|
||||||
if 'all' in options['langs']:
|
if "all" in options["langs"]:
|
||||||
options['langs'] = [name for name, _ in settings.LANGUAGES]
|
options["langs"] = [name for name, _ in settings.LANGUAGES]
|
||||||
self.export_dir = options['export_dir']
|
self.export_dir = options["export_dir"]
|
||||||
|
|
||||||
if options['static']:
|
if options["static"]:
|
||||||
for lang in options['langs']:
|
for lang in options["langs"]:
|
||||||
self.export_static(lang)
|
self.export_static(lang)
|
||||||
if options['docuwiki']:
|
if options["docuwiki"]:
|
||||||
self.export_docuwiki(options['langs'])
|
self.export_docuwiki(options["langs"])
|
||||||
self.stdout.write(self.style.SUCCESS('Ok.'))
|
self.stdout.write(self.style.SUCCESS("Ok."))
|
||||||
|
|
|
@ -6,44 +6,35 @@ import os
|
||||||
|
|
||||||
class Element(models.Model):
|
class Element(models.Model):
|
||||||
parent = models.ForeignKey(
|
parent = models.ForeignKey(
|
||||||
'Element',
|
"Element",
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
limit_choices_to={'parent': None}
|
limit_choices_to={"parent": None},
|
||||||
)
|
)
|
||||||
link = models.CharField(max_length=512, blank=True)
|
link = models.CharField(max_length=512, blank=True)
|
||||||
new_window = models.BooleanField(default=False)
|
new_window = models.BooleanField(default=False)
|
||||||
add_locale = models.BooleanField(default=False)
|
add_locale = models.BooleanField(default=False)
|
||||||
icon = models.FilePathField(
|
icon = models.FilePathField(
|
||||||
path='navbar/static/navbar/icons',
|
path="navbar/static/navbar/icons", match=".png", null=True, blank=True
|
||||||
match=".png",
|
|
||||||
null=True,
|
|
||||||
blank=True
|
|
||||||
)
|
)
|
||||||
weight = models.PositiveSmallIntegerField()
|
weight = models.PositiveSmallIntegerField()
|
||||||
|
|
||||||
def icon_path(self):
|
def icon_path(self):
|
||||||
return os.path.join('navbar/icons', os.path.basename(self.icon))
|
return os.path.join("navbar/icons", os.path.basename(self.icon))
|
||||||
|
|
||||||
def children(self):
|
def children(self):
|
||||||
return sorted(
|
return sorted(
|
||||||
list(Element.objects.filter(parent=self.id).order_by('weight')) +
|
list(Element.objects.filter(parent=self.id).order_by("weight"))
|
||||||
list(
|
+ list(ElementSeparator.objects.filter(parent=self.id).order_by("weight")),
|
||||||
ElementSeparator.objects.filter(parent=self.id)
|
key=lambda c: c.weight,
|
||||||
.order_by('weight')
|
|
||||||
),
|
|
||||||
key=lambda c: c.weight
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
lang = get_language()
|
lang = get_language()
|
||||||
if lang is None:
|
if lang is None:
|
||||||
lang = settings.LANGUAGE_CODE
|
lang = settings.LANGUAGE_CODE
|
||||||
return ElementDescription.objects.filter(
|
return ElementDescription.objects.filter(element=self.id, language=lang).first()
|
||||||
element=self.id,
|
|
||||||
language=lang
|
|
||||||
).first()
|
|
||||||
|
|
||||||
def localized_link(self):
|
def localized_link(self):
|
||||||
link = self.link
|
link = self.link
|
||||||
|
@ -71,9 +62,7 @@ class ElementDescription(models.Model):
|
||||||
|
|
||||||
class ElementSeparator(models.Model):
|
class ElementSeparator(models.Model):
|
||||||
parent = models.ForeignKey(
|
parent = models.ForeignKey(
|
||||||
Element,
|
Element, on_delete=models.CASCADE, limit_choices_to={"parent": None}
|
||||||
on_delete=models.CASCADE,
|
|
||||||
limit_choices_to={'parent': None}
|
|
||||||
)
|
)
|
||||||
weight = models.PositiveSmallIntegerField()
|
weight = models.PositiveSmallIntegerField()
|
||||||
|
|
||||||
|
@ -81,4 +70,4 @@ class ElementSeparator(models.Model):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{} ({})'.format(self.parent, self.weight)
|
return "{} ({})".format(self.parent, self.weight)
|
||||||
|
|
|
@ -13,46 +13,39 @@ import re
|
||||||
|
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
path_re = re.compile('^(/[a-z]+)/(.*)')
|
path_re = re.compile("^(/[a-z]+)/(.*)")
|
||||||
|
|
||||||
|
|
||||||
def get_lang_name(lang_code):
|
def get_lang_name(lang_code):
|
||||||
li = get_language_info(lang_code)
|
li = get_language_info(lang_code)
|
||||||
return li['name_local']
|
return li["name_local"]
|
||||||
|
|
||||||
|
|
||||||
def get_lang_data(path_info, lang_code, curr_lang):
|
def get_lang_data(path_info, lang_code, curr_lang):
|
||||||
lang_name = get_lang_name(lang_code)
|
lang_name = get_lang_name(lang_code)
|
||||||
rm = resolve(path_info)
|
rm = resolve(path_info)
|
||||||
activate_lang(lang_code)
|
activate_lang(lang_code)
|
||||||
lang_url = reverse(
|
lang_url = reverse(rm.view_name, current_app="npb", args=rm.args, kwargs=rm.kwargs)
|
||||||
rm.view_name,
|
|
||||||
current_app='npb',
|
|
||||||
args=rm.args,
|
|
||||||
kwargs=rm.kwargs
|
|
||||||
)
|
|
||||||
activate_lang(curr_lang)
|
activate_lang(curr_lang)
|
||||||
return (lang_code, lang_name, lang_url)
|
return (lang_code, lang_name, lang_url)
|
||||||
|
|
||||||
|
|
||||||
def get_base_context(lang, url):
|
def get_base_context(lang, url):
|
||||||
return {
|
return {
|
||||||
'user': None,
|
"user": None,
|
||||||
'current_url': url,
|
"current_url": url,
|
||||||
'elems': Element.objects.filter(parent=None).order_by('weight'),
|
"elems": Element.objects.filter(parent=None).order_by("weight"),
|
||||||
'current_lang_code': lang,
|
"current_lang_code": lang,
|
||||||
'current_lang_name': get_lang_name(lang),
|
"current_lang_name": get_lang_name(lang),
|
||||||
'all_langs': [
|
"all_langs": [get_lang_data(url, l[0], lang) for l in settings.LANGUAGES],
|
||||||
get_lang_data(url, l[0], lang) for l in settings.LANGUAGES
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def navbar(context):
|
def navbar(context):
|
||||||
request = context['request']
|
request = context["request"]
|
||||||
curr_lang = get_language()
|
curr_lang = get_language()
|
||||||
ctx = get_base_context(curr_lang, request.path_info)
|
ctx = get_base_context(curr_lang, request.path_info)
|
||||||
ctx['user'] = request.user
|
ctx["user"] = request.user
|
||||||
tpl = TemplateResponse(request, 'navbar/navbar.html', context=ctx).render()
|
tpl = TemplateResponse(request, "navbar/navbar.html", context=ctx).render()
|
||||||
return mark_safe(tpl.rendered_content)
|
return mark_safe(tpl.rendered_content)
|
||||||
|
|
|
@ -5,16 +5,26 @@ from .views import send_activation_email
|
||||||
|
|
||||||
|
|
||||||
class NelUserAdmin(admin.ModelAdmin):
|
class NelUserAdmin(admin.ModelAdmin):
|
||||||
list_display = ('email', 'date_joined', 'last_login', 'is_active', 'is_staff', 'is_superuser')
|
list_display = (
|
||||||
readonly_fields = ('date_joined', 'last_login')
|
"email",
|
||||||
list_filter = ('is_active', 'is_staff', 'is_superuser')
|
"date_joined",
|
||||||
search_fields = ('email', )
|
"last_login",
|
||||||
|
"is_active",
|
||||||
|
"is_staff",
|
||||||
|
"is_superuser",
|
||||||
|
)
|
||||||
|
readonly_fields = ("date_joined", "last_login")
|
||||||
|
list_filter = ("is_active", "is_staff", "is_superuser")
|
||||||
|
search_fields = ("email",)
|
||||||
fieldsets = [
|
fieldsets = [
|
||||||
(_('info'), {'fields': ['is_active', 'email', 'date_joined', 'last_login']}),
|
(_("info"), {"fields": ["is_active", "email", "date_joined", "last_login"]}),
|
||||||
(_('user_permissions'), {'fields': ['is_staff', 'is_superuser', 'groups', 'user_permissions']}),
|
(
|
||||||
(_('misc'), {'fields': ['nsfw_allowed']}),
|
_("user_permissions"),
|
||||||
|
{"fields": ["is_staff", "is_superuser", "groups", "user_permissions"]},
|
||||||
|
),
|
||||||
|
(_("misc"), {"fields": ["nsfw_allowed"]}),
|
||||||
]
|
]
|
||||||
actions = ['resend_activation_link']
|
actions = ["resend_activation_link"]
|
||||||
|
|
||||||
def save_model(self, request, obj, form, change):
|
def save_model(self, request, obj, form, change):
|
||||||
super().save_model(request, obj, form, change)
|
super().save_model(request, obj, form, change)
|
||||||
|
@ -24,6 +34,8 @@ class NelUserAdmin(admin.ModelAdmin):
|
||||||
for user in queryset:
|
for user in queryset:
|
||||||
if not user.is_active:
|
if not user.is_active:
|
||||||
send_activation_email(request, user)
|
send_activation_email(request, user)
|
||||||
resend_activation_link.short_description = _('resend_activation_link')
|
|
||||||
|
resend_activation_link.short_description = _("resend_activation_link")
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(NelUser, NelUserAdmin)
|
admin.site.register(NelUser, NelUserAdmin)
|
||||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class NeluserConfig(AppConfig):
|
class NeluserConfig(AppConfig):
|
||||||
name = 'neluser'
|
name = "neluser"
|
||||||
|
|
|
@ -15,54 +15,48 @@ class RegistrationForm(UserCreationForm):
|
||||||
|
|
||||||
class ChangePasswordForm(forms.Form):
|
class ChangePasswordForm(forms.Form):
|
||||||
current_password = forms.CharField(
|
current_password = forms.CharField(
|
||||||
label=_('current_password'),
|
label=_("current_password"), widget=forms.PasswordInput
|
||||||
widget=forms.PasswordInput
|
|
||||||
)
|
|
||||||
new_password = forms.CharField(
|
|
||||||
label=_('new_password'),
|
|
||||||
widget=forms.PasswordInput
|
|
||||||
)
|
)
|
||||||
|
new_password = forms.CharField(label=_("new_password"), widget=forms.PasswordInput)
|
||||||
new_password_confirm = forms.CharField(
|
new_password_confirm = forms.CharField(
|
||||||
label=_('new_password_confirm'),
|
label=_("new_password_confirm"), widget=forms.PasswordInput
|
||||||
widget=forms.PasswordInput
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.request = kwargs.pop('request')
|
self.request = kwargs.pop("request")
|
||||||
return super().__init__(*args, **kwargs)
|
return super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super().clean()
|
cleaned_data = super().clean()
|
||||||
old_pass = cleaned_data.get('current_password')
|
old_pass = cleaned_data.get("current_password")
|
||||||
new_pass = cleaned_data.get('new_password')
|
new_pass = cleaned_data.get("new_password")
|
||||||
new_pass_confirm = cleaned_data.get('new_password_confirm')
|
new_pass_confirm = cleaned_data.get("new_password_confirm")
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
if new_pass != new_pass_confirm:
|
if new_pass != new_pass_confirm:
|
||||||
msg = _('The new password does not match its confirmation.')
|
msg = _("The new password does not match its confirmation.")
|
||||||
raise forms.ValidationError(msg)
|
raise forms.ValidationError(msg)
|
||||||
try:
|
try:
|
||||||
validate_password(new_pass, user=user)
|
validate_password(new_pass, user=user)
|
||||||
except ValidationError as error:
|
except ValidationError as error:
|
||||||
raise forms.ValidationError(error)
|
raise forms.ValidationError(error)
|
||||||
if not user.check_password(old_pass):
|
if not user.check_password(old_pass):
|
||||||
msg = _('The current password is incorrect.')
|
msg = _("The current password is incorrect.")
|
||||||
raise forms.ValidationError(msg)
|
raise forms.ValidationError(msg)
|
||||||
|
|
||||||
|
|
||||||
class DeleteAccountForm(forms.Form):
|
class DeleteAccountForm(forms.Form):
|
||||||
current_password = forms.CharField(
|
current_password = forms.CharField(
|
||||||
label=_('current_password'),
|
label=_("current_password"), widget=forms.PasswordInput
|
||||||
widget=forms.PasswordInput
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.request = kwargs.pop('request')
|
self.request = kwargs.pop("request")
|
||||||
return super().__init__(*args, **kwargs)
|
return super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super().clean()
|
cleaned_data = super().clean()
|
||||||
password = cleaned_data.get('current_password')
|
password = cleaned_data.get("current_password")
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
if not user.check_password(password):
|
if not user.check_password(password):
|
||||||
msg = _('The current password is incorrect.')
|
msg = _("The current password is incorrect.")
|
||||||
raise forms.ValidationError(msg)
|
raise forms.ValidationError(msg)
|
||||||
|
|
|
@ -11,7 +11,7 @@ class NelUserManager(BaseUserManager):
|
||||||
|
|
||||||
def _create_user(self, email, password, **extra_fields):
|
def _create_user(self, email, password, **extra_fields):
|
||||||
if not email:
|
if not email:
|
||||||
raise ValueError('The given email must be set')
|
raise ValueError("The given email must be set")
|
||||||
email = self.normalize_email(email)
|
email = self.normalize_email(email)
|
||||||
user = self.model(email=email, **extra_fields)
|
user = self.model(email=email, **extra_fields)
|
||||||
user.set_password(password)
|
user.set_password(password)
|
||||||
|
@ -19,59 +19,56 @@ class NelUserManager(BaseUserManager):
|
||||||
return user
|
return user
|
||||||
|
|
||||||
def create_user(self, email, password=None, **extra_fields):
|
def create_user(self, email, password=None, **extra_fields):
|
||||||
extra_fields.setdefault('is_staff', False)
|
extra_fields.setdefault("is_staff", False)
|
||||||
extra_fields.setdefault('is_superuser', False)
|
extra_fields.setdefault("is_superuser", False)
|
||||||
return self._create_user(email, password, **extra_fields)
|
return self._create_user(email, password, **extra_fields)
|
||||||
|
|
||||||
def create_superuser(self, email, password, **extra_fields):
|
def create_superuser(self, email, password, **extra_fields):
|
||||||
extra_fields.setdefault('is_staff', True)
|
extra_fields.setdefault("is_staff", True)
|
||||||
extra_fields.setdefault('is_superuser', True)
|
extra_fields.setdefault("is_superuser", True)
|
||||||
extra_fields.setdefault('is_active', True)
|
extra_fields.setdefault("is_active", True)
|
||||||
|
|
||||||
if extra_fields.get('is_staff') is not True:
|
if extra_fields.get("is_staff") is not True:
|
||||||
raise ValueError('Superuser must have is_staff=True.')
|
raise ValueError("Superuser must have is_staff=True.")
|
||||||
if extra_fields.get('is_superuser') is not True:
|
if extra_fields.get("is_superuser") is not True:
|
||||||
raise ValueError('Superuser must have is_superuser=True.')
|
raise ValueError("Superuser must have is_superuser=True.")
|
||||||
|
|
||||||
return self._create_user(email, password, **extra_fields)
|
return self._create_user(email, password, **extra_fields)
|
||||||
|
|
||||||
|
|
||||||
class NelUser(AbstractBaseUser, PermissionsMixin):
|
class NelUser(AbstractBaseUser, PermissionsMixin):
|
||||||
email = models.EmailField(_('email'), unique=True, null=True)
|
email = models.EmailField(_("email"), unique=True, null=True)
|
||||||
is_staff = models.BooleanField(
|
is_staff = models.BooleanField(
|
||||||
_('staff status'),
|
_("staff status"),
|
||||||
default=False,
|
default=False,
|
||||||
help_text=_(
|
help_text=_("Designates whether the user can log into this admin site."),
|
||||||
'Designates whether the user can log into this admin site.'
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
is_active = models.BooleanField(
|
is_active = models.BooleanField(
|
||||||
_('active'),
|
_("active"),
|
||||||
default=False,
|
default=False,
|
||||||
help_text=_(
|
help_text=_(
|
||||||
'Designates whether this user should be treated as active. '
|
"Designates whether this user should be treated as active. "
|
||||||
'Unselect this instead of deleting accounts.'
|
"Unselect this instead of deleting accounts."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
|
date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
|
||||||
nsfw_allowed = models.BooleanField(
|
nsfw_allowed = models.BooleanField(
|
||||||
_('NSFW flag'),
|
_("NSFW flag"),
|
||||||
default=False,
|
default=False,
|
||||||
help_text=_(
|
help_text=_(
|
||||||
'Indicate whether or not adult or sensitive content should '
|
"Indicate whether or not adult or sensitive content should " "be displayed."
|
||||||
'be displayed.'
|
),
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
objects = NelUserManager()
|
objects = NelUserManager()
|
||||||
|
|
||||||
EMAIL_FIELD = 'email'
|
EMAIL_FIELD = "email"
|
||||||
USERNAME_FIELD = 'email'
|
USERNAME_FIELD = "email"
|
||||||
REQUIRED_FIELDS = []
|
REQUIRED_FIELDS = []
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('user')
|
verbose_name = _("user")
|
||||||
verbose_name_plural = _('users')
|
verbose_name_plural = _("users")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.email.strip()
|
return self.email.strip()
|
||||||
|
|
|
@ -6,70 +6,65 @@ from . import views
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# Login and logout
|
# Login and logout
|
||||||
path(
|
path(
|
||||||
'login/',
|
"login/",
|
||||||
auth_views.LoginView.as_view(template_name='neluser/login.html'),
|
auth_views.LoginView.as_view(template_name="neluser/login.html"),
|
||||||
name='login'
|
name="login",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'logout/',
|
"logout/",
|
||||||
auth_views.LogoutView.as_view(next_page=reverse_lazy('index')),
|
auth_views.LogoutView.as_view(next_page=reverse_lazy("index")),
|
||||||
name='logout'
|
name="logout",
|
||||||
),
|
),
|
||||||
|
|
||||||
# Account activation
|
# Account activation
|
||||||
path('register/', views.register, name='register'),
|
path("register/", views.register, name="register"),
|
||||||
path('activate/<uidb64>/<token>/', views.activate, name='activate'),
|
path("activate/<uidb64>/<token>/", views.activate, name="activate"),
|
||||||
|
|
||||||
# Forgotten password
|
# Forgotten password
|
||||||
path(
|
path(
|
||||||
'forgotten_password/',
|
"forgotten_password/",
|
||||||
auth_views.PasswordResetView.as_view(
|
auth_views.PasswordResetView.as_view(
|
||||||
template_name='neluser/password_reset.html',
|
template_name="neluser/password_reset.html",
|
||||||
email_template_name='neluser/password_reset_email.txt',
|
email_template_name="neluser/password_reset_email.txt",
|
||||||
html_email_template_name='neluser/password_reset_email.html',
|
html_email_template_name="neluser/password_reset_email.html",
|
||||||
subject_template_name='neluser/password_reset_email_subject.txt'
|
subject_template_name="neluser/password_reset_email_subject.txt",
|
||||||
),
|
),
|
||||||
name='password_reset'
|
name="password_reset",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'forgotten_password/done/',
|
"forgotten_password/done/",
|
||||||
auth_views.PasswordResetDoneView.as_view(
|
auth_views.PasswordResetDoneView.as_view(
|
||||||
template_name='neluser/password_reset_email_sent.html'
|
template_name="neluser/password_reset_email_sent.html"
|
||||||
),
|
),
|
||||||
name='password_reset_done'
|
name="password_reset_done",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'password/reset/<uidb64>/<token>/',
|
"password/reset/<uidb64>/<token>/",
|
||||||
auth_views.PasswordResetConfirmView.as_view(
|
auth_views.PasswordResetConfirmView.as_view(
|
||||||
template_name='neluser/password_reset_confirm.html'
|
template_name="neluser/password_reset_confirm.html"
|
||||||
),
|
),
|
||||||
name='password_reset_confirm'
|
name="password_reset_confirm",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'password/reset/done/',
|
"password/reset/done/",
|
||||||
auth_views.PasswordResetCompleteView.as_view(
|
auth_views.PasswordResetCompleteView.as_view(
|
||||||
template_name='neluser/password_reset_done.html'
|
template_name="neluser/password_reset_done.html"
|
||||||
),
|
),
|
||||||
name='password_reset_complete'
|
name="password_reset_complete",
|
||||||
),
|
),
|
||||||
|
|
||||||
# --------
|
# --------
|
||||||
# Settings
|
# Settings
|
||||||
# --------
|
# --------
|
||||||
path('settings/', views.settings_default, name='settings'),
|
path("settings/", views.settings_default, name="settings"),
|
||||||
|
|
||||||
# Preferences
|
# Preferences
|
||||||
path('settings/preferences/nsfw/', views.set_nsfw, name='set_nsfw'),
|
path("settings/preferences/nsfw/", views.set_nsfw, name="set_nsfw"),
|
||||||
|
|
||||||
# Security
|
# Security
|
||||||
path(
|
path(
|
||||||
'settings/security/password/',
|
"settings/security/password/",
|
||||||
views.ChangePasswordView.as_view(),
|
views.ChangePasswordView.as_view(),
|
||||||
name='password_change'
|
name="password_change",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'settings/security/delete_account/',
|
"settings/security/delete_account/",
|
||||||
views.DeleteAccountView.as_view(),
|
views.DeleteAccountView.as_view(),
|
||||||
name='delete_account'
|
name="delete_account",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,39 +21,39 @@ from .models import NelUser
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def settings_default(request):
|
def settings_default(request):
|
||||||
next_page = reverse_lazy('set_nsfw')
|
next_page = reverse_lazy("set_nsfw")
|
||||||
return redirect(next_page)
|
return redirect(next_page)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def set_nsfw(request):
|
def set_nsfw(request):
|
||||||
ctx = {
|
ctx = {
|
||||||
'nsfw_allowed': is_nsfw_allowed(request),
|
"nsfw_allowed": is_nsfw_allowed(request),
|
||||||
'current_url': reverse_lazy('set_nsfw'),
|
"current_url": reverse_lazy("set_nsfw"),
|
||||||
'tab': 'preferences',
|
"tab": "preferences",
|
||||||
'active_block': 'nsfw_filter'
|
"active_block": "nsfw_filter",
|
||||||
}
|
}
|
||||||
return render(request, 'neluser/settings/preferences/nsfw.html', ctx)
|
return render(request, "neluser/settings/preferences/nsfw.html", ctx)
|
||||||
|
|
||||||
|
|
||||||
class ChangePasswordView(LoginRequiredMixin, FormView):
|
class ChangePasswordView(LoginRequiredMixin, FormView):
|
||||||
template_name = 'neluser/settings/security/password.html'
|
template_name = "neluser/settings/security/password.html"
|
||||||
form_class = ChangePasswordForm
|
form_class = ChangePasswordForm
|
||||||
success_url = reverse_lazy('password_change')
|
success_url = reverse_lazy("password_change")
|
||||||
|
|
||||||
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['tab'] = 'security'
|
context["tab"] = "security"
|
||||||
context['active_block'] = 'password'
|
context["active_block"] = "password"
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kw = super().get_form_kwargs()
|
kw = super().get_form_kwargs()
|
||||||
kw['request'] = self.request
|
kw["request"] = self.request
|
||||||
return kw
|
return kw
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
new_password = form.cleaned_data['new_password']
|
new_password = form.cleaned_data["new_password"]
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
user.set_password(new_password)
|
user.set_password(new_password)
|
||||||
user.save()
|
user.save()
|
||||||
|
@ -61,50 +61,49 @@ class ChangePasswordView(LoginRequiredMixin, FormView):
|
||||||
|
|
||||||
|
|
||||||
class DeleteAccountView(LoginRequiredMixin, FormView):
|
class DeleteAccountView(LoginRequiredMixin, FormView):
|
||||||
template_name = 'neluser/settings/security/delete_account.html'
|
template_name = "neluser/settings/security/delete_account.html"
|
||||||
form_class = DeleteAccountForm
|
form_class = DeleteAccountForm
|
||||||
success_url = reverse_lazy('delete_account')
|
success_url = reverse_lazy("delete_account")
|
||||||
|
|
||||||
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['tab'] = 'security'
|
context["tab"] = "security"
|
||||||
context['active_block'] = 'delete_account'
|
context["active_block"] = "delete_account"
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kw = super().get_form_kwargs()
|
kw = super().get_form_kwargs()
|
||||||
kw['request'] = self.request
|
kw["request"] = self.request
|
||||||
return kw
|
return kw
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
self.request.user.delete()
|
self.request.user.delete()
|
||||||
logout(self.request)
|
logout(self.request)
|
||||||
messages.info(self.request, _('Your account has been deleted.'))
|
messages.info(self.request, _("Your account has been deleted."))
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
def send_activation_email(request, user):
|
def send_activation_email(request, user):
|
||||||
current_site = get_current_site(request)
|
current_site = get_current_site(request)
|
||||||
context = {
|
context = {
|
||||||
'email': user.email,
|
"email": user.email,
|
||||||
'domain': current_site.domain,
|
"domain": current_site.domain,
|
||||||
'site_name': current_site.name,
|
"site_name": current_site.name,
|
||||||
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
|
"uid": urlsafe_base64_encode(force_bytes(user.pk)),
|
||||||
'user': user,
|
"user": user,
|
||||||
'token': default_token_generator.make_token(user),
|
"token": default_token_generator.make_token(user),
|
||||||
'protocol': 'https' if request.is_secure() else 'http',
|
"protocol": "https" if request.is_secure() else "http",
|
||||||
}
|
}
|
||||||
subject = render_to_string('neluser/activate_email_subject.txt', context)
|
subject = render_to_string("neluser/activate_email_subject.txt", context)
|
||||||
subject = ''.join(subject.splitlines())
|
subject = "".join(subject.splitlines())
|
||||||
email_message = EmailMultiAlternatives(
|
email_message = EmailMultiAlternatives(
|
||||||
subject,
|
subject,
|
||||||
render_to_string('neluser/activate_email.txt', context),
|
render_to_string("neluser/activate_email.txt", context),
|
||||||
settings.DEFAULT_FROM_EMAIL,
|
settings.DEFAULT_FROM_EMAIL,
|
||||||
[user.email]
|
[user.email],
|
||||||
)
|
)
|
||||||
email_message.attach_alternative(
|
email_message.attach_alternative(
|
||||||
render_to_string('neluser/activate_email.html', context),
|
render_to_string("neluser/activate_email.html", context), "text/html"
|
||||||
'text/html'
|
|
||||||
)
|
)
|
||||||
email_message.send()
|
email_message.send()
|
||||||
|
|
||||||
|
@ -115,24 +114,21 @@ def activate(request, uidb64, token):
|
||||||
if default_token_generator.check_token(user, token):
|
if default_token_generator.check_token(user, token):
|
||||||
user.is_active = True
|
user.is_active = True
|
||||||
user.save()
|
user.save()
|
||||||
return render(
|
return render(request, "neluser/activate_done.html")
|
||||||
request,
|
|
||||||
'neluser/activate_done.html'
|
|
||||||
)
|
|
||||||
raise Http404("Unable to activate user %d with token %s." % (uid, token))
|
raise Http404("Unable to activate user %d with token %s." % (uid, token))
|
||||||
|
|
||||||
|
|
||||||
def register(request):
|
def register(request):
|
||||||
if request.method == 'GET':
|
if request.method == "GET":
|
||||||
form = RegistrationForm()
|
form = RegistrationForm()
|
||||||
elif request.method == 'POST':
|
elif request.method == "POST":
|
||||||
form = RegistrationForm(data=request.POST)
|
form = RegistrationForm(data=request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
user = form.save(commit=False)
|
user = form.save(commit=False)
|
||||||
user.set_password(form.cleaned_data.get('password1'))
|
user.set_password(form.cleaned_data.get("password1"))
|
||||||
user.is_active = not settings.REGISTER_REQUIRE_VALIDATION
|
user.is_active = not settings.REGISTER_REQUIRE_VALIDATION
|
||||||
user.save()
|
user.save()
|
||||||
if settings.REGISTER_REQUIRE_VALIDATION:
|
if settings.REGISTER_REQUIRE_VALIDATION:
|
||||||
send_activation_email(request, user)
|
send_activation_email(request, user)
|
||||||
return render(request, 'neluser/register_done.html')
|
return render(request, "neluser/register_done.html")
|
||||||
return render(request, 'neluser/register.html', {'form': form})
|
return render(request, "neluser/register.html", {"form": form})
|
||||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class NsfwConfig(AppConfig):
|
class NsfwConfig(AppConfig):
|
||||||
name = 'nsfw'
|
name = "nsfw"
|
||||||
|
|
|
@ -4,7 +4,7 @@ from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', views.warn_view, name='nsfw'),
|
path("", views.warn_view, name="nsfw"),
|
||||||
path('enable/<max_age>/', views.enable_view, name='enable_nsfw'),
|
path("enable/<max_age>/", views.enable_view, name="enable_nsfw"),
|
||||||
path('disable/', views.disable_view, name='disable_nsfw'),
|
path("disable/", views.disable_view, name="disable_nsfw"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,7 +13,7 @@ def is_nsfw_allowed(request):
|
||||||
if isinstance(request.user, NelUser):
|
if isinstance(request.user, NelUser):
|
||||||
if request.user.nsfw_allowed:
|
if request.user.nsfw_allowed:
|
||||||
return True
|
return True
|
||||||
s = request.COOKIES.get(settings.KHAGANAT_NSFW_NAME) or ''
|
s = request.COOKIES.get(settings.KHAGANAT_NSFW_NAME) or ""
|
||||||
return s.lower() in settings.KHAGANAT_NSFW_OK
|
return s.lower() in settings.KHAGANAT_NSFW_OK
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ def disable_view(request):
|
||||||
if isinstance(request.user, NelUser):
|
if isinstance(request.user, NelUser):
|
||||||
request.user.nsfw_allowed = False
|
request.user.nsfw_allowed = False
|
||||||
request.user.save()
|
request.user.save()
|
||||||
next_url = QueryDict(request.META.get('QUERY_STRING')).get('next')
|
next_url = QueryDict(request.META.get("QUERY_STRING")).get("next")
|
||||||
if not is_link_legit(next_url):
|
if not is_link_legit(next_url):
|
||||||
next_url = reverse('index')
|
next_url = reverse("index")
|
||||||
response = HttpResponseRedirect(next_url)
|
response = HttpResponseRedirect(next_url)
|
||||||
response.delete_cookie(settings.KHAGANAT_NSFW_NAME)
|
response.delete_cookie(settings.KHAGANAT_NSFW_NAME)
|
||||||
return response
|
return response
|
||||||
|
@ -34,64 +34,55 @@ def enable_view(request, max_age):
|
||||||
max_age = int(max_age) or None
|
max_age = int(max_age) or None
|
||||||
except ValueError:
|
except ValueError:
|
||||||
max_age = None
|
max_age = None
|
||||||
next_url = QueryDict(request.META.get('QUERY_STRING')).get('next')
|
next_url = QueryDict(request.META.get("QUERY_STRING")).get("next")
|
||||||
if not is_link_legit(next_url):
|
if not is_link_legit(next_url):
|
||||||
next_url = reverse('index')
|
next_url = reverse("index")
|
||||||
response = HttpResponseRedirect(next_url)
|
response = HttpResponseRedirect(next_url)
|
||||||
if isinstance(request.user, NelUser) and not max_age:
|
if isinstance(request.user, NelUser) and not max_age:
|
||||||
request.user.nsfw_allowed = True
|
request.user.nsfw_allowed = True
|
||||||
request.user.save()
|
request.user.save()
|
||||||
else:
|
else:
|
||||||
response.set_cookie(
|
response.set_cookie(
|
||||||
settings.KHAGANAT_NSFW_NAME,
|
settings.KHAGANAT_NSFW_NAME, settings.KHAGANAT_NSFW_OK[0], max_age=max_age
|
||||||
settings.KHAGANAT_NSFW_OK[0],
|
|
||||||
max_age=max_age
|
|
||||||
)
|
)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
def warn_view(request):
|
def warn_view(request):
|
||||||
next_url = QueryDict(request.META.get('QUERY_STRING')).get('next') or '/'
|
next_url = QueryDict(request.META.get("QUERY_STRING")).get("next") or "/"
|
||||||
if not is_link_legit(next_url):
|
if not is_link_legit(next_url):
|
||||||
next_url = '/'
|
next_url = "/"
|
||||||
prev_url = QueryDict(request.META.get('QUERY_STRING')).get('prev')
|
prev_url = QueryDict(request.META.get("QUERY_STRING")).get("prev")
|
||||||
if not is_link_legit(prev_url):
|
if not is_link_legit(prev_url):
|
||||||
prev_url = None
|
prev_url = None
|
||||||
context = {
|
context = {
|
||||||
'prev_url': prev_url,
|
"prev_url": prev_url,
|
||||||
'go_home': True,
|
"go_home": True,
|
||||||
'next_url': next_url,
|
"next_url": next_url,
|
||||||
'is_authenticated': request.user.is_authenticated,
|
"is_authenticated": request.user.is_authenticated,
|
||||||
}
|
}
|
||||||
return render(request, 'nsfw/redirect_page.html', context=context)
|
return render(request, "nsfw/redirect_page.html", context=context)
|
||||||
|
|
||||||
|
|
||||||
def warn_msg(request, next_url=None):
|
def warn_msg(request, next_url=None):
|
||||||
context = {
|
context = {
|
||||||
'prev_url': None,
|
"prev_url": None,
|
||||||
'go_home': False,
|
"go_home": False,
|
||||||
'next_url': next_url,
|
"next_url": next_url,
|
||||||
'is_authenticated': request.user.is_authenticated,
|
"is_authenticated": request.user.is_authenticated,
|
||||||
}
|
}
|
||||||
ret = render_to_string(
|
ret = render_to_string(request, "nsfw/redirect_page.html", context=context)
|
||||||
request,
|
|
||||||
'nsfw/redirect_page.html',
|
|
||||||
context=context
|
|
||||||
)
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def redirect(request):
|
def redirect(request):
|
||||||
dest = '{to_url}?next={next_url}'.format(
|
dest = "{to_url}?next={next_url}".format(
|
||||||
to_url=reverse(warn_view),
|
to_url=reverse(warn_view), next_url=request.get_full_path()
|
||||||
next_url=request.get_full_path()
|
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(dest)
|
return HttpResponseRedirect(dest)
|
||||||
|
|
||||||
|
|
||||||
def alert(request, next_url=None):
|
def alert(request, next_url=None):
|
||||||
context = {
|
context = {"next_url": next_url}
|
||||||
'next_url': next_url,
|
msg = render_to_string("nsfw/disabled_alert.html", context=context)
|
||||||
}
|
messages.info(request, msg, extra_tags="safe")
|
||||||
msg = render_to_string('nsfw/disabled_alert.html', context=context)
|
|
||||||
messages.info(request, msg, extra_tags='safe')
|
|
||||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class PagesConfig(AppConfig):
|
class PagesConfig(AppConfig):
|
||||||
name = 'pages'
|
name = "pages"
|
||||||
|
|
|
@ -24,14 +24,14 @@ class PageContent(models.Model):
|
||||||
return markdown.markdown(
|
return markdown.markdown(
|
||||||
self.content,
|
self.content,
|
||||||
extensions=[
|
extensions=[
|
||||||
'markdown.extensions.extra',
|
"markdown.extensions.extra",
|
||||||
'markdown.extensions.admonition',
|
"markdown.extensions.admonition",
|
||||||
'markdown.extensions.nl2br',
|
"markdown.extensions.nl2br",
|
||||||
'markdown.extensions.sane_lists',
|
"markdown.extensions.sane_lists",
|
||||||
'markdown.extensions.smarty',
|
"markdown.extensions.smarty",
|
||||||
'markdown.extensions.toc',
|
"markdown.extensions.toc",
|
||||||
],
|
],
|
||||||
output_format='html5',
|
output_format="html5",
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
@ -7,9 +7,6 @@ register = template.Library()
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def get_page(context, slug):
|
def get_page(context, slug):
|
||||||
request = context['request']
|
request = context["request"]
|
||||||
obj = PageContent.objects.filter(
|
obj = PageContent.objects.filter(language=get_language(), page__slug=slug).first
|
||||||
language=get_language(),
|
|
||||||
page__slug=slug
|
|
||||||
).first
|
|
||||||
return obj
|
return obj
|
||||||
|
|
|
@ -3,6 +3,6 @@ from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('<slug:slug>/', views.PageView.as_view(), name='page'),
|
path("<slug:slug>/", views.PageView.as_view(), name="page"),
|
||||||
path('', views.index, name='index'),
|
path("", views.index, name="index"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -8,13 +8,13 @@ from .models import Page, PageContent
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
default_page = Page.objects.filter(default=True).first()
|
default_page = Page.objects.filter(default=True).first()
|
||||||
return HttpResponseRedirect(reverse('page', args=(default_page.slug, )))
|
return HttpResponseRedirect(reverse("page", args=(default_page.slug,)))
|
||||||
|
|
||||||
|
|
||||||
class PageView(generic.DetailView):
|
class PageView(generic.DetailView):
|
||||||
model = PageContent
|
model = PageContent
|
||||||
context_object_name = 'page'
|
context_object_name = "page"
|
||||||
template_name = 'pages/page.html'
|
template_name = "pages/page.html"
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
if self.get_object().page.is_nsfw:
|
if self.get_object().page.is_nsfw:
|
||||||
|
@ -26,9 +26,8 @@ class PageView(generic.DetailView):
|
||||||
|
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
obj = PageContent.objects.filter(
|
obj = PageContent.objects.filter(
|
||||||
language=get_language(),
|
language=get_language(), page__slug=self.kwargs["slug"]
|
||||||
page__slug=self.kwargs['slug']
|
|
||||||
).first()
|
).first()
|
||||||
if obj is None:
|
if obj is None:
|
||||||
raise Http404('Page not found: %s' % self.kwargs['slug'])
|
raise Http404("Page not found: %s" % self.kwargs["slug"])
|
||||||
return obj
|
return obj
|
||||||
|
|
|
@ -2,4 +2,4 @@ from django.contrib.staticfiles.apps import StaticFilesConfig
|
||||||
|
|
||||||
|
|
||||||
class KhaganatStaticFilesConfig(StaticFilesConfig):
|
class KhaganatStaticFilesConfig(StaticFilesConfig):
|
||||||
ignore_patterns = ['CVS', '.*', '*~', 'sass']
|
ignore_patterns = ["CVS", ".*", "*~", "sass"]
|
||||||
|
|
Loading…
Reference in a new issue