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