1
0
Fork 0

Merge branch 'main' into partially-read-shelf

This commit is contained in:
Thomas Versteeg 2022-02-25 21:00:29 +00:00 committed by GitHub
commit e9dfa42e11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
209 changed files with 14317 additions and 4796 deletions

View file

@ -2,6 +2,7 @@
# site admin
from .admin.announcements import Announcements, Announcement
from .admin.announcements import EditAnnouncement, delete_announcement
from .admin.automod import AutoMod, automod_delete, run_automod
from .admin.dashboard import Dashboard
from .admin.federation import Federation, FederatedServer
from .admin.federation import AddFederatedServer, ImportServerBlocklist
@ -113,6 +114,7 @@ from .reading import ReadingStatus
from .report import Report
from .rss_feed import RssFeed
from .search import Search
from .setup import InstanceConfig, CreateAdmin
from .status import CreateStatus, EditStatus, DeleteStatus, update_progress
from .status import edit_readthrough
from .updates import get_notification_count, get_unread_status_string

View file

@ -0,0 +1,64 @@
""" moderation via flagged posts and users """
from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.http import require_POST
from bookwyrm import forms, models
@method_decorator(login_required, name="dispatch")
@method_decorator(
permission_required("bookwyrm.moderate_user", raise_exception=True),
name="dispatch",
)
@method_decorator(
permission_required("bookwyrm.moderate_post", raise_exception=True),
name="dispatch",
)
# pylint: disable=no-self-use
class AutoMod(View):
"""Manage automated flagging"""
def get(self, request):
"""view rules"""
data = {"rules": models.AutoMod.objects.all(), "form": forms.AutoModRuleForm()}
return TemplateResponse(request, "settings/automod/rules.html", data)
def post(self, request):
"""add rule"""
form = forms.AutoModRuleForm(request.POST)
success = form.is_valid()
if success:
form.save()
form = forms.AutoModRuleForm()
data = {
"rules": models.AutoMod.objects.all(),
"form": form,
"success": success,
}
return TemplateResponse(request, "settings/automod/rules.html", data)
@require_POST
@permission_required("bookwyrm.moderate_user", raise_exception=True)
@permission_required("bookwyrm.moderate_post", raise_exception=True)
# pylint: disable=unused-argument
def automod_delete(request, rule_id):
"""Remove a rule"""
rule = get_object_or_404(models.AutoMod, id=rule_id)
rule.delete()
return redirect("settings-automod")
@require_POST
@permission_required("bookwyrm.moderate_user", raise_exception=True)
@permission_required("bookwyrm.moderate_post", raise_exception=True)
# pylint: disable=unused-argument
def run_automod(request):
"""run scan"""
models.automod_task.delay()
return redirect("settings-automod")

View file

@ -1,6 +1,7 @@
""" instance overview """
from datetime import timedelta
from dateutil.parser import parse
from packaging import version
from django.contrib.auth.decorators import login_required, permission_required
from django.db.models import Q
@ -9,7 +10,9 @@ from django.utils import timezone
from django.utils.decorators import method_decorator
from django.views import View
from bookwyrm import models
from bookwyrm import models, settings
from bookwyrm.connectors.abstract_connector import get_data
from bookwyrm.connectors.connector_manager import ConnectorException
# pylint: disable= no-self-use
@ -107,6 +110,19 @@ class Dashboard(View):
"register_stats": register_chart.get_chart(start, end, interval),
"works_stats": works_chart.get_chart(start, end, interval),
}
# check version
try:
release = get_data(settings.RELEASE_API, timeout=3)
available_version = release.get("tag_name", None)
if available_version and version.parse(available_version) > version.parse(
settings.VERSION
):
data["current_version"] = settings.VERSION
data["available_version"] = available_version
except ConnectorException:
pass
return TemplateResponse(request, "settings/dashboard/dashboard.html", data)

View file

@ -1,6 +1,5 @@
""" manage site settings """
from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
from django.views import View
@ -32,7 +31,8 @@ class Site(View):
return TemplateResponse(request, "settings/site.html", data)
form.save()
return redirect("settings-site")
data = {"site_form": forms.SiteForm(instance=site), "success": True}
return TemplateResponse(request, "settings/site.html", data)
@login_required

View file

@ -1,7 +1,7 @@
""" the good people stuff! the authors! """
from django.contrib.auth.decorators import login_required, permission_required
from django.core.paginator import Paginator
from django.db.models import Q
from django.db.models import Avg, Q
from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
@ -28,7 +28,8 @@ class Author(View):
books = (
models.Work.objects.filter(Q(authors=author) | Q(editions__authors=author))
.order_by("-published_date")
.annotate(Avg("editions__review__rating"))
.order_by("editions__review__rating__avg")
.distinct()
)

View file

@ -1,8 +1,9 @@
""" non-interactive pages """
from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.views import View
from bookwyrm import forms
from bookwyrm import forms, models
from bookwyrm.views.feed import Feed
@ -15,6 +16,11 @@ class Home(View):
if request.user.is_authenticated:
feed_view = Feed.as_view()
return feed_view(request, "home")
site = models.SiteSettings.objects.get()
if site.install_mode:
return redirect("setup")
landing_view = Landing.as_view()
return landing_view(request)

View file

@ -25,6 +25,10 @@ class Register(View):
def post(self, request):
"""join the server"""
settings = models.SiteSettings.get()
# no registration allowed when the site is being installed
if settings.install_mode:
raise PermissionDenied()
if not settings.allow_registration:
invite_code = request.POST.get("invite_code")
@ -38,9 +42,16 @@ class Register(View):
invite = None
form = forms.RegisterForm(request.POST)
errors = False
if not form.is_valid():
errors = True
data = {
"login_form": forms.LoginForm(),
"register_form": form,
"invite": invite,
"valid": invite.valid() if invite else True,
}
if invite:
return TemplateResponse(request, "landing/invite.html", data)
return TemplateResponse(request, "landing/login.html", data)
localname = form.data["localname"].strip()
email = form.data["email"]
@ -52,22 +63,6 @@ class Register(View):
# treat this like a successful registration, but don't do anything
return redirect("confirm-email")
# check localname and email uniqueness
if models.User.objects.filter(localname=localname).first():
form.errors["localname"] = ["User with this username already exists"]
errors = True
if errors:
data = {
"login_form": forms.LoginForm(),
"register_form": form,
"invite": invite,
"valid": invite.valid() if invite else True,
}
if invite:
return TemplateResponse(request, "landing/invite.html", data)
return TemplateResponse(request, "landing/login.html", data)
username = f"{localname}@{DOMAIN}"
user = models.User.objects.create_user(
username,

99
bookwyrm/views/setup.py Normal file
View file

@ -0,0 +1,99 @@
""" Installation wizard 🧙 """
import re
from django.contrib.auth import login
from django.contrib.auth.models import Group
from django.core.exceptions import PermissionDenied
from django.db import transaction
from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.views import View
from bookwyrm import forms, models
from bookwyrm import settings
from bookwyrm.utils import regex
# pylint: disable= no-self-use
class InstanceConfig(View):
"""make sure the instance looks correct before adding any data"""
def get(self, request):
"""Check out this cool instance"""
# only allow this view when an instance is being configured
site = models.SiteSettings.objects.get()
if not site.install_mode:
raise PermissionDenied()
# check for possible problems with the instance configuration
warnings = {}
warnings["debug"] = settings.DEBUG
warnings["invalid_domain"] = not re.match(rf"^{regex.DOMAIN}$", settings.DOMAIN)
warnings["protocol"] = not settings.DEBUG and not settings.USE_HTTPS
# pylint: disable=line-too-long
data = {
"warnings": warnings,
"info": {
"domain": settings.DOMAIN,
"version": settings.VERSION,
"use_https": settings.USE_HTTPS,
"language": settings.LANGUAGE_CODE,
"use_s3": settings.USE_S3,
"email_sender": f"{settings.EMAIL_SENDER_NAME}@{settings.EMAIL_SENDER_DOMAIN}",
"preview_images": settings.ENABLE_PREVIEW_IMAGES,
"thumbnails": settings.ENABLE_THUMBNAIL_GENERATION,
},
}
return TemplateResponse(request, "setup/config.html", data)
class CreateAdmin(View):
"""manage things like the instance name"""
def get(self, request):
"""Create admin user form"""
# only allow this view when an instance is being configured
site = models.SiteSettings.objects.get()
if not site.install_mode:
raise PermissionDenied()
data = {"register_form": forms.RegisterForm()}
return TemplateResponse(request, "setup/admin.html", data)
@transaction.atomic
def post(self, request):
"""Create that user"""
site = models.SiteSettings.objects.get()
# you can't create an admin user if you're in config mode
if not site.install_mode:
raise PermissionDenied()
form = forms.RegisterForm(request.POST)
if not form.is_valid():
data = {"register_form": form}
return TemplateResponse(request, "setup/admin.html", data)
localname = form.data["localname"].strip()
username = f"{localname}@{settings.DOMAIN}"
user = models.User.objects.create_superuser(
username,
form.data["email"],
form.data["password"],
localname=localname,
local=True,
deactivation_reason=None,
is_active=True,
)
# Set "admin" role
try:
user.groups.set(Group.objects.filter(name__in=["admin", "moderator"]))
except Group.DoesNotExist:
# this should only happen in tests
pass
login(request, user)
site.install_mode = False
site.save()
return redirect("settings-site")