fix dynamic fields and ext db migration
This commit is contained in:
+1
-1
@@ -314,7 +314,7 @@ async def restore_installed_extension(app: FastAPI, ext: InstallableExtension):
|
|||||||
register_ext_routes(app, extension)
|
register_ext_routes(app, extension)
|
||||||
|
|
||||||
current_version = (await get_dbversions()).get(ext.id, 0)
|
current_version = (await get_dbversions()).get(ext.id, 0)
|
||||||
await migrate_extension_database(extension, current_version)
|
await migrate_extension_database(ext, current_version)
|
||||||
|
|
||||||
# mount routes for the new version
|
# mount routes for the new version
|
||||||
core_app_extra.register_new_ext_routes(extension)
|
core_app_extra.register_new_ext_routes(extension)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ async def install_extension(ext_info: InstallableExtension) -> Extension:
|
|||||||
ext_info.extract_archive()
|
ext_info.extract_archive()
|
||||||
|
|
||||||
db_version = (await get_dbversions()).get(ext_id, 0)
|
db_version = (await get_dbversions()).get(ext_id, 0)
|
||||||
await migrate_extension_database(extension, db_version)
|
await migrate_extension_database(ext_info, db_version)
|
||||||
|
|
||||||
await create_installed_extension(ext_info)
|
await create_installed_extension(ext_info)
|
||||||
|
|
||||||
|
|||||||
+14
-11
@@ -13,23 +13,22 @@ from lnbits.core.crud import (
|
|||||||
update_migration_version,
|
update_migration_version,
|
||||||
)
|
)
|
||||||
from lnbits.core.db import db as core_db
|
from lnbits.core.db import db as core_db
|
||||||
from lnbits.core.extensions.models import (
|
from lnbits.core.extensions.models import InstallableExtension
|
||||||
Extension,
|
|
||||||
)
|
|
||||||
from lnbits.db import COCKROACH, POSTGRES, SQLITE, Connection
|
from lnbits.db import COCKROACH, POSTGRES, SQLITE, Connection
|
||||||
from lnbits.settings import settings
|
from lnbits.settings import settings
|
||||||
|
|
||||||
|
|
||||||
async def migrate_extension_database(ext: Extension, current_version):
|
async def migrate_extension_database(ext: InstallableExtension, current_version: int):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ext_migrations = importlib.import_module(f"{ext.module_name}.migrations")
|
ext_migrations = importlib.import_module(f"{ext.module_name}.migrations")
|
||||||
ext_db = importlib.import_module(ext.module_name).db
|
ext_db = importlib.import_module(ext.module_name).db
|
||||||
except ImportError as exc:
|
except ImportError as exc:
|
||||||
logger.error(exc)
|
logger.error(exc)
|
||||||
raise ImportError(f"Cannot import module for extension '{ext.code}'.") from exc
|
raise ImportError(f"Cannot import module for extension '{ext.id}'.") from exc
|
||||||
|
|
||||||
async with ext_db.connect() as ext_conn:
|
async with ext_db.connect() as ext_conn:
|
||||||
await run_migration(ext_conn, ext_migrations, ext.code, current_version)
|
await run_migration(ext_conn, ext_migrations, ext.id, current_version)
|
||||||
|
|
||||||
|
|
||||||
async def run_migration(
|
async def run_migration(
|
||||||
@@ -72,6 +71,7 @@ async def load_disabled_extension_list() -> None:
|
|||||||
async def migrate_databases():
|
async def migrate_databases():
|
||||||
"""Creates the necessary databases if they don't exist already; or migrates them."""
|
"""Creates the necessary databases if they don't exist already; or migrates them."""
|
||||||
|
|
||||||
|
current_versions = await get_dbversions()
|
||||||
async with core_db.connect() as conn:
|
async with core_db.connect() as conn:
|
||||||
exists = False
|
exists = False
|
||||||
if conn.type == SQLITE:
|
if conn.type == SQLITE:
|
||||||
@@ -87,7 +87,6 @@ async def migrate_databases():
|
|||||||
if not exists:
|
if not exists:
|
||||||
await core_migrations.m000_create_migrations_table(conn)
|
await core_migrations.m000_create_migrations_table(conn)
|
||||||
|
|
||||||
current_versions = await get_dbversions(conn)
|
|
||||||
core_version = current_versions.get("core", 0)
|
core_version = current_versions.get("core", 0)
|
||||||
await run_migration(conn, core_migrations, "core", core_version)
|
await run_migration(conn, core_migrations, "core", core_version)
|
||||||
|
|
||||||
@@ -95,13 +94,17 @@ async def migrate_databases():
|
|||||||
# `installed_extensions` table has been created
|
# `installed_extensions` table has been created
|
||||||
await load_disabled_extension_list()
|
await load_disabled_extension_list()
|
||||||
|
|
||||||
# todo: revisit, use installed extensions
|
for ext in await get_installed_extensions():
|
||||||
for ext in Extension.get_valid_extensions(False):
|
current_version = current_versions.get(ext.id)
|
||||||
current_version = current_versions.get(ext.code, 0)
|
if current_version is None:
|
||||||
|
logger.warning(
|
||||||
|
f"Extension {ext.id} has no migration version. This should not happen."
|
||||||
|
)
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
await migrate_extension_database(ext, current_version)
|
await migrate_extension_database(ext, current_version)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Error migrating extension {ext.code}: {e}")
|
logger.exception(f"Error migrating extension {ext.id}: {e}")
|
||||||
|
|
||||||
logger.info("✔️ All migrations done.")
|
logger.info("✔️ All migrations done.")
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -579,12 +579,14 @@ def insert_query(table_name: str, model: BaseModel) -> str:
|
|||||||
return f"INSERT INTO {table_name} ({fields}) VALUES ({values})"
|
return f"INSERT INTO {table_name} ({fields}) VALUES ({values})"
|
||||||
|
|
||||||
|
|
||||||
def update_query(table_name: str, model: BaseModel, where: str = "id = :id") -> str:
|
def update_query(
|
||||||
|
table_name: str, model: BaseModel, where: str = "WHERE id = :id"
|
||||||
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Generate an update query with placeholders for a given table and model
|
Generate an update query with placeholders for a given table and model
|
||||||
:param table_name: Name of the table
|
:param table_name: Name of the table
|
||||||
:param model: Pydantic model
|
:param model: Pydantic model
|
||||||
:param where: Where string, default to `id = :id`
|
:param where: Where string, default to `WHERE id = :id`
|
||||||
"""
|
"""
|
||||||
fields = []
|
fields = []
|
||||||
for field in model_to_dict(model).keys():
|
for field in model_to_dict(model).keys():
|
||||||
@@ -592,7 +594,7 @@ def update_query(table_name: str, model: BaseModel, where: str = "id = :id") ->
|
|||||||
# add quotes to keys to avoid SQL conflicts (e.g. `user` is a reserved keyword)
|
# add quotes to keys to avoid SQL conflicts (e.g. `user` is a reserved keyword)
|
||||||
fields.append(f'"{field}" = {placeholder}')
|
fields.append(f'"{field}" = {placeholder}')
|
||||||
query = ", ".join(fields)
|
query = ", ".join(fields)
|
||||||
return f"UPDATE {table_name} SET {query} WHERE {where}"
|
return f"UPDATE {table_name} SET {query} {where}"
|
||||||
|
|
||||||
|
|
||||||
def model_to_dict(model: BaseModel) -> dict:
|
def model_to_dict(model: BaseModel) -> dict:
|
||||||
|
|||||||
@@ -405,7 +405,7 @@ window.app.component('lnbits-notifications-btn', {
|
|||||||
window.app.component('lnbits-dynamic-fields', {
|
window.app.component('lnbits-dynamic-fields', {
|
||||||
template: '#lnbits-dynamic-fields',
|
template: '#lnbits-dynamic-fields',
|
||||||
mixins: [window.windowMixin],
|
mixins: [window.windowMixin],
|
||||||
props: ['options', 'value'],
|
props: ['options', 'modelValue'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
formData: null,
|
formData: null,
|
||||||
@@ -427,11 +427,11 @@ window.app.component('lnbits-dynamic-fields', {
|
|||||||
}, {})
|
}, {})
|
||||||
},
|
},
|
||||||
handleValueChanged() {
|
handleValueChanged() {
|
||||||
this.$emit('input', this.formData)
|
this.$emit('update:model-value', this.formData)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.formData = this.buildData(this.options, this.value)
|
this.formData = this.buildData(this.options, this.modelValue)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user