mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-22 14:22:55 +01:00
migration tracking.
This commit is contained in:
parent
f238b3d1ef
commit
c965bca41d
17 changed files with 86 additions and 130 deletions
4
Makefile
4
Makefile
|
@ -8,7 +8,7 @@ prettier: $(shell find lnbits -name "*.js" -name ".html")
|
||||||
./node_modules/.bin/prettier --write lnbits/static/js/*.js lnbits/core/static/js/*.js lnbits/extensions/*/templates/*/*.html ./lnbits/core/templates/core/*.html lnbits/templates/*.html lnbits/extensions/*/static/js/*.js
|
./node_modules/.bin/prettier --write lnbits/static/js/*.js lnbits/core/static/js/*.js lnbits/extensions/*/templates/*/*.html ./lnbits/core/templates/core/*.html lnbits/templates/*.html lnbits/extensions/*/static/js/*.js
|
||||||
|
|
||||||
black: $(shell find lnbits -name "*.py")
|
black: $(shell find lnbits -name "*.py")
|
||||||
./venv/bin/black --line-length 120 lnbits
|
./venv/bin/black lnbits
|
||||||
|
|
||||||
mypy: $(shell find lnbits -name "*.py")
|
mypy: $(shell find lnbits -name "*.py")
|
||||||
./venv/bin/mypy lnbits
|
./venv/bin/mypy lnbits
|
||||||
|
@ -17,4 +17,4 @@ checkprettier: $(shell find lnbits -name "*.js" -name ".html")
|
||||||
./node_modules/.bin/prettier --check lnbits/static/js/*.js lnbits/core/static/js/*.js lnbits/extensions/*/templates/*/*.html ./lnbits/core/templates/core/*.html lnbits/templates/*.html lnbits/extensions/*/static/js/*.js
|
./node_modules/.bin/prettier --check lnbits/static/js/*.js lnbits/core/static/js/*.js lnbits/extensions/*/templates/*/*.html ./lnbits/core/templates/core/*.html lnbits/templates/*.html lnbits/extensions/*/static/js/*.js
|
||||||
|
|
||||||
checkblack: $(shell find lnbits -name "*.py")
|
checkblack: $(shell find lnbits -name "*.py")
|
||||||
./venv/bin/black --check --line-length 120 lnbits
|
./venv/bin/black --check lnbits
|
||||||
|
|
|
@ -19,7 +19,7 @@ find . -type f -print0 | xargs -0 sed -i 's/example/mysuperplugin/g' # Change al
|
||||||
Going over the example extension's structure:
|
Going over the example extension's structure:
|
||||||
* views_api.py: This is where your public API would go. It will be exposed at "$DOMAIN/$PLUGIN/$ROUTE". For example: https://lnbits.com/mysuperplugin/api/v1/tools.
|
* views_api.py: This is where your public API would go. It will be exposed at "$DOMAIN/$PLUGIN/$ROUTE". For example: https://lnbits.com/mysuperplugin/api/v1/tools.
|
||||||
* views.py: The `/` path will show up as your plugin's home page in lnbits' UI. Other pages you can define yourself. The `templates` folder should explain itself in relation to this.
|
* views.py: The `/` path will show up as your plugin's home page in lnbits' UI. Other pages you can define yourself. The `templates` folder should explain itself in relation to this.
|
||||||
* migrations.py: Create database tables for your plugin. They'll be created when you run `pipenv run flask migrate`.
|
* migrations.py: Create database tables for your plugin. They'll be created automatically when you start lnbits.
|
||||||
|
|
||||||
... This document is a work-in-progress. Send pull requests if you get stuck, so others don't.
|
... This document is a work-in-progress. Send pull requests if you get stuck, so others don't.
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,7 @@ Running the server
|
||||||
LNbits uses [Flask][flask] as an application server.
|
LNbits uses [Flask][flask] as an application server.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ pipenv run flask migrate
|
$ pipenv run python main.py
|
||||||
$ pipenv run flask run
|
|
||||||
```
|
```
|
||||||
|
|
||||||
There is an environment variable called `FLASK_ENV` that has to be set to `development`
|
There is an environment variable called `FLASK_ENV` that has to be set to `development`
|
||||||
|
|
|
@ -19,11 +19,10 @@ $ source ./.venv/bin/activate
|
||||||
|
|
||||||
You will need to set the variables in `.env.example`, and rename the file to `.env`.
|
You will need to set the variables in `.env.example`, and rename the file to `.env`.
|
||||||
|
|
||||||
Run the migrations and the Flask server:
|
Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
(.venv) $ flask migrate
|
(.venv) $ python main.py
|
||||||
(.venv) $ flask run
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You might also need to install additional packages, depending on the [backend wallet](./wallets.md) you use.
|
You might also need to install additional packages, depending on the [backend wallet](./wallets.md) you use.
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
import re
|
||||||
import importlib
|
import importlib
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask_assets import Environment, Bundle # type: ignore
|
from flask_assets import Environment, Bundle # type: ignore
|
||||||
|
@ -8,9 +10,10 @@ from flask_talisman import Talisman # type: ignore
|
||||||
from os import getenv
|
from os import getenv
|
||||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||||
|
|
||||||
from .core import core_app, migrations as core_migrations
|
from .core import core_app
|
||||||
from .helpers import ExtensionManager
|
from .helpers import ExtensionManager
|
||||||
from .settings import FORCE_HTTPS
|
from .settings import FORCE_HTTPS
|
||||||
|
from .db import open_db, open_ext_db
|
||||||
|
|
||||||
|
|
||||||
disabled_extensions = getenv("LNBITS_DISABLED_EXTENSIONS", "").split(",")
|
disabled_extensions = getenv("LNBITS_DISABLED_EXTENSIONS", "").split(",")
|
||||||
|
@ -73,21 +76,40 @@ assets.register("base_css", Bundle("scss/base.scss", filters="pyscss", output="c
|
||||||
# --------
|
# --------
|
||||||
|
|
||||||
|
|
||||||
@app.cli.command("migrate")
|
|
||||||
def migrate_databases():
|
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."""
|
||||||
core_migrations.migrate()
|
|
||||||
|
from .core import migrations as core_migrations
|
||||||
|
|
||||||
|
with open_db() as core_db:
|
||||||
|
try:
|
||||||
|
rows = core_db.fetchall("SELECT * FROM dbversions")
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
# migration 3 wasn't ran
|
||||||
|
core_migrations.m000_create_migrations_table(core_db)
|
||||||
|
rows = core_db.fetchall("SELECT * FROM dbversions")
|
||||||
|
|
||||||
|
current_versions = {row["db"]: row["version"] for row in rows}
|
||||||
|
matcher = re.compile(r"^m(\d\d\d)_")
|
||||||
|
|
||||||
|
def run_migration(db, migrations_module):
|
||||||
|
db_name = migrations_module.__name__.split(".")[-2]
|
||||||
|
for key, run_migration in migrations_module.__dict__.items():
|
||||||
|
if match := matcher.match(key):
|
||||||
|
version = int(match.group(1))
|
||||||
|
if version > current_versions.get(db_name, 0):
|
||||||
|
print(f"running migration {db_name}.{version}")
|
||||||
|
run_migration(db)
|
||||||
|
core_db.execute(
|
||||||
|
"INSERT OR REPLACE INTO dbversions (db, version) VALUES (?, ?)", (db_name, version)
|
||||||
|
)
|
||||||
|
|
||||||
|
run_migration(core_db, core_migrations)
|
||||||
|
|
||||||
for ext in valid_extensions:
|
for ext in valid_extensions:
|
||||||
try:
|
try:
|
||||||
ext_migrations = importlib.import_module(f"lnbits.extensions.{ext.code}.migrations")
|
ext_migrations = importlib.import_module(f"lnbits.extensions.{ext.code}.migrations")
|
||||||
ext_migrations.migrate()
|
with open_ext_db(ext.code) as db:
|
||||||
except Exception:
|
run_migration(db, ext_migrations)
|
||||||
|
except ImportError:
|
||||||
raise ImportError(f"Please make sure that the extension `{ext.code}` has a migrations file.")
|
raise ImportError(f"Please make sure that the extension `{ext.code}` has a migrations file.")
|
||||||
|
|
||||||
|
|
||||||
# init
|
|
||||||
# ----
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app.run()
|
|
||||||
|
|
|
@ -1,4 +1,15 @@
|
||||||
from lnbits.db import open_db
|
import sqlite3
|
||||||
|
|
||||||
|
|
||||||
|
def m000_create_migrations_table(db):
|
||||||
|
db.execute(
|
||||||
|
"""
|
||||||
|
CREATE TABLE dbversions (
|
||||||
|
db TEXT PRIMARY KEY,
|
||||||
|
version INT NOT NULL
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def m001_initial(db):
|
def m001_initial(db):
|
||||||
|
@ -76,6 +87,7 @@ def m002_add_fields_to_apipayments(db):
|
||||||
Adding fields to apipayments for better accounting,
|
Adding fields to apipayments for better accounting,
|
||||||
and renaming payhash to checking_id since that is what it really is.
|
and renaming payhash to checking_id since that is what it really is.
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
db.execute("ALTER TABLE apipayments RENAME COLUMN payhash TO checking_id")
|
db.execute("ALTER TABLE apipayments RENAME COLUMN payhash TO checking_id")
|
||||||
db.execute("ALTER TABLE apipayments ADD COLUMN hash TEXT")
|
db.execute("ALTER TABLE apipayments ADD COLUMN hash TEXT")
|
||||||
db.execute("CREATE INDEX by_hash ON apipayments (hash)")
|
db.execute("CREATE INDEX by_hash ON apipayments (hash)")
|
||||||
|
@ -102,9 +114,9 @@ def m002_add_fields_to_apipayments(db):
|
||||||
(json.dumps({"tag": ext}), new, row["checking_id"], row["memo"]),
|
(json.dumps({"tag": ext}), new, row["checking_id"], row["memo"]),
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
# this is necessary now because it may be the case that this migration will
|
||||||
def migrate():
|
# run twice in some environments.
|
||||||
with open_db() as db:
|
# catching errors like this won't be necessary in anymore now that we
|
||||||
m001_initial(db)
|
# keep track of db versions so no migration ever runs twice.
|
||||||
m002_add_fields_to_apipayments(db)
|
pass
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
from lnbits.db import open_ext_db
|
|
||||||
|
|
||||||
|
|
||||||
def m001_initial(db):
|
def m001_initial(db):
|
||||||
"""
|
"""
|
||||||
Initial amilks table.
|
Initial amilks table.
|
||||||
|
@ -16,8 +13,3 @@ def m001_initial(db):
|
||||||
);
|
);
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def migrate():
|
|
||||||
with open_ext_db("amilk") as db:
|
|
||||||
m001_initial(db)
|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
from lnbits.db import open_ext_db
|
|
||||||
|
|
||||||
|
|
||||||
def m001_initial(db):
|
def m001_initial(db):
|
||||||
"""
|
"""
|
||||||
Initial products table.
|
Initial products table.
|
||||||
|
@ -61,8 +58,3 @@ def m001_initial(db):
|
||||||
);
|
);
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def migrate():
|
|
||||||
with open_ext_db("diagonalley") as db:
|
|
||||||
m001_initial(db)
|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
from lnbits.db import open_ext_db
|
|
||||||
|
|
||||||
|
|
||||||
def m001_initial(db):
|
def m001_initial(db):
|
||||||
|
|
||||||
db.execute(
|
db.execute(
|
||||||
|
@ -86,9 +83,3 @@ def m002_changed(db):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
db.execute("DROP TABLE tickets")
|
db.execute("DROP TABLE tickets")
|
||||||
|
|
||||||
|
|
||||||
def migrate():
|
|
||||||
with open_ext_db("events") as db:
|
|
||||||
m001_initial(db)
|
|
||||||
m002_changed(db)
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
from lnbits.db import open_ext_db
|
|
||||||
|
|
||||||
|
|
||||||
def migrate():
|
|
||||||
print("pending")
|
|
|
@ -1,6 +1,3 @@
|
||||||
from lnbits.db import open_ext_db
|
|
||||||
|
|
||||||
|
|
||||||
def m001_initial(db):
|
def m001_initial(db):
|
||||||
|
|
||||||
db.execute(
|
db.execute(
|
||||||
|
@ -86,9 +83,3 @@ def m002_changed(db):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
db.execute("DROP TABLE tickets")
|
db.execute("DROP TABLE tickets")
|
||||||
|
|
||||||
|
|
||||||
def migrate():
|
|
||||||
with open_ext_db("lnticket") as db:
|
|
||||||
m001_initial(db)
|
|
||||||
m002_changed(db)
|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
from lnbits.db import open_ext_db
|
|
||||||
|
|
||||||
|
|
||||||
def m001_initial(db):
|
def m001_initial(db):
|
||||||
"""
|
"""
|
||||||
Initial pay table.
|
Initial pay table.
|
||||||
|
@ -17,8 +14,3 @@ def m001_initial(db):
|
||||||
);
|
);
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def migrate():
|
|
||||||
with open_ext_db("lnurlp") as db:
|
|
||||||
m001_initial(db)
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
from sqlite3 import OperationalError
|
from sqlite3 import OperationalError
|
||||||
|
|
||||||
from lnbits.db import open_ext_db
|
|
||||||
|
|
||||||
|
|
||||||
def m001_initial(db):
|
def m001_initial(db):
|
||||||
"""
|
"""
|
||||||
|
@ -65,9 +63,3 @@ def m002_redux(db):
|
||||||
)
|
)
|
||||||
|
|
||||||
db.execute("DROP TABLE paywalls_old")
|
db.execute("DROP TABLE paywalls_old")
|
||||||
|
|
||||||
|
|
||||||
def migrate():
|
|
||||||
with open_ext_db("paywall") as db:
|
|
||||||
m001_initial(db)
|
|
||||||
m002_redux(db)
|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
from lnbits.db import open_ext_db
|
|
||||||
|
|
||||||
|
|
||||||
def m001_initial(db):
|
def m001_initial(db):
|
||||||
"""
|
"""
|
||||||
Initial tposs table.
|
Initial tposs table.
|
||||||
|
@ -15,8 +12,3 @@ def m001_initial(db):
|
||||||
);
|
);
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def migrate():
|
|
||||||
with open_ext_db("tpos") as db:
|
|
||||||
m001_initial(db)
|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
from lnbits.db import open_ext_db
|
|
||||||
|
|
||||||
|
|
||||||
def m001_initial(db):
|
def m001_initial(db):
|
||||||
"""
|
"""
|
||||||
Initial users table.
|
Initial users table.
|
||||||
|
@ -32,8 +29,3 @@ def m001_initial(db):
|
||||||
);
|
);
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def migrate():
|
|
||||||
with open_ext_db("usermanager") as db:
|
|
||||||
m001_initial(db)
|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
from lnbits.db import open_ext_db
|
|
||||||
|
|
||||||
|
|
||||||
def m001_initial(db):
|
def m001_initial(db):
|
||||||
"""
|
"""
|
||||||
Creates an improved withdraw table and migrates the existing data.
|
Creates an improved withdraw table and migrates the existing data.
|
||||||
|
@ -97,9 +94,3 @@ def m002_change_withdraw_table(db):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
db.execute("DROP TABLE withdraw_links")
|
db.execute("DROP TABLE withdraw_links")
|
||||||
|
|
||||||
|
|
||||||
def migrate():
|
|
||||||
with open_ext_db("withdraw") as db:
|
|
||||||
m001_initial(db)
|
|
||||||
m002_change_withdraw_table(db)
|
|
||||||
|
|
4
main.py
Normal file
4
main.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
from lnbits import app, migrate_databases
|
||||||
|
|
||||||
|
migrate_databases()
|
||||||
|
app.run()
|
Loading…
Add table
Reference in a new issue