Added admin settings page. Improve dynamic_preferences integration.

This commit is contained in:
2018-12-29 17:11:20 +02:00
parent 33ee71dcbb
commit 8eca3dc7a9
20 changed files with 233 additions and 82 deletions

View File

@ -2,10 +2,12 @@ from django.contrib.auth import login, authenticate
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User
from django.contrib.auth.views import LoginView
from django.http import HttpResponseForbidden
from django.urls import reverse_lazy
from django.views.generic import FormView, TemplateView
from .forms.auth import ExtendedAuthenticationForm, ExtendedUserCreationForm
from YtManagerApp.management.appconfig import appconfig
from YtManagerApp.views.forms.auth import ExtendedAuthenticationForm, ExtendedUserCreationForm
class ExtendedLoginView(LoginView):
@ -33,6 +35,12 @@ class RegisterView(FormView):
context['is_first_user'] = (User.objects.count() == 0)
return context
def post(self, request, *args, **kwargs):
if not appconfig.allow_registrations:
return HttpResponseForbidden("Registrations are disabled!")
return super().post(request, *args, **kwargs)
class RegisterDoneView(LoginRequiredMixin, TemplateView):
template_name = 'registration/register_done.html'

View File

@ -7,7 +7,7 @@ from django.shortcuts import redirect
from django.urls import reverse_lazy
from django.views.generic import FormView
from YtManagerApp.management.appconfig import global_prefs
from YtManagerApp.management.appconfig import appconfig
from YtManagerApp.views.forms.auth import ExtendedAuthenticationForm
from YtManagerApp.views.forms.first_time import WelcomeForm, ApiKeyForm, PickAdminUserForm, ServerConfigForm, DoneForm, UserCreationForm
@ -18,7 +18,7 @@ class WizardStepMixin(object):
def get(self, request, *args, **kwargs):
# Prevent access if application is already initialized
if global_prefs['hidden__initialized']:
if appconfig.initialized:
logger.debug(f"Attempted to access {request.path}, but first time setup already run. Redirected to home "
f"page.")
return redirect('home')
@ -26,7 +26,7 @@ class WizardStepMixin(object):
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
if global_prefs['hidden__initialized']:
if appconfig.initialized:
logger.debug(f"Attempted to post {request.path}, but first time setup already run.")
return HttpResponseForbidden()
return super().post(request, *args, **kwargs)
@ -51,14 +51,14 @@ class Step1ApiKeyView(WizardStepMixin, FormView):
def get_initial(self):
initial = super().get_initial()
initial['api_key'] = global_prefs['general__youtube_api_key']
initial['api_key'] = appconfig.youtube_api_key
return initial
def form_valid(self, form):
key = form.cleaned_data['api_key']
# TODO: validate key
if key is not None and len(key) > 0:
global_prefs['general__youtube_api_key'] = key
appconfig.youtube_api_key = key
#
@ -100,9 +100,6 @@ class Step2SetupAdminUserView(WizardStepMixin, FormView):
return super().get(request, *args, **kwargs)
def form_invalid(self, form):
print("FORM INVALID!")
def form_valid(self, form):
if isinstance(form, ExtendedAuthenticationForm):
login(self.request, form.get_user())
@ -139,8 +136,8 @@ class Step3ConfigureView(WizardStepMixin, FormView):
def get_initial(self):
initial = super().get_initial()
initial['allow_registrations'] = global_prefs['general__allow_registrations']
initial['sync_schedule'] = global_prefs['scheduler__synchronization_schedule']
initial['allow_registrations'] = appconfig.allow_registrations
initial['sync_schedule'] = appconfig.sync_schedule
initial['auto_download'] = self.request.user.preferences['downloader__auto_enabled']
initial['download_location'] = self.request.user.preferences['downloader__download_path']
return initial
@ -148,11 +145,11 @@ class Step3ConfigureView(WizardStepMixin, FormView):
def form_valid(self, form):
allow_registrations = form.cleaned_data['allow_registrations']
if allow_registrations is not None:
global_prefs['general__allow_registrations'] = allow_registrations
appconfig.allow_registrations = allow_registrations
sync_schedule = form.cleaned_data['sync_schedule']
if sync_schedule is not None and len(sync_schedule) > 0:
global_prefs['scheduler__synchronization_schedule'] = sync_schedule
appconfig.sync_schedule = sync_schedule
auto_download = form.cleaned_data['auto_download']
if auto_download is not None:
@ -163,7 +160,7 @@ class Step3ConfigureView(WizardStepMixin, FormView):
self.request.user.preferences['downloader__download_path'] = download_location
# Set initialized to true
global_prefs['hidden__initialized'] = True
appconfig.initialized = True
return super().form_valid(form)

View File

@ -3,11 +3,10 @@ import logging
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, HTML, Submit, Column
from django import forms
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from YtManagerApp.views.forms.auth import ExtendedUserCreationForm
from django.urls import reverse_lazy
from YtManagerApp.management.appconfig import global_prefs
from YtManagerApp.views.forms.auth import ExtendedUserCreationForm
logger = logging.getLogger("FirstTimeWizard")

View File

@ -0,0 +1,80 @@
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, HTML, Submit
from django import forms
from YtManagerApp.models import UserSettings
class SettingsForm(forms.ModelForm):
class Meta:
model = UserSettings
exclude = ['user']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-lg-3'
self.helper.field_class = 'col-lg-9'
self.helper.layout = Layout(
'mark_deleted_as_watched',
'delete_watched',
HTML('<h2>Download settings</h2>'),
'auto_download',
'download_path',
'download_file_pattern',
'download_format',
'download_order',
'download_global_limit',
'download_subscription_limit',
HTML('<h2>Subtitles download settings</h2>'),
'download_subtitles',
'download_subtitles_langs',
'download_subtitles_all',
'download_autogenerated_subtitles',
'download_subtitles_format',
Submit('submit', value='Save')
)
class AdminSettingsForm(forms.Form):
api_key = forms.CharField(label="YouTube API key")
allow_registrations = forms.BooleanField(
label="Allow user registrations",
help_text="Disabling this option will prevent anyone from registering to the site.",
initial=True,
required=False
)
sync_schedule = forms.CharField(
label="Synchronization schedule",
help_text="How often should the application look for new videos.",
initial="5 * * * *",
required=True
)
scheduler_concurrency = forms.IntegerField(
label="Synchronization concurrency",
help_text="How many jobs are executed executed in parallel. Since most jobs are I/O bound (mostly use the hard "
"drive and network), there is no significant advantage to increase it.",
initial=2,
required=True
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-lg-3'
self.helper.field_class = 'col-lg-9'
self.helper.layout = Layout(
HTML('<h2>General settings</h2>'),
'api_key',
'allow_registrations',
HTML('<h2>Scheduler settings</h2>'),
'sync_schedule',
'scheduler_concurrency',
Submit('submit', value='Save')
)

View File

@ -10,7 +10,7 @@ from django.views.generic import CreateView, UpdateView, DeleteView, FormView
from django.views.generic.edit import FormMixin
from django.conf import settings
from YtManagerApp.management.videos import get_videos
from YtManagerApp.management.appconfig import global_prefs
from YtManagerApp.management.appconfig import appconfig
from YtManagerApp.models import Subscription, SubscriptionFolder, VIDEO_ORDER_CHOICES, VIDEO_ORDER_MAPPING
from YtManagerApp.utils import youtube, subscription_file_parser
from YtManagerApp.views.controls.modal import ModalMixin
@ -96,7 +96,7 @@ def __tree_sub_id(sub_id):
def index(request: HttpRequest):
if not global_prefs['hidden__initialized']:
if not appconfig.initialized:
return redirect('first_time_0')
context = {

View File

@ -1,43 +1,11 @@
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, HTML, Submit
from django import forms
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseForbidden
from django.urls import reverse_lazy
from django.views.generic import UpdateView
from django.views.generic import UpdateView, FormView
from YtManagerApp.management.appconfig import appconfig
from YtManagerApp.models import UserSettings
class SettingsForm(forms.ModelForm):
class Meta:
model = UserSettings
exclude = ['user']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-lg-3'
self.helper.field_class = 'col-lg-9'
self.helper.layout = Layout(
'mark_deleted_as_watched',
'delete_watched',
HTML('<h2>Download settings</h2>'),
'auto_download',
'download_path',
'download_file_pattern',
'download_format',
'download_order',
'download_global_limit',
'download_subscription_limit',
HTML('<h2>Subtitles download settings</h2>'),
'download_subtitles',
'download_subtitles_langs',
'download_subtitles_all',
'download_autogenerated_subtitles',
'download_subtitles_format',
Submit('submit', value='Save')
)
from YtManagerApp.views.forms.settings import SettingsForm, AdminSettingsForm
class SettingsView(LoginRequiredMixin, UpdateView):
@ -49,3 +17,53 @@ class SettingsView(LoginRequiredMixin, UpdateView):
def get_object(self, queryset=None):
obj, _ = self.model.objects.get_or_create(user=self.request.user)
return obj
class AdminSettingsView(LoginRequiredMixin, FormView):
form_class = AdminSettingsForm
template_name = 'YtManagerApp/settings_admin.html'
success_url = reverse_lazy('home')
def get(self, request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.is_superuser:
return HttpResponseForbidden()
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.is_superuser:
return HttpResponseForbidden()
return super().post(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# TODO: present stats
return context
def get_initial(self):
initial = super().get_initial()
initial['api_key'] = appconfig.youtube_api_key
initial['allow_registrations'] = appconfig.allow_registrations
initial['sync_schedule'] = appconfig.sync_schedule
initial['scheduler_concurrency'] = appconfig.concurrency
return initial
def form_valid(self, form):
api_key = form.cleaned_data['api_key']
if api_key is not None and len(api_key) > 0:
appconfig.youtube_api_key = api_key
allow_registrations = form.cleaned_data['allow_registrations']
if allow_registrations is not None:
appconfig.allow_registrations = allow_registrations
sync_schedule = form.cleaned_data['sync_schedule']
if sync_schedule is not None and len(sync_schedule) > 0:
appconfig.sync_schedule = sync_schedule
concurrency = form.cleaned_data['scheduler_concurrency']
if concurrency is not None:
appconfig.concurrency = concurrency
return super().form_valid(form)