diff --git a/cps/templates/admin.html b/cps/templates/admin.html
index f99a44ad..e16bc11c 100644
--- a/cps/templates/admin.html
+++ b/cps/templates/admin.html
@@ -13,9 +13,9 @@
{{_('Upload')}}
{{_('Edit')}}
{{_('Passwd')}}
-
{% for user in content %}
+ {% if not user.role_anonymous() or config.ANON_BROWSE %}
{{user.nickname}}
{{user.email}}
@@ -26,7 +26,8 @@
{% if user.role_upload() %} {% else %} {% endif %}
{% if user.role_edit() %} {% else %} {% endif %}
{% if user.role_passwd() %} {% else %} {% endif %}
-
+
+ {% endif %}
{% endfor %}
diff --git a/cps/templates/detail.html b/cps/templates/detail.html
index 682eff92..ca5a0b4f 100644
--- a/cps/templates/detail.html
+++ b/cps/templates/detail.html
@@ -104,11 +104,11 @@
{{entry.comments[0].text|safe}}
{% endif %}
- {% if g.user.is_authenticated %}
+
-
+ {% if g.user.is_authenticated %}
{% if g.user.shelf.all() or g.public_shelfes %}
{% endif %}
-
+ {% endif %}
{% if g.user.role_edit() %}
diff --git a/cps/templates/feed.xml b/cps/templates/feed.xml
index 296ddd2e..dd7d58a0 100644
--- a/cps/templates/feed.xml
+++ b/cps/templates/feed.xml
@@ -10,12 +10,11 @@
+{% if pagination.has_prev %}
-
+{% endif %}
{% if pagination.has_next %}
{{shelf.name}}
{% endfor %}
{% if not g.user.is_anonymous() %}
- {{_('Create a Shelf')}}
+ {{_('Create a Shelf')}}
+ {{_('About')}}
{% endif %}
{% endif %}
- {{_('About')}}
+
diff --git a/cps/templates/user_edit.html b/cps/templates/user_edit.html
index 090975c5..d8403fc1 100644
--- a/cps/templates/user_edit.html
+++ b/cps/templates/user_edit.html
@@ -13,7 +13,7 @@
{{_('Email address')}}
- {% if g.user and g.user.role_passwd() or g.user.role_admin()%}
+ {% if ( g.user and g.user.role_passwd() or g.user.role_admin() ) and not content.role_anonymous() %}
{{_('Password')}}
@@ -23,6 +23,7 @@
{{_('Kindle E-Mail')}}
+ {% if not content.role_anonymous() %}
{{_('Language')}}
@@ -31,6 +32,7 @@
{% endfor %}
+ {% endif %}
{{_('Show books with language')}}
@@ -62,11 +64,12 @@
{% if g.user and g.user.role_admin() and not profile %}
-
+ {% if not content.role_anonymous() %}
{{_('Admin user')}}
+ {% endif %}
{{_('Allow Downloads')}}
@@ -79,19 +82,21 @@
{{_('Allow Edit')}}
-
-
- {{_('Allow Changing Password')}}
-
+ {% if not content.role_anonymous() %}
+
+
+ {{_('Allow Changing Password')}}
+
+ {% endif %}
{% endif %}
- {% if g.user and g.user.role_admin() and not profile and not new_user %}
-
-
- {{_('Delete this user')}}
-
-
+ {% if g.user and g.user.role_admin() and not profile and not new_user and not content.role_anonymous() %}
+
+
+ {{_('Delete this user')}}
+
+
{% endif %}
- {{_('Submit')}}
+ {{_('Submit')}}
{% if not profile %}
{{_('Back')}}
{% endif %}
diff --git a/cps/ub.py b/cps/ub.py
index 40839aa1..be802d8e 100644
--- a/cps/ub.py
+++ b/cps/ub.py
@@ -5,9 +5,12 @@ from sqlalchemy import *
from sqlalchemy import exc
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import *
+from flask_login import AnonymousUserMixin
import os
import config
+import traceback
from werkzeug.security import generate_password_hash
+from flask_babel import gettext as _
dbpath = os.path.join(config.APP_DB_ROOT, "app.db")
engine = create_engine('sqlite:///{0}'.format(dbpath), echo=False)
@@ -19,28 +22,11 @@ ROLE_DOWNLOAD = 2
ROLE_UPLOAD = 4
ROLE_EDIT = 8
ROLE_PASSWD = 16
+ROLE_ANONYMOUS = 32
DEFAULT_PASS = "admin123"
-class User(Base):
- __tablename__ = 'user'
-
- id = Column(Integer, primary_key=True)
- nickname = Column(String(64), unique=True)
- email = Column(String(120), unique=True, default="")
- role = Column(SmallInteger, default=ROLE_USER)
- password = Column(String)
- kindle_mail = Column(String(120), default="")
- shelf = relationship('Shelf', backref='user', lazy='dynamic')
- downloads = relationship('Downloads', backref='user', lazy='dynamic')
- locale = Column(String(2), default="en")
- random_books = Column(Integer, default=1)
- language_books = Column(Integer, default=1)
- series_books = Column(Integer, default=1)
- category_books = Column(Integer, default=1)
- hot_books = Column(Integer, default=1)
- default_language = Column(String(3), default="all")
-
+class UserBase():
def is_authenticated(self):
return True
@@ -74,6 +60,12 @@ class User(Base):
else:
return False
+ def role_anonymous(self):
+ if self.role is not None:
+ return True if self.role & ROLE_ANONYMOUS == ROLE_ANONYMOUS else False
+ else:
+ return False
+
def is_active(self):
return True
@@ -105,6 +97,52 @@ class User(Base):
return '' % self.nickname
+class User(UserBase,Base):
+ __tablename__ = 'user'
+
+ id = Column(Integer, primary_key=True)
+ nickname = Column(String(64), unique=True)
+ email = Column(String(120), unique=True, default="")
+ role = Column(SmallInteger, default=ROLE_USER)
+ password = Column(String)
+ kindle_mail = Column(String(120), default="")
+ shelf = relationship('Shelf', backref='user', lazy='dynamic')
+ downloads = relationship('Downloads', backref='user', lazy='dynamic')
+ locale = Column(String(2), default="en")
+ random_books = Column(Integer, default=1)
+ language_books = Column(Integer, default=1)
+ series_books = Column(Integer, default=1)
+ category_books = Column(Integer, default=1)
+ hot_books = Column(Integer, default=1)
+ default_language = Column(String(3), default="all")
+
+
+class Anonymous(AnonymousUserMixin,UserBase):
+ def __init__(self):
+ self.loadSettings()
+
+ def loadSettings(self):
+ data=session.query(User).filter(User.role.op('&')(ROLE_ANONYMOUS) == ROLE_ANONYMOUS).first()
+ self.nickname = data.nickname
+ self.role = data.role
+ self.random_books = data.random_books
+ self.default_language = data.default_language
+ self.language_books = data.language_books
+ self.series_books = data.series_books
+ self.category_books = data.category_books
+ self.hot_books = data.hot_books
+ self.default_language = data.default_language
+
+ def role_admin(self):
+ return False
+
+ def is_active(self):
+ return False
+
+ def is_anonymous(self):
+ return config.ANON_BROWSE
+
+
class Shelf(Base):
__tablename__ = 'shelf'
@@ -155,6 +193,8 @@ class Settings(Base):
def migrate_Database():
+ if session.query(User).filter(User.role.op('&')(ROLE_ANONYMOUS) == ROLE_ANONYMOUS).first() is None:
+ create_anonymous_user()
try:
session.query(exists().where(User.random_books)).scalar()
session.commit()
@@ -213,6 +253,20 @@ def get_mail_settings():
return data
+def create_anonymous_user():
+ user = User()
+ user.nickname = _("Guest")
+ user.email='no@email'
+ user.role = ROLE_ANONYMOUS
+ user.password = generate_password_hash('1')
+
+ session.add(user)
+ try:
+ session.commit()
+ except:
+ session.rollback()
+ pass
+
def create_admin_user():
user = User()
@@ -236,6 +290,7 @@ if not os.path.exists(dbpath):
Base.metadata.create_all(engine)
create_default_config()
create_admin_user()
+ create_anonymous_user()
except Exception:
pass
else:
diff --git a/cps/web.py b/cps/web.py
index 2ff149e4..737551be 100755
--- a/cps/web.py
+++ b/cps/web.py
@@ -14,7 +14,7 @@ from sqlalchemy.sql.expression import func
from sqlalchemy.sql.expression import false
from sqlalchemy.exc import IntegrityError
from math import ceil
-from flask_login import LoginManager, login_user, logout_user, login_required, current_user, AnonymousUserMixin
+from flask_login import LoginManager, login_user, logout_user, login_required, current_user
from flask_principal import Principal, Identity, AnonymousIdentity, identity_changed
from flask_babel import Babel
from flask_babel import gettext as _
@@ -115,49 +115,10 @@ global global_queue
global_queue = None
-class Anonymous(AnonymousUserMixin):
- def __init__(self):
- self.nickname = 'Guest'
- self.role = -1
-
- def role_admin(self):
- return False
-
- def role_download(self):
- return False
-
- def role_upload(self):
- return False
-
- def role_edit(self):
- return False
-
- def filter_language(self):
- return 'all'
-
- def show_random_books(self):
- return True
-
- def show_hot_books(self):
- return True
-
- def show_series(self):
- return True
-
- def show_category(self):
- return True
-
- def show_language(self):
- return True
-
- def is_anonymous(self):
- return config.ANON_BROWSE
-
-
lm = LoginManager(app)
lm.init_app(app)
lm.login_view = 'login'
-lm.anonymous_user = Anonymous
+lm.anonymous_user = ub.Anonymous
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
@@ -237,9 +198,9 @@ def requires_basic_auth_if_no_ano(f):
# simple pagination for the feed
class Pagination(object):
def __init__(self, page, per_page, total_count):
- self.page = page
- self.per_page = per_page
- self.total_count = total_count
+ self.page = int(page)
+ self.per_page = int(per_page)
+ self.total_count = int(total_count)
@property
def next_offset(self):
@@ -247,7 +208,7 @@ class Pagination(object):
@property
def previous_offset(self):
- return int((self.page-1) * self.per_page)
+ return int((self.page-2) * self.per_page)
@property
def last_offset(self):
@@ -453,11 +414,17 @@ def feed_osd():
response.headers["Content-Type"] = "application/xml"
return response
+@app.route("/opds/search/")
+def feed_cc_search(query):
+ return feed_search(query.strip())
+
@app.route("/opds/search", methods=["GET"])
@requires_basic_auth_if_no_ano
-def feed_search():
- term = request.args.get("query").strip()
+def feed_normal_search():
+ return feed_search(request.args.get("query").strip())
+
+def feed_search(term):
if current_user.filter_language() != "all":
filter = db.Books.languages.any(db.Languages.lang_code == current_user.filter_language())
else:
@@ -466,8 +433,8 @@ def feed_search():
entries = db.session.query(db.Books).filter(db.or_(db.Books.tags.any(db.Tags.name.like("%" + term + "%")),
db.Books.authors.any(db.Authors.name.like("%" + term + "%")),
db.Books.title.like("%" + term + "%"))).filter(filter).all()
-
- xml = render_template('feed.xml', searchterm=term, entries=entries)
+ pagination = Pagination( 1,len(entries),len(entries))
+ xml = render_template('feed.xml', searchterm=term, entries=entries, pagination=pagination)
else:
xml = render_template('feed.xml', searchterm="")
response = make_response(xml)
@@ -1145,13 +1112,14 @@ def read_book(book_id, format):
@app.route("/download//")
-@login_required
+@login_required_if_no_ano
@download_required
def get_download_link(book_id, format):
format = format.split(".")[0]
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == format.upper()).first()
- helper.update_download(book_id, int(current_user.id))
+ if current_user.is_authenticated: # collect downloaded books only for registered user and not for anonymous user
+ helper.update_download(book_id, int(current_user.id))
author = helper.get_normalized_author(book.author_sort)
file_name = book.title
if len(author) > 0:
@@ -1392,7 +1360,7 @@ def show_shelf(shelf_id):
@app.route("/shelf/order/", methods=["GET", "POST"])
-@login_required_if_no_ano
+@login_required
def order_shelf(shelf_id):
if request.method == "POST":
to_save = request.form.to_dict()
@@ -1619,7 +1587,7 @@ def edit_user(user_id):
flash(_(u"User '%(nick)s' deleted", nick=content.nickname), category="success")
return redirect(url_for('admin'))
else:
- if to_save["password"]:
+ if "password" in to_save and to_save["password"]:
content.password = generate_password_hash(to_save["password"])
if "admin_role" in to_save and not content.role_admin():
@@ -1663,7 +1631,7 @@ def edit_user(user_id):
content.hot_books = 1
if "default_language" in to_save:
content.default_language = to_save["default_language"]
- if to_save["locale"]:
+ if "locale" in to_save and to_save["locale"]:
content.locale = to_save["locale"]
if to_save["email"] and to_save["email"] != content.email:
content.email = to_save["email"]
@@ -1680,7 +1648,7 @@ def edit_user(user_id):
@app.route("/admin/book/", methods=['GET', 'POST'])
-@login_required
+@login_required_if_no_ano
@edit_required
def edit_book(book_id):
# create the function for sorting...
@@ -1889,7 +1857,7 @@ def edit_book(book_id):
@app.route("/upload", methods=["GET", "POST"])
-@login_required
+@login_required_if_no_ano
@upload_required
def upload():
if not config.UPLOADING: