From 0adcd1b3d9e4ab7cf4172657d08a5a589329ddc5 Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Sun, 3 May 2020 10:55:33 +0200 Subject: [PATCH] UI Improvements Added additional restrictions to Calibre DB interface --- cps/admin.py | 3 +- cps/config_sql.py | 1 + cps/db.py | 66 +++++++++++++++-------------- cps/editbooks.py | 12 +++--- cps/templates/admin.html | 24 +++++++---- cps/templates/config_edit.html | 64 +++++++++++++++++----------- cps/templates/config_view_edit.html | 2 +- cps/templates/email_edit.html | 11 ++++- cps/templates/search_form.html | 2 +- cps/templates/user_edit.html | 2 + 10 files changed, 112 insertions(+), 75 deletions(-) diff --git a/cps/admin.py b/cps/admin.py index deac22a4..f6d4a917 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -772,8 +772,7 @@ def new_user(): @admin_required def edit_mailsettings(): content = config.get_mail_settings() - # log.debug("edit_mailsettings %r", content) - return render_title_template("email_edit.html", content=content, title=_(u"Edit e-mail server settings"), + return render_title_template("email_edit.html", content=content, title=_(u"Edit E-mail Server Settings"), page="mailset") diff --git a/cps/config_sql.py b/cps/config_sql.py index d17583d8..41c4f144 100644 --- a/cps/config_sql.py +++ b/cps/config_sql.py @@ -44,6 +44,7 @@ class _Settings(_Base): mail_login = Column(String, default='mail@example.com') mail_password = Column(String, default='mypassword') mail_from = Column(String, default='automailer ') + mail_size = Column(Integer, default=25) config_calibre_dir = Column(String) config_port = Column(Integer, default=constants.DEFAULT_PORT) diff --git a/cps/db.py b/cps/db.py index e758dc0a..6a2229d3 100755 --- a/cps/db.py +++ b/cps/db.py @@ -22,10 +22,11 @@ import sys import os import re import ast +from datetime import datetime from sqlalchemy import create_engine -from sqlalchemy import Table, Column, ForeignKey -from sqlalchemy import String, Integer, Boolean, TIMESTAMP, Float, DateTime +from sqlalchemy import Table, Column, ForeignKey, CheckConstraint +from sqlalchemy import String, Integer, Boolean, TIMESTAMP, Float, DateTime, REAL from sqlalchemy.orm import relationship, sessionmaker, scoped_session from sqlalchemy.ext.declarative import declarative_base @@ -72,9 +73,9 @@ class Identifiers(Base): __tablename__ = 'identifiers' id = Column(Integer, primary_key=True) - type = Column(String) - val = Column(String) - book = Column(Integer, ForeignKey('books.id')) + type = Column(String(collation='NOCASE'), nullable=False, default="isbn") + val = Column(String(collation='NOCASE'), nullable=False) + book = Column(Integer, ForeignKey('books.id'), nullable=False) def __init__(self, val, id_type, book): self.val = val @@ -126,8 +127,8 @@ class Comments(Base): __tablename__ = 'comments' id = Column(Integer, primary_key=True) - text = Column(String) - book = Column(Integer, ForeignKey('books.id')) + text = Column(String(collation='NOCASE'), nullable=False) + book = Column(Integer, ForeignKey('books.id'), nullable=False) def __init__(self, text, book): self.text = text @@ -141,7 +142,7 @@ class Tags(Base): __tablename__ = 'tags' id = Column(Integer, primary_key=True, autoincrement=True) - name = Column(String) + name = Column(String(collation='NOCASE'), unique=True, nullable=False) def __init__(self, name): self.name = name @@ -154,9 +155,9 @@ class Authors(Base): __tablename__ = 'authors' id = Column(Integer, primary_key=True) - name = Column(String) - sort = Column(String) - link = Column(String) + name = Column(String(collation='NOCASE'), unique=True, nullable=False) + sort = Column(String(collation='NOCASE')) + link = Column(String, nullable=False, default="") def __init__(self, name, sort, link): self.name = name @@ -171,8 +172,8 @@ class Series(Base): __tablename__ = 'series' id = Column(Integer, primary_key=True) - name = Column(String) - sort = Column(String) + name = Column(String(collation='NOCASE'), unique=True, nullable=False) + sort = Column(String(collation='NOCASE')) def __init__(self, name, sort): self.name = name @@ -186,7 +187,7 @@ class Ratings(Base): __tablename__ = 'ratings' id = Column(Integer, primary_key=True) - rating = Column(Integer) + rating = Column(Integer, CheckConstraint('rating>-1 AND rating<11'), unique=True) def __init__(self, rating): self.rating = rating @@ -199,7 +200,7 @@ class Languages(Base): __tablename__ = 'languages' id = Column(Integer, primary_key=True) - lang_code = Column(String) + lang_code = Column(String(collation='NOCASE'), nullable=False, unique=True) def __init__(self, lang_code): self.lang_code = lang_code @@ -212,8 +213,8 @@ class Publishers(Base): __tablename__ = 'publishers' id = Column(Integer, primary_key=True) - name = Column(String) - sort = Column(String) + name = Column(String(collation='NOCASE'), nullable=False, unique=True) + sort = Column(String(collation='NOCASE')) def __init__(self, name, sort): self.name = name @@ -227,10 +228,10 @@ class Data(Base): __tablename__ = 'data' id = Column(Integer, primary_key=True) - book = Column(Integer, ForeignKey('books.id')) - format = Column(String) - uncompressed_size = Column(Integer) - name = Column(String) + book = Column(Integer, ForeignKey('books.id'), nullable=False) + format = Column(String(collation='NOCASE'), nullable=False) + uncompressed_size = Column(Integer, nullable=False) + name = Column(String, nullable=False) def __init__(self, book, book_format, uncompressed_size, name): self.book = book @@ -247,17 +248,20 @@ class Books(Base): DEFAULT_PUBDATE = "0101-01-01 00:00:00+00:00" - id = Column(Integer, primary_key=True) - title = Column(String) - sort = Column(String) - author_sort = Column(String) - timestamp = Column(TIMESTAMP) - pubdate = Column(String) - series_index = Column(String) - last_modified = Column(TIMESTAMP) - path = Column(String) - has_cover = Column(Integer) + id = Column(Integer, primary_key=True, autoincrement=True) + title = Column(String(collation='NOCASE'), nullable=False, default='Unknown') + sort = Column(String(collation='NOCASE')) + author_sort = Column(String(collation='NOCASE')) + timestamp = Column(TIMESTAMP, default=datetime.utcnow) + pubdate = Column(TIMESTAMP, default=datetime.utcnow) + series_index = Column(REAL, nullable=False, default=1.0) + last_modified = Column(TIMESTAMP, default=datetime.utcnow) + path = Column(String, default="", nullable=False) + has_cover = Column(Integer, default=0) uuid = Column(String) + isbn = Column(String(collation='NOCASE'), default="") + # Iccn = Column(String(collation='NOCASE'), default="") + flags = Column(Integer, nullable=False, default=1) authors = relationship('Authors', secondary=books_authors_link, backref='books') tags = relationship('Tags', secondary=books_tags_link, backref='books',order_by="Tags.name") diff --git a/cps/editbooks.py b/cps/editbooks.py index 000ac384..08a7d34a 100644 --- a/cps/editbooks.py +++ b/cps/editbooks.py @@ -30,6 +30,7 @@ from uuid import uuid4 from flask import Blueprint, request, flash, redirect, url_for, abort, Markup, Response from flask_babel import gettext as _ from flask_login import current_user, login_required +from sqlalchemy import func from . import constants, logger, isoLanguages, gdriveutils, uploader, helper from . import config, get_locale, db, ub, worker @@ -680,10 +681,6 @@ def upload(): tags = meta.tags series = meta.series series_index = meta.series_id - title_dir = helper.get_valid_filename(title) - author_dir = helper.get_valid_filename(authr) - filepath = os.path.join(config.config_calibre_dir, author_dir, title_dir) - saved_filename = os.path.join(filepath, title_dir + meta.extension.lower()) if title != _(u'Unknown') and authr != _(u'Unknown'): entry = helper.check_exists_book(authr, title) @@ -692,6 +689,11 @@ def upload(): flash(_(u"Uploaded book probably exists in the library, consider to change before upload new: ") + Markup(render_title_template('book_exists_flash.html', entry=entry)), category="warning") + title_dir = helper.get_valid_filename(title) + author_dir = helper.get_valid_filename(authr) + filepath = os.path.join(config.config_calibre_dir, author_dir, title_dir) + saved_filename = os.path.join(filepath, title_dir + meta.extension.lower()) + # check if file path exists, otherwise create it, copy file to calibre path and delete temp file if not os.path.exists(filepath): try: @@ -721,7 +723,7 @@ def upload(): has_cover = 1 # handle authors - is_author = db.session.query(db.Authors).filter(db.Authors.name == authr).first() + is_author = db.session.query(db.Authors).filter(db.Authors.name == func.binary(authr)).first() if is_author: db_author = is_author else: diff --git a/cps/templates/admin.html b/cps/templates/admin.html index ab143c59..a21fae48 100644 --- a/cps/templates/admin.html +++ b/cps/templates/admin.html @@ -13,11 +13,14 @@ {{_('E-mail Address')}} {{_('Send to Kindle E-mail Address')}} {{_('Downloads')}} - {{_('Admin')}} - {{_('Download')}} - {{_('View Books')}} - {{_('Upload')}} - {{_('Edit')}} + {{_('Admin')}} + {{_('Password')}} + {{_('Upload')}} + {{_('Download')}} + {{_('View Books')}} + {{_('Edit')}} + {{_('Delete')}} + {{_('Public Shelf')}} {% for user in allUser %} {% if not user.role_anonymous() or config.config_anonbrowse %} @@ -27,10 +30,13 @@ {{user.kindle_mail}} {{user.downloads.count()}} {{ display_bool_setting(user.role_admin()) }} - {{ display_bool_setting(user.role_download()) }} - {{ display_bool_setting(user.role_viewer()) }} - {{ display_bool_setting(user.role_upload()) }} - {{ display_bool_setting(user.role_edit()) }} + {{ display_bool_setting(user.role_passwd()) }} + {{ display_bool_setting(user.role_upload()) }} + {{ display_bool_setting(user.role_download()) }} + {{ display_bool_setting(user.role_viewer()) }} + {{ display_bool_setting(user.role_edit()) }} + {{ display_bool_setting(user.role_delete_books()) }} + {{ display_bool_setting(user.role_edit_shelfs()) }} {% endif %} {% endfor %} diff --git a/cps/templates/config_edit.html b/cps/templates/config_edit.html index f5b9efbb..44360f9c 100644 --- a/cps/templates/config_edit.html +++ b/cps/templates/config_edit.html @@ -3,7 +3,7 @@

{{title}}

-
+

@@ -15,10 +15,13 @@

-
- - -
+
+ + + + + +
{% if feature_support['gdrive'] %}
@@ -87,21 +90,25 @@
-
- - +
+ + + + +
-
- - +
+ + + + +
@@ -342,18 +349,27 @@
-
- - +
+ + + + +
-
- - +
+ + + + +
{% if feature_support['rar'] %} -
- - +
+ + + + +
{% endif %}
diff --git a/cps/templates/config_view_edit.html b/cps/templates/config_view_edit.html index 4cade736..12820dda 100644 --- a/cps/templates/config_view_edit.html +++ b/cps/templates/config_view_edit.html @@ -7,7 +7,7 @@

{{title}}

-
+

diff --git a/cps/templates/email_edit.html b/cps/templates/email_edit.html index 2ac9d463..ec2f587a 100644 --- a/cps/templates/email_edit.html +++ b/cps/templates/email_edit.html @@ -6,14 +6,14 @@ {% block body %}

{{title}}

- +
- +
@@ -34,6 +34,13 @@
+
+
+ + + + +
diff --git a/cps/templates/search_form.html b/cps/templates/search_form.html index e53a1cc6..1b7e4c08 100644 --- a/cps/templates/search_form.html +++ b/cps/templates/search_form.html @@ -1,6 +1,6 @@ {% extends "layout.html" %} {% block body %} -
+
diff --git a/cps/templates/user_edit.html b/cps/templates/user_edit.html index 6adae1e7..14229f37 100644 --- a/cps/templates/user_edit.html +++ b/cps/templates/user_edit.html @@ -3,6 +3,7 @@

{{title}}

+
{% if new_user or ( g.user and content.nickname != "Guest" and g.user.role_admin() ) %}
@@ -65,6 +66,7 @@
{% endif %} +
{% for element in sidebar %} {% if element['config_show'] %}