flask-appbuilder 5.0.2__tar.gz → 5.1.0rc1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/CHANGELOG.rst +6 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/Flask_AppBuilder.egg-info/PKG-INFO +2 -1
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/Flask_AppBuilder.egg-info/SOURCES.txt +5 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/Flask_AppBuilder.egg-info/requires.txt +3 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/PKG-INFO +2 -1
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/security.rst +142 -2
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/__init__.py +1 -1
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/const.py +1 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/manager.py +283 -2
- flask_appbuilder-5.1.0rc1/flask_appbuilder/security/saml/metadata.py +26 -0
- flask_appbuilder-5.1.0rc1/flask_appbuilder/security/saml/types.py +73 -0
- flask_appbuilder-5.1.0rc1/flask_appbuilder/security/saml/utils.py +54 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/manager.py +11 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/views.py +205 -1
- flask_appbuilder-5.1.0rc1/flask_appbuilder/templates/appbuilder/general/security/login_saml.html +45 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/setup.py +1 -0
- flask_appbuilder-5.1.0rc1/tests/sqla/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/.coveragerc +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/.env +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/.github/ISSUE_TEMPLATE.md +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/.github/prlint.json +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/.github/stale.yml +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/.github/workflows/ci.yml +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/.github/workflows/odbcinst.ini +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/.gitignore +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/CONTRIBUTING.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/Flask_AppBuilder.egg-info/dependency_links.txt +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/Flask_AppBuilder.egg-info/entry_points.txt +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/Flask_AppBuilder.egg-info/not-zip-safe +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/Flask_AppBuilder.egg-info/top_level.txt +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/LICENSE +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/MANIFEST.in +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/RELEASE.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/bin/babel_extract.sh +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/bin/babel_init.sh +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/bin/bootswatch_update.sh +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/bin/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/bin/db_create.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/bin/db_migrate.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/bin/db_upgrade.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/bin/hash_db_password.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/bin/migrate_db_0.7.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/bin/migrate_db_1.3.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/bin/sqlite_upgrade_1.3.sql +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docker-compose.yml +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/Makefile +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_static/Flask-AppBuilder.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_templates/layout.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_themes/LICENSE +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_themes/README +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_themes/flask/layout.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_themes/flask/relations.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_themes/flask/static/Flask-AppBuilder.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_themes/flask/static/flasky.css_t +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_themes/flask/theme.conf +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_themes/flask_small/layout.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_themes/flask_small/static/flasky.css_t +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_themes/flask_small/theme.conf +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/_themes/flask_theme_support.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/actions.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/addons.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/advanced.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/api.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/cli.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/conf.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/config.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/customizing.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/diagrams.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/generic_datasource.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/i18n.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/ListThumbnail.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/chart.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/chart_time1.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/chart_time2.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/charts.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/contact_list.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/contacts.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/direct_chart.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/fab.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/group_list.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/grouped_chart.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/groups.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/images_list.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/list_cascade.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/list_cascade_block.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/list_compact_inline.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/list_master_detail.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/login.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/login_db.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/oauth_login.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/oauth_login_one_provider.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/security.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/simpleview2.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/swagger001.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/images/swagger002.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/index.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/installation.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/intro.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/make.bat +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/multipledbs.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/quickcharts.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/quickfiles.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/quickhowto.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/quickminimal.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/relations.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/rest_api.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/templates.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/user_registration.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/versionmigration.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/docs/views.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/base_api/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/base_api/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/base_api/app/api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/base_api/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/basefilter/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/composite_keys/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/composite_keys/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/composite_keys/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/composite_keys/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/composite_keys/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/composite_keys/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/crud_rest_api/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/crud_rest_api/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/crud_rest_api/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/crud_rest_api/app/api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/crud_rest_api/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/crud_rest_api/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/crud_rest_api/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/crud_rest_api/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/crud_rest_api/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/crud_rest_api/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/crud_rest_api/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/employees/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/employees/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/employees/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/employees/app/security.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/employees/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/employees/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/employees/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/enums/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/enums/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/enums/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/enums/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/enums/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/enums/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/enums/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/enums/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/enums/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/enums/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/enums/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/app/sec.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/app/sec_forms.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/app/sec_views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/app/sec.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/app/sec_forms.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/app/sec_views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/extendsecurity2/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/factoryapp/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/masterdetail/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/masterdetail/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/masterdetail/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/masterdetail/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/masterdetail/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/masterdetail/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/masterdetail/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/masterdetail/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/masterdetail/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/masterdetail/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/masterdetail/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/oauth/.gitignore +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/oauth/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/oauth/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/oauth/app/forms.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/oauth/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/oauth/app/security.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/oauth/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/oauth/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/oauth/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/oauth/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/oauth/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/productsale/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/productsale/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/productsale/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/productsale/app/translations/es/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/productsale/app/translations/es/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/productsale/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/productsale/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/productsale/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/productsale/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/productsale/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/productsale/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickactions/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickactions/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickactions/app/translations/es/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickactions/app/translations/es/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickactions/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickactions/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickactions/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickactions/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickactions/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickactions/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickactions/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts/app/data.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/build/bdist.linux-i686/egg/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/build/bdist.linux-i686/egg/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/build/bdist.linux-i686/egg/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/build/lib/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/build/lib/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/build/lib/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickcharts2/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/app/translations/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/app/translations/es/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/app/translations/es/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/app/translations/es/LC_MESSAGES/messages.po~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/app/translations/pt/LC_MESSAGES/messages.po~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickfiles/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/forms.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/indexview.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/sec.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/sec_models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/sec_views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/angularAssets/abBtnAdd.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/angularAssets/abBtnDelete.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/angularAssets/abBtnEdit.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/angularAssets/abBtnShow.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/angularAssets/abDate.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/angularAssets/abMenuPageSize.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/angularAssets/abModalOkCancel.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/angularAssets/abModelSearch.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/angularAssets/abModelTable.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/angularAssets/abPagination.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/angularAssets/abSelect.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/css/clean-blog.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/css/scrolling-nav.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/img/brand.jpg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/img/loading.gif +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/js/Controllers/alertsCtrl.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/js/Controllers/searchCtrl.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/js/Controllers/tableCtrl.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/js/Directives/bigDirectives.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/js/Directives/btnDirectives.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/js/Services/apiService.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/js/angular.min.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/js/app.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/js/clean-blog.min.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/static/js/scrolling-nav.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/templates/appbuilder/index.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/templates/index.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/templates/list_angulajs.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/templates/list_contacts.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/templates/list_json.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/templates/mylist.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/templates/new_base.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/templates/show_contacts.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/templates/widgets/list.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/templates/widgets/list_override.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto2/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/.coverage +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/migrate_db_0.7.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickhowto3/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickimages/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickimages/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickimages/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickimages/app/translations/es/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickimages/app/translations/es/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickimages/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickimages/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickimages/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickimages/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickimages/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickmigrate/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickmigrate/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickmigrate/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickmigrate/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickmigrate/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickmigrate/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickmigrate/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickmigrate/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickmigrate/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickmigrate/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickmigrate/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quickminimal/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/.idea/encodings.xml +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/.idea/misc.xml +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/.idea/modules.xml +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/.idea/quicksqlviews.iml +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/.idea/workspace.xml +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicksqlviews/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/app/static/css/landing-page.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/app/templates/mybase.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/quicktemplates/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/.babelrc +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/README.md +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/package-lock.json +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/package.json +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/package.json.react-original +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/public/favicon.ico +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/public/index.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/public/manifest.json +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/src/App.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/src/api/Api.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/src/components/CRUDButtons.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/src/components/Forms.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/src/components/Table.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/src/index.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/static/webpack.config.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/templates/base.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/templates/react.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/react-rest-api/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/related_fields/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/.gitignore +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/app/forms.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/app/templates/404.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleform/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview1/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview1/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview1/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview1/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview1/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview1/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview1/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview2/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview2/app/templates/method3.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview2/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview2/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview2/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview2/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/simpleview2/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/user_registration/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/NAMES.DIC +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/README.rst +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/app/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/app/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/app/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/app/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/app/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/babel/babel.cfg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/babel/messages.pot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/babel/messages.pot~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/config.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/run.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/examples/widgets/testdata.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/_compat.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/actions.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/api/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/api/convert.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/api/manager.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/api/schemas.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/babel/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/babel/manager.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/babel/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/base.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/basemanager.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/baseviews.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/charts/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/charts/jsontools.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/charts/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/charts/widgets.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/cli.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/exceptions.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/fields.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/fieldwidgets.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/filemanager.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/filters.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/forms.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/hooks.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/menu.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/messages.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/base.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/decorators.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/filters.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/generic/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/generic/filters.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/generic/interface.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/group.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/mixins.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/sqla/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/sqla/base.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/sqla/base_legacy.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/sqla/filters.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/models/sqla/interface.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/decorators.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/forms.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/registerviews.py +0 -0
- {flask_appbuilder-5.0.2/flask_appbuilder/security/sqla → flask_appbuilder-5.1.0rc1/flask_appbuilder/security/saml}/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/schemas.py +0 -0
- {flask_appbuilder-5.0.2/flask_appbuilder/translations → flask_appbuilder-5.1.0rc1/flask_appbuilder/security/sqla}/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/group/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/group/api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/group/schema.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/permission/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/permission/api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/permission_view_menu/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/permission_view_menu/api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/role/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/role/api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/role/schema.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/user/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/user/api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/user/schema.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/user/validator.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/view_menu/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/apis/view_menu/api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/sqla/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/security/utils.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/.DS_Store +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/ab.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/bootstrap-datepicker/bootstrap-datepicker3.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/bootstrap.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/bootstrap.min.css.map +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/flags/flags16.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/fontawesome/all.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/fontawesome/brands.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/fontawesome/fontawesome.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/fontawesome/regular.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/fontawesome/solid.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/fontawesome/svg-with-js.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/fontawesome/v4-font-face.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/fontawesome/v4-shims.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/fontawesome/v5-font-face.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/images/flags16.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/select2/select2-bootstrap.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/select2/select2.min.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/swagger/swagger-ui.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/amelia.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/cerulean.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/cosmo.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/cyborg.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/darkly.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/flatly.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/journal.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/lumen.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/paper.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/readable.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/sandstone.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/simplex.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/slate.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/solar.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/spacelab.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/superhero.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/united.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/themes/yeti.css +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/webfonts/fa-brands-400.ttf +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/webfonts/fa-brands-400.woff2 +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/webfonts/fa-regular-400.ttf +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/webfonts/fa-regular-400.woff2 +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/webfonts/fa-solid-900.ttf +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/webfonts/fa-solid-900.woff2 +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/webfonts/fa-v4compatibility.ttf +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/css/webfonts/fa-v4compatibility.woff2 +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/fonts/glyphicons-halflings-regular.eot +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/fonts/glyphicons-halflings-regular.svg +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/fonts/glyphicons-halflings-regular.ttf +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/fonts/glyphicons-halflings-regular.woff +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/fonts/glyphicons-halflings-regular.woff2 +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/img/fab.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/img/glyphicons-halflings-white.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/img/glyphicons-halflings.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/js/ab.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/js/ab_actions.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/js/ab_filters.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/js/ab_keep_tab.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/js/bootstrap-datepicker/bootstrap-datepicker.min.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/js/bootstrap.min.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/js/google_charts.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/js/jquery-latest.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/js/select2/select2.min.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/static/appbuilder/js/swagger-ui-bundle.js +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/_formhelpers.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/base.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/baselayout.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/baselib.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/flash.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/footer.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/alert.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/charts/chart.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/charts/chart_time.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/charts/jsonchart.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/confirm.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/lib.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/model/add.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/model/edit.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/model/edit_cascade.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/model/left_master_detail.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/model/list.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/model/multiple_views.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/model/search.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/model/show.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/model/show_cascade.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/security/activation.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/security/login_db.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/security/login_ldap.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/security/login_oauth.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/security/register_mail.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/security/register_oauth.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/base_list.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/chart.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/direct_chart.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/form.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/form_horizontal.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/form_inline.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/form_vertical.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/group_form_list.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/list.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/list_block.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/list_carousel.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/list_item.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/list_link.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/list_master.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/list_thumbnail.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/multiple_chart.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/roles/list.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/roles/show.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/search.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/show.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/show_block.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/general/widgets/show_vertical.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/index.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/init.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/navbar.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/navbar_menu.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/navbar_right.html +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/templates/appbuilder/swagger/swagger.html +0 -0
- {flask_appbuilder-5.0.2/flask_appbuilder/utils → flask_appbuilder-5.1.0rc1/flask_appbuilder/translations}/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/de/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/de/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/el/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/el/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/es/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/es/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/fa/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/fa/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/fr/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/it/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/it/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/ja_JP/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/ja_JP/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/ko/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/ko/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/nl/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/nl/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/pl/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/pl/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/pt/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/pt/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/pt/LC_MESSAGES/messages.po~ +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/pt_BR/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/pt_BR/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/ru/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/ru/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/sl/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/sl/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/tr/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/tr/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/zh/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/zh_HK/LC_MESSAGES/messages.mo +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/translations/zh_HK/LC_MESSAGES/messages.po +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/upload.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/urltools.py +0 -0
- {flask_appbuilder-5.0.2/tests → flask_appbuilder-5.1.0rc1/flask_appbuilder/utils}/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/utils/base.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/utils/legacy.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/utils/limit.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/validators.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/views.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/flask_appbuilder/widgets.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/ListThumbnail.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/chart.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/chart_time1.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/chart_time2.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/charts.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/contact_list.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/contacts.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/direct_chart.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/fab.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/group_list.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/grouped_chart.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/groups.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/images_list.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/list_cascade.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/list_cascade_block.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/list_compact_inline.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/list_master_detail.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/login.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/login_db.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/login_oauth.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/login_oid.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/security.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/images/simpleview2.png +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/release.sh +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/scripts/babel_extract.sh +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/scripts/babel_init.sh +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/setup.cfg +0 -0
- {flask_appbuilder-5.0.2/tests/fixtures → flask_appbuilder-5.1.0rc1/tests}/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/base.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/config_api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/config_oauth.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/config_security.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/config_security_api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/const.py +0 -0
- {flask_appbuilder-5.0.2/tests/security → flask_appbuilder-5.1.0rc1/tests/fixtures}/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/fixtures/addon_manager.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/fixtures/data_models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/fixtures/users.py +0 -0
- {flask_appbuilder-5.0.2/tests/sqla → flask_appbuilder-5.1.0rc1/tests/security}/__init__.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/security/test_auth_ldap.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/security/test_auth_oauth.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/security/test_base_security_manager.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/security/test_mvc_security.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/security/test_password_complexity.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/security/test_rate_limiter.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/sqla/models.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/test_addon.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/test_api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/test_custom_indexview.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/test_fab_cli.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/test_menu.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/test_mvc.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/test_mvc_oauth.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/test_security_api.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/test_sqlalchemy.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tests/test_urltools.py +0 -0
- {flask_appbuilder-5.0.2 → flask_appbuilder-5.1.0rc1}/tox.ini +0 -0
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
Flask-AppBuilder ChangeLog
|
|
2
2
|
==========================
|
|
3
3
|
|
|
4
|
+
Improvements and Bug fixes on 5.1.0rc1
|
|
5
|
+
-----------------------------------
|
|
6
|
+
|
|
7
|
+
- feat: SAML Authentication (#2426) [Daniel Vaz Gaspar]
|
|
8
|
+
- fix: update user.changed_on when roles are modified (#2423) [alok kumar priyadarshi]
|
|
9
|
+
|
|
4
10
|
Improvements and Bug fixes on 5.0.2
|
|
5
11
|
-----------------------------------
|
|
6
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: flask-appbuilder
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.1.0rc1
|
|
4
4
|
Summary: Simple and rapid application development framework, built on top of Flask. includes detailed security, auto CRUD generation for your models, google charts and much more.
|
|
5
5
|
Home-page: https://github.com/dpgaspar/flask-appbuilder/
|
|
6
6
|
Author: Daniel Vaz Gaspar
|
|
@@ -22,6 +22,7 @@ Requires-Python: ~=3.7
|
|
|
22
22
|
Description-Content-Type: text/x-rst
|
|
23
23
|
Provides-Extra: jmespath
|
|
24
24
|
Provides-Extra: oauth
|
|
25
|
+
Provides-Extra: saml
|
|
25
26
|
Provides-Extra: talisman
|
|
26
27
|
License-File: LICENSE
|
|
27
28
|
|
|
@@ -559,6 +559,10 @@ flask_appbuilder/security/registerviews.py
|
|
|
559
559
|
flask_appbuilder/security/schemas.py
|
|
560
560
|
flask_appbuilder/security/utils.py
|
|
561
561
|
flask_appbuilder/security/views.py
|
|
562
|
+
flask_appbuilder/security/saml/__init__.py
|
|
563
|
+
flask_appbuilder/security/saml/metadata.py
|
|
564
|
+
flask_appbuilder/security/saml/types.py
|
|
565
|
+
flask_appbuilder/security/saml/utils.py
|
|
562
566
|
flask_appbuilder/security/sqla/__init__.py
|
|
563
567
|
flask_appbuilder/security/sqla/manager.py
|
|
564
568
|
flask_appbuilder/security/sqla/models.py
|
|
@@ -672,6 +676,7 @@ flask_appbuilder/templates/appbuilder/general/security/activation.html
|
|
|
672
676
|
flask_appbuilder/templates/appbuilder/general/security/login_db.html
|
|
673
677
|
flask_appbuilder/templates/appbuilder/general/security/login_ldap.html
|
|
674
678
|
flask_appbuilder/templates/appbuilder/general/security/login_oauth.html
|
|
679
|
+
flask_appbuilder/templates/appbuilder/general/security/login_saml.html
|
|
675
680
|
flask_appbuilder/templates/appbuilder/general/security/register_mail.html
|
|
676
681
|
flask_appbuilder/templates/appbuilder/general/security/register_oauth.html
|
|
677
682
|
flask_appbuilder/templates/appbuilder/general/widgets/base_list.html
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: flask_appbuilder
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.1.0rc1
|
|
4
4
|
Summary: Simple and rapid application development framework, built on top of Flask. includes detailed security, auto CRUD generation for your models, google charts and much more.
|
|
5
5
|
Home-page: https://github.com/dpgaspar/flask-appbuilder/
|
|
6
6
|
Author: Daniel Vaz Gaspar
|
|
@@ -22,6 +22,7 @@ Requires-Python: ~=3.7
|
|
|
22
22
|
Description-Content-Type: text/x-rst
|
|
23
23
|
Provides-Extra: jmespath
|
|
24
24
|
Provides-Extra: oauth
|
|
25
|
+
Provides-Extra: saml
|
|
25
26
|
Provides-Extra: talisman
|
|
26
27
|
License-File: LICENSE
|
|
27
28
|
|
|
@@ -16,6 +16,7 @@ Supported Authentication Types
|
|
|
16
16
|
It's the web server responsibility to authenticate the user, useful for intranet sites, when the server (Apache, Nginx)
|
|
17
17
|
is configured to use kerberos, no need for the user to login with username and password on F.A.B.
|
|
18
18
|
:OAUTH: Authentication using OAUTH (v1 or v2). You need to install authlib.
|
|
19
|
+
:SAML: Authentication using SAML 2.0 (e.g., Microsoft Entra ID, Okta, OneLogin). You need to install python3-saml.
|
|
19
20
|
|
|
20
21
|
.. note::
|
|
21
22
|
**Deprecated Authentication Types (Removed in Flask-AppBuilder 5.0+)**
|
|
@@ -31,7 +32,7 @@ The session is preserved and encrypted using Flask-Login.
|
|
|
31
32
|
Authentication Methods
|
|
32
33
|
----------------------
|
|
33
34
|
|
|
34
|
-
You can choose one from
|
|
35
|
+
You can choose one from 5 authentication methods. Configure the method to be used
|
|
35
36
|
on the **config.py** (when using the create-app, or following the proposed app structure). First the
|
|
36
37
|
configuration imports the constants for the authentication methods::
|
|
37
38
|
|
|
@@ -39,7 +40,8 @@ configuration imports the constants for the authentication methods::
|
|
|
39
40
|
AUTH_DB,
|
|
40
41
|
AUTH_LDAP,
|
|
41
42
|
AUTH_OAUTH,
|
|
42
|
-
AUTH_REMOTE_USER
|
|
43
|
+
AUTH_REMOTE_USER,
|
|
44
|
+
AUTH_SAML,
|
|
43
45
|
)
|
|
44
46
|
|
|
45
47
|
Next you will use the **AUTH_TYPE** key to choose the type::
|
|
@@ -437,6 +439,138 @@ Therefore, you can send tweets, post on the users Facebook, retrieve the user's
|
|
|
437
439
|
Take a look at the `example <https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples/oauth>`_
|
|
438
440
|
to get an idea of a simple use for this.
|
|
439
441
|
|
|
442
|
+
Authentication: SAML
|
|
443
|
+
--------------------
|
|
444
|
+
|
|
445
|
+
This method will authenticate users via SAML 2.0 identity providers such as
|
|
446
|
+
Microsoft Entra ID (formerly Azure AD), Okta, OneLogin, etc.
|
|
447
|
+
|
|
448
|
+
.. note:: To use SAML you need to install `python3-saml <https://github.com/SAML-Toolkits/python3-saml>`_:
|
|
449
|
+
``pip install flask-appbuilder[saml]``
|
|
450
|
+
|
|
451
|
+
Configure your SAML providers and SP settings in **config.py**::
|
|
452
|
+
|
|
453
|
+
AUTH_TYPE = AUTH_SAML
|
|
454
|
+
|
|
455
|
+
# registration configs
|
|
456
|
+
AUTH_USER_REGISTRATION = True
|
|
457
|
+
AUTH_USER_REGISTRATION_ROLE = "Public"
|
|
458
|
+
|
|
459
|
+
# Sync roles at login from SAML assertion
|
|
460
|
+
AUTH_ROLES_SYNC_AT_LOGIN = True
|
|
461
|
+
|
|
462
|
+
# Map SAML group names to FAB roles
|
|
463
|
+
AUTH_ROLES_MAPPING = {
|
|
464
|
+
"admins": ["Admin"],
|
|
465
|
+
"users": ["Public"],
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
# SAML Identity Providers
|
|
469
|
+
SAML_PROVIDERS = [
|
|
470
|
+
{
|
|
471
|
+
"name": "entra_id",
|
|
472
|
+
"icon": "fa-microsoft",
|
|
473
|
+
"idp": {
|
|
474
|
+
"entityId": "https://sts.windows.net/<TENANT_ID>/",
|
|
475
|
+
"singleSignOnService": {
|
|
476
|
+
"url": "https://login.microsoftonline.com/<TENANT_ID>/saml2",
|
|
477
|
+
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
|
|
478
|
+
},
|
|
479
|
+
"singleLogoutService": {
|
|
480
|
+
"url": "https://login.microsoftonline.com/<TENANT_ID>/saml2",
|
|
481
|
+
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
|
|
482
|
+
},
|
|
483
|
+
"x509cert": "<IDP_CERTIFICATE_BASE64>",
|
|
484
|
+
},
|
|
485
|
+
"attribute_mapping": {
|
|
486
|
+
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "email",
|
|
487
|
+
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname": "first_name",
|
|
488
|
+
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname": "last_name",
|
|
489
|
+
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "username",
|
|
490
|
+
"http://schemas.microsoft.com/ws/2008/06/identity/claims/groups": "role_keys",
|
|
491
|
+
},
|
|
492
|
+
},
|
|
493
|
+
]
|
|
494
|
+
|
|
495
|
+
# Global SAML Service Provider configuration
|
|
496
|
+
SAML_CONFIG = {
|
|
497
|
+
"strict": True,
|
|
498
|
+
"debug": False,
|
|
499
|
+
"sp": {
|
|
500
|
+
"entityId": "https://myapp.example.com/saml/metadata/",
|
|
501
|
+
"assertionConsumerService": {
|
|
502
|
+
"url": "https://myapp.example.com/saml/acs/",
|
|
503
|
+
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
|
|
504
|
+
},
|
|
505
|
+
"singleLogoutService": {
|
|
506
|
+
"url": "https://myapp.example.com/saml/slo/",
|
|
507
|
+
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
|
|
508
|
+
},
|
|
509
|
+
"NameIDFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
|
510
|
+
"x509cert": "",
|
|
511
|
+
# "privateKey": "",
|
|
512
|
+
},
|
|
513
|
+
"security": {
|
|
514
|
+
"nameIdEncrypted": False,
|
|
515
|
+
"authnRequestsSigned": False,
|
|
516
|
+
"logoutRequestSigned": False,
|
|
517
|
+
"logoutResponseSigned": False,
|
|
518
|
+
"signMetadata": False,
|
|
519
|
+
"wantMessagesSigned": False,
|
|
520
|
+
"wantAssertionsSigned": True,
|
|
521
|
+
"wantAssertionsEncrypted": False,
|
|
522
|
+
"wantNameId": True,
|
|
523
|
+
"wantNameIdEncrypted": False,
|
|
524
|
+
"wantAttributeStatement": True,
|
|
525
|
+
},
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
Each SAML provider entry has the following keys:
|
|
529
|
+
|
|
530
|
+
:name: A unique name for the identity provider.
|
|
531
|
+
:icon: A Font Awesome icon class for the login button.
|
|
532
|
+
:idp: The IdP SAML metadata (entityId, SSO/SLO URLs, and signing certificate).
|
|
533
|
+
:attribute_mapping: Maps SAML assertion attribute names (left) to FAB user fields (right).
|
|
534
|
+
Supported FAB fields: ``username``, ``email``, ``first_name``, ``last_name``, ``role_keys``.
|
|
535
|
+
|
|
536
|
+
The ``SAML_CONFIG`` dict holds the global Service Provider settings. The ``sp`` section defines
|
|
537
|
+
your application's SAML endpoints. These URLs must match what you configure on the IdP side.
|
|
538
|
+
|
|
539
|
+
SAML Endpoints
|
|
540
|
+
~~~~~~~~~~~~~~
|
|
541
|
+
|
|
542
|
+
The following endpoints are automatically registered:
|
|
543
|
+
|
|
544
|
+
- ``/login/`` — Login page with IdP selection (or auto-redirect for single IdP)
|
|
545
|
+
- ``/login/<idp>`` — Initiate SSO with a specific IdP
|
|
546
|
+
- ``/saml/acs/`` — Assertion Consumer Service (receives SAML responses)
|
|
547
|
+
- ``/saml/slo/`` — Single Logout endpoint
|
|
548
|
+
- ``/saml/metadata/`` — SP metadata XML (configure this URL on your IdP)
|
|
549
|
+
|
|
550
|
+
SAML Role Mapping
|
|
551
|
+
~~~~~~~~~~~~~~~~~
|
|
552
|
+
|
|
553
|
+
You can map SAML group claims to FAB roles, just like with OAuth and LDAP::
|
|
554
|
+
|
|
555
|
+
AUTH_ROLES_MAPPING = {
|
|
556
|
+
"admins": ["Admin"],
|
|
557
|
+
"users": ["User"],
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
AUTH_ROLES_SYNC_AT_LOGIN = True
|
|
561
|
+
|
|
562
|
+
PERMANENT_SESSION_LIFETIME = 1800
|
|
563
|
+
|
|
564
|
+
The ``role_keys`` field in ``attribute_mapping`` defines which SAML attribute contains the
|
|
565
|
+
user's group memberships.
|
|
566
|
+
|
|
567
|
+
You can also use JMESPath expressions for dynamic role assignment::
|
|
568
|
+
|
|
569
|
+
AUTH_USER_REGISTRATION_ROLE_JMESPATH = "role_keys[0]"
|
|
570
|
+
|
|
571
|
+
Take a look at the `SAML example <https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples/saml>`_
|
|
572
|
+
|
|
573
|
+
|
|
440
574
|
Authentication: Rate limiting
|
|
441
575
|
-----------------------------
|
|
442
576
|
|
|
@@ -848,6 +982,9 @@ F.A.B. uses a different user view for each authentication method
|
|
|
848
982
|
|
|
849
983
|
:UserDBModelView: For database auth method
|
|
850
984
|
:UserLDAPModelView: For LDAP auth method
|
|
985
|
+
:UserOAuthModelView: For OAuth auth method
|
|
986
|
+
:UserRemoteUserModelView: For Remote User auth method
|
|
987
|
+
:UserSAMLModelView: For SAML auth method
|
|
851
988
|
|
|
852
989
|
You can extend or create from scratch your own, and then tell F.A.B. to use them instead, by overriding their
|
|
853
990
|
correspondent lower case properties on **SecurityManager** (just like on the given example).
|
|
@@ -881,6 +1018,7 @@ If you're using:
|
|
|
881
1018
|
:AUTH_LDAP: Extend UserLDAPModelView
|
|
882
1019
|
:AUTH_REMOTE_USER: Extend UserRemoteUserModelView
|
|
883
1020
|
:AUTH_OAUTH: Extend UserOAuthModelView
|
|
1021
|
+
:AUTH_SAML: Extend UserSAMLModelView
|
|
884
1022
|
|
|
885
1023
|
So using AUTH_DB::
|
|
886
1024
|
|
|
@@ -955,6 +1093,8 @@ Note that this is for AUTH_DB, so if you're using:
|
|
|
955
1093
|
:AUTH_DB: Override userdbmodelview
|
|
956
1094
|
:AUTH_LDAP: Override userldapmodelview
|
|
957
1095
|
:AUTH_REMOTE_USER: Override userremoteusermodelview
|
|
1096
|
+
:AUTH_OAUTH: Override useroauthmodelview
|
|
1097
|
+
:AUTH_SAML: Override usersamlmodelview
|
|
958
1098
|
|
|
959
1099
|
Finally (as shown on the previous example) tell F.A.B. to use your SecurityManager class, so when initializing
|
|
960
1100
|
**AppBuilder** (on __init__.py)::
|
|
@@ -4,9 +4,9 @@ import datetime
|
|
|
4
4
|
import importlib
|
|
5
5
|
import logging
|
|
6
6
|
import re
|
|
7
|
-
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
|
7
|
+
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, TYPE_CHECKING, Union
|
|
8
8
|
|
|
9
|
-
from flask import current_app, Flask, g, session, url_for
|
|
9
|
+
from flask import current_app, Flask, g, request, session, url_for
|
|
10
10
|
from flask_appbuilder.exceptions import InvalidLoginAttempt, OAuthProviderUnknown
|
|
11
11
|
from flask_babel import lazy_gettext as _
|
|
12
12
|
from flask_jwt_extended import current_user as current_user_jwt
|
|
@@ -28,6 +28,7 @@ from .views import (
|
|
|
28
28
|
AuthLDAPView,
|
|
29
29
|
AuthOAuthView,
|
|
30
30
|
AuthRemoteUserView,
|
|
31
|
+
AuthSAMLView,
|
|
31
32
|
PermissionModelView,
|
|
32
33
|
PermissionViewModelView,
|
|
33
34
|
RegisterUserModelView,
|
|
@@ -40,6 +41,7 @@ from .views import (
|
|
|
40
41
|
UserLDAPModelView,
|
|
41
42
|
UserOAuthModelView,
|
|
42
43
|
UserRemoteUserModelView,
|
|
44
|
+
UserSAMLModelView,
|
|
43
45
|
UserStatsChartView,
|
|
44
46
|
ViewMenuModelView,
|
|
45
47
|
)
|
|
@@ -49,6 +51,7 @@ from ..const import (
|
|
|
49
51
|
AUTH_LDAP,
|
|
50
52
|
AUTH_OAUTH,
|
|
51
53
|
AUTH_REMOTE_USER,
|
|
54
|
+
AUTH_SAML,
|
|
52
55
|
LOGMSG_ERR_SEC_ADD_REGISTER_USER,
|
|
53
56
|
LOGMSG_ERR_SEC_AUTH_LDAP,
|
|
54
57
|
LOGMSG_ERR_SEC_AUTH_LDAP_TLS,
|
|
@@ -59,6 +62,9 @@ from ..const import (
|
|
|
59
62
|
PERMISSION_PREFIX,
|
|
60
63
|
)
|
|
61
64
|
|
|
65
|
+
if TYPE_CHECKING:
|
|
66
|
+
from flask_appbuilder.security.saml.types import SAMLConfig, SAMLProvider
|
|
67
|
+
|
|
62
68
|
log = logging.getLogger(__name__)
|
|
63
69
|
|
|
64
70
|
|
|
@@ -186,6 +192,11 @@ class BaseSecurityManager(AbstractSecurityManager):
|
|
|
186
192
|
""" Override if you want your own Authentication OAuth view """
|
|
187
193
|
authremoteuserview = AuthRemoteUserView
|
|
188
194
|
""" Override if you want your own Authentication REMOTE_USER view """
|
|
195
|
+
authsamlview = AuthSAMLView
|
|
196
|
+
""" Override if you want your own Authentication SAML view """
|
|
197
|
+
|
|
198
|
+
usersamlmodelview = UserSAMLModelView
|
|
199
|
+
""" Override if you want your own user SAML view """
|
|
189
200
|
|
|
190
201
|
registeruserdbview = RegisterUserDBView
|
|
191
202
|
""" Override if you want your own register user db view """
|
|
@@ -519,6 +530,41 @@ class BaseSecurityManager(AbstractSecurityManager):
|
|
|
519
530
|
def oauth_providers(self):
|
|
520
531
|
return current_app.config["OAUTH_PROVIDERS"]
|
|
521
532
|
|
|
533
|
+
@property
|
|
534
|
+
def saml_providers(self) -> List["SAMLProvider"]:
|
|
535
|
+
return current_app.config.get("SAML_PROVIDERS", [])
|
|
536
|
+
|
|
537
|
+
@property
|
|
538
|
+
def saml_config(self) -> "SAMLConfig":
|
|
539
|
+
return current_app.config.get("SAML_CONFIG", {})
|
|
540
|
+
|
|
541
|
+
def get_saml_provider(self, name: str) -> Optional["SAMLProvider"]:
|
|
542
|
+
"""Return a specific SAML provider by name."""
|
|
543
|
+
for provider in self.saml_providers:
|
|
544
|
+
if provider["name"] == name:
|
|
545
|
+
return provider
|
|
546
|
+
return None
|
|
547
|
+
|
|
548
|
+
def get_saml_settings(self, provider_name: str) -> "SAMLConfig":
|
|
549
|
+
"""Build the python3-saml settings dict for a given provider.
|
|
550
|
+
|
|
551
|
+
Merges the global SAML_CONFIG with the provider-specific IdP config.
|
|
552
|
+
"""
|
|
553
|
+
import copy
|
|
554
|
+
|
|
555
|
+
provider = self.get_saml_provider(provider_name)
|
|
556
|
+
if not provider:
|
|
557
|
+
raise ValueError(
|
|
558
|
+
f"SAML provider '{provider_name}' not found in configuration"
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
base_config = copy.deepcopy(self.saml_config)
|
|
562
|
+
|
|
563
|
+
if "idp" in provider:
|
|
564
|
+
base_config["idp"] = provider["idp"]
|
|
565
|
+
|
|
566
|
+
return base_config
|
|
567
|
+
|
|
522
568
|
@property
|
|
523
569
|
def is_auth_limited(self) -> bool:
|
|
524
570
|
return current_app.config["AUTH_RATE_LIMITED"]
|
|
@@ -807,6 +853,9 @@ class BaseSecurityManager(AbstractSecurityManager):
|
|
|
807
853
|
elif self.auth_type == AUTH_REMOTE_USER:
|
|
808
854
|
self.user_view = self.userremoteusermodelview
|
|
809
855
|
self.auth_view = self.authremoteuserview()
|
|
856
|
+
elif self.auth_type == AUTH_SAML:
|
|
857
|
+
self.user_view = self.usersamlmodelview
|
|
858
|
+
self.auth_view = self.authsamlview()
|
|
810
859
|
self.appbuilder.add_view_no_menu(self.auth_view)
|
|
811
860
|
|
|
812
861
|
# this needs to be done after the view is added, otherwise the blueprint
|
|
@@ -1448,6 +1497,238 @@ class BaseSecurityManager(AbstractSecurityManager):
|
|
|
1448
1497
|
else:
|
|
1449
1498
|
return None
|
|
1450
1499
|
|
|
1500
|
+
@staticmethod
|
|
1501
|
+
def _prepare_saml_request() -> Dict[str, Any]:
|
|
1502
|
+
"""Prepare Flask request data in the format expected by python3-saml."""
|
|
1503
|
+
return {
|
|
1504
|
+
"https": "on" if request.scheme == "https" else "off",
|
|
1505
|
+
"http_host": request.host,
|
|
1506
|
+
"server_port": request.environ.get("SERVER_PORT", "443"),
|
|
1507
|
+
"script_name": request.path,
|
|
1508
|
+
"get_data": request.args.copy(),
|
|
1509
|
+
"post_data": request.form.copy(),
|
|
1510
|
+
"query_string": request.query_string.decode("utf-8"),
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
def _get_saml_auth(self, idp: str):
|
|
1514
|
+
"""Create a OneLogin_Saml2_Auth instance for the given IdP."""
|
|
1515
|
+
from onelogin.saml2.auth import OneLogin_Saml2_Auth
|
|
1516
|
+
|
|
1517
|
+
return OneLogin_Saml2_Auth(
|
|
1518
|
+
self._prepare_saml_request(), self.get_saml_settings(idp)
|
|
1519
|
+
)
|
|
1520
|
+
|
|
1521
|
+
def get_saml_login_redirect_url(self, idp: str) -> str:
|
|
1522
|
+
"""Create a SAML authentication request and return the redirect URL.
|
|
1523
|
+
|
|
1524
|
+
:param idp: The SAML identity provider name.
|
|
1525
|
+
:returns: The IdP redirect URL for SSO.
|
|
1526
|
+
"""
|
|
1527
|
+
return self._get_saml_auth(idp).login()
|
|
1528
|
+
|
|
1529
|
+
def get_saml_userinfo(self, idp: str) -> Optional[Dict[str, Any]]:
|
|
1530
|
+
"""Process a SAML ACS response and return mapped user info.
|
|
1531
|
+
|
|
1532
|
+
:param idp: The SAML identity provider name.
|
|
1533
|
+
:returns: A dict with mapped user info, session_index, and name_id,
|
|
1534
|
+
or None if authentication failed.
|
|
1535
|
+
"""
|
|
1536
|
+
from flask_appbuilder.security.saml.utils import map_saml_attributes
|
|
1537
|
+
|
|
1538
|
+
auth = self._get_saml_auth(idp)
|
|
1539
|
+
auth.process_response()
|
|
1540
|
+
errors = auth.get_errors()
|
|
1541
|
+
|
|
1542
|
+
if errors:
|
|
1543
|
+
error_reason = auth.get_last_error_reason() or ""
|
|
1544
|
+
# Check for issuer mismatch (multi-tab / wrong IdP scenario)
|
|
1545
|
+
if "issuer" in error_reason.lower():
|
|
1546
|
+
log.error(
|
|
1547
|
+
"SAML Issuer mismatch for IdP '%s'. This may happen if you "
|
|
1548
|
+
"initiated login with a different IdP in another tab. "
|
|
1549
|
+
"Error: %s",
|
|
1550
|
+
idp,
|
|
1551
|
+
error_reason,
|
|
1552
|
+
)
|
|
1553
|
+
else:
|
|
1554
|
+
log.error(
|
|
1555
|
+
"SAML ACS errors for IdP '%s': %s (reason: %s)",
|
|
1556
|
+
idp,
|
|
1557
|
+
errors,
|
|
1558
|
+
error_reason,
|
|
1559
|
+
)
|
|
1560
|
+
return None
|
|
1561
|
+
|
|
1562
|
+
if not auth.is_authenticated():
|
|
1563
|
+
return None
|
|
1564
|
+
|
|
1565
|
+
saml_attributes = auth.get_attributes()
|
|
1566
|
+
name_id = auth.get_nameid()
|
|
1567
|
+
log.debug(
|
|
1568
|
+
"SAML attributes from IdP '%s': %s, NameID: %s",
|
|
1569
|
+
idp,
|
|
1570
|
+
saml_attributes,
|
|
1571
|
+
name_id,
|
|
1572
|
+
)
|
|
1573
|
+
|
|
1574
|
+
provider = self.get_saml_provider(idp)
|
|
1575
|
+
attribute_mapping = provider.get("attribute_mapping", {})
|
|
1576
|
+
userinfo = map_saml_attributes(saml_attributes, attribute_mapping, name_id)
|
|
1577
|
+
|
|
1578
|
+
# Include session data needed for SLO
|
|
1579
|
+
userinfo["saml_name_id"] = name_id
|
|
1580
|
+
userinfo["saml_session_index"] = auth.get_session_index()
|
|
1581
|
+
|
|
1582
|
+
log.debug("Mapped SAML userinfo: %s", userinfo)
|
|
1583
|
+
return userinfo
|
|
1584
|
+
|
|
1585
|
+
def get_saml_logout_redirect_url(
|
|
1586
|
+
self,
|
|
1587
|
+
idp: str,
|
|
1588
|
+
name_id: Optional[str] = None,
|
|
1589
|
+
session_index: Optional[str] = None,
|
|
1590
|
+
) -> Tuple[Optional[str], bool]:
|
|
1591
|
+
"""Process SAML SLO or initiate a logout request.
|
|
1592
|
+
|
|
1593
|
+
Handles three cases:
|
|
1594
|
+
- Incoming SLO request from IdP (SAMLRequest)
|
|
1595
|
+
- SLO response from IdP (SAMLResponse)
|
|
1596
|
+
- SP-initiated logout (returns redirect URL to IdP)
|
|
1597
|
+
|
|
1598
|
+
:param idp: The SAML identity provider name.
|
|
1599
|
+
:param name_id: The SAML NameID for the session.
|
|
1600
|
+
:param session_index: The SAML session index.
|
|
1601
|
+
:returns: Tuple of (redirect URL or None, should_logout flag).
|
|
1602
|
+
The caller should call logout_user() if should_logout is True.
|
|
1603
|
+
"""
|
|
1604
|
+
auth = self._get_saml_auth(idp)
|
|
1605
|
+
should_logout = False
|
|
1606
|
+
|
|
1607
|
+
def mark_logout():
|
|
1608
|
+
nonlocal should_logout
|
|
1609
|
+
should_logout = True
|
|
1610
|
+
|
|
1611
|
+
# Incoming SLO request from IdP
|
|
1612
|
+
if "SAMLRequest" in request.form or "SAMLRequest" in request.args:
|
|
1613
|
+
url = auth.process_slo(delete_session_cb=mark_logout)
|
|
1614
|
+
return url, should_logout
|
|
1615
|
+
|
|
1616
|
+
# SLO response from IdP
|
|
1617
|
+
if "SAMLResponse" in request.form or "SAMLResponse" in request.args:
|
|
1618
|
+
auth.process_slo(delete_session_cb=mark_logout)
|
|
1619
|
+
return None, should_logout
|
|
1620
|
+
|
|
1621
|
+
# SP-initiated logout
|
|
1622
|
+
return auth.logout(name_id=name_id, session_index=session_index), True
|
|
1623
|
+
|
|
1624
|
+
def _saml_calculate_user_roles(self, userinfo) -> List[str]:
|
|
1625
|
+
user_role_objects = set()
|
|
1626
|
+
|
|
1627
|
+
# apply AUTH_ROLES_MAPPING
|
|
1628
|
+
if len(self.auth_roles_mapping) > 0:
|
|
1629
|
+
user_role_keys = userinfo.get("role_keys", [])
|
|
1630
|
+
user_role_objects.update(self.get_roles_from_keys(user_role_keys))
|
|
1631
|
+
|
|
1632
|
+
# apply AUTH_USER_REGISTRATION_ROLE
|
|
1633
|
+
if self.auth_user_registration:
|
|
1634
|
+
registration_role_name = self.auth_user_registration_role
|
|
1635
|
+
|
|
1636
|
+
if self.auth_user_registration_role_jmespath:
|
|
1637
|
+
import jmespath
|
|
1638
|
+
|
|
1639
|
+
registration_role_name = jmespath.search(
|
|
1640
|
+
self.auth_user_registration_role_jmespath, userinfo
|
|
1641
|
+
)
|
|
1642
|
+
|
|
1643
|
+
fab_role = self.find_role(registration_role_name)
|
|
1644
|
+
if fab_role:
|
|
1645
|
+
user_role_objects.add(fab_role)
|
|
1646
|
+
else:
|
|
1647
|
+
log.warning(
|
|
1648
|
+
"Can't find AUTH_USER_REGISTRATION role: %s", registration_role_name
|
|
1649
|
+
)
|
|
1650
|
+
|
|
1651
|
+
return list(user_role_objects)
|
|
1652
|
+
|
|
1653
|
+
def auth_user_saml(self, userinfo):
|
|
1654
|
+
"""
|
|
1655
|
+
Method for authenticating user with SAML.
|
|
1656
|
+
|
|
1657
|
+
:param userinfo: dict with user information extracted from SAML assertion
|
|
1658
|
+
(keys are the same as User model columns)
|
|
1659
|
+
"""
|
|
1660
|
+
# extract the username from userinfo
|
|
1661
|
+
if "username" in userinfo:
|
|
1662
|
+
username = userinfo["username"]
|
|
1663
|
+
elif "email" in userinfo:
|
|
1664
|
+
username = userinfo["email"]
|
|
1665
|
+
else:
|
|
1666
|
+
log.error("SAML userinfo does not have username or email %s", userinfo)
|
|
1667
|
+
return None
|
|
1668
|
+
|
|
1669
|
+
if (username is None) or username == "":
|
|
1670
|
+
return None
|
|
1671
|
+
|
|
1672
|
+
# Search the DB for this user by username or email
|
|
1673
|
+
user = self.find_user(username=username)
|
|
1674
|
+
if not user and userinfo.get("email"):
|
|
1675
|
+
user = self.find_user(email=userinfo["email"])
|
|
1676
|
+
|
|
1677
|
+
# If user is not active, go away
|
|
1678
|
+
if user and (not user.is_active):
|
|
1679
|
+
return None
|
|
1680
|
+
|
|
1681
|
+
# If user is not registered, and not self-registration, go away
|
|
1682
|
+
if (not user) and (not self.auth_user_registration):
|
|
1683
|
+
return None
|
|
1684
|
+
|
|
1685
|
+
# Sync the user's roles and info
|
|
1686
|
+
if user:
|
|
1687
|
+
updated = False
|
|
1688
|
+
|
|
1689
|
+
if self.auth_roles_sync_at_login:
|
|
1690
|
+
new_roles = self._saml_calculate_user_roles(userinfo)
|
|
1691
|
+
if new_roles:
|
|
1692
|
+
user.roles = new_roles
|
|
1693
|
+
updated = True
|
|
1694
|
+
log.debug(
|
|
1695
|
+
"Calculated new roles for user='%s' as: %s",
|
|
1696
|
+
username,
|
|
1697
|
+
user.roles,
|
|
1698
|
+
)
|
|
1699
|
+
|
|
1700
|
+
# Update user info from SAML assertion
|
|
1701
|
+
for field in ("first_name", "last_name", "email"):
|
|
1702
|
+
new_val = userinfo.get(field)
|
|
1703
|
+
if new_val and getattr(user, field) != new_val:
|
|
1704
|
+
setattr(user, field, new_val)
|
|
1705
|
+
updated = True
|
|
1706
|
+
|
|
1707
|
+
if updated:
|
|
1708
|
+
self.update_user(user)
|
|
1709
|
+
|
|
1710
|
+
# If the user is new, register them
|
|
1711
|
+
if (not user) and self.auth_user_registration:
|
|
1712
|
+
user = self.add_user(
|
|
1713
|
+
username=username,
|
|
1714
|
+
first_name=userinfo.get("first_name", ""),
|
|
1715
|
+
last_name=userinfo.get("last_name", ""),
|
|
1716
|
+
email=userinfo.get("email", "") or f"{username}@email.notfound",
|
|
1717
|
+
role=self._saml_calculate_user_roles(userinfo),
|
|
1718
|
+
)
|
|
1719
|
+
log.debug("New SAML user registered: %s", user)
|
|
1720
|
+
|
|
1721
|
+
if not user:
|
|
1722
|
+
log.error("Error creating a new SAML user %s", username)
|
|
1723
|
+
return None
|
|
1724
|
+
|
|
1725
|
+
# LOGIN SUCCESS
|
|
1726
|
+
if user:
|
|
1727
|
+
self.update_user_auth_stat(user)
|
|
1728
|
+
return user
|
|
1729
|
+
else:
|
|
1730
|
+
return None
|
|
1731
|
+
|
|
1451
1732
|
"""
|
|
1452
1733
|
----------------------------------------
|
|
1453
1734
|
PERMISSION ACCESS CHECK
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""SP metadata generation for SAML authentication."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Any, Dict
|
|
7
|
+
|
|
8
|
+
log = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_sp_metadata(saml_settings: Dict[str, Any]) -> str:
|
|
12
|
+
"""
|
|
13
|
+
Generate SP metadata XML from SAML settings.
|
|
14
|
+
|
|
15
|
+
:param saml_settings: The python3-saml settings dict
|
|
16
|
+
:return: SP metadata XML string
|
|
17
|
+
"""
|
|
18
|
+
from onelogin.saml2.settings import OneLogin_Saml2_Settings
|
|
19
|
+
|
|
20
|
+
settings = OneLogin_Saml2_Settings(saml_settings, sp_validation_only=True)
|
|
21
|
+
metadata = settings.get_sp_metadata()
|
|
22
|
+
errors = settings.validate_metadata(metadata)
|
|
23
|
+
if errors:
|
|
24
|
+
log.error("SP Metadata validation errors: %s", errors)
|
|
25
|
+
raise ValueError(f"SP Metadata validation errors: {errors}")
|
|
26
|
+
return metadata
|