First time setup improvements

This commit is contained in:
Tiberiu Chibici 2018-12-21 12:28:06 +02:00
parent 899de7adf5
commit 022d3aa4f5
9 changed files with 77 additions and 24 deletions

View File

@ -1,6 +1,7 @@
import logging import logging
import logging.handlers import logging.handlers
import os import os
import sys
from django.conf import settings as dj_settings from django.conf import settings as dj_settings
@ -9,20 +10,29 @@ from .management.jobs.synchronize import schedule_synchronize_global
from .scheduler import initialize_scheduler from .scheduler import initialize_scheduler
from django.db.utils import OperationalError from django.db.utils import OperationalError
def __initialize_logger(): def __initialize_logger():
log_dir = os.path.join(dj_settings.DATA_DIR, 'logs') log_dir = os.path.join(dj_settings.DATA_DIR, 'logs')
os.makedirs(log_dir, exist_ok=True) os.makedirs(log_dir, exist_ok=True)
handlers = []
file_handler = logging.handlers.RotatingFileHandler( file_handler = logging.handlers.RotatingFileHandler(
os.path.join(log_dir, "log.log"), os.path.join(log_dir, "log.log"),
maxBytes=1024 * 1024, maxBytes=1024 * 1024,
backupCount=5 backupCount=5
) )
handlers.append(file_handler)
if dj_settings.DEBUG:
console_handler = logging.StreamHandler(stream=sys.stdout)
console_handler.setLevel(logging.DEBUG)
handlers.append(console_handler)
logging.basicConfig( logging.basicConfig(
level=dj_settings.LOG_LEVEL, level=dj_settings.LOG_LEVEL,
format=dj_settings.LOG_FORMAT, format=dj_settings.LOG_FORMAT,
handlers=[file_handler] handlers=handlers
) )

View File

@ -1,5 +1,6 @@
#main_body { #main_body {
margin-bottom: 4rem; } margin-bottom: 4rem;
margin-top: 2rem; }
#main_footer { #main_footer {
position: fixed; position: fixed;

View File

@ -1,6 +1,6 @@
{ {
"version": 3, "version": 3,
"mappings": "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", "mappings": "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",
"sources": ["style.scss"], "sources": ["style.scss"],
"names": [], "names": [],
"file": "style.css" "file": "style.css"

View File

@ -2,6 +2,7 @@ $accent-color: #007bff;
#main_body { #main_body {
margin-bottom: 4rem; margin-bottom: 4rem;
margin-top: 2rem;
} }
#main_footer { #main_footer {

View File

@ -8,10 +8,10 @@
<h1>Step 1: Set up YouTube API key (optional)</h1> <h1>Step 1: Set up YouTube API key (optional)</h1>
<p>This program uses the YouTube API in order to obtain information about videos, channels and playlists. <p>This program uses the YouTube API in order to obtain information about videos, channels and playlists.
In order to access this API, YouTube requires that we register on their site and request an API key. YouTube To access this API, YouTube requires users to register on their site and request an API key. YouTube
uses this key in order to limit the number of requests made to their platform, in order to prevent abuses.</p> uses this key to control access and limit the number of requests made to their platform, in order to prevent abuses.</p>
<p>To use this program, it is <em>recommended</em> that you create an API key for your own account. While a key <p>To use this program, it is <em>recommended</em>, but not required, that you create an API key for your own account. While a key
is already provided the developer, there is a chance that the quota limits will be reached, which will prevent is already provided the developer, there is a chance that the quota limits will be reached, which will prevent
this program from reaching YouTube. Follow the steps below, or press <strong>Skip</strong> to use the provided key.</p> this program from reaching YouTube. Follow the steps below, or press <strong>Skip</strong> to use the provided key.</p>
@ -59,8 +59,6 @@
{% crispy form %} {% crispy form %}
<a href="{% url 'first_time_2' %}">Skip</a>
</div> </div>
{% endblock body %} {% endblock body %}

View File

@ -24,12 +24,6 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if is_first_user %}
<div class="alert alert-info" role="alert">
Since this is the first user to register, it will be the system administrator.
</div>
{% endif %}
<h5>Register</h5> <h5>Register</h5>
{% crispy form %} {% crispy form %}

View File

@ -64,6 +64,7 @@ urlpatterns = [
path('first_time/step0_welcome', first_time.Step0WelcomeView.as_view(), name='first_time_0'), path('first_time/step0_welcome', first_time.Step0WelcomeView.as_view(), name='first_time_0'),
path('first_time/step1_apikey', first_time.Step1ApiKeyView.as_view(), name='first_time_1'), path('first_time/step1_apikey', first_time.Step1ApiKeyView.as_view(), name='first_time_1'),
path('first_time/step2_admin', first_time.Step2CreateAdminUserView.as_view(), name='first_time_2'), path('first_time/step2_admin', first_time.Step2CreateAdminUserView.as_view(), name='first_time_2'),
path('first_time/step2_login', first_time.Step2LoginAdminUserView.as_view(), name='first_time_2_login'),
path('first_time/step3_config', first_time.Step3ConfigureView.as_view(), name='first_time_3'), path('first_time/step3_config', first_time.Step3ConfigureView.as_view(), name='first_time_3'),
path('first_time/done', first_time.DoneView.as_view(), name='first_time_done'), path('first_time/done', first_time.DoneView.as_view(), name='first_time_done'),

View File

@ -58,13 +58,8 @@ class RegisterView(FormView):
success_url = reverse_lazy('register_done') success_url = reverse_lazy('register_done')
def form_valid(self, form): def form_valid(self, form):
is_first_user = (User.objects.count() == 0)
user = form.save() form.save()
if is_first_user:
user.is_staff = True
user.is_superuser = True
user.save()
username = form.cleaned_data.get('username') username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password1') password = form.cleaned_data.get('password1')

View File

@ -1,26 +1,35 @@
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, HTML, Submit from crispy_forms.layout import Layout, HTML, Submit, Column
from django import forms from django import forms
from django.contrib.auth import authenticate, login
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.views.generic import UpdateView, FormView from django.views.generic import UpdateView, FormView
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from YtManagerApp.views.auth import RegisterView from YtManagerApp.views.auth import RegisterView, ExtendedUserCreationForm, ExtendedAuthenticationForm
from YtManagerApp.models import UserSettings from YtManagerApp.models import UserSettings
from YtManagerApp.management.appconfig import global_prefs from YtManagerApp.management.appconfig import global_prefs
from django.http import HttpResponseForbidden from django.http import HttpResponseForbidden
import logging
logger = logging.getLogger("FirstTimeWizard")
class ProtectInitializedMixin(object): class ProtectInitializedMixin(object):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
if global_prefs['hidden__initialized']: if global_prefs['hidden__initialized']:
logger.debug(f"Attempted to access {request.path}, but first time setup already run. Redirected to home page.")
return redirect('home') return redirect('home')
return super().get(request, *args, **kwargs) return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
if global_prefs['hidden__initialized']: if global_prefs['hidden__initialized']:
logger.debug(f"Attempted to post {request.path}, but first time setup already run.")
return HttpResponseForbidden() return HttpResponseForbidden()
return super().post(request, *args, **kwargs) return super().post(request, *args, **kwargs)
@ -54,7 +63,10 @@ class Step1ApiKeyForm(forms.Form):
self.helper = FormHelper() self.helper = FormHelper()
self.helper.layout = Layout( self.helper.layout = Layout(
'api_key', 'api_key',
Column(
Submit('submit', value='Continue'), Submit('submit', value='Continue'),
HTML('<a href="{% url \'first_time_2\' %}" class="btn">Skip</a>')
)
) )
@ -73,9 +85,50 @@ class Step1ApiKeyView(ProtectInitializedMixin, FormView):
# #
# Step 2: create admin user # Step 2: create admin user
# #
class Step2CreateAdminUserView(ProtectInitializedMixin, RegisterView): class Step2CreateAdminUserView(ProtectInitializedMixin, FormView):
template_name = 'YtManagerApp/first_time_setup/step2_admin.html' template_name = 'YtManagerApp/first_time_setup/step2_admin.html'
success_url = reverse_lazy('first_time_3') success_url = reverse_lazy('first_time_3')
form_class = ExtendedUserCreationForm
def get(self, request, *args, **kwargs):
# Skip if admin is already logged in
if request.user.is_authenticated and request.user.is_superuser:
logger.debug("Admin user already exists and is logged in!")
return redirect(self.success_url)
# Check if an admin user already exists
if User.objects.filter(is_superuser=True).count() > 0:
logger.warn("Admin user already exists! Will redirect to login page!")
return redirect('first_time_2_login')
return super().get(request, *args, **kwargs)
def form_valid(self, form):
user = form.save()
user.is_staff = True
user.is_superuser = True
user.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=password)
login(self.request, user)
return super().form_valid(form)
#
# Step 2: create admin user
#
class Step2LoginAdminUserView(ProtectInitializedMixin, FormView):
template_name = 'YtManagerApp/first_time_setup/step2_admin.html'
success_url = reverse_lazy('first_time_3')
form_class = ExtendedAuthenticationForm
def form_valid(self, form):
login(self.request, form.get_user())
return super().form_valid(form)
# #