Merge remote-tracking branch 'tags_restrict/master' into Develop

This commit is contained in:
Ozzieisaacs 2019-12-30 15:15:07 +01:00
commit 1c18a788f4
9 changed files with 142 additions and 56 deletions

8
.gitignore vendored
View File

@ -7,9 +7,11 @@ __pycache__/
# Distribution / packaging
.Python
env/
venv/
eggs/
dist/
build/
vendor/
.eggs/
*.egg-info/
.installed.cfg
@ -19,16 +21,12 @@ build/
# calibre-web
*.db
*.log
config.ini
cps/static/[0-9]*
.idea/
*.bak
*.log.*
tags
settings.yaml
gdrive_credentials
vendor
client_secrets.json

View File

@ -144,7 +144,10 @@ def configuration():
def view_configuration():
readColumn = db.session.query(db.Custom_Columns)\
.filter(and_(db.Custom_Columns.datatype == 'bool',db.Custom_Columns.mark_for_delete == 0)).all()
restrictColumns= db.session.query(db.Custom_Columns)\
.filter(and_(db.Custom_Columns.datatype == 'text',db.Custom_Columns.mark_for_delete == 0)).all()
return render_title_template("config_view_edit.html", conf=config, readColumns=readColumn,
restrictColumns=restrictColumns,
title=_(u"UI Configuration"), page="uiconfig")
@ -160,7 +163,7 @@ def update_view_configuration():
_config_string("config_calibre_web_title")
_config_string("config_columns_to_ignore")
_config_string("config_mature_content_tags")
# _config_string("config_mature_content_tags")
reboot_required |= _config_string("config_title_regex")
_config_int("config_read_column")
@ -169,6 +172,10 @@ def update_view_configuration():
_config_int("config_books_per_page")
_config_int("config_authors_max")
_config_string("config_restricted_tags")
_config_int("config_restricted_column")
_config_string("config_restricted_column_value")
if config.config_google_drive_watch_changes_response:
config.config_google_drive_watch_changes_response = json.dumps(config.config_google_drive_watch_changes_response)
@ -176,8 +183,8 @@ def update_view_configuration():
config.config_default_role &= ~constants.ROLE_ANONYMOUS
config.config_default_show = sum(int(k[5:]) for k in to_save if k.startswith('show_'))
if "Show_mature_content" in to_save:
config.config_default_show |= constants.MATURE_CONTENT
'''if "Show_mature_content" in to_save:
config.config_default_show |= constants.MATURE_CONTENT'''
config.save()
flash(_(u"Calibre-Web configuration updated"), category="success")
@ -448,7 +455,7 @@ def new_user():
if request.method == "POST":
to_save = request.form.to_dict()
content.default_language = to_save["default_language"]
content.mature_content = "Show_mature_content" in to_save
# content.mature_content = "Show_mature_content" in to_save
content.locale = to_save.get("locale", content.locale)
content.sidebar_view = sum(int(key[5:]) for key in to_save if key.startswith('show_'))
@ -490,7 +497,10 @@ def new_user():
else:
content.role = config.config_default_role
content.sidebar_view = config.config_default_show
content.mature_content = bool(config.config_default_show & constants.MATURE_CONTENT)
content.restricted_tags = config.config_restricted_tags
content.restricted_column = config.config_restricted_column
content.restricted_column_value = config.config_restricted_column_value
# content.mature_content = bool(config.config_default_show & constants.MATURE_CONTENT)
return render_title_template("user_edit.html", new_user=1, content=content, translations=translations,
languages=languages, title=_(u"Add new user"), page="newuser",
registered_oauth=oauth_check)
@ -593,7 +603,13 @@ def edit_user(user_id):
else:
content.sidebar_view &= ~constants.DETAIL_RANDOM
content.mature_content = "Show_mature_content" in to_save
# content.mature_content = "Show_mature_content" in to_save
if "restricted_tags" in to_save:
content.restricted_tags = to_save["restricted_tags"]
if "config_restricted_column" in to_save:
content.restricted_tags = to_save["config_restricted_column"]
if "config_restricted_column_value" in to_save:
content.restricted_tags = to_save["config_restricted_column_value"]
if "default_language" in to_save:
content.default_language = to_save["default_language"]

View File

@ -57,7 +57,7 @@ class _Settings(_Base):
config_authors_max = Column(Integer, default=0)
config_read_column = Column(Integer, default=0)
config_title_regex = Column(String, default=u'^(A|The|An|Der|Die|Das|Den|Ein|Eine|Einen|Dem|Des|Einem|Eines)\s+')
config_mature_content_tags = Column(String, default='')
# config_mature_content_tags = Column(String, default='')
config_theme = Column(Integer, default=0)
config_log_level = Column(SmallInteger, default=logger.DEFAULT_LOG_LEVEL)
@ -70,10 +70,13 @@ class _Settings(_Base):
config_public_reg = Column(SmallInteger, default=0)
config_remote_login = Column(Boolean, default=False)
config_default_role = Column(SmallInteger, default=0)
config_default_show = Column(SmallInteger, default=6143)
config_columns_to_ignore = Column(String)
config_restricted_tags = Column(String)
config_restricted_column = Column(SmallInteger, default=0)
config_restricted_column_value = Column(String)
config_allowed_column_value = Column(String)
config_use_google_drive = Column(Boolean, default=False)
config_google_drive_folder = Column(String)
@ -177,12 +180,12 @@ class _ConfigSQL(object):
def show_detail_random(self):
return self.show_element_new_user(constants.DETAIL_RANDOM)
def show_mature_content(self):
return self.show_element_new_user(constants.MATURE_CONTENT)
'''def show_mature_content(self):
return self.show_element_new_user(constants.MATURE_CONTENT)'''
def mature_content_tags(self):
'''def mature_content_tags(self):
mct = self.config_mature_content_tags.split(",")
return [t.strip() for t in mct]
return [t.strip() for t in mct]'''
def get_log_level(self):
return logger.get_level_name(self.config_log_level)

View File

@ -686,14 +686,36 @@ def common_filters():
lang_filter = db.Books.languages.any(db.Languages.lang_code == current_user.filter_language())
else:
lang_filter = true()
content_rating_filter = false() if current_user.mature_content else \
db.Books.tags.any(db.Tags.name.in_(config.mature_content_tags()))
return and_(lang_filter, ~content_rating_filter)
negtags_list = current_user.list_restricted_tags()
postags_list = current_user.list_allowed_tags()
neg_content_tags_filter = false() if negtags_list == [''] else db.Books.tags.any(db.Tags.name.in_(negtags_list))
pos_content_tags_filter = true() if postags_list == [''] else db.Books.tags.any(db.Tags.name.in_(postags_list))
# db.session.query(db.Books).filter(db.Books.custom_column_5.any(db.cc_classes[5].value == 'nikto')).first()
# db.session.query(db.Books).filter(
# getattr(db.Books, 'custom_column_' + str(5)).any(db.cc_classes[5].value == 'nikto').first())
if config.config_restricted_column:
pos_cc_list = current_user.allowed_column_value.split(',')
pos_content_cc_filter = true() if pos_cc_list == [''] else \
getattr(db.Books, 'custom_column_' + str(config.config_restricted_column)).\
any(db.cc_classes[config.config_restricted_column].value.in_(pos_cc_list))
neg_cc_list = current_user.restricted_column_value.split(',')
neg_content_cc_filter = true() if neg_cc_list == [''] else \
getattr(db.Books, 'custom_column_' + str(config.config_restricted_column)).\
any(db.cc_classes[config.config_restricted_column].value.in_(neg_cc_list))
else:
pos_content_cc_filter = true()
neg_content_cc_filter = false()
return and_(lang_filter, pos_content_tags_filter, ~neg_content_tags_filter,
pos_content_cc_filter, ~neg_content_cc_filter)
def tags_filters():
return ~(false() if current_user.mature_content else \
db.Tags.name.in_(config.mature_content_tags()))
# return db.session.query(db.Tags).filter(~content_rating_filter).order_by(db.Tags.name).all()
negtags_list = current_user.list_restricted_tags()
postags_list = current_user.list_allowed_tags()
neg_content_tags_filter = false() if negtags_list == [''] else db.Tags.name.in_(negtags_list)
pos_content_tags_filter = true() if postags_list == [''] else db.Tags.name.in_(postags_list)
return and_(pos_content_tags_filter, ~neg_content_tags_filter)
# return ~(false()) if postags_list == [''] else db.Tags.in_(postags_list)
# Creates for all stored languages a translated speaking name in the array for the UI

View File

@ -71,7 +71,7 @@
</div>
</div>
</div>
{% if show_back_button %}
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
@ -316,11 +316,14 @@
</div>
</div>
</div>
{% endif %}
</div>
<div class="col-sm-12">
{% if not show_login_button %}
<button type="submit" name="submit" class="btn btn-default">{{_('Submit')}}</button>
{% endif %}
{% if show_back_button %}
<a href="{{ url_for('admin.admin') }}" class="btn btn-default">{{_('Back')}}</a>
{% endif %}

View File

@ -51,16 +51,19 @@
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="config_restricted_column">{{_('View restriction based on Calibre column')}}</label>
<select name="config_restricted_column" id="config_restricted_column" class="form-control">
<option value="0" {% if conf.config_restricted_column == 0 %}selected{% endif %}>{{ _('None') }}</option>
{% for restrictColumn in restrictColumns %}
<option value="{{ restrictColumn.id }}" {% if restrictColumn.id == conf.config_restricted_column %}selected{% endif %}>{{ restrictColumn.name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="config_title_regex">{{_('Regular expression for title sorting')}}</label>
<input type="text" class="form-control" name="config_title_regex" id="config_title_regex" value="{% if conf.config_title_regex != None %}{{ conf.config_title_regex }}{% endif %}" autocomplete="off">
</div>
<div class="form-group">
<label for="config_mature_content_tags">{{_('Tags for Mature Content')}}</label>
<input type="text" class="form-control" name="config_mature_content_tags" id="config_mature_content_tags"
value="{% if conf.config_mature_content_tags != None%}{{ conf.config_mature_content_tags }}{% endif %}"
autocomplete="off"
>
</div>
</div>
</div>
@ -108,6 +111,14 @@
<input type="checkbox" name="edit_shelf_role" id="edit_shelf_role" {% if conf.role_edit_shelfs() %}checked{% endif %}>
<label for="edit_shelf_role">{{_('Allow Editing Public Shelfs')}}</label>
</div>
<div class="form-group">
<label for="config_restricted_tags">{{_('Restrict Tags')}}</label>
<input type="text" class="form-control" name="config_restricted_tags" id="config_restricted_tags" value="{{ conf.config_restricted_tags if conf.config_restricted_tags != None }}" autocomplete="off">
</div>
<div class="form-group">
<label for="config_restricted_column_value">{{_('Restricted Column Content')}}</label>
<input type="text" class="form-control" name="config_restricted_column_value" id="config_restricted_column_value" value="{{ conf.config_restricted_column_value if conf.config_restricted_column_value != None }}" autocomplete="off">
</div>
</div>
</div>
</div>
@ -134,14 +145,9 @@
<input type="checkbox" name="Show_detail_random" id="Show_detail_random" {% if conf.show_detail_random() %}checked{% endif %}>
<label for="Show_detail_random">{{_('Show random books in detail view')}}</label>
</div>
<div class="form-group">
<input type="checkbox" name="Show_mature_content" id="Show_mature_content" {% if conf.show_mature_content() %}checked{% endif %}>
<label for="Show_mature_content">{{_('Show mature content')}}</label>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-12">
<button type="submit" name="submit" class="btn btn-default">{{_('Submit')}}</button>
<a href="{{ url_for('admin.admin') }}" class="btn btn-default">{{_('Back')}}</a>

View File

@ -14,9 +14,9 @@
<input type="email" class="form-control" name="email" id="email" value="{{ content.email if content.email != None }}" autocomplete="off">
</div>
{% if ( g.user and g.user.role_passwd() or g.user.role_admin() ) and not content.role_anonymous() %}
{% if g.user and g.user.role_admin() and g.allow_registration and not new_user and not profile %}
<div class="btn btn-default" id="resend_password"><a href="{{url_for('admin.reset_password', user_id = content.id) }}">{{_('Reset user Password')}}</a></div>
{% else %}
{% if g.user and g.user.role_admin() and not new_user and not profile and ( mail_configured and content.email if content.email != None ) %}
<div class="btn btn-default" id="resend_password"><a href="{{url_for('admin.reset_user_password', user_id = content.id) }}">{{_('Reset user Password')}}</a></div>
{% endif %}
<div class="form-group">
<label for="password">{{_('Password')}}</label>
<input type="password" class="form-control" name="password" id="password" value="" autocomplete="off">
@ -39,7 +39,14 @@
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="restricted_tags">{{_('Restricted Tags')}}</label>
<input type="text" class="form-control" name="restricted_tags" id="restricted_tags" value="{{ content.restricted_tags if content.restricted_tags != None }}" autocomplete="off">
</div>
<div class="form-group">
<label for="restricted_column_value">{{_('Restricted Column Content')}}</label>
<input type="text" class="form-control" name="restricted_column_value" id="restricted_column_value" value="{{ content.restricted_column_value if content.restricted_column_value != None }}" autocomplete="off">
</div>
<div class="form-group">
<label for="default_language">{{_('Show books with language')}}</label>
<select name="default_language" id="default_language" class="form-control">
@ -49,7 +56,6 @@
{% endfor %}
</select>
</div>
{% if registered_oauth.keys()| length > 0 %}
{% for id, name in registered_oauth.items() %}
<div class="form-group">
@ -61,9 +67,7 @@
{% endif %}
{% endfor %}
</div>
{% endif %}
<div class="col-sm-6">
{% for element in sidebar %}
{% if element['config_show'] %}
@ -87,10 +91,10 @@
<label for="admin_role">{{_('Admin user')}}</label>
</div>
{% endif %}
<div class="form-group">
<!--div class="form-group">
<input type="checkbox" name="Show_mature_content" id="Show_mature_content" {% if content.mature_content %}checked{% endif %}>
<label for="Show_mature_content">{{_('Show mature content')}}</label>
</div>
</div-->
<div class="form-group">
<input type="checkbox" name="download_role" id="download_role" {% if content.role_download() %}checked{% endif %}>
<label for="download_role">{{_('Allow Downloads')}}</label>

View File

@ -157,6 +157,27 @@ class UserBase:
def show_detail_random(self):
return self.check_visibility(constants.DETAIL_RANDOM)
def list_restricted_tags(self):
# return [line in (line.strip("," ) for line in self.restricted_tags.split(",") if not line.startswith('~'))]
# return [line in (line.strip(",") for line in self.restricted_tags.split(",") if not line.startswith('~'))]
#return [p.strip(",") for p in self.restricted_tags.split(",") if not(p.startswith(starter))]
'''for line in self.restricted_tags.split(","):
if not line.startswith('~'):
continue'''
mct = self.restricted_tags.split(",")
return [t.strip() for t in mct]
def list_allowed_tags(self):
# return [line in (line.strip("," ) for line in self.restricted_tags.split(",") if not line.startswith('~'))]
# return [line in (line.strip(",") for line in self.restricted_tags.split(",") if not line.startswith('~'))]
#return [p.strip(",") for p in self.restricted_tags.split(",") if not(p.startswith(starter))]
'''for line in self.restricted_tags.split(","):
if not line.startswith('~'):
continue'''
mct = self.allowed_tags.split(",")
return [t.strip() for t in mct]
def __repr__(self):
return '<User %r>' % self.nickname
@ -178,7 +199,11 @@ class User(UserBase, Base):
locale = Column(String(2), default="en")
sidebar_view = Column(Integer, default=1)
default_language = Column(String(3), default="all")
mature_content = Column(Boolean, default=True)
# mature_content = Column(Boolean, default=True)
restricted_tags = Column(String, default="")
allowed_tags = Column(String, default="")
restricted_column_value = Column(String, default="")
allowed_column_value = Column(String, default="")
if oauth_support:
@ -212,11 +237,13 @@ class Anonymous(AnonymousUserMixin, UserBase):
self.sidebar_view = data.sidebar_view
self.default_language = data.default_language
self.locale = data.locale
self.mature_content = data.mature_content
# self.mature_content = data.mature_content
self.kindle_mail = data.kindle_mail
# settings = session.query(config).first()
# self.anon_browse = settings.config_anonbrowse
self.restricted_tags = data.restricted_tags
self.allowed_tags = data.allowed_tags
# self.restricted_column = data.restricted_column
self.restricted_column_value = data.restricted_column_value
self.allowed_column_value = data.allowed_column_value
def role_admin(self):
return False
@ -370,11 +397,19 @@ def migrate_Database(session):
'side_autor': constants.SIDEBAR_AUTHOR,
'detail_random': constants.DETAIL_RANDOM})
session.commit()
try:
'''try:
session.query(exists().where(User.mature_content)).scalar()
except exc.OperationalError:
conn = engine.connect()
conn.execute("ALTER TABLE user ADD column `mature_content` INTEGER DEFAULT 1")
conn.execute("ALTER TABLE user ADD column `mature_content` INTEGER DEFAULT 1")'''
try:
session.query(exists().where(User.restricted_tags)).scalar()
except exc.OperationalError: # Database is not compatible, some columns are missing
conn = engine.connect()
conn.execute("ALTER TABLE user ADD column `restricted_tags` String DEFAULT ''")
conn.execute("ALTER TABLE user ADD column `allowed_tags` String DEFAULT ''")
conn.execute("ALTER TABLE user ADD column `restricted_column_value` DEFAULT ''")
conn.execute("ALTER TABLE user ADD column `allowed_column_value` DEFAULT ''")
if session.query(User).filter(User.role.op('&')(constants.ROLE_ANONYMOUS) == constants.ROLE_ANONYMOUS).first() is None:
create_anonymous_user(session)
try:

View File

@ -229,7 +229,6 @@ def edit_required(f):
return inner
# ################################### Helper functions ################################################################
@ -1089,7 +1088,7 @@ def register():
content.password = generate_password_hash(password)
content.role = config.config_default_role
content.sidebar_view = config.config_default_show
content.mature_content = bool(config.config_default_show & constants.MATURE_CONTENT)
#content.mature_content = bool(config.config_default_show & constants.MATURE_CONTENT)
try:
ub.session.add(content)
ub.session.commit()
@ -1290,8 +1289,8 @@ def profile():
current_user.password = generate_password_hash(to_save["password"])
if "kindle_mail" in to_save and to_save["kindle_mail"] != current_user.kindle_mail:
current_user.kindle_mail = to_save["kindle_mail"]
if "kobo_user_key" in to_save and to_save["kobo_user_key"]:
current_user.kobo_user_key_hash = generate_password_hash(to_save["kobo_user_key"])
if "allowed_tags" in to_save and to_save["allowed_tags"] != current_user.allowed_tags:
current_user.allowed_tags = to_save["allowed_tags"].strip()
if to_save["email"] and to_save["email"] != current_user.email:
if config.config_public_reg and not check_valid_domain(to_save["email"]):
flash(_(u"E-mail is not from valid domain"), category="error")
@ -1329,7 +1328,7 @@ def profile():
if "Show_detail_random" in to_save:
current_user.sidebar_view += constants.DETAIL_RANDOM
current_user.mature_content = "Show_mature_content" in to_save
#current_user.mature_content = "Show_mature_content" in to_save
try:
ub.session.commit()