1
0
mirror of https://github.com/janeczku/calibre-web synced 2024-12-18 06:00:32 +00:00

Added migration of user_session table, removed several old migration routes

This commit is contained in:
Ozzie Isaacs 2024-07-14 17:10:13 +02:00
parent ebe7cd7ba4
commit 155cf04536
2 changed files with 8 additions and 205 deletions

View File

@ -185,7 +185,7 @@ def login_user(user, remember=False, duration=None, force=False, fresh=True):
session["_user_id"] = user_id session["_user_id"] = user_id
session["_fresh"] = fresh session["_fresh"] = fresh
session["_id"] = current_app.login_manager._session_identifier_generator() session["_id"] = current_app.login_manager._session_identifier_generator()
session["_random"] = os.urandom(10) session["_random"] = os.urandom(10).decode('utf-8')
if remember: if remember:
session["_remember"] = "set" session["_remember"] = "set"

211
cps/ub.py
View File

@ -562,228 +562,31 @@ class Thumbnail(Base):
# Add missing tables during migration of database # Add missing tables during migration of database
def add_missing_tables(engine, _session): def add_missing_tables(engine, _session):
if not engine.dialect.has_table(engine.connect(), "book_read_link"):
ReadBook.__table__.create(bind=engine)
if not engine.dialect.has_table(engine.connect(), "bookmark"):
Bookmark.__table__.create(bind=engine)
if not engine.dialect.has_table(engine.connect(), "kobo_reading_state"):
KoboReadingState.__table__.create(bind=engine)
if not engine.dialect.has_table(engine.connect(), "kobo_bookmark"):
KoboBookmark.__table__.create(bind=engine)
if not engine.dialect.has_table(engine.connect(), "kobo_statistics"):
KoboStatistics.__table__.create(bind=engine)
if not engine.dialect.has_table(engine.connect(), "archived_book"): if not engine.dialect.has_table(engine.connect(), "archived_book"):
ArchivedBook.__table__.create(bind=engine) ArchivedBook.__table__.create(bind=engine)
if not engine.dialect.has_table(engine.connect(), "thumbnail"): if not engine.dialect.has_table(engine.connect(), "thumbnail"):
Thumbnail.__table__.create(bind=engine) Thumbnail.__table__.create(bind=engine)
if not engine.dialect.has_table(engine.connect(), "registration"):
Registration.__table__.create(bind=engine)
with engine.connect() as conn:
trans = conn.begin()
conn.execute("insert into registration (domain, allow) values('%.%',1)")
trans.commit()
# migrate all settings missing in registration table def migrate_user_session_table(engine, _session):
def migrate_registration_table(engine, _session):
try: try:
_session.query(exists().where(Registration.allow)).scalar() _session.query(exists().where(User_Sessions.random)).scalar()
_session.commit() _session.commit()
except exc.OperationalError: # Database is not compatible, some columns are missing except exc.OperationalError: # Database is not compatible, some columns are missing
with engine.connect() as conn: with engine.connect() as conn:
trans = conn.begin() trans = conn.begin()
conn.execute(text("ALTER TABLE registration ADD column 'allow' INTEGER")) conn.execute(text("ALTER TABLE user_session ADD column 'random' String"))
conn.execute(text("update registration set 'allow' = 1")) conn.execute(text("ALTER TABLE user_session ADD column 'expiry' String"))
trans.commit()
try:
# Handle table exists, but no content
cnt = _session.query(Registration).count()
if not cnt:
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("insert into registration (domain, allow) values('%.%',1)"))
trans.commit()
except exc.OperationalError: # Database is not writeable
print('Settings database is not writeable. Exiting...')
sys.exit(2)
# Remove login capability of user Guest
def migrate_guest_password(engine):
try:
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("UPDATE user SET password='' where name = 'Guest' and password !=''"))
trans.commit()
except exc.OperationalError:
print('Settings database is not writeable. Exiting...')
sys.exit(2)
def migrate_shelfs(engine, _session):
try:
_session.query(exists().where(Shelf.uuid)).scalar()
except exc.OperationalError:
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("ALTER TABLE shelf ADD column 'uuid' STRING"))
conn.execute(text("ALTER TABLE shelf ADD column 'created' DATETIME"))
conn.execute(text("ALTER TABLE shelf ADD column 'last_modified' DATETIME"))
conn.execute(text("ALTER TABLE book_shelf_link ADD column 'date_added' DATETIME"))
conn.execute(text("ALTER TABLE shelf ADD column 'kobo_sync' BOOLEAN DEFAULT false"))
trans.commit()
for shelf in _session.query(Shelf).all():
shelf.uuid = str(uuid.uuid4())
shelf.created = datetime.datetime.now()
shelf.last_modified = datetime.datetime.now()
for book_shelf in _session.query(BookShelf).all():
book_shelf.date_added = datetime.datetime.now()
_session.commit()
try:
_session.query(exists().where(Shelf.kobo_sync)).scalar()
except exc.OperationalError:
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("ALTER TABLE shelf ADD column 'kobo_sync' BOOLEAN DEFAULT false"))
trans.commit()
try:
_session.query(exists().where(BookShelf.order)).scalar()
except exc.OperationalError: # Database is not compatible, some columns are missing
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("ALTER TABLE book_shelf_link ADD column 'order' INTEGER DEFAULT 1"))
trans.commit() trans.commit()
def migrate_readBook(engine, _session):
try:
_session.query(exists().where(ReadBook.read_status)).scalar()
except exc.OperationalError:
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("ALTER TABLE book_read_link ADD column 'read_status' INTEGER DEFAULT 0"))
conn.execute(text("UPDATE book_read_link SET 'read_status' = 1 WHERE is_read"))
conn.execute(text("ALTER TABLE book_read_link ADD column 'last_modified' DATETIME"))
conn.execute(text("ALTER TABLE book_read_link ADD column 'last_time_started_reading' DATETIME"))
conn.execute(text("ALTER TABLE book_read_link ADD column 'times_started_reading' INTEGER DEFAULT 0"))
trans.commit()
test = _session.query(ReadBook).filter(ReadBook.last_modified == None).all()
for book in test:
book.last_modified = datetime.datetime.utcnow()
_session.commit()
def migrate_remoteAuthToken(engine, _session):
try:
_session.query(exists().where(RemoteAuthToken.token_type)).scalar()
_session.commit()
except exc.OperationalError: # Database is not compatible, some columns are missing
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("ALTER TABLE remote_auth_token ADD column 'token_type' INTEGER DEFAULT 0"))
conn.execute(text("update remote_auth_token set 'token_type' = 0"))
trans.commit()
# Migrate database to current version, has to be updated after every database change. Currently migration from # Migrate database to current version, has to be updated after every database change. Currently migration from
# everywhere to current should work. Migration is done by checking if relevant columns are existing, and than adding # maybe 4/5 versions back to current should work.
# rows with SQL commands # Migration is done by checking if relevant columns are existing, and then adding rows with SQL commands
def migrate_Database(_session): def migrate_Database(_session):
engine = _session.bind engine = _session.bind
add_missing_tables(engine, _session) add_missing_tables(engine, _session)
migrate_registration_table(engine, _session) migrate_user_session_table(engine, _session)
migrate_readBook(engine, _session)
migrate_remoteAuthToken(engine, _session)
migrate_shelfs(engine, _session)
try:
create = False
_session.query(exists().where(User.sidebar_view)).scalar()
except exc.OperationalError: # Database is not compatible, some columns are missing
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("ALTER TABLE user ADD column `sidebar_view` Integer DEFAULT 1"))
trans.commit()
create = True
try:
if create:
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("SELECT language_books FROM user"))
trans.commit()
except exc.OperationalError:
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("UPDATE user SET 'sidebar_view' = (random_books* :side_random + language_books * :side_lang "
"+ series_books * :side_series + category_books * :side_category + hot_books * "
":side_hot + :side_autor + :detail_random)"),
{'side_random': constants.SIDEBAR_RANDOM, 'side_lang': constants.SIDEBAR_LANGUAGE,
'side_series': constants.SIDEBAR_SERIES, 'side_category': constants.SIDEBAR_CATEGORY,
'side_hot': constants.SIDEBAR_HOT, 'side_autor': constants.SIDEBAR_AUTHOR,
'detail_random': constants.DETAIL_RANDOM})
trans.commit()
try:
_session.query(exists().where(User.denied_tags)).scalar()
except exc.OperationalError: # Database is not compatible, some columns are missing
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("ALTER TABLE user ADD column `denied_tags` String DEFAULT ''"))
conn.execute(text("ALTER TABLE user ADD column `allowed_tags` String DEFAULT ''"))
conn.execute(text("ALTER TABLE user ADD column `denied_column_value` String DEFAULT ''"))
conn.execute(text("ALTER TABLE user ADD column `allowed_column_value` String DEFAULT ''"))
trans.commit()
try:
_session.query(exists().where(User.view_settings)).scalar()
except exc.OperationalError:
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("ALTER TABLE user ADD column `view_settings` VARCHAR(10) DEFAULT '{}'"))
trans.commit()
try:
_session.query(exists().where(User.kobo_only_shelves_sync)).scalar()
except exc.OperationalError:
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("ALTER TABLE user ADD column `kobo_only_shelves_sync` SMALLINT DEFAULT 0"))
trans.commit()
try:
# check if name is in User table instead of nickname
_session.query(exists().where(User.name)).scalar()
except exc.OperationalError:
# Create new table user_id and copy contents of table user into it
with engine.connect() as conn:
trans = conn.begin()
conn.execute(text("CREATE TABLE user_id (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
"name VARCHAR(64),"
"email VARCHAR(120),"
"role SMALLINT,"
"password VARCHAR,"
"kindle_mail VARCHAR(120),"
"locale VARCHAR(2),"
"sidebar_view INTEGER,"
"default_language VARCHAR(3),"
"denied_tags VARCHAR,"
"allowed_tags VARCHAR,"
"denied_column_value VARCHAR,"
"allowed_column_value VARCHAR,"
"view_settings JSON,"
"kobo_only_shelves_sync SMALLINT,"
"UNIQUE (name),"
"UNIQUE (email))"))
conn.execute(text("INSERT INTO user_id(id, name, email, role, password, kindle_mail,locale,"
"sidebar_view, default_language, denied_tags, allowed_tags, denied_column_value, "
"allowed_column_value, view_settings, kobo_only_shelves_sync)"
"SELECT id, nickname, email, role, password, kindle_mail, locale,"
"sidebar_view, default_language, denied_tags, allowed_tags, denied_column_value, "
"allowed_column_value, view_settings, kobo_only_shelves_sync FROM user"))
# delete old user table and rename new user_id table to user:
conn.execute(text("DROP TABLE user"))
conn.execute(text("ALTER TABLE user_id RENAME TO user"))
trans.commit()
if _session.query(User).filter(User.role.op('&')(constants.ROLE_ANONYMOUS) == constants.ROLE_ANONYMOUS).first() \
is None:
create_anonymous_user(_session)
migrate_guest_password(engine)
def clean_database(_session): def clean_database(_session):