mirror of
https://github.com/ajurna/cbwebreader.git
synced 2025-12-06 06:17:17 +00:00
Classification (#32)
* added some code cleanup for views.py * added some code cleanup for views.py * fixed comics not working in the base directory.
This commit is contained in:
@@ -47,5 +47,5 @@ class ComicStatusAdmin(admin.ModelAdmin):
|
||||
|
||||
@admin.register(UserMisc)
|
||||
class UserMiscAdmin(admin.ModelAdmin):
|
||||
list_display = ('id', 'user', 'feed_id')
|
||||
list_display = ('user', 'feed_id', 'allowed_to_read')
|
||||
list_filter = ('user',)
|
||||
@@ -3,6 +3,8 @@ from os import path
|
||||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from comic.models import Directory
|
||||
|
||||
|
||||
class InitialSetupForm(forms.Form):
|
||||
username = forms.CharField(widget=forms.TextInput(attrs={"class": "form-control"}))
|
||||
@@ -87,28 +89,23 @@ class EditUserForm(forms.Form):
|
||||
required=False,
|
||||
widget=forms.TextInput(attrs={"class": "form-control disabled", "readonly": True}),
|
||||
)
|
||||
email = forms.CharField(widget=forms.TextInput(attrs={"class": "form-control"}))
|
||||
email = forms.EmailField(widget=forms.TextInput(attrs={"class": "form-control"}))
|
||||
password = forms.CharField(
|
||||
required=False, widget=forms.PasswordInput(attrs={"class": "form-control"})
|
||||
)
|
||||
# TODO: allow setting superuser on users
|
||||
allowed_to_read = forms.ChoiceField(choices=Directory.Classification.choices)
|
||||
|
||||
@staticmethod
|
||||
def get_initial_values(user):
|
||||
out = {"username": user.username, "email": user.email}
|
||||
out = {"username": user.username, "email": user.email, "allowed_to_read": user.usermisc.allowed_to_read}
|
||||
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
|
||||
return data
|
||||
|
||||
|
||||
class DirectoryEditForm(forms.Form):
|
||||
classification = forms.ChoiceField(choices=Directory.Classification.choices)
|
||||
|
||||
23
comic/migrations/0025_auto_20210506_1342.py
Normal file
23
comic/migrations/0025_auto_20210506_1342.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 3.2 on 2021-05-06 12:42
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('comic', '0024_auto_20210422_0855'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='directory',
|
||||
name='classification',
|
||||
field=models.PositiveSmallIntegerField(choices=[(0, 'G'), (1, 'PG'), (2, '12'), (3, '15'), (4, '18')], default=4),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='usermisc',
|
||||
name='allowed_to_read',
|
||||
field=models.PositiveSmallIntegerField(choices=[(0, 'G'), (1, 'PG'), (2, '12'), (3, '15'), (4, '18')], default=4),
|
||||
),
|
||||
]
|
||||
22
comic/migrations/0026_alter_usermisc_user.py
Normal file
22
comic/migrations/0026_alter_usermisc_user.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# Generated by Django 3.2 on 2021-05-06 12:50
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
import django.db.models.deletion
|
||||
import django_boost.models.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('comic', '0025_auto_20210506_1342'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='usermisc',
|
||||
name='user',
|
||||
field=django_boost.models.fields.AutoOneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
26
comic/migrations/0027_auto_20210506_1356.py
Normal file
26
comic/migrations/0027_auto_20210506_1356.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# Generated by Django 3.2 on 2021-05-06 12:56
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
import django.db.models.deletion
|
||||
import django_boost.models.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('comic', '0026_alter_usermisc_user'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='usermisc',
|
||||
name='id',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='usermisc',
|
||||
name='user',
|
||||
field=django_boost.models.fields.AutoOneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -3,8 +3,7 @@ import mimetypes
|
||||
import uuid
|
||||
import zipfile
|
||||
from functools import reduce
|
||||
from itertools import zip_longest
|
||||
from os import listdir
|
||||
from itertools import zip_longest, chain
|
||||
from pathlib import Path
|
||||
from typing import Optional, List, Union, Tuple
|
||||
|
||||
@@ -18,6 +17,7 @@ from django.db import models
|
||||
from django.db.transaction import atomic
|
||||
from django.templatetags.static import static
|
||||
from django.utils.http import urlsafe_base64_encode
|
||||
from django_boost.models.fields import AutoOneToOneField
|
||||
from imagekit.models import ProcessedImageField
|
||||
from imagekit.processors import ResizeToFill
|
||||
|
||||
@@ -28,6 +28,13 @@ if settings.UNRAR_TOOL:
|
||||
|
||||
|
||||
class Directory(models.Model):
|
||||
class Classification(models.IntegerChoices):
|
||||
C_G = 0, 'G'
|
||||
C_PG = 1, 'PG'
|
||||
C_12 = 2, '12'
|
||||
C_15 = 3, '15'
|
||||
C_18 = 4, '18'
|
||||
|
||||
name = models.CharField(max_length=100)
|
||||
parent = models.ForeignKey("Directory", null=True, blank=True, on_delete=models.CASCADE)
|
||||
selector = models.UUIDField(unique=True, default=uuid.uuid4, db_index=True)
|
||||
@@ -40,6 +47,7 @@ class Directory(models.Model):
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='directory_thumbnail_issue')
|
||||
thumbnail_index = models.PositiveIntegerField(default=0)
|
||||
classification = models.PositiveSmallIntegerField(choices=Classification.choices, default=Classification.C_18)
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
@@ -108,6 +116,10 @@ class Directory(models.Model):
|
||||
def url_safe_selector(self):
|
||||
return urlsafe_base64_encode(self.selector.bytes)
|
||||
|
||||
def set_classification(self, form_data):
|
||||
self.classification = form_data['classification']
|
||||
self.save()
|
||||
|
||||
|
||||
class ComicBook(models.Model):
|
||||
file_name = models.TextField()
|
||||
@@ -144,7 +156,7 @@ class ComicBook(models.Model):
|
||||
def url_safe_selector(self):
|
||||
return urlsafe_base64_encode(self.selector.bytes)
|
||||
|
||||
def get_pdf(self):
|
||||
def get_pdf(self) -> Path:
|
||||
base_dir = settings.COMIC_BOOK_VOLUME
|
||||
return Path(base_dir, self.directory.get_path(), self.file_name)
|
||||
|
||||
@@ -209,6 +221,7 @@ class ComicBook(models.Model):
|
||||
self.save()
|
||||
|
||||
def _get_pdf_image(self, page_index: int):
|
||||
# noinspection PyTypeChecker
|
||||
doc = fitz.open(self.get_pdf())
|
||||
page = doc[page_index]
|
||||
pix = page.get_pixmap()
|
||||
@@ -219,7 +232,6 @@ class ComicBook(models.Model):
|
||||
img.seek(0)
|
||||
return img, pil_data
|
||||
|
||||
|
||||
def is_last_page(self, page):
|
||||
if (self.page_count - 1) == page:
|
||||
return True
|
||||
@@ -265,9 +277,9 @@ class ComicBook(models.Model):
|
||||
book = ComicBook.objects.get(file_name=prev_comic, directory__isnull=True)
|
||||
except ComicBook.DoesNotExist:
|
||||
if self.directory:
|
||||
book = ComicBook.process_comic_book(prev_comic, self.directory)
|
||||
book = ComicBook.process_comic_book(Path(prev_comic), self.directory)
|
||||
else:
|
||||
book = ComicBook.process_comic_book(prev_comic)
|
||||
book = ComicBook.process_comic_book(Path(prev_comic))
|
||||
cs, _ = ComicStatus.objects.get_or_create(comic=book, user=user)
|
||||
comic_path = urlsafe_base64_encode(book.selector.bytes)
|
||||
|
||||
@@ -290,9 +302,9 @@ class ComicBook(models.Model):
|
||||
book = ComicBook.objects.get(file_name=next_comic, directory__isnull=True)
|
||||
except ComicBook.DoesNotExist:
|
||||
if self.directory:
|
||||
book = ComicBook.process_comic_book(next_comic, self.directory)
|
||||
book = ComicBook.process_comic_book(Path(next_comic), self.directory)
|
||||
else:
|
||||
book = ComicBook.process_comic_book(next_comic)
|
||||
book = ComicBook.process_comic_book(Path(next_comic))
|
||||
except ComicBook.MultipleObjectsReturned:
|
||||
if self.directory:
|
||||
books = ComicBook.objects.filter(file_name=next_comic, directory=self.directory).order_by('id')
|
||||
@@ -353,21 +365,21 @@ class ComicBook(models.Model):
|
||||
with atomic():
|
||||
for page_index in range(archive.page_count):
|
||||
page = ComicPage(
|
||||
Comic=book, index=page_index, page_file_name=page_index+1, content_type='application/pdf'
|
||||
Comic=book, index=page_index, page_file_name=page_index + 1, content_type='application/pdf'
|
||||
)
|
||||
page.save()
|
||||
return book
|
||||
|
||||
@staticmethod
|
||||
def get_ordered_dir_list(folder):
|
||||
def get_ordered_dir_list(folder: Path) -> List[str]:
|
||||
directories = []
|
||||
files = []
|
||||
for item in listdir(folder):
|
||||
if Path(folder, item).is_dir():
|
||||
for item in folder.glob('*'):
|
||||
if item.is_dir():
|
||||
directories.append(item)
|
||||
else:
|
||||
files.append(item)
|
||||
return sorted(directories) + sorted(files)
|
||||
return [x.name for x in chain(sorted(directories), sorted(files))]
|
||||
|
||||
@property
|
||||
def get_archive_path(self):
|
||||
@@ -388,6 +400,7 @@ class ComicBook(models.Model):
|
||||
pass
|
||||
|
||||
try:
|
||||
# noinspection PyUnresolvedReferences
|
||||
return fitz.open(str(archive_path)), 'pdf'
|
||||
except RuntimeError:
|
||||
pass
|
||||
@@ -475,5 +488,8 @@ class ComicStatus(models.Model):
|
||||
|
||||
|
||||
class UserMisc(models.Model):
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||
|
||||
user = AutoOneToOneField(User, on_delete=models.CASCADE, primary_key=True)
|
||||
feed_id = models.UUIDField(unique=True, default=uuid.uuid4, db_index=True)
|
||||
allowed_to_read = models.PositiveSmallIntegerField(default=Directory.Classification.C_18,
|
||||
choices=Directory.Classification.choices)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% load bootstrap4 %}
|
||||
{% load static %}
|
||||
{% block title %}{{ title }}{% endblock %}
|
||||
|
||||
@@ -48,7 +49,7 @@
|
||||
{% endif %}
|
||||
</a>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<h5 class="card-title {{ file.selector }}">
|
||||
{% if file.item_type == 'Directory' %}
|
||||
<a href="{% url "comic_list" file.selector %}" class="search-name">
|
||||
{% elif file.item_type == 'ComicBook' %}
|
||||
@@ -63,7 +64,7 @@
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="{{ file.percent }}" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</p>
|
||||
<div class="btn-group" role="group" aria-label="Comic Actions">
|
||||
<div class="btn-group w-100" role="group" aria-label="Comic Actions">
|
||||
<button type="button" class="btn btn-primary comic_action" title="Mark Un-Read" selector="{{ file.selector }}" itemtype="{{ file.item_type }}" comic_action="mark_unread"><i class="fas fa-book"></i></button>
|
||||
<button type="button" class="btn btn-primary comic_action" title="Mark Read" selector="{{ file.selector }}" itemtype="{{ file.item_type }}" comic_action="mark_read"><i class="fas fa-book-open"></i></button>
|
||||
<div class="btn-group" role="group">
|
||||
@@ -75,25 +76,48 @@
|
||||
<button type="button" class="btn btn-primary dropdown-item comic_action" title="Mark Read" selector="{{ file.selector }}" itemtype="{{ file.item_type }}" comic_action="mark_read"><i class="fas fa-book-open">Mark Read</i></button>
|
||||
{% if file.item_type != 'Directory' %}
|
||||
<button type="button" class="btn btn-primary dropdown-item comic_action" title="Mark Previous Read" selector="{{ file.selector }}" itemtype="{{ file.item_type }}" comic_action="mark_previous"><i class="fas fa-book"><i class="fas fa-arrow-up">Mark Previous Read</i></i></button>
|
||||
{% else %}
|
||||
<button type="button" class="btn btn-primary dropdown-item modal-button" title="Edit Comic" data-toggle="modal" data-target="#editModal" selector="{{ file.selector }}" itemtype="{{ file.item_type }}"><i class="fas fa-edit">Edit Comic</i></button>
|
||||
{% endif %}
|
||||
{# <button type="button" class="btn btn-primary dropdown-item" title="Edit Comic"><i class="fas fa-edit">Edit Comic</i></button>#}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% if file.total_unread and file.item_type == 'Directory' %}
|
||||
<span class="badge rounded-pill bg-primary card-badge">{{ file.total_unread }}</span>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% if file.total_unread and file.item_type == 'Directory' %}
|
||||
<span class="badge rounded-pill bg-primary unread-badge">{{ file.total_unread }}</span>
|
||||
{% endif %}
|
||||
<span class="badge rounded-pill bg-warning {{ file.selector }} classification-badge" classification="{{ file.obj.classification }}">{{ file.obj.get_classification_display }}</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="editModalLabel">Modal title</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary" id="save_button">Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script type="text/javascript" src="{% static "js/comic_list.min.js" %}"></script>
|
||||
{{ js_urls|json_script:'js_urls' }}
|
||||
<script type="text/javascript" src="{% static "js/comic_list.min.js" %}"></script>
|
||||
{% endblock %}
|
||||
@@ -11,6 +11,7 @@
|
||||
<th>Username</th>
|
||||
<th>Email</th>
|
||||
<th>Superuser</th>
|
||||
<th>Classification</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-link="row" class="rowlink">
|
||||
@@ -20,6 +21,7 @@
|
||||
<td><a href="{% url 'user_details' user.id %}">{{user.username}}</a></td>
|
||||
<td>{{user.email}}</td>
|
||||
<td>{{user.is_superuser}}</td>
|
||||
<td>{{ user.usermisc.get_allowed_to_read_display }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
0
comic/templatetags/__init__.py
Normal file
0
comic/templatetags/__init__.py
Normal file
4
comic/templatetags/comic_tags.py
Normal file
4
comic/templatetags/comic_tags.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from django import template
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@@ -17,7 +17,7 @@ urlpatterns = [
|
||||
path("recent/", views.recent_comics, name="recent_comics"),
|
||||
path("recent/json/", views.recent_comics_json, name="recent_comics_json"),
|
||||
path("edit/", views.comic_edit, name="comic_edit"),
|
||||
path("feed/<int:user_selector>/", feeds.RecentComics()),
|
||||
path("feed/<user_selector>/", feeds.RecentComics()),
|
||||
path("<directory_selector>/", views.comic_list, name="comic_list"),
|
||||
path("<directory_selector>/thumb", views.directory_thumbnail, name="directory_thumbnail"),
|
||||
path("action/<operation>/<item_type>/<selector>/", views.perform_action, name="perform_action")
|
||||
|
||||
@@ -4,7 +4,8 @@ from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
from django.conf import settings
|
||||
from django.db.models import Count, Q, F
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import Count, Q, F, Case, When, PositiveSmallIntegerField
|
||||
from django.utils.http import urlsafe_base64_encode
|
||||
|
||||
from .models import ComicBook, Directory, ComicStatus
|
||||
@@ -112,7 +113,7 @@ class DirFile:
|
||||
self.name = self.obj.file_name
|
||||
|
||||
|
||||
def generate_directory(user, directory=False):
|
||||
def generate_directory(user: User, directory=False):
|
||||
"""
|
||||
:type user: User
|
||||
:type directory: Directory
|
||||
@@ -150,7 +151,12 @@ def generate_directory(user, directory=False):
|
||||
total_read=F('comicstatus__last_read_page'),
|
||||
finished=F('comicstatus__finished'),
|
||||
unread=F('comicstatus__unread'),
|
||||
user=F('comicstatus__user')
|
||||
user=F('comicstatus__user'),
|
||||
classification=Case(
|
||||
When(directory__isnull=True, then=Directory.Classification.C_18),
|
||||
default=F('directory__classification'),
|
||||
output_field=PositiveSmallIntegerField(choices=Directory.Classification.choices)
|
||||
)
|
||||
).filter(Q(user__isnull=True) | Q(user=user.id))
|
||||
|
||||
for directory_obj in dir_list_obj:
|
||||
@@ -170,6 +176,7 @@ def generate_directory(user, directory=False):
|
||||
directory_obj.total = 0
|
||||
directory_obj.total_read = 0
|
||||
files.append(DirFile(directory_obj))
|
||||
files = [file for file in files if file.obj.classification <= user.usermisc.allowed_to_read]
|
||||
|
||||
for file_name in file_list:
|
||||
if file_name.suffix.lower() in [".rar", ".zip", ".cbr", ".cbz", ".pdf"]:
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from PIL import Image
|
||||
from django.contrib.auth import authenticate, login
|
||||
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.files.uploadedfile import InMemoryUploadedFile
|
||||
from django.db.models import Max, Count, F
|
||||
from django.db.transaction import atomic
|
||||
from django.http import HttpResponse, FileResponse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
|
||||
from django.views.decorators.clickjacking import xframe_options_sameorigin
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
from django.views.decorators.http import require_POST
|
||||
|
||||
from .forms import AccountForm, AddUserForm, EditUserForm, InitialSetupForm
|
||||
from .models import ComicBook, ComicPage, ComicStatus, Directory, UserMisc
|
||||
from .forms import AccountForm, AddUserForm, EditUserForm, InitialSetupForm, DirectoryEditForm
|
||||
from .models import ComicBook, ComicPage, ComicStatus, Directory
|
||||
from .util import (
|
||||
Menu,
|
||||
generate_breadcrumbs_from_menu,
|
||||
@@ -47,6 +46,7 @@ def comic_list(request, directory_selector=False):
|
||||
breadcrumbs = generate_breadcrumbs_from_path()
|
||||
|
||||
files = generate_directory(request.user, directory)
|
||||
form = DirectoryEditForm()
|
||||
|
||||
return render(
|
||||
request,
|
||||
@@ -56,14 +56,18 @@ def comic_list(request, directory_selector=False):
|
||||
"menu": Menu(request.user, "Browse"),
|
||||
"title": title,
|
||||
"files": files,
|
||||
"selector": directory_selector if directory_selector else 'None'
|
||||
"form": form,
|
||||
"selector": directory_selector if directory_selector else 'None',
|
||||
'js_urls': {
|
||||
"perform_action": reverse('perform_action', args=('operation', 'item_type', 'selector'))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
def perform_action(request, operation, item_type, selector):
|
||||
if operation not in ['mark_read', 'mark_unread', 'mark_previous']:
|
||||
if operation not in ['mark_read', 'mark_unread', 'mark_previous', 'set_classification']:
|
||||
return HttpResponse(400)
|
||||
elif operation == 'mark_previous' and item_type == 'Directory':
|
||||
return HttpResponse(422)
|
||||
@@ -74,20 +78,29 @@ def perform_action(request, operation, item_type, selector):
|
||||
for book in ComicBook.objects.filter(directory__isnull=True):
|
||||
getattr(book, operation)(request.user)
|
||||
return HttpResponse(204)
|
||||
else:
|
||||
return HttpResponse(400)
|
||||
if operation == 'set_classification':
|
||||
form = DirectoryEditForm(request.POST)
|
||||
if form.is_valid() and item_type == 'Directory':
|
||||
pass
|
||||
else:
|
||||
return HttpResponse(400)
|
||||
if item_type == 'ComicBook':
|
||||
book = get_object_or_404(ComicBook, selector=selector_uuid)
|
||||
getattr(book, operation)(request.user)
|
||||
return HttpResponse(204)
|
||||
elif item_type == 'Directory':
|
||||
directory = get_object_or_404(Directory, selector=selector_uuid)
|
||||
getattr(directory, operation)(request.user)
|
||||
if operation == 'set_classification':
|
||||
getattr(directory, operation)(form.cleaned_data)
|
||||
else:
|
||||
getattr(directory, operation)(request.user)
|
||||
return HttpResponse(204)
|
||||
|
||||
|
||||
@login_required
|
||||
def recent_comics(request):
|
||||
feed_id, _ = UserMisc.objects.get_or_create(user=request.user)
|
||||
|
||||
return render(
|
||||
request,
|
||||
"comic/recent_comics.html",
|
||||
@@ -95,7 +108,7 @@ def recent_comics(request):
|
||||
"breadcrumbs": generate_breadcrumbs_from_menu([("Recent", "/comic/recent/")]),
|
||||
"menu": Menu(request.user, "Recent"),
|
||||
"title": "Recent Comics",
|
||||
"feed_id": urlsafe_base64_encode(feed_id.feed_id.bytes),
|
||||
"feed_id": urlsafe_base64_encode(request.user.usermisc.feed_id.bytes),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -197,7 +210,7 @@ def account_page(request):
|
||||
|
||||
@user_passes_test(lambda u: u.is_superuser)
|
||||
def users_page(request):
|
||||
users = User.objects.all()
|
||||
users = User.objects.all().select_related('usermisc')
|
||||
crumbs = [("Users", "/comic/settings/users/")]
|
||||
context = {
|
||||
"users": users,
|
||||
@@ -221,6 +234,8 @@ def user_config_page(request, user_id):
|
||||
if form.cleaned_data["email"] != user.email:
|
||||
user.email = form.cleaned_data["email"]
|
||||
success_message.append("Email Updated.</br>")
|
||||
user.usermisc.allowed_to_read = form.cleaned_data['allowed_to_read']
|
||||
user.usermisc.save()
|
||||
user.save()
|
||||
else:
|
||||
form = EditUserForm(initial=EditUserForm.get_initial_values(user))
|
||||
@@ -248,7 +263,6 @@ def user_add_page(request):
|
||||
user = User(username=form.cleaned_data["username"], email=form.cleaned_data["email"])
|
||||
user.set_password(form.cleaned_data["password"])
|
||||
user.save()
|
||||
UserMisc.objects.create(user=user)
|
||||
success_message = "User {} created.".format(user.username)
|
||||
|
||||
else:
|
||||
@@ -269,14 +283,10 @@ def user_add_page(request):
|
||||
def read_comic(request, comic_selector):
|
||||
|
||||
selector = uuid.UUID(bytes=urlsafe_base64_decode(comic_selector))
|
||||
try:
|
||||
book = ComicBook.objects.get(selector=selector)
|
||||
except ComicBook.DoesNotExist:
|
||||
Directory.objects.get(selector=selector)
|
||||
return redirect('comic_list', directory_selector=comic_selector)
|
||||
except Directory.DoesNotExist:
|
||||
return HttpResponse(status=404)
|
||||
book = get_object_or_404(ComicBook, selector=selector)
|
||||
if book.directory:
|
||||
if book.directory.classification > request.user.usermisc.allowed_to_read:
|
||||
return redirect('index')
|
||||
|
||||
pages = ComicPage.objects.filter(Comic=book)
|
||||
|
||||
@@ -318,33 +328,42 @@ def set_read_page(request, comic_selector, page):
|
||||
|
||||
@xframe_options_sameorigin
|
||||
@login_required
|
||||
def get_image(_, comic_selector, page):
|
||||
def get_image(request, comic_selector, page):
|
||||
selector = uuid.UUID(bytes=urlsafe_base64_decode(comic_selector))
|
||||
book = ComicBook.objects.get(selector=selector)
|
||||
if book.directory:
|
||||
if book.directory.classification > request.user.usermisc.allowed_to_read:
|
||||
return HttpResponse(status=401)
|
||||
img, content = book.get_image(int(page))
|
||||
return FileResponse(img, content_type=content)
|
||||
|
||||
|
||||
@xframe_options_sameorigin
|
||||
@login_required
|
||||
def comic_thumbnail(_, comic_selector):
|
||||
def comic_thumbnail(request, comic_selector):
|
||||
selector = uuid.UUID(bytes=urlsafe_base64_decode(comic_selector))
|
||||
book = ComicBook.objects.get(selector=selector)
|
||||
if book.directory.classification > request.user.usermisc.allowed_to_read:
|
||||
return HttpResponse(status=401)
|
||||
return redirect(book.get_thumbnail_url())
|
||||
|
||||
|
||||
@xframe_options_sameorigin
|
||||
@login_required
|
||||
def directory_thumbnail(_, directory_selector):
|
||||
def directory_thumbnail(request, directory_selector):
|
||||
selector = uuid.UUID(bytes=urlsafe_base64_decode(directory_selector))
|
||||
folder = Directory.objects.get(selector=selector)
|
||||
if folder.classification > request.user.usermisc.allowed_to_read:
|
||||
return HttpResponse(status=401)
|
||||
return redirect(folder.get_thumbnail_url())
|
||||
|
||||
|
||||
@login_required
|
||||
def get_pdf(_, comic_selector):
|
||||
def get_pdf(request, comic_selector):
|
||||
selector = uuid.UUID(bytes=urlsafe_base64_decode(comic_selector))
|
||||
book = ComicBook.objects.get(selector=selector)
|
||||
if book.directory.classification > request.user.usermisc.allowed_to_read:
|
||||
return HttpResponse(status=401)
|
||||
return FileResponse(open(book.get_pdf(), 'rb'), content_type='application/pdf')
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user