This is an automated email from the ASF dual-hosted git repository.
vincbeck pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 6f26a388b25 Remove FAB db manager as an `external_db_managers` default
(#48070)
6f26a388b25 is described below
commit 6f26a388b25ba61914cf1de6d2c2bb551126b5e2
Author: Jed Cunningham <[email protected]>
AuthorDate: Wed Apr 2 07:30:27 2025 -0600
Remove FAB db manager as an `external_db_managers` default (#48070)
* Remove FAB db manager as an `external_db_managers` default
Now that the FAB auth manager isn't the default auth manager, it doesn't
makes sense to have the FAB db manager as a default in
`external_db_managers`.
* Update migration to work when FAB is not among configured DB managers
* Sync perms only when using FABAuthManager
* Run tests with or without the fabauthmanager
* Fix tests
* Auth managers can now provide their own db manager!
* Update airflow-core/src/airflow/dag_processing/collection.py
Co-authored-by: Jed Cunningham
<[email protected]>
* Make 'ab_user' table a hard requirement when user is downgrading below
3.0.0
* Apply suggestions from code review
* Fix whitespace in migration test
* use env var for migration test
* properly handle downgrade check
* fixup! properly handle downgrade check
* Update .pre-commit-config.yaml
* apply suggestions from code review
---------
Co-authored-by: Ephraim Anierobi <[email protected]>
---
.github/actions/migration_tests/action.yml | 3 +
airflow-core/docs/img/airflow_erd.svg | 547 +++++----------------
.../src/airflow/config_templates/config.yml | 4 +-
.../src/airflow/dag_processing/collection.py | 6 +-
airflow-core/src/airflow/utils/db.py | 18 +-
airflow-core/src/airflow/utils/db_manager.py | 8 +-
.../tests/unit/dag_processing/test_collection.py | 5 +
airflow-core/tests/unit/utils/test_db.py | 48 +-
airflow-core/tests/unit/utils/test_db_manager.py | 2 +-
.../src/airflow_breeze/params/shell_params.py | 3 +-
devel-common/src/tests_common/pytest_plugin.py | 4 +-
devel-common/src/tests_common/test_utils/db.py | 3 +
12 files changed, 207 insertions(+), 444 deletions(-)
diff --git a/.github/actions/migration_tests/action.yml
b/.github/actions/migration_tests/action.yml
index f6a7b81a2c2..32f77bea198 100644
--- a/.github/actions/migration_tests/action.yml
+++ b/.github/actions/migration_tests/action.yml
@@ -30,6 +30,7 @@ runs:
airflow db migrate"
env:
COMPOSE_PROJECT_NAME: "docker-compose"
+ AIRFLOW__DATABASE__EXTERNAL_DB_MANAGERS:
"airflow.providers.fab.auth_manager.models.db.FABDBManager"
- name: "Bring composer down"
shell: bash
run: breeze down
@@ -45,6 +46,7 @@ runs:
COMPOSE_PROJECT_NAME: "docker-compose"
env:
COMPOSE_PROJECT_NAME: "docker-compose"
+ AIRFLOW__DATABASE__EXTERNAL_DB_MANAGERS:
"airflow.providers.fab.auth_manager.models.db.FABDBManager"
- name: "Bring compose down again"
shell: bash
run: breeze down
@@ -58,6 +60,7 @@ runs:
airflow db migrate -s"
env:
COMPOSE_PROJECT_NAME: "docker-compose"
+ AIRFLOW__DATABASE__EXTERNAL_DB_MANAGERS:
"airflow.providers.fab.auth_manager.models.db.FABDBManager"
if: env.BACKEND != 'sqlite'
- name: "Bring any containers left down"
shell: bash
diff --git a/airflow-core/docs/img/airflow_erd.svg
b/airflow-core/docs/img/airflow_erd.svg
index 2df7e992b7b..f6e4b1c81af 100644
--- a/airflow-core/docs/img/airflow_erd.svg
+++ b/airflow-core/docs/img/airflow_erd.svg
@@ -4,11 +4,11 @@
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: %3 Pages: 1 -->
-<svg width="2108pt" height="4728pt"
- viewBox="0.00 0.00 2108.00 4727.50" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4
4723.5)">
+<svg width="2108pt" height="4054pt"
+ viewBox="0.00 0.00 2108.00 4053.50" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4
4049.5)">
<title>%3</title>
-<polygon fill="white" stroke="transparent" points="-4,4 -4,-4723.5
2104,-4723.5 2104,4 -4,4"/>
+<polygon fill="white" stroke="transparent" points="-4,4 -4,-4049.5
2104,-4049.5 2104,4 -4,4"/>
<!-- dag_priority_parsing_request -->
<g id="node1" class="node">
<title>dag_priority_parsing_request</title>
@@ -305,23 +305,23 @@
<!-- asset_alias -->
<g id="node9" class="node">
<title>asset_alias</title>
-<polygon fill="none" stroke="black" points="515,-2836.5 515,-2864.5
777,-2864.5 777,-2836.5 515,-2836.5"/>
-<text text-anchor="start" x="597" y="-2847.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">asset_alias</text>
-<polygon fill="none" stroke="black" points="515,-2811.5 515,-2836.5
777,-2836.5 777,-2811.5 515,-2811.5"/>
-<text text-anchor="start" x="520" y="-2821.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
-<text text-anchor="start" x="533" y="-2821.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="538" y="-2821.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<text text-anchor="start" x="615" y="-2821.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="515,-2786.5 515,-2811.5
777,-2811.5 777,-2786.5 515,-2786.5"/>
-<text text-anchor="start" x="520" y="-2796.3"
font-family="Helvetica,sans-Serif" font-size="14.00">group</text>
-<text text-anchor="start" x="561" y="-2796.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="566" y="-2796.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(1500)]</text>
-<text text-anchor="start" x="696" y="-2796.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="515,-2761.5 515,-2786.5
777,-2786.5 777,-2761.5 515,-2761.5"/>
-<text text-anchor="start" x="520" y="-2771.3"
font-family="Helvetica,sans-Serif" font-size="14.00">name</text>
-<text text-anchor="start" x="560" y="-2771.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="565" y="-2771.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(1500)]</text>
-<text text-anchor="start" x="695" y="-2771.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
+<polygon fill="none" stroke="black" points="515,-2837.5 515,-2865.5
777,-2865.5 777,-2837.5 515,-2837.5"/>
+<text text-anchor="start" x="597" y="-2848.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">asset_alias</text>
+<polygon fill="none" stroke="black" points="515,-2812.5 515,-2837.5
777,-2837.5 777,-2812.5 515,-2812.5"/>
+<text text-anchor="start" x="520" y="-2822.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
+<text text-anchor="start" x="533" y="-2822.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
+<text text-anchor="start" x="538" y="-2822.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
+<text text-anchor="start" x="615" y="-2822.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
+<polygon fill="none" stroke="black" points="515,-2787.5 515,-2812.5
777,-2812.5 777,-2787.5 515,-2787.5"/>
+<text text-anchor="start" x="520" y="-2797.3"
font-family="Helvetica,sans-Serif" font-size="14.00">group</text>
+<text text-anchor="start" x="561" y="-2797.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
+<text text-anchor="start" x="566" y="-2797.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(1500)]</text>
+<text text-anchor="start" x="696" y="-2797.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
+<polygon fill="none" stroke="black" points="515,-2762.5 515,-2787.5
777,-2787.5 777,-2762.5 515,-2762.5"/>
+<text text-anchor="start" x="520" y="-2772.3"
font-family="Helvetica,sans-Serif" font-size="14.00">name</text>
+<text text-anchor="start" x="560" y="-2772.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
+<text text-anchor="start" x="565" y="-2772.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(1500)]</text>
+<text text-anchor="start" x="695" y="-2772.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
</g>
<!-- asset_alias_asset -->
<g id="node10" class="node">
@@ -342,9 +342,9 @@
<!-- asset_alias--asset_alias_asset -->
<g id="edge1" class="edge">
<title>asset_alias--asset_alias_asset</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M785.19,-2802.35C849.13,-2797.19 924.36,-2791.12 985.83,-2786.16"/>
-<text text-anchor="start" x="954.83" y="-2774.96" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="785.19" y="-2791.15" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M785.19,-2803.05C849.13,-2797.75 924.36,-2791.51 985.83,-2786.42"/>
+<text text-anchor="start" x="954.83" y="-2775.22" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="785.19" y="-2791.85" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- asset_alias_asset_event -->
<g id="node11" class="node">
@@ -365,9 +365,9 @@
<!-- asset_alias--asset_alias_asset_event -->
<g id="edge2" class="edge">
<title>asset_alias--asset_alias_asset_event</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M785.01,-2864.12C812.21,-2879.94 837.9,-2900.11 856,-2925.5 915.19,-3008.53
861.61,-3301.98 929,-3378.5 943.78,-3395.28 963.67,-3406.77 984.78,-3414.61"/>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M785,-2865.12C812.2,-2880.94 837.89,-2901.11 856,-2926.5 915.08,-3009.34
861.74,-3302.15 929,-3378.5 943.78,-3395.28 963.68,-3406.77 984.78,-3414.61"/>
<text text-anchor="start" x="953.78" y="-3403.41" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="785.01" y="-2852.92" font-family="Times,serif"
font-size="14.00">1</text>
+<text text-anchor="start" x="785" y="-2853.92" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- dag_schedule_asset_alias_reference -->
<g id="node12" class="node">
@@ -398,57 +398,57 @@
<!-- asset_alias--dag_schedule_asset_alias_reference -->
<g id="edge3" class="edge">
<title>asset_alias--dag_schedule_asset_alias_reference</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M785.1,-2786.71C810.42,-2777.49 835.34,-2765.1 856,-2748.5 907.05,-2707.47
880.28,-2664.27 929,-2620.5 932.36,-2617.48 935.85,-2614.57 939.46,-2611.76"/>
-<text text-anchor="start" x="908.46" y="-2615.56" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="785.1" y="-2775.51" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M785.18,-2788.53C810.49,-2779.41 835.39,-2767.11 856,-2750.5 907.6,-2708.93
879.85,-2664.95 929,-2620.5 932.35,-2617.47 935.83,-2614.55 939.43,-2611.73"/>
+<text text-anchor="start" x="908.43" y="-2615.53" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="785.18" y="-2777.33" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- asset -->
<g id="node13" class="node">
<title>asset</title>
-<polygon fill="none" stroke="black" points="513,-2707.5 513,-2735.5
779,-2735.5 779,-2707.5 513,-2707.5"/>
-<text text-anchor="start" x="621.5" y="-2718.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">asset</text>
-<polygon fill="none" stroke="black" points="513,-2682.5 513,-2707.5
779,-2707.5 779,-2682.5 513,-2682.5"/>
-<text text-anchor="start" x="518" y="-2692.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
-<text text-anchor="start" x="531" y="-2692.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="536" y="-2692.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<text text-anchor="start" x="613" y="-2692.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="513,-2657.5 513,-2682.5
779,-2682.5 779,-2657.5 513,-2657.5"/>
-<text text-anchor="start" x="518" y="-2667.3"
font-family="Helvetica,sans-Serif" font-size="14.00">created_at</text>
-<text text-anchor="start" x="591" y="-2667.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="596" y="-2667.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [TIMESTAMP]</text>
-<text text-anchor="start" x="692" y="-2667.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="513,-2632.5 513,-2657.5
779,-2657.5 779,-2632.5 513,-2632.5"/>
-<text text-anchor="start" x="518" y="-2642.3"
font-family="Helvetica,sans-Serif" font-size="14.00">extra</text>
-<text text-anchor="start" x="555" y="-2642.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="560" y="-2642.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [JSON]</text>
-<text text-anchor="start" x="611" y="-2642.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="513,-2607.5 513,-2632.5
779,-2632.5 779,-2607.5 513,-2607.5"/>
-<text text-anchor="start" x="518" y="-2617.3"
font-family="Helvetica,sans-Serif" font-size="14.00">group</text>
-<text text-anchor="start" x="559" y="-2617.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="564" y="-2617.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(1500)]</text>
-<text text-anchor="start" x="694" y="-2617.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="513,-2582.5 513,-2607.5
779,-2607.5 779,-2582.5 513,-2582.5"/>
-<text text-anchor="start" x="518" y="-2592.3"
font-family="Helvetica,sans-Serif" font-size="14.00">name</text>
-<text text-anchor="start" x="558" y="-2592.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="563" y="-2592.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(1500)]</text>
-<text text-anchor="start" x="693" y="-2592.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="513,-2557.5 513,-2582.5
779,-2582.5 779,-2557.5 513,-2557.5"/>
-<text text-anchor="start" x="518" y="-2567.3"
font-family="Helvetica,sans-Serif" font-size="14.00">updated_at</text>
-<text text-anchor="start" x="597" y="-2567.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="602" y="-2567.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [TIMESTAMP]</text>
-<text text-anchor="start" x="698" y="-2567.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="513,-2532.5 513,-2557.5
779,-2557.5 779,-2532.5 513,-2532.5"/>
-<text text-anchor="start" x="518" y="-2542.3"
font-family="Helvetica,sans-Serif" font-size="14.00">uri</text>
-<text text-anchor="start" x="537" y="-2542.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="542" y="-2542.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(1500)]</text>
-<text text-anchor="start" x="672" y="-2542.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
+<polygon fill="none" stroke="black" points="513,-2708.5 513,-2736.5
779,-2736.5 779,-2708.5 513,-2708.5"/>
+<text text-anchor="start" x="621.5" y="-2719.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">asset</text>
+<polygon fill="none" stroke="black" points="513,-2683.5 513,-2708.5
779,-2708.5 779,-2683.5 513,-2683.5"/>
+<text text-anchor="start" x="518" y="-2693.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
+<text text-anchor="start" x="531" y="-2693.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
+<text text-anchor="start" x="536" y="-2693.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
+<text text-anchor="start" x="613" y="-2693.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
+<polygon fill="none" stroke="black" points="513,-2658.5 513,-2683.5
779,-2683.5 779,-2658.5 513,-2658.5"/>
+<text text-anchor="start" x="518" y="-2668.3"
font-family="Helvetica,sans-Serif" font-size="14.00">created_at</text>
+<text text-anchor="start" x="591" y="-2668.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
+<text text-anchor="start" x="596" y="-2668.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [TIMESTAMP]</text>
+<text text-anchor="start" x="692" y="-2668.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
+<polygon fill="none" stroke="black" points="513,-2633.5 513,-2658.5
779,-2658.5 779,-2633.5 513,-2633.5"/>
+<text text-anchor="start" x="518" y="-2643.3"
font-family="Helvetica,sans-Serif" font-size="14.00">extra</text>
+<text text-anchor="start" x="555" y="-2643.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
+<text text-anchor="start" x="560" y="-2643.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [JSON]</text>
+<text text-anchor="start" x="611" y="-2643.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
+<polygon fill="none" stroke="black" points="513,-2608.5 513,-2633.5
779,-2633.5 779,-2608.5 513,-2608.5"/>
+<text text-anchor="start" x="518" y="-2618.3"
font-family="Helvetica,sans-Serif" font-size="14.00">group</text>
+<text text-anchor="start" x="559" y="-2618.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
+<text text-anchor="start" x="564" y="-2618.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(1500)]</text>
+<text text-anchor="start" x="694" y="-2618.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
+<polygon fill="none" stroke="black" points="513,-2583.5 513,-2608.5
779,-2608.5 779,-2583.5 513,-2583.5"/>
+<text text-anchor="start" x="518" y="-2593.3"
font-family="Helvetica,sans-Serif" font-size="14.00">name</text>
+<text text-anchor="start" x="558" y="-2593.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
+<text text-anchor="start" x="563" y="-2593.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(1500)]</text>
+<text text-anchor="start" x="693" y="-2593.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
+<polygon fill="none" stroke="black" points="513,-2558.5 513,-2583.5
779,-2583.5 779,-2558.5 513,-2558.5"/>
+<text text-anchor="start" x="518" y="-2568.3"
font-family="Helvetica,sans-Serif" font-size="14.00">updated_at</text>
+<text text-anchor="start" x="597" y="-2568.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
+<text text-anchor="start" x="602" y="-2568.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [TIMESTAMP]</text>
+<text text-anchor="start" x="698" y="-2568.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
+<polygon fill="none" stroke="black" points="513,-2533.5 513,-2558.5
779,-2558.5 779,-2533.5 513,-2533.5"/>
+<text text-anchor="start" x="518" y="-2543.3"
font-family="Helvetica,sans-Serif" font-size="14.00">uri</text>
+<text text-anchor="start" x="537" y="-2543.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
+<text text-anchor="start" x="542" y="-2543.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(1500)]</text>
+<text text-anchor="start" x="672" y="-2543.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
</g>
<!-- asset--asset_alias_asset -->
<g id="edge4" class="edge">
<title>asset--asset_alias_asset</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M787.02,-2679.87C832.26,-2694.35 882.69,-2710.29 929,-2724.5 947.32,-2730.12
966.75,-2735.97 985.76,-2741.62"/>
-<text text-anchor="start" x="954.76" y="-2730.42" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="787.02" y="-2668.67" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M787.05,-2680.28C832.29,-2694.59 882.72,-2710.38 929,-2724.5 947.33,-2730.09
966.77,-2735.92 985.78,-2741.57"/>
+<text text-anchor="start" x="954.78" y="-2730.37" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="787.05" y="-2669.08" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- asset_trigger -->
<g id="node14" class="node">
@@ -469,9 +469,9 @@
<!-- asset--asset_trigger -->
<g id="edge5" class="edge">
<title>asset--asset_trigger</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M787.12,-2702.49C810.99,-2716.41 834.86,-2731.92 856,-2748.5 893.87,-2778.21
888.19,-2802.98 929,-2828.5 944.84,-2838.41 962.66,-2846.5 980.73,-2853.1"/>
-<text text-anchor="start" x="949.73" y="-2841.9" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="787.12" y="-2691.29" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M787.2,-2704.6C811,-2718.55 834.83,-2734.04 856,-2750.5 893.49,-2779.64
888.58,-2803.58 929,-2828.5 944.91,-2838.31 962.76,-2846.35 980.84,-2852.92"/>
+<text text-anchor="start" x="949.84" y="-2841.72" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="787.2" y="-2693.4" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- asset_active -->
<g id="node15" class="node">
@@ -492,16 +492,16 @@
<!-- asset--asset_active -->
<g id="edge6" class="edge">
<title>asset--asset_active</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M787.06,-2639.83C844.47,-2643.95 910.72,-2649.45 967.88,-2654.85"/>
-<text text-anchor="start" x="957.88" y="-2643.65" font-family="Times,serif"
font-size="14.00">1</text>
-<text text-anchor="start" x="787.06" y="-2628.63" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M787.06,-2640.53C844.47,-2644.52 910.72,-2649.87 967.88,-2655.15"/>
+<text text-anchor="start" x="957.88" y="-2643.95" font-family="Times,serif"
font-size="14.00">1</text>
+<text text-anchor="start" x="787.06" y="-2629.33" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- asset--asset_active -->
<g id="edge7" class="edge">
<title>asset--asset_active</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M787.06,-2652.38C844.47,-2657.78 910.72,-2663.27 967.88,-2667.34"/>
-<text text-anchor="start" x="957.88" y="-2671.14" font-family="Times,serif"
font-size="14.00">1</text>
-<text text-anchor="start" x="787.06" y="-2652.43" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M787.06,-2653.08C844.47,-2658.35 910.72,-2663.69 967.88,-2667.64"/>
+<text text-anchor="start" x="957.88" y="-2671.44" font-family="Times,serif"
font-size="14.00">1</text>
+<text text-anchor="start" x="787.06" y="-2653.13" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- dag_schedule_asset_reference -->
<g id="node16" class="node">
@@ -532,9 +532,9 @@
<!-- asset--dag_schedule_asset_reference -->
<g id="edge8" class="edge">
<title>asset--dag_schedule_asset_reference</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M787.05,-2546.35C831.74,-2519.5 881.85,-2490.71 929,-2466.5 938.07,-2461.84
947.49,-2457.2 957.03,-2452.64"/>
-<text text-anchor="start" x="926.03" y="-2441.44" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="787.05" y="-2535.15" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M787.36,-2546.55C831.96,-2519.6 881.94,-2490.74 929,-2466.5 938.21,-2461.75
947.78,-2457.03 957.49,-2452.39"/>
+<text text-anchor="start" x="926.49" y="-2441.19" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="787.36" y="-2535.35" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- task_outlet_asset_reference -->
<g id="node17" class="node">
@@ -570,9 +570,9 @@
<!-- asset--task_outlet_asset_reference -->
<g id="edge9" class="edge">
<title>asset--task_outlet_asset_reference</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M692.34,-2528.87C739.48,-2429.18 821.43,-2280.73 929,-2182.5 940.02,-2172.43
952.4,-2163.22 965.34,-2154.86"/>
-<text text-anchor="start" x="934.34" y="-2143.66" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="682.34" y="-2517.67" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M692.44,-2529.98C739.65,-2430.36 821.65,-2281.97 929,-2183.5 940.03,-2173.39
952.4,-2164.11 965.35,-2155.68"/>
+<text text-anchor="start" x="934.35" y="-2144.48" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="682.44" y="-2518.78" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- asset_dag_run_queue -->
<g id="node18" class="node">
@@ -598,9 +598,9 @@
<!-- asset--asset_dag_run_queue -->
<g id="edge10" class="edge">
<title>asset--asset_dag_run_queue</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M717.92,-2528.97C769.42,-2459.3 844.64,-2370.48 929,-2312.5 934.25,-2308.89
939.72,-2305.46 945.35,-2302.19"/>
-<text text-anchor="start" x="914.35" y="-2290.99" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="707.92" y="-2517.77" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M717.86,-2529.64C769.32,-2459.74 844.54,-2370.65 929,-2312.5 934.24,-2308.89
939.71,-2305.45 945.34,-2302.18"/>
+<text text-anchor="start" x="914.34" y="-2290.98" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="707.86" y="-2518.44" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- asset_event -->
<g id="node19" class="node">
@@ -647,9 +647,9 @@
<!-- asset_event--asset_alias_asset_event -->
<g id="edge11" class="edge">
<title>asset_event--asset_alias_asset_event</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M785.2,-3863.32C811.72,-3845.77 837.08,-3824.54 856,-3799.5 928.61,-3703.39
856.37,-3634.59 929,-3538.5 949.14,-3511.85 977.95,-3490.31 1006.46,-3473.68"/>
-<text text-anchor="start" x="975.46" y="-3477.48" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="785.2" y="-3852.12" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M785.19,-3863.99C811.72,-3846.57 837.08,-3825.45 856,-3800.5 928.78,-3704.52
856.57,-3635.74 929,-3539.5 949.36,-3512.45 978.56,-3490.57 1007.37,-3473.71"/>
+<text text-anchor="start" x="976.37" y="-3477.51" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="785.19" y="-3852.79" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- dagrun_asset_event -->
<g id="node20" class="node">
@@ -977,30 +977,30 @@
<!-- task_instance--task_map -->
<g id="edge43" class="edge">
<title>task_instance--task_map</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M1692.06,-3469.79C1719.29,-3494.49 1747.87,-3519.35 1776,-3541.5
1791.9,-3554.02 1809.37,-3566.42 1826.75,-3578.41"/>
-<text text-anchor="start" x="1795.75" y="-3567.21" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="1692.06" y="-3458.59" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M1692.25,-3470.93C1719.4,-3495.61 1747.9,-3520.43 1776,-3542.5
1791.48,-3554.66 1808.47,-3566.68 1825.42,-3578.3"/>
+<text text-anchor="start" x="1794.42" y="-3567.1" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="1692.25" y="-3459.73" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- task_instance--task_map -->
<g id="edge44" class="edge">
<title>task_instance--task_map</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M1692.06,-3487.55C1719.29,-3512.49 1747.87,-3537.35 1776,-3559.5
1784.08,-3565.86 1792.57,-3572.19 1801.24,-3578.43"/>
-<text text-anchor="start" x="1770.24" y="-3582.23" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="1692.06" y="-3476.35" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M1692.25,-3488.7C1719.4,-3513.61 1747.9,-3538.43 1776,-3560.5
1783.68,-3566.53 1791.72,-3572.52 1799.95,-3578.42"/>
+<text text-anchor="start" x="1768.95" y="-3582.22" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="1692.25" y="-3477.5" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- task_instance--task_map -->
<g id="edge45" class="edge">
<title>task_instance--task_map</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M1692.06,-3505.31C1719.29,-3530.49 1747.87,-3555.35 1776,-3577.5
1783.43,-3583.35 1791.2,-3589.17 1799.15,-3594.89"/>
-<text text-anchor="start" x="1768.15" y="-3598.69" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="1692.06" y="-3494.11" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M1692.25,-3506.46C1719.4,-3531.61 1747.9,-3556.43 1776,-3578.5
1783.42,-3584.32 1791.18,-3590.12 1799.11,-3595.8"/>
+<text text-anchor="start" x="1768.11" y="-3599.6" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="1692.25" y="-3495.26" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- task_instance--task_map -->
<g id="edge46" class="edge">
<title>task_instance--task_map</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M1692.06,-3523.07C1719.29,-3548.49 1747.87,-3573.35 1776,-3595.5
1783.43,-3601.35 1791.2,-3607.17 1799.15,-3612.87"/>
-<text text-anchor="start" x="1768.15" y="-3616.67" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="1692.06" y="-3511.87" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M1692.25,-3524.22C1719.4,-3549.61 1747.9,-3574.43 1776,-3596.5
1783.42,-3602.32 1791.18,-3608.12 1799.11,-3613.77"/>
+<text text-anchor="start" x="1768.11" y="-3617.57" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="1692.25" y="-3513.02" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- task_reschedule -->
<g id="node41" class="node">
@@ -1474,9 +1474,9 @@
<!-- dag_run--dagrun_asset_event -->
<g id="edge16" class="edge">
<title>dag_run--dagrun_asset_event</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M795.55,-3620.01C881.21,-3683.15 984.1,-3759 1047.13,-3805.47"/>
-<text text-anchor="start" x="1016.13" y="-3794.27" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="795.55" y="-3608.81" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M795.53,-3620.09C838.58,-3651.84 885.66,-3686.56 929,-3718.5 968.37,-3747.52
1012.68,-3780.16 1047.06,-3805.47"/>
+<text text-anchor="start" x="1016.06" y="-3794.27" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="795.53" y="-3608.89" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- dag_run--task_instance -->
<g id="edge20" class="edge">
@@ -1678,9 +1678,9 @@
<!-- backfill--backfill_dag_run -->
<g id="edge23" class="edge">
<title>backfill--backfill_dag_run</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M363.17,-3217.95C499.11,-3208.6 689.78,-3202.07 856,-3220.5 891.3,-3224.41
928.9,-3231.35 963.92,-3239.04"/>
-<text text-anchor="start" x="932.92" y="-3227.84" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="363.17" y="-3206.75" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M363.15,-3218.55C499.08,-3209.57 689.75,-3203.39 856,-3221.5 891.28,-3225.34
928.87,-3232.15 963.89,-3239.7"/>
+<text text-anchor="start" x="932.89" y="-3228.5" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="363.15" y="-3207.35" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- dag_bundle -->
<g id="node29" class="node">
@@ -1828,9 +1828,9 @@
<!-- dag--dag_schedule_asset_reference -->
<g id="edge28" class="edge">
<title>dag--dag_schedule_asset_reference</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M856.21,-2242.82C879.15,-2267.64 903.5,-2290.99 929,-2311.5 937.75,-2318.53
947.22,-2325.06 957.09,-2331.1"/>
-<text text-anchor="start" x="926.09" y="-2319.9" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="856.21" y="-2231.62" font-family="Times,serif"
font-size="14.00">1</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M856.04,-2243.78C879.02,-2268.63 903.42,-2292 929,-2312.5 937.74,-2319.5
947.21,-2325.99 957.08,-2331.98"/>
+<text text-anchor="start" x="926.08" y="-2320.78" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="856.04" y="-2232.58" font-family="Times,serif"
font-size="14.00">1</text>
</g>
<!-- dag--task_outlet_asset_reference -->
<g id="edge29" class="edge">
@@ -1849,9 +1849,9 @@
<!-- dag--deadline -->
<g id="edge35" class="edge">
<title>dag--deadline</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M769.94,-2244.74C801.01,-2332.83 832.25,-2429.1 856,-2519.5 903.36,-2699.78
822.08,-2779.81 929,-2932.5 938.54,-2946.13 950.53,-2958.19 963.74,-2968.8"/>
-<text text-anchor="start" x="932.74" y="-2957.6" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="769.94" y="-2248.54" font-family="Times,serif"
font-size="14.00">{0,1}</text>
+<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M769.45,-2244.69C800.65,-2333.4 832.09,-2430.43 856,-2521.5 903.12,-2700.94
822.52,-2780.57 929,-2932.5 938.55,-2946.12 950.54,-2958.18 963.75,-2968.79"/>
+<text text-anchor="start" x="932.75" y="-2957.59" font-family="Times,serif"
font-size="14.00">0..N</text>
+<text text-anchor="start" x="769.45" y="-2248.49" font-family="Times,serif"
font-size="14.00">{0,1}</text>
</g>
<!-- dag_schedule_asset_name_reference -->
<g id="node31" class="node">
@@ -2154,318 +2154,13 @@
<!-- alembic_version -->
<g id="node45" class="node">
<title>alembic_version</title>
-<polygon fill="none" stroke="black" points="35.5,-3825.5 35.5,-3853.5
328.5,-3853.5 328.5,-3825.5 35.5,-3825.5"/>
-<text text-anchor="start" x="109.5" y="-3836.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">alembic_version</text>
-<polygon fill="none" stroke="black" points="35.5,-3800.5 35.5,-3825.5
328.5,-3825.5 328.5,-3800.5 35.5,-3800.5"/>
-<text text-anchor="start" x="40.5" y="-3810.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">version_num</text>
-<text text-anchor="start" x="130.5" y="-3810.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="135.5" y="-3810.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(32)]</text>
-<text text-anchor="start" x="247.5" y="-3810.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-</g>
-<!-- ab_user -->
-<g id="node46" class="node">
-<title>ab_user</title>
-<polygon fill="none" stroke="black" points="503,-4651.5 503,-4679.5
789,-4679.5 789,-4651.5 503,-4651.5"/>
-<text text-anchor="start" x="611" y="-4662.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">ab_user</text>
-<polygon fill="none" stroke="black" points="503,-4626.5 503,-4651.5
789,-4651.5 789,-4626.5 503,-4626.5"/>
-<text text-anchor="start" x="508" y="-4636.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
-<text text-anchor="start" x="521" y="-4636.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="526" y="-4636.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<text text-anchor="start" x="603" y="-4636.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="503,-4601.5 503,-4626.5
789,-4626.5 789,-4601.5 503,-4601.5"/>
-<text text-anchor="start" x="508" y="-4611.3"
font-family="Helvetica,sans-Serif" font-size="14.00">active</text>
-<text text-anchor="start" x="550" y="-4611.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="555" y="-4611.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [BOOLEAN]</text>
-<polygon fill="none" stroke="black" points="503,-4576.5 503,-4601.5
789,-4601.5 789,-4576.5 503,-4576.5"/>
-<text text-anchor="start" x="508" y="-4586.3"
font-family="Helvetica,sans-Serif" font-size="14.00">changed_by_fk</text>
-<text text-anchor="start" x="613" y="-4586.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="618" y="-4586.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<polygon fill="none" stroke="black" points="503,-4551.5 503,-4576.5
789,-4576.5 789,-4551.5 503,-4551.5"/>
-<text text-anchor="start" x="508" y="-4561.3"
font-family="Helvetica,sans-Serif" font-size="14.00">changed_on</text>
-<text text-anchor="start" x="593" y="-4561.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="598" y="-4561.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [TIMESTAMP]</text>
-<polygon fill="none" stroke="black" points="503,-4526.5 503,-4551.5
789,-4551.5 789,-4526.5 503,-4526.5"/>
-<text text-anchor="start" x="508" y="-4536.3"
font-family="Helvetica,sans-Serif" font-size="14.00">created_by_fk</text>
-<text text-anchor="start" x="605" y="-4536.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="610" y="-4536.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<polygon fill="none" stroke="black" points="503,-4501.5 503,-4526.5
789,-4526.5 789,-4501.5 503,-4501.5"/>
-<text text-anchor="start" x="508" y="-4511.3"
font-family="Helvetica,sans-Serif" font-size="14.00">created_on</text>
-<text text-anchor="start" x="584" y="-4511.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="589" y="-4511.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [TIMESTAMP]</text>
-<polygon fill="none" stroke="black" points="503,-4476.5 503,-4501.5
789,-4501.5 789,-4476.5 503,-4476.5"/>
-<text text-anchor="start" x="508" y="-4486.3"
font-family="Helvetica,sans-Serif" font-size="14.00">email</text>
-<text text-anchor="start" x="546" y="-4486.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="551" y="-4486.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(512)]</text>
-<text text-anchor="start" x="672" y="-4486.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="503,-4451.5 503,-4476.5
789,-4476.5 789,-4451.5 503,-4451.5"/>
-<text text-anchor="start" x="508" y="-4461.3"
font-family="Helvetica,sans-Serif" font-size="14.00">fail_login_count</text>
-<text text-anchor="start" x="616" y="-4461.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="621" y="-4461.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<polygon fill="none" stroke="black" points="503,-4426.5 503,-4451.5
789,-4451.5 789,-4426.5 503,-4426.5"/>
-<text text-anchor="start" x="508" y="-4436.3"
font-family="Helvetica,sans-Serif" font-size="14.00">first_name</text>
-<text text-anchor="start" x="582" y="-4436.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="587" y="-4436.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(256)]</text>
-<text text-anchor="start" x="708" y="-4436.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="503,-4401.5 503,-4426.5
789,-4426.5 789,-4401.5 503,-4401.5"/>
-<text text-anchor="start" x="508" y="-4411.3"
font-family="Helvetica,sans-Serif" font-size="14.00">last_login</text>
-<text text-anchor="start" x="574" y="-4411.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="579" y="-4411.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [TIMESTAMP]</text>
-<polygon fill="none" stroke="black" points="503,-4376.5 503,-4401.5
789,-4401.5 789,-4376.5 503,-4376.5"/>
-<text text-anchor="start" x="508" y="-4386.3"
font-family="Helvetica,sans-Serif" font-size="14.00">last_name</text>
-<text text-anchor="start" x="579" y="-4386.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="584" y="-4386.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(256)]</text>
-<text text-anchor="start" x="705" y="-4386.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="503,-4351.5 503,-4376.5
789,-4376.5 789,-4351.5 503,-4351.5"/>
-<text text-anchor="start" x="508" y="-4361.3"
font-family="Helvetica,sans-Serif" font-size="14.00">login_count</text>
-<text text-anchor="start" x="588" y="-4361.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="593" y="-4361.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<polygon fill="none" stroke="black" points="503,-4326.5 503,-4351.5
789,-4351.5 789,-4326.5 503,-4326.5"/>
-<text text-anchor="start" x="508" y="-4336.3"
font-family="Helvetica,sans-Serif" font-size="14.00">password</text>
-<text text-anchor="start" x="575" y="-4336.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="580" y="-4336.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(256)]</text>
-<polygon fill="none" stroke="black" points="503,-4301.5 503,-4326.5
789,-4326.5 789,-4301.5 503,-4301.5"/>
-<text text-anchor="start" x="508" y="-4311.3"
font-family="Helvetica,sans-Serif" font-size="14.00">username</text>
-<text text-anchor="start" x="578" y="-4311.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="583" y="-4311.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(512)]</text>
-<text text-anchor="start" x="704" y="-4311.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-</g>
-<!-- ab_user--ab_user -->
-<g id="edge57" class="edge">
-<title>ab_user--ab_user</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M630.23,-4683.52C634.02,-4694.77 639.27,-4701.5 646,-4701.5 652.73,-4701.5
657.98,-4694.77 661.77,-4683.52"/>
-<text text-anchor="start" x="661.77" y="-4687.32" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="630.23" y="-4687.32" font-family="Times,serif"
font-size="14.00">{0,1}</text>
-</g>
-<!-- ab_user--ab_user -->
-<g id="edge58" class="edge">
-<title>ab_user--ab_user</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M607.05,-4683.88C614.4,-4705.51 627.38,-4719.5 646,-4719.5 664.62,-4719.5
677.6,-4705.51 684.95,-4683.88"/>
-<text text-anchor="start" x="684.95" y="-4687.68" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="566.05" y="-4687.68" font-family="Times,serif"
font-size="14.00">{0,1}</text>
-</g>
-<!-- ab_user_role -->
-<g id="node47" class="node">
-<title>ab_user_role</title>
-<polygon fill="none" stroke="black" points="1016.5,-4335.5 1016.5,-4363.5
1197.5,-4363.5 1197.5,-4335.5 1016.5,-4335.5"/>
-<text text-anchor="start" x="1050" y="-4346.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">ab_user_role</text>
-<polygon fill="none" stroke="black" points="1016.5,-4310.5 1016.5,-4335.5
1197.5,-4335.5 1197.5,-4310.5 1016.5,-4310.5"/>
-<text text-anchor="start" x="1021.5" y="-4320.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
-<text text-anchor="start" x="1034.5" y="-4320.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="1039.5" y="-4320.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<text text-anchor="start" x="1116.5" y="-4320.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="1016.5,-4285.5 1016.5,-4310.5
1197.5,-4310.5 1197.5,-4285.5 1016.5,-4285.5"/>
-<text text-anchor="start" x="1021.5" y="-4295.3"
font-family="Helvetica,sans-Serif" font-size="14.00">role_id</text>
-<text text-anchor="start" x="1067.5" y="-4295.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="1072.5" y="-4295.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<polygon fill="none" stroke="black" points="1016.5,-4260.5 1016.5,-4285.5
1197.5,-4285.5 1197.5,-4260.5 1016.5,-4260.5"/>
-<text text-anchor="start" x="1021.5" y="-4270.3"
font-family="Helvetica,sans-Serif" font-size="14.00">user_id</text>
-<text text-anchor="start" x="1072.5" y="-4270.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="1077.5" y="-4270.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-</g>
-<!-- ab_user--ab_user_role -->
-<g id="edge59" class="edge">
-<title>ab_user--ab_user_role</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M797.13,-4432.22C866.34,-4405.35 946.51,-4374.22 1007.76,-4350.44"/>
-<text text-anchor="start" x="976.76" y="-4339.24" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="797.13" y="-4421.02" font-family="Times,serif"
font-size="14.00">{0,1}</text>
-</g>
-<!-- ab_register_user -->
-<g id="node48" class="node">
-<title>ab_register_user</title>
-<polygon fill="none" stroke="black" points="38.5,-4436.5 38.5,-4464.5
324.5,-4464.5 324.5,-4436.5 38.5,-4436.5"/>
-<text text-anchor="start" x="106.5" y="-4447.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">ab_register_user</text>
-<polygon fill="none" stroke="black" points="38.5,-4411.5 38.5,-4436.5
324.5,-4436.5 324.5,-4411.5 38.5,-4411.5"/>
-<text text-anchor="start" x="43.5" y="-4421.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
-<text text-anchor="start" x="56.5" y="-4421.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="61.5" y="-4421.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<text text-anchor="start" x="138.5" y="-4421.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="38.5,-4386.5 38.5,-4411.5
324.5,-4411.5 324.5,-4386.5 38.5,-4386.5"/>
-<text text-anchor="start" x="43.5" y="-4396.3"
font-family="Helvetica,sans-Serif" font-size="14.00">email</text>
-<text text-anchor="start" x="81.5" y="-4396.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="86.5" y="-4396.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(512)]</text>
-<text text-anchor="start" x="207.5" y="-4396.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="38.5,-4361.5 38.5,-4386.5
324.5,-4386.5 324.5,-4361.5 38.5,-4361.5"/>
-<text text-anchor="start" x="43.5" y="-4371.3"
font-family="Helvetica,sans-Serif" font-size="14.00">first_name</text>
-<text text-anchor="start" x="117.5" y="-4371.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="122.5" y="-4371.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(256)]</text>
-<text text-anchor="start" x="243.5" y="-4371.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="38.5,-4336.5 38.5,-4361.5
324.5,-4361.5 324.5,-4336.5 38.5,-4336.5"/>
-<text text-anchor="start" x="43.5" y="-4346.3"
font-family="Helvetica,sans-Serif" font-size="14.00">last_name</text>
-<text text-anchor="start" x="114.5" y="-4346.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="119.5" y="-4346.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(256)]</text>
-<text text-anchor="start" x="240.5" y="-4346.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="38.5,-4311.5 38.5,-4336.5
324.5,-4336.5 324.5,-4311.5 38.5,-4311.5"/>
-<text text-anchor="start" x="43.5" y="-4321.3"
font-family="Helvetica,sans-Serif" font-size="14.00">password</text>
-<text text-anchor="start" x="110.5" y="-4321.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="115.5" y="-4321.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(256)]</text>
-<polygon fill="none" stroke="black" points="38.5,-4286.5 38.5,-4311.5
324.5,-4311.5 324.5,-4286.5 38.5,-4286.5"/>
-<text text-anchor="start" x="43.5" y="-4296.3"
font-family="Helvetica,sans-Serif" font-size="14.00">registration_date</text>
-<text text-anchor="start" x="161.5" y="-4296.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="166.5" y="-4296.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [TIMESTAMP]</text>
-<polygon fill="none" stroke="black" points="38.5,-4261.5 38.5,-4286.5
324.5,-4286.5 324.5,-4261.5 38.5,-4261.5"/>
-<text text-anchor="start" x="43.5" y="-4271.3"
font-family="Helvetica,sans-Serif" font-size="14.00">registration_hash</text>
-<text text-anchor="start" x="164.5" y="-4271.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="169.5" y="-4271.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(256)]</text>
-<polygon fill="none" stroke="black" points="38.5,-4236.5 38.5,-4261.5
324.5,-4261.5 324.5,-4236.5 38.5,-4236.5"/>
-<text text-anchor="start" x="43.5" y="-4246.3"
font-family="Helvetica,sans-Serif" font-size="14.00">username</text>
-<text text-anchor="start" x="113.5" y="-4246.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="118.5" y="-4246.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(512)]</text>
-<text text-anchor="start" x="239.5" y="-4246.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-</g>
-<!-- ab_permission -->
-<g id="node49" class="node">
-<title>ab_permission</title>
-<polygon fill="none" stroke="black" points="55.5,-4182.5 55.5,-4210.5
307.5,-4210.5 307.5,-4182.5 55.5,-4182.5"/>
-<text text-anchor="start" x="116.5" y="-4193.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">ab_permission</text>
-<polygon fill="none" stroke="black" points="55.5,-4157.5 55.5,-4182.5
307.5,-4182.5 307.5,-4157.5 55.5,-4157.5"/>
-<text text-anchor="start" x="60.5" y="-4167.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
-<text text-anchor="start" x="73.5" y="-4167.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="78.5" y="-4167.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<text text-anchor="start" x="155.5" y="-4167.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="55.5,-4132.5 55.5,-4157.5
307.5,-4157.5 307.5,-4132.5 55.5,-4132.5"/>
-<text text-anchor="start" x="60.5" y="-4142.3"
font-family="Helvetica,sans-Serif" font-size="14.00">name</text>
-<text text-anchor="start" x="100.5" y="-4142.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="105.5" y="-4142.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(100)]</text>
-<text text-anchor="start" x="226.5" y="-4142.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-</g>
-<!-- ab_permission_view -->
-<g id="node50" class="node">
-<title>ab_permission_view</title>
-<polygon fill="none" stroke="black" points="551,-4142.5 551,-4170.5
741,-4170.5 741,-4142.5 551,-4142.5"/>
-<text text-anchor="start" x="556.5" y="-4153.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">ab_permission_view</text>
-<polygon fill="none" stroke="black" points="551,-4117.5 551,-4142.5
741,-4142.5 741,-4117.5 551,-4117.5"/>
-<text text-anchor="start" x="556" y="-4127.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
-<text text-anchor="start" x="569" y="-4127.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="574" y="-4127.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<text text-anchor="start" x="651" y="-4127.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="551,-4092.5 551,-4117.5
741,-4117.5 741,-4092.5 551,-4092.5"/>
-<text text-anchor="start" x="556" y="-4102.3"
font-family="Helvetica,sans-Serif" font-size="14.00">permission_id</text>
-<text text-anchor="start" x="652" y="-4102.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="657" y="-4102.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<polygon fill="none" stroke="black" points="551,-4067.5 551,-4092.5
741,-4092.5 741,-4067.5 551,-4067.5"/>
-<text text-anchor="start" x="556" y="-4077.3"
font-family="Helvetica,sans-Serif" font-size="14.00">view_menu_id</text>
-<text text-anchor="start" x="654" y="-4077.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="659" y="-4077.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-</g>
-<!-- ab_permission--ab_permission_view -->
-<g id="edge60" class="edge">
-<title>ab_permission--ab_permission_view</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M315.65,-4156.53C387.97,-4148.4 476,-4138.5 542.85,-4130.98"/>
-<text text-anchor="start" x="511.85" y="-4119.78" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="315.65" y="-4145.33" font-family="Times,serif"
font-size="14.00">{0,1}</text>
-</g>
-<!-- ab_permission_view_role -->
-<g id="node51" class="node">
-<title>ab_permission_view_role</title>
-<polygon fill="none" stroke="black" points="990.5,-4193.5 990.5,-4221.5
1223.5,-4221.5 1223.5,-4193.5 990.5,-4193.5"/>
-<text text-anchor="start" x="995.5" y="-4204.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">ab_permission_view_role</text>
-<polygon fill="none" stroke="black" points="990.5,-4168.5 990.5,-4193.5
1223.5,-4193.5 1223.5,-4168.5 990.5,-4168.5"/>
-<text text-anchor="start" x="995.5" y="-4178.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
-<text text-anchor="start" x="1008.5" y="-4178.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="1013.5" y="-4178.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<text text-anchor="start" x="1090.5" y="-4178.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="990.5,-4143.5 990.5,-4168.5
1223.5,-4168.5 1223.5,-4143.5 990.5,-4143.5"/>
-<text text-anchor="start" x="995.5" y="-4153.3"
font-family="Helvetica,sans-Serif" font-size="14.00">permission_view_id</text>
-<text text-anchor="start" x="1129.5" y="-4153.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="1134.5" y="-4153.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<polygon fill="none" stroke="black" points="990.5,-4118.5 990.5,-4143.5
1223.5,-4143.5 1223.5,-4118.5 990.5,-4118.5"/>
-<text text-anchor="start" x="995.5" y="-4128.3"
font-family="Helvetica,sans-Serif" font-size="14.00">role_id</text>
-<text text-anchor="start" x="1041.5" y="-4128.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="1046.5" y="-4128.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-</g>
-<!-- ab_permission_view--ab_permission_view_role -->
-<g id="edge61" class="edge">
-<title>ab_permission_view--ab_permission_view_role</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M749.04,-4130.85C817.78,-4138.5 908.85,-4148.63 981.73,-4156.73"/>
-<text text-anchor="start" x="950.73" y="-4145.53" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="749.04" y="-4119.65" font-family="Times,serif"
font-size="14.00">{0,1}</text>
-</g>
-<!-- ab_view_menu -->
-<g id="node52" class="node">
-<title>ab_view_menu</title>
-<polygon fill="none" stroke="black" points="55.5,-4078.5 55.5,-4106.5
307.5,-4106.5 307.5,-4078.5 55.5,-4078.5"/>
-<text text-anchor="start" x="116.5" y="-4089.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">ab_view_menu</text>
-<polygon fill="none" stroke="black" points="55.5,-4053.5 55.5,-4078.5
307.5,-4078.5 307.5,-4053.5 55.5,-4053.5"/>
-<text text-anchor="start" x="60.5" y="-4063.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
-<text text-anchor="start" x="73.5" y="-4063.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="78.5" y="-4063.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<text text-anchor="start" x="155.5" y="-4063.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="55.5,-4028.5 55.5,-4053.5
307.5,-4053.5 307.5,-4028.5 55.5,-4028.5"/>
-<text text-anchor="start" x="60.5" y="-4038.3"
font-family="Helvetica,sans-Serif" font-size="14.00">name</text>
-<text text-anchor="start" x="100.5" y="-4038.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="105.5" y="-4038.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(250)]</text>
-<text text-anchor="start" x="226.5" y="-4038.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-</g>
-<!-- ab_view_menu--ab_permission_view -->
-<g id="edge62" class="edge">
-<title>ab_view_menu--ab_permission_view</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M315.65,-4082.47C387.97,-4090.6 476,-4100.5 542.85,-4108.02"/>
-<text text-anchor="start" x="511.85" y="-4096.82" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="315.65" y="-4071.27" font-family="Times,serif"
font-size="14.00">{0,1}</text>
-</g>
-<!-- ab_role -->
-<g id="node53" class="node">
-<title>ab_role</title>
-<polygon fill="none" stroke="black" points="525,-4247.5 525,-4275.5
768,-4275.5 768,-4247.5 525,-4247.5"/>
-<text text-anchor="start" x="613.5" y="-4258.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">ab_role</text>
-<polygon fill="none" stroke="black" points="525,-4222.5 525,-4247.5
768,-4247.5 768,-4222.5 525,-4222.5"/>
-<text text-anchor="start" x="530" y="-4232.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
-<text text-anchor="start" x="543" y="-4232.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="548" y="-4232.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<text text-anchor="start" x="625" y="-4232.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="525,-4197.5 525,-4222.5
768,-4222.5 768,-4197.5 525,-4197.5"/>
-<text text-anchor="start" x="530" y="-4207.3"
font-family="Helvetica,sans-Serif" font-size="14.00">name</text>
-<text text-anchor="start" x="570" y="-4207.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="575" y="-4207.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(64)]</text>
-<text text-anchor="start" x="687" y="-4207.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-</g>
-<!-- ab_role--ab_user_role -->
-<g id="edge63" class="edge">
-<title>ab_role--ab_user_role</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M775.63,-4257.82C849.27,-4270.03 940.2,-4285.1 1007.92,-4296.33"/>
-<text text-anchor="start" x="976.92" y="-4285.13" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="775.63" y="-4246.62" font-family="Times,serif"
font-size="14.00">{0,1}</text>
-</g>
-<!-- ab_role--ab_permission_view_role -->
-<g id="edge64" class="edge">
-<title>ab_role--ab_permission_view_role</title>
-<path fill="none" stroke="#7f7f7f" stroke-dasharray="5,2"
d="M775.63,-4217.98C840.13,-4208.7 917.89,-4197.51 981.71,-4188.32"/>
-<text text-anchor="start" x="950.71" y="-4177.12" font-family="Times,serif"
font-size="14.00">0..N</text>
-<text text-anchor="start" x="775.63" y="-4206.78" font-family="Times,serif"
font-size="14.00">{0,1}</text>
-</g>
-<!-- alembic_version_fab -->
-<g id="node54" class="node">
-<title>alembic_version_fab</title>
-<polygon fill="none" stroke="black" points="35.5,-4515.5 35.5,-4543.5
328.5,-4543.5 328.5,-4515.5 35.5,-4515.5"/>
-<text text-anchor="start" x="91.5" y="-4526.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">alembic_version_fab</text>
-<polygon fill="none" stroke="black" points="35.5,-4490.5 35.5,-4515.5
328.5,-4515.5 328.5,-4490.5 35.5,-4490.5"/>
-<text text-anchor="start" x="40.5" y="-4500.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">version_num</text>
-<text text-anchor="start" x="130.5" y="-4500.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="135.5" y="-4500.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(32)]</text>
-<text text-anchor="start" x="247.5" y="-4500.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-</g>
-<!-- session -->
-<g id="node55" class="node">
-<title>session</title>
-<polygon fill="none" stroke="black" points="77.5,-4670.5 77.5,-4698.5
285.5,-4698.5 285.5,-4670.5 77.5,-4670.5"/>
-<text text-anchor="start" x="147.5" y="-4681.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">session</text>
-<polygon fill="none" stroke="black" points="77.5,-4645.5 77.5,-4670.5
285.5,-4670.5 285.5,-4645.5 77.5,-4645.5"/>
-<text text-anchor="start" x="82.5" y="-4655.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">id</text>
-<text text-anchor="start" x="95.5" y="-4655.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="100.5" y="-4655.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [INTEGER]</text>
-<text text-anchor="start" x="177.5" y="-4655.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
-<polygon fill="none" stroke="black" points="77.5,-4620.5 77.5,-4645.5
285.5,-4645.5 285.5,-4620.5 77.5,-4620.5"/>
-<text text-anchor="start" x="82.5" y="-4630.3"
font-family="Helvetica,sans-Serif" font-size="14.00">data</text>
-<text text-anchor="start" x="113.5" y="-4630.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="118.5" y="-4630.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [BYTEA]</text>
-<polygon fill="none" stroke="black" points="77.5,-4595.5 77.5,-4620.5
285.5,-4620.5 285.5,-4595.5 77.5,-4595.5"/>
-<text text-anchor="start" x="82.5" y="-4605.3"
font-family="Helvetica,sans-Serif" font-size="14.00">expiry</text>
-<text text-anchor="start" x="126.5" y="-4605.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="131.5" y="-4605.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [TIMESTAMP]</text>
-<polygon fill="none" stroke="black" points="77.5,-4570.5 77.5,-4595.5
285.5,-4595.5 285.5,-4570.5 77.5,-4570.5"/>
-<text text-anchor="start" x="82.5" y="-4580.3"
font-family="Helvetica,sans-Serif" font-size="14.00">session_id</text>
-<text text-anchor="start" x="154.5" y="-4580.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
-<text text-anchor="start" x="159.5" y="-4580.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(255)]</text>
+<polygon fill="none" stroke="black" points="35.5,-3625.5 35.5,-3653.5
328.5,-3653.5 328.5,-3625.5 35.5,-3625.5"/>
+<text text-anchor="start" x="109.5" y="-3636.7"
font-family="Helvetica,sans-Serif" font-weight="bold"
font-size="16.00">alembic_version</text>
+<polygon fill="none" stroke="black" points="35.5,-3600.5 35.5,-3625.5
328.5,-3625.5 328.5,-3600.5 35.5,-3600.5"/>
+<text text-anchor="start" x="40.5" y="-3610.3"
font-family="Helvetica,sans-Serif" text-decoration="underline"
font-size="14.00">version_num</text>
+<text text-anchor="start" x="130.5" y="-3610.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
+<text text-anchor="start" x="135.5" y="-3610.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> [VARCHAR(32)]</text>
+<text text-anchor="start" x="247.5" y="-3610.3"
font-family="Helvetica,sans-Serif" font-size="14.00"> NOT NULL</text>
</g>
</g>
</svg>
diff --git a/airflow-core/src/airflow/config_templates/config.yml
b/airflow-core/src/airflow/config_templates/config.yml
index e2d8ca4f0c6..1a0b670547d 100644
--- a/airflow-core/src/airflow/config_templates/config.yml
+++ b/airflow-core/src/airflow/config_templates/config.yml
@@ -701,8 +701,8 @@ database:
from BaseDBManager
version_added: 3.0.0
type: string
- example: ~
- default: "airflow.providers.fab.auth_manager.models.db.FABDBManager"
+ example: "airflow.providers.fab.auth_manager.models.db.FABDBManager"
+ default: ~
logging:
description: ~
options:
diff --git a/airflow-core/src/airflow/dag_processing/collection.py
b/airflow-core/src/airflow/dag_processing/collection.py
index 7edc10d470b..2304e5612b1 100644
--- a/airflow-core/src/airflow/dag_processing/collection.py
+++ b/airflow-core/src/airflow/dag_processing/collection.py
@@ -195,11 +195,11 @@ def _serialize_dag_capturing_errors(
min_update_interval=settings.MIN_SERIALIZED_DAG_UPDATE_INTERVAL,
session=session,
)
- if dag_was_updated:
- _sync_dag_perms(dag, session=session)
- else:
+ if not dag_was_updated:
# Check and update DagCode
DagCode.update_source_code(dag.dag_id, dag.fileloc)
+ elif "FabAuthManager" in conf.get("core", "auth_manager"):
+ _sync_dag_perms(dag, session=session)
return []
except OperationalError:
diff --git a/airflow-core/src/airflow/utils/db.py
b/airflow-core/src/airflow/utils/db.py
index 0d46f67802c..4e1b52033b2 100644
--- a/airflow-core/src/airflow/utils/db.py
+++ b/airflow-core/src/airflow/utils/db.py
@@ -1212,7 +1212,23 @@ def downgrade(*, to_revision, from_revision=None,
show_sql_only=False, session:
log.info("Attempting downgrade to revision %s", to_revision)
config = _get_alembic_config()
-
+ # Check if downgrade is less than 3.0.0 and requires that `ab_user` fab
table is present
+ if _revision_greater(config, _REVISION_HEADS_MAP["3.0.0"], to_revision):
+ if conf.getboolean("core", "unit_test_mode"):
+ try:
+ from airflow.providers.fab.auth_manager.models.db import
FABDBManager
+
+ dbm = FABDBManager(session)
+ dbm.initdb()
+ except ImportError:
+ log.warning("Import error occurred while importing
FABDBManager. Skipping the check.")
+ pass
+ if not inspect(settings.engine).has_table("ab_user"):
+ log.error(
+ "Downgrade to revision less than 3.0.0 requires that `ab_user`
table is present. "
+ "Please add FabDBManager to [core] external_db_managers and
run fab migrations before proceeding"
+ )
+ return
with create_global_lock(session=session, lock=DBLocks.MIGRATIONS):
if show_sql_only:
log.warning("Generating sql scripts for manual migration.")
diff --git a/airflow-core/src/airflow/utils/db_manager.py
b/airflow-core/src/airflow/utils/db_manager.py
index f18528c33fc..6483c446f01 100644
--- a/airflow-core/src/airflow/utils/db_manager.py
+++ b/airflow-core/src/airflow/utils/db_manager.py
@@ -144,13 +144,15 @@ class RunDBManager(LoggingMixin):
def __init__(self):
super().__init__()
self._managers: list[BaseDBManager] = []
- managers = conf.get("database", "external_db_managers").split(",")
-
+ managers_config = conf.get("database", "external_db_managers",
fallback=None)
+ if not managers_config:
+ managers = []
+ else:
+ managers = managers_config.split(",")
# Add DB manager specified by auth manager (if any)
auth_manager_db_manager = create_auth_manager().get_db_manager()
if auth_manager_db_manager and auth_manager_db_manager not in managers:
managers.append(auth_manager_db_manager)
-
for module in managers:
manager = import_string(module)
self._managers.append(manager)
diff --git a/airflow-core/tests/unit/dag_processing/test_collection.py
b/airflow-core/tests/unit/dag_processing/test_collection.py
index 1748d44f743..f45d710692c 100644
--- a/airflow-core/tests/unit/dag_processing/test_collection.py
+++ b/airflow-core/tests/unit/dag_processing/test_collection.py
@@ -31,6 +31,7 @@ from sqlalchemy import func, select
from sqlalchemy.exc import OperationalError, SAWarning
import airflow.dag_processing.collection
+from airflow.configuration import conf
from airflow.dag_processing.collection import (
AssetModelOperation,
_get_latest_runs_stmt,
@@ -264,6 +265,10 @@ class TestUpdateDagParsingResults:
ser_dict = SerializedDAG.to_dict(dag)
return LazyDeserializedDAG(data=ser_dict)
+ @pytest.mark.skipif(
+ condition="FabAuthManager" not in conf.get("core", "auth_manager"),
+ reason="This is only for FabAuthManager",
+ )
@pytest.mark.usefixtures("clean_db") # sync_perms in fab has bad session
commit hygiene
def test_sync_perms_syncs_dag_specific_perms_on_update(
self, monkeypatch, spy_agency: SpyAgency, session, time_machine,
testing_dag_bundle
diff --git a/airflow-core/tests/unit/utils/test_db.py
b/airflow-core/tests/unit/utils/test_db.py
index 5d2417b32c5..05186d573f0 100644
--- a/airflow-core/tests/unit/utils/test_db.py
+++ b/airflow-core/tests/unit/utils/test_db.py
@@ -35,8 +35,10 @@ from alembic.script import ScriptDirectory
from sqlalchemy import Column, Integer, MetaData, Table, select
from airflow.models import Base as airflow_base
+from airflow.providers.fab.auth_manager.models.db import FABDBManager
from airflow.settings import engine
from airflow.utils.db import (
+ _REVISION_HEADS_MAP,
LazySelectSequence,
_get_alembic_config,
check_migrations,
@@ -68,7 +70,9 @@ class TestDb:
for dbmanager in external_db_managers._managers:
for table_name, table in dbmanager.metadata.tables.items():
all_meta_data._add_table(table_name, table.schema, table)
-
+ # test FAB models
+ for table_name, table in FABDBManager.metadata.tables.items():
+ all_meta_data._add_table(table_name, table.schema, table)
# create diff between database schema and SQLAlchemy model
mctx = MigrationContext.configure(
engine.connect(),
@@ -131,11 +135,35 @@ class TestDb:
check_migrations(0)
check_migrations(1)
+ @pytest.mark.parametrize(
+ "auth, expected",
+ [
+ (
+ {
+ (
+ "core",
+ "auth_manager",
+ ):
"airflow.api_fastapi.auth.managers.simple.simple_auth_manager.SimpleAuthManager"
+ },
+ 1,
+ ),
+ (
+ {
+ (
+ "core",
+ "auth_manager",
+ ):
"airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager"
+ },
+ 2,
+ ),
+ ],
+ )
@mock.patch("alembic.command")
- def test_upgradedb(self, mock_alembic_command):
- upgradedb()
- mock_alembic_command.upgrade.assert_called_with(mock.ANY,
revision="heads")
- assert mock_alembic_command.upgrade.call_count == 2
+ def test_upgradedb(self, mock_alembic_command, auth, expected):
+ with conf_vars(auth):
+ upgradedb()
+ mock_alembic_command.upgrade.assert_called_with(mock.ANY,
revision="heads")
+ assert mock_alembic_command.upgrade.call_count == expected
@pytest.mark.parametrize(
"from_revision, to_revision",
@@ -264,3 +292,13 @@ class TestDb:
lss = LazySelectSequence.from_select(select(t.c.id), order_by=[],
session=MockSession())
assert bool(lss) is False
+
+ @conf_vars({("core", "unit_test_mode"): "False"})
+ @mock.patch("airflow.utils.db.inspect")
+ def test_upgradedb_raises_if_lower_than_v3_0_0(self, mock_inspect, caplog):
+ mock_inspect.return_value.has_table.return_value = False
+ downgrade(to_revision=_REVISION_HEADS_MAP["2.7.0"])
+ assert (
+ "Downgrade to revision less than 3.0.0 requires that `ab_user`
table is present. "
+ "Please add FabDBManager to [core] external_db_managers and run
fab migrations before proceeding"
+ ) in caplog.text
diff --git a/airflow-core/tests/unit/utils/test_db_manager.py
b/airflow-core/tests/unit/utils/test_db_manager.py
index 34f849bf2e0..075e87c0cbe 100644
--- a/airflow-core/tests/unit/utils/test_db_manager.py
+++ b/airflow-core/tests/unit/utils/test_db_manager.py
@@ -35,7 +35,7 @@ class TestRunDBManager:
@conf_vars(
{("database", "external_db_managers"):
"airflow.providers.fab.auth_manager.models.db.FABDBManager"}
)
- def test_fab_db_manager_is_default(self):
+ def test_db_manager_uses_config(self):
from airflow.providers.fab.auth_manager.models.db import FABDBManager
run_db_manager = RunDBManager()
diff --git a/dev/breeze/src/airflow_breeze/params/shell_params.py
b/dev/breeze/src/airflow_breeze/params/shell_params.py
index ad55b4ac71a..135975b7027 100644
--- a/dev/breeze/src/airflow_breeze/params/shell_params.py
+++ b/dev/breeze/src/airflow_breeze/params/shell_params.py
@@ -521,7 +521,8 @@ class ShellParams:
_set_var(_env, "AIRFLOW__CELERY__BROKER_URL",
self.airflow_celery_broker_url)
_set_var(_env, "AIRFLOW__CORE__AUTH_MANAGER", self.auth_manager_path)
_set_var(_env, "AIRFLOW__CORE__EXECUTOR", self.executor)
- _set_var(_env, "AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS",
"admin:admin,viewer:viewer")
+ if self.auth_manager == SIMPLE_AUTH_MANAGER:
+ _set_var(_env, "AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS",
"admin:admin,viewer:viewer")
_set_var(
_env,
"AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_PASSWORDS_FILE",
diff --git a/devel-common/src/tests_common/pytest_plugin.py
b/devel-common/src/tests_common/pytest_plugin.py
index 97b425ba40c..3cc66ac9f96 100644
--- a/devel-common/src/tests_common/pytest_plugin.py
+++ b/devel-common/src/tests_common/pytest_plugin.py
@@ -849,6 +849,7 @@ def dag_maker(request) -> Generator[DagMaker, None, None]:
SchedulerJobRunner._activate_referenced_assets(assets,
session=self.session)
def __exit__(self, type, value, traceback):
+ from airflow.configuration import conf
from airflow.models import DagModel
from airflow.models.serialized_dag import SerializedDagModel
@@ -863,12 +864,11 @@ def dag_maker(request) -> Generator[DagMaker, None, None]:
else:
dag.sync_to_db(session=self.session)
- if dag.access_control:
+ if dag.access_control and "FabAuthManager" in conf.get("core",
"auth_manager"):
if AIRFLOW_V_3_0_PLUS:
from airflow.providers.fab.www.security_appless import
ApplessAirflowSecurityManager
else:
from airflow.www.security_appless import
ApplessAirflowSecurityManager
-
security_manager =
ApplessAirflowSecurityManager(session=self.session)
security_manager.sync_perm_for_dag(dag.dag_id,
dag.access_control)
self.dag_model = self.session.get(DagModel, dag.dag_id)
diff --git a/devel-common/src/tests_common/test_utils/db.py
b/devel-common/src/tests_common/test_utils/db.py
index 723cd0b6d4a..26138e4a0fc 100644
--- a/devel-common/src/tests_common/test_utils/db.py
+++ b/devel-common/src/tests_common/test_utils/db.py
@@ -19,6 +19,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
+from airflow.configuration import conf
from airflow.jobs.job import Job
from airflow.models import (
Connection,
@@ -298,6 +299,8 @@ def clear_db_dag_bundles():
def clear_dag_specific_permissions():
+ if "FabAuthManager" not in conf.get("core", "auth_manager"):
+ return
try:
from airflow.providers.fab.auth_manager.models import Permission,
Resource, assoc_permission_role
except ImportError: