diff --git a/app/YtManagerApp/appmain.py b/app/YtManagerApp/appmain.py index f8397b8..8651670 100644 --- a/app/YtManagerApp/appmain.py +++ b/app/YtManagerApp/appmain.py @@ -1,6 +1,7 @@ import logging import logging.handlers import os +import sys 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 django.db.utils import OperationalError + def __initialize_logger(): log_dir = os.path.join(dj_settings.DATA_DIR, 'logs') os.makedirs(log_dir, exist_ok=True) + handlers = [] + file_handler = logging.handlers.RotatingFileHandler( os.path.join(log_dir, "log.log"), maxBytes=1024 * 1024, 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( level=dj_settings.LOG_LEVEL, format=dj_settings.LOG_FORMAT, - handlers=[file_handler] + handlers=handlers ) diff --git a/app/YtManagerApp/static/YtManagerApp/css/style.css b/app/YtManagerApp/static/YtManagerApp/css/style.css index 8d36944..5c9b046 100644 --- a/app/YtManagerApp/static/YtManagerApp/css/style.css +++ b/app/YtManagerApp/static/YtManagerApp/css/style.css @@ -1,5 +1,6 @@ #main_body { - margin-bottom: 4rem; } + margin-bottom: 4rem; + margin-top: 2rem; } #main_footer { position: fixed; diff --git a/app/YtManagerApp/static/YtManagerApp/css/style.css.map b/app/YtManagerApp/static/YtManagerApp/css/style.css.map index 43d0ab3..af57370 100644 --- a/app/YtManagerApp/static/YtManagerApp/css/style.css.map +++ b/app/YtManagerApp/static/YtManagerApp/css/style.css.map @@ -1,6 +1,6 @@ { "version": 3, -"mappings": "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", +"mappings": "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", "sources": ["style.scss"], "names": [], "file": "style.css" diff --git a/app/YtManagerApp/static/YtManagerApp/css/style.scss b/app/YtManagerApp/static/YtManagerApp/css/style.scss index a88a682..5b14f45 100644 --- a/app/YtManagerApp/static/YtManagerApp/css/style.scss +++ b/app/YtManagerApp/static/YtManagerApp/css/style.scss @@ -2,6 +2,7 @@ $accent-color: #007bff; #main_body { margin-bottom: 4rem; + margin-top: 2rem; } #main_footer { diff --git a/app/YtManagerApp/templates/YtManagerApp/first_time_setup/step1_apikey.html b/app/YtManagerApp/templates/YtManagerApp/first_time_setup/step1_apikey.html index 9ee5997..ac5d796 100644 --- a/app/YtManagerApp/templates/YtManagerApp/first_time_setup/step1_apikey.html +++ b/app/YtManagerApp/templates/YtManagerApp/first_time_setup/step1_apikey.html @@ -8,10 +8,10 @@

Step 1: Set up YouTube API key (optional)

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 - uses this key in order to limit the number of requests made to their platform, in order to prevent abuses.

+ To access this API, YouTube requires users to register on their site and request an API key. YouTube + uses this key to control access and limit the number of requests made to their platform, in order to prevent abuses.

-

To use this program, it is recommended that you create an API key for your own account. While a key +

To use this program, it is recommended, 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 this program from reaching YouTube. Follow the steps below, or press Skip to use the provided key.

@@ -59,8 +59,6 @@ {% crispy form %} - Skip - {% endblock body %} \ No newline at end of file diff --git a/app/YtManagerApp/templates/registration/register.html b/app/YtManagerApp/templates/registration/register.html index e29dcec..73f9c99 100644 --- a/app/YtManagerApp/templates/registration/register.html +++ b/app/YtManagerApp/templates/registration/register.html @@ -24,12 +24,6 @@ {% endif %} {% endif %} - {% if is_first_user %} - - {% endif %} -
Register
{% crispy form %} diff --git a/app/YtManagerApp/urls.py b/app/YtManagerApp/urls.py index ec60500..614b2e1 100644 --- a/app/YtManagerApp/urls.py +++ b/app/YtManagerApp/urls.py @@ -64,6 +64,7 @@ urlpatterns = [ 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/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/done', first_time.DoneView.as_view(), name='first_time_done'), diff --git a/app/YtManagerApp/views/auth.py b/app/YtManagerApp/views/auth.py index b6584f5..a95e8fb 100644 --- a/app/YtManagerApp/views/auth.py +++ b/app/YtManagerApp/views/auth.py @@ -58,13 +58,8 @@ class RegisterView(FormView): success_url = reverse_lazy('register_done') def form_valid(self, form): - is_first_user = (User.objects.count() == 0) - user = form.save() - if is_first_user: - user.is_staff = True - user.is_superuser = True - user.save() + form.save() username = form.cleaned_data.get('username') password = form.cleaned_data.get('password1') diff --git a/app/YtManagerApp/views/first_time.py b/app/YtManagerApp/views/first_time.py index aa32d2c..adc58cc 100644 --- a/app/YtManagerApp/views/first_time.py +++ b/app/YtManagerApp/views/first_time.py @@ -1,26 +1,35 @@ 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.contrib.auth import authenticate, login from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib.auth.models import User from django.urls import reverse_lazy from django.views.generic import UpdateView, FormView 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.management.appconfig import global_prefs from django.http import HttpResponseForbidden +import logging + + +logger = logging.getLogger("FirstTimeWizard") + class ProtectInitializedMixin(object): def get(self, request, *args, **kwargs): 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 super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): if global_prefs['hidden__initialized']: + logger.debug(f"Attempted to post {request.path}, but first time setup already run.") return HttpResponseForbidden() return super().post(request, *args, **kwargs) @@ -54,7 +63,10 @@ class Step1ApiKeyForm(forms.Form): self.helper = FormHelper() self.helper.layout = Layout( 'api_key', - Submit('submit', value='Continue'), + Column( + Submit('submit', value='Continue'), + HTML('Skip') + ) ) @@ -73,9 +85,50 @@ class Step1ApiKeyView(ProtectInitializedMixin, FormView): # # Step 2: create admin user # -class Step2CreateAdminUserView(ProtectInitializedMixin, RegisterView): +class Step2CreateAdminUserView(ProtectInitializedMixin, FormView): template_name = 'YtManagerApp/first_time_setup/step2_admin.html' 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) #