diff --git a/comic/forms.py b/comic/forms.py index adec6d2..2baea92 100644 --- a/comic/forms.py +++ b/comic/forms.py @@ -1,6 +1,8 @@ from django import forms +from django.contrib.auth.models import User from comic.models import Setting + class AccountForm(forms.Form): username = forms.CharField(help_text='Username', required=False, @@ -16,20 +18,131 @@ class AccountForm(forms.Form): 'class': 'form-control' } )) - password1 = forms.CharField(help_text='New Password', - required=False, - widget=forms.PasswordInput( - attrs={ - 'class': 'form-control', - } - )) - password2 = forms.CharField(help_text='New Password Confirmation', - required=False, - widget=forms.PasswordInput( - attrs={ - 'class': 'form-control', - } - )) + password = forms.CharField(help_text='New Password', + required=False, + widget=forms.PasswordInput( + attrs={ + 'class': 'form-control', + } + )) + password_confirm = forms.CharField(help_text='New Password Confirmation', + required=False, + widget=forms.PasswordInput( + attrs={ + 'class': 'form-control', + } + )) + + def clean_email(self): + data = self.cleaned_data['email'] + user = User.objects.get(username=self.cleaned_data['username']) + if data == user.email: + return data + if User.objects.filter(email=data).exists(): + raise forms.ValidationError('Email Address is in use') + return data + + def clean(self): + form_data = self.cleaned_data + if form_data['password'] != form_data['password_confirm']: + raise forms.ValidationError('Passwords do not match.') + if len(form_data['password']) < 8 & len(form_data['password']) != 0: + raise forms.ValidationError('Password is too short') + return form_data + + +class AddUserForm(forms.Form): + username = forms.CharField(help_text='Username', + widget=forms.TextInput( + attrs={ + 'class': 'form-control', + } + )) + email = forms.CharField(help_text='Email Address', + widget=forms.TextInput( + attrs={ + 'class': 'form-control' + } + )) + password = forms.CharField(help_text='New Password', + widget=forms.PasswordInput( + attrs={ + 'class': 'form-control', + } + )) + password_confirm = forms.CharField(help_text='New Password Confirmation', + widget=forms.PasswordInput( + attrs={ + 'class': 'form-control', + } + )) + + def clean_username(self): + data = self.cleaned_data['username'] + if User.objects.filter(username=data).exists(): + raise forms.ValidationError('This username Exists.') + return data + + def clean_email(self): + data = self.cleaned_data['email'] + if User.objects.filter(email=data).exists(): + raise forms.ValidationError('Email Address is in use') + return data + + def clean(self): + form_data = self.cleaned_data + if form_data['password'] != form_data['password_confirm']: + raise forms.ValidationError('Passwords do not match.') + if len(form_data['password']) < 8: + raise forms.ValidationError('Password is too short') + return form_data + + +class EditUserForm(forms.Form): + username = forms.CharField(help_text='Username', + required=False, + widget=forms.TextInput( + attrs={ + 'class': 'form-control disabled', + 'readonly': True, + } + )) + email = forms.CharField(help_text='Email Address', + widget=forms.TextInput( + attrs={ + 'class': 'form-control' + } + )) + password = forms.CharField(help_text='New Password', + required=False, + widget=forms.PasswordInput( + attrs={ + 'class': 'form-control', + } + )) + + @staticmethod + def get_initial_values(user): + out = { + 'username': user.username, + 'email': user.email + } + return out + + def clean_email(self): + data = self.cleaned_data['email'] + user = User.objects.get(username=self.cleaned_data['username']) + if data == user.email: + return data + if User.objects.filter(email=data).exists(): + raise forms.ValidationError('Email Address is in use') + return data + + def clean_password(self): + data = self.cleaned_data['password'] + if len(data) < 8 & len(data) != 0: + raise forms.ValidationError('Password is too short') + return data class SettingsForm(forms.Form): diff --git a/comic/templates/base.html b/comic/templates/base.html index 3de9515..3be4b05 100644 --- a/comic/templates/base.html +++ b/comic/templates/base.html @@ -41,7 +41,7 @@ diff --git a/comic/templates/comic/settings_page.html b/comic/templates/comic/settings_page.html index 0da870f..5138b09 100644 --- a/comic/templates/comic/settings_page.html +++ b/comic/templates/comic/settings_page.html @@ -2,6 +2,16 @@ {% block title %}CBreader - Settings{% endblock %} +{% block breadcrumb %} + {% for crumb in breadcrumbs %} + {% if not forloop.last %} +
  • {{ crumb.name }}
  • + {% else %} +
  • {{ crumb.name }}
  • + {% endif %} + {% endfor %} +{% endblock %} + {% block content %} {% if error_message %} @@ -13,7 +23,7 @@ {% csrf_token %} {% for item in form %}
    - + {{ item }}
    {% endfor %} diff --git a/comic/templates/comic/users_page.html b/comic/templates/comic/users_page.html index 5795ed7..3d1b83d 100644 --- a/comic/templates/comic/users_page.html +++ b/comic/templates/comic/users_page.html @@ -2,6 +2,16 @@ {% block title %}CBreader - Users{% endblock %} +{% block breadcrumb %} + {% for crumb in breadcrumbs %} + {% if not forloop.last %} +
  • {{ crumb.name }}
  • + {% else %} +
  • {{ crumb.name }}
  • + {% endif %} + {% endfor %} +{% endblock %} + {% block content %} @@ -23,8 +33,9 @@ {% endfor %} -
    + +Add User {% endblock %} {% block script %} diff --git a/comic/urls.py b/comic/urls.py index e1ccbf4..aa53442 100644 --- a/comic/urls.py +++ b/comic/urls.py @@ -6,6 +6,8 @@ urlpatterns = [ url(r'^$', views.comic_list, name='index'), url(r'^settings/$', views.settings_page, name='settings'), url(r'^settings/users/$', views.users_page, name='users'), + url(r'^settings/users/(?P[0-9]+)/$', views.user_config_page, name='users'), + url(r'^settings/users/add/$', views.user_add_page, name='users'), url(r'^account/$', views.account_page, name='account'), url(r'^(?P[\w]+)/$', views.comic_list, name='comic_list'), url(r'^read/(?P[\w]+)/(?P[0-9]+)/$', views.read_comic, name='read_comic'), diff --git a/comic/util.py b/comic/util.py index 27031ac..3c434ce 100644 --- a/comic/util.py +++ b/comic/util.py @@ -33,7 +33,7 @@ class Breadcrumb: return self.name -def generate_breadcrumbs(comic_path): +def generate_breadcrumbs_from_path(comic_path): output = [Breadcrumb()] prefix = '/comic/' last = '' @@ -50,6 +50,15 @@ def generate_breadcrumbs(comic_path): return output +def generate_breadcrumbs_from_menu(paths): + output = [Breadcrumb()] + for item in paths: + bc = Breadcrumb() + bc.name = item[0] + bc.url = item[1] + output.append(bc) + return output + def get_ordered_dir_list(folder): directories = [] files = [] diff --git a/comic/views.py b/comic/views.py index b57c899..e558bf2 100644 --- a/comic/views.py +++ b/comic/views.py @@ -1,18 +1,19 @@ from django.http import HttpResponse from django.template import RequestContext from django.utils.http import urlsafe_base64_decode -from django.shortcuts import render, redirect +from django.shortcuts import render, redirect, get_object_or_404 from django.contrib.auth.decorators import login_required, user_passes_test from django.core.validators import validate_email from django.core.exceptions import ValidationError from django.contrib.auth.models import User from comic.models import Setting, ComicBook, ComicStatus -from util import generate_breadcrumbs -from forms import SettingsForm, AccountForm +from util import generate_breadcrumbs_from_path, generate_breadcrumbs_from_menu +from forms import SettingsForm, AccountForm, EditUserForm, AddUserForm from util import Menu from os import path + @login_required def comic_list(request, comic_path=''): try: @@ -23,38 +24,27 @@ def comic_list(request, comic_path=''): return redirect('/comic/settings/') comic_path = urlsafe_base64_decode(comic_path) - breadcrumbs = generate_breadcrumbs(comic_path) files = ComicBook.generate_directory(request.user, base_dir, comic_path) context = RequestContext(request, { 'file_list': files, - 'breadcrumbs': breadcrumbs, + 'breadcrumbs': generate_breadcrumbs_from_path(comic_path), 'menu': Menu(request.user, 'Browse'), }) return render(request, 'comic/comic_list.html', context) + @login_required def account_page(request): - error_message = [] success_message = [] if request.POST: form = AccountForm(request.POST) if form.is_valid(): - if form.cleaned_data['password1'] != '': - if form.cleaned_data['password1'] == form.cleaned_data['password2']: - if len(form.cleaned_data['password1']) < 8: - error_message.append('Password is too short') - else: - success_message.append('password changed') - request.user.set_password(form.cleaned_data['password1']) - else: - error_message.append("Passwords don't match") if form.cleaned_data['email'] != request.user.email: - try: - validate_email(form.cleaned_data['email']) - success_message.append('Email Address updated') - request.user.email = form.cleaned_data['email'] - except ValidationError: - error_message.append('Invalid E-mail.') + request.user.email = form.cleaned_data['email'] + success_message.append('Email Updated.') + if len(form.cleaned_data['password']) != 0: + request.user.set_password(form.cleaned_data['password']) + success_message.append('Password Updated.') request.user.save() else: form = AccountForm(initial={ @@ -64,23 +54,90 @@ def account_page(request): context = RequestContext(request, { 'form': form, 'menu': Menu(request.user, 'Account'), - 'error_message': '
    '.join(error_message), + 'error_message': form.errors, 'success_message': '
    '.join(success_message), }) return render(request, 'comic/settings_page.html', context) + @user_passes_test(lambda u: u.is_superuser) def users_page(request): users = User.objects.all() + crumbs = [ + ('Users', '/comic/settings/users/'), + ] context = RequestContext(request, { - #'form': form, 'users': users, - 'menu': Menu(request.user, 'Account'), - #'error_message': '
    '.join(error_message), - #'success_message': '
    '.join(success_message), + 'menu': Menu(request.user, 'Users'), + 'breadcrumbs': generate_breadcrumbs_from_menu(crumbs), }) return render(request, 'comic/users_page.html', context) + +@user_passes_test(lambda u: u.is_superuser) +def user_config_page(request, user_id): + user = get_object_or_404(User, id=user_id) + success_message = [] + if request.POST: + form = EditUserForm(request.POST) + if form.is_valid(): + if 'password' in form.cleaned_data: + if len(form.cleaned_data['password']) != 0: + user.set_password(form.cleaned_data['password']) + success_message.append('Password Updated.') + if form.cleaned_data['email'] != user.email: + user.email = form.cleaned_data['email'] + success_message.append('Email Updated.
    ') + user.save() + else: + form = EditUserForm(initial=EditUserForm.get_initial_values(user)) + + users = User.objects.all() + crumbs = [ + ('Users', '/comic/settings/users/'), + (user.username, '/comic/settings/users/' + str(user.id)), + ] + context = RequestContext(request, { + 'form': form, + 'users': users, + 'menu': Menu(request.user, 'Users'), + 'error_message': form.errors, + 'breadcrumbs': generate_breadcrumbs_from_menu(crumbs), + 'success_message': '
    '.join(success_message), + }) + return render(request, 'comic/settings_page.html', context) + + +@user_passes_test(lambda u: u.is_superuser) +def user_add_page(request): + success_message = '' + if request.POST: + form = AddUserForm(request.POST) + if form.is_valid(): + user = User( + username=form.cleaned_data['username'], + email=form.cleaned_data['email'], + ) + user.set_password(form.cleaned_data['password']) + user.save() + success_message = 'User {} created.'.format(user.username) + + else: + form = AddUserForm() + crumbs = [ + ('Users', '/comic/settings/users/'), + ('Add', '/comic/settings/users/add/'), + ] + context = RequestContext(request, { + 'form': form, + 'menu': Menu(request.user, 'Users'), + 'breadcrumbs': generate_breadcrumbs_from_menu(crumbs), + 'error_message': form.errors, + 'success_message': success_message, + }) + return render(request, 'comic/settings_page.html', context) + + @user_passes_test(lambda u: u.is_superuser) def settings_page(request): error_message = '' @@ -119,7 +176,7 @@ def read_comic(request, comic_path, page): base_dir = Setting.objects.get(name='BASE_DIR').value page = int(page) decoded_path = urlsafe_base64_decode(comic_path) - breadcrumbs = generate_breadcrumbs(decoded_path) + breadcrumbs = generate_breadcrumbs_from_path(decoded_path) _, comic_file_name = path.split(decoded_path) try: book = ComicBook.objects.get(file_name=comic_file_name) @@ -138,6 +195,7 @@ def read_comic(request, comic_path, page): }) return render(request, 'comic/read_comic.html', context) + @login_required def get_image(_, comic_path, page): base_dir = Setting.objects.get(name='BASE_DIR').value