cmdbox 0.5.0.8__tar.gz → 0.5.1__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.
Potentially problematic release.
This version of cmdbox might be problematic. Click here for more details.
- {cmdbox-0.5.0.8/cmdbox.egg-info → cmdbox-0.5.1}/PKG-INFO +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/edge.py +96 -12
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_edge_config.py +9 -3
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_gui_start.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_start.py +2 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_bbforce_cmd.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_copyright.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_del_cmd.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_del_pipe.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_do_signin.py +88 -32
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_exec_cmd.py +2 -2
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_exec_pipe.py +2 -2
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_filer download.py +2 -3
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_filer.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_filer_upload.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_get_cmd_choices.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_get_cmds.py +2 -2
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_get_modes.py +2 -2
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_get_server_opt.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_gui.py +2 -2
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_list_cmd.py +2 -2
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_list_pipe.py +2 -2
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_load_cmd.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_load_pin.py +3 -5
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_load_pipe.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_raw_cmd.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_raw_pipe.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_result.py +2 -2
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_save_cmd.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_save_pin.py +2 -2
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_save_pipe.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_signin.py +26 -8
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_users.py +35 -37
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_versions_cmdbox.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_versions_used.py +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/options.py +8 -8
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/web.py +76 -555
- cmdbox-0.5.1/cmdbox/extensions/sample_project/sample/extensions/features.yml +48 -0
- cmdbox-0.5.1/cmdbox/extensions/sample_project/sample/extensions/user_list.yml +129 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/user_list.yml +10 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/version.py +2 -2
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/list_cmd.js +50 -2
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/signin.js +7 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/gui.html +1 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/signin.html +7 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1/cmdbox.egg-info}/PKG-INFO +1 -1
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox.egg-info/SOURCES.txt +0 -1
- cmdbox-0.5.0.8/cmdbox/app/signin.py +0 -56
- cmdbox-0.5.0.8/cmdbox/extensions/sample_project/sample/extensions/features.yml +0 -23
- cmdbox-0.5.0.8/cmdbox/extensions/sample_project/sample/extensions/user_list.yml +0 -87
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/LICENSE +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/MANIFEST.in +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/README.md +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/__init__.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/__main__.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/__init__.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/app.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/client.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/common.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/commons/convert.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/commons/loghandler.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/commons/module.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/commons/redis_client.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/feature.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_client_file_copy.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_client_file_download.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_client_file_list.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_client_file_mkdir.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_client_file_move.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_client_file_remove.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_client_file_rmdir.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_client_file_upload.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_client_server_info.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_edge_start.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_gui_stop.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_server_list.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_server_start.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_server_stop.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_apikey_add.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_apikey_del.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_gencert.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_genpass.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_group_add.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_group_del.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_group_edit.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_group_list.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_stop.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_user_add.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_user_del.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_user_edit.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/cli/cmdbox_web_user_list.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_assets.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_do_signout.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_gui_callback.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/features/web/cmdbox_web_usesignout.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/filer.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/app/server.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/config.yml +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/features.yml +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/sample_project/.vscode/launch.json +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/sample_project/requirements.txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/sample_project/sample/__init__.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/sample_project/sample/__main__.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/sample_project/sample/app/app.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/sample_project/sample/app/features/cli/sample_client_time.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/sample_project/sample/app/features/cli/sample_server_time.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/sample_project/sample/logconf_sample.yml +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/sample_project/sample/version.py +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/sample_project/sample/web/assets/sample/favicon.ico +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/extensions/sample_project/sample/web/assets/sample/icon.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.Jinja2.3.1.4(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.MarkupSafe.3.0.2(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.PyYAML.6.0.2(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.Pygments.2.18.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.Sphinx.8.1.3(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.alabaster.1.0.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.annotated-types.0.7.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.anyio.4.6.2.post1(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.argcomplete.3.5.1(Apache Software License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.babel.2.16.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.backports.tarfile.1.2.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.certifi.2024.8.30(Mozilla Public License 2.0 (MPL 2.0)).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.cffi.1.17.1(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.charset-normalizer.3.4.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.click.8.1.7(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.colorama.0.4.6(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.cryptography.43.0.3(Apache Software License; BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.docutils.0.21.2(BSD License; GNU General Public License (GPL); Public Domain; Python Software Foundation License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.fastapi.0.115.5(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.gevent.24.11.1(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.greenlet.3.1.1(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.h11.0.14.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.httptools.0.6.4(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.idna.3.10(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.imagesize.1.4.1(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.importlib_metadata.8.5.0(Apache Software License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.itsdangerous.2.2.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.jaraco.classes.3.4.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.jaraco.context.6.0.1(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.jaraco.functools.4.1.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.keyring.25.5.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.markdown-it-py.3.0.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.mdurl.0.1.2(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.more-itertools.10.5.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.nh3.0.2.18(MIT).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.numpy.2.1.3(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.packaging.24.2(Apache Software License; BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.pillow.11.0.0(CMU License (MIT-CMU)).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.pip.24.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.pkginfo.1.10.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.prettytable.3.12.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.pycparser.2.22(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.pydantic.2.10.2(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.pydantic_core.2.27.1(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.python-dotenv.1.0.1(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.python-multipart.0.0.17(Apache Software License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.pywin32-ctypes.0.2.3(BSD-3-Clause).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.readme_renderer.44.0(Apache Software License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.redis.5.2.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.requests-toolbelt.1.0.0(Apache Software License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.requests.2.32.3(Apache Software License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.rfc3986.2.0.0(Apache Software License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.rich.13.9.4(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.setuptools.65.5.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.six.1.16.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sniffio.1.3.1(Apache Software License; MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.snowballstemmer.2.2.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sphinx-intl.2.3.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sphinx-rtd-theme.3.0.2(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sphinx-sitemap.2.6.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sphinx_fontawesome.0.0.6(GNU General Public License v2 (GPLv2)).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sphinxcontrib-applehelp.2.0.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sphinxcontrib-devhelp.2.0.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sphinxcontrib-htmlhelp.2.1.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sphinxcontrib-jquery.4.1(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sphinxcontrib-jsmath.1.0.1(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sphinxcontrib-qthelp.2.0.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.sphinxcontrib-serializinghtml.2.0.0(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.starlette.0.41.3(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.tabulate.0.9.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.tomli.2.1.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.twine.5.1.1(Apache Software License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.typing_extensions.4.12.2(Python Software Foundation License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.urllib3.2.2.3(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.uvicorn.0.32.1(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.watchfiles.1.0.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.wcwidth.0.2.13(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.websockets.14.1(BSD License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.wheel.0.45.1(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.zipp.3.21.0(MIT License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.zope.event.5.0(Zope Public License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/LICENSE.zope.interface.7.1.1(Zope Public License).txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/licenses/files.txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/logconf_client.yml +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/logconf_edge.yml +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/logconf_gui.yml +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/logconf_server.yml +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/logconf_web.yml +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/bootstrap/bootstrap.bundle.min.5.3.0.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/bootstrap/bootstrap.min.5.3.0.css +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/common.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/favicon.ico +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/filer_modal.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/icon.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/list_pipe.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/main.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/open_capture.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/open_output_json.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/result.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/users.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/view_raw.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/cmdbox/view_result.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/encodingjs/LICENSE.txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/encodingjs/encoding.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/encodingjs/encoding.min.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/filer/filer.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/filer/main.css +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/filer/main.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/highlight/default.css +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/highlight/highlight.min.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/highlight/styles/tokyo-night-dark.min.css +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery/jquery.min.3.2.0.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-linedtextarea/README.md +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-linedtextarea/jquery-linedtextarea-license.txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-linedtextarea/jquery-linedtextarea.css +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-linedtextarea/jquery-linedtextarea.html +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-linedtextarea/jquery-linedtextarea.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-resizable/jquery-resizable.min.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/AUTHORS.txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/LICENSE.txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/images/ui-icons_444444_256x240.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/images/ui-icons_555555_256x240.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/images/ui-icons_777620_256x240.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/images/ui-icons_777777_256x240.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/images/ui-icons_cc0000_256x240.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/images/ui-icons_ffffff_256x240.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/jquery-ui.min.css +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/jquery-ui.min.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/jquery-ui.structure.min.css +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/jquery-ui.theme.min.css +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/jquery-ui/package.json +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/lightbox2/css/lightbox.min.css +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/lightbox2/images/close.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/lightbox2/images/loading.gif +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/lightbox2/images/next.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/lightbox2/images/prev.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/lightbox2/js/lightbox.min.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/split-pane/split-pane.css +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/split-pane/split-pane.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/tree-menu/css/tree-menu.css +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/tree-menu/image/file.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/tree-menu/image/folder-close.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/tree-menu/image/folder-open.png +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets/tree-menu/js/tree-menu.js +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/assets_license_list.txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/filer.html +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/result.html +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox/web/users.html +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox.egg-info/dependency_links.txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox.egg-info/entry_points.txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox.egg-info/requires.txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/cmdbox.egg-info/top_level.txt +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/setup.cfg +0 -0
- {cmdbox-0.5.0.8 → cmdbox-0.5.1}/setup.py +0 -0
|
@@ -149,6 +149,9 @@ class Edge(object):
|
|
|
149
149
|
msg = dict(warn=f"Please set the numeric value in the oauth2_port. oauth2_port={opt['oauth2_port']}")
|
|
150
150
|
return msg
|
|
151
151
|
opt['oauth2_port'] = int(opt['oauth2_port'])
|
|
152
|
+
if opt['oauth2'] == 'azure' and ('oauth2_tenant_id' not in opt or opt['oauth2_tenant_id'] is None):
|
|
153
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_tenant_id.")
|
|
154
|
+
return msg
|
|
152
155
|
if opt['auth_type'] == 'oauth2' and ('oauth2_client_id' not in opt or opt['oauth2_client_id'] is None):
|
|
153
156
|
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_client_id.")
|
|
154
157
|
return msg
|
|
@@ -181,7 +184,8 @@ class Edge(object):
|
|
|
181
184
|
if self.svcert_no_verify:
|
|
182
185
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
183
186
|
status, msg = self.signin(opt['auth_type'], opt['user'], opt['password'], opt['apikey'],
|
|
184
|
-
opt['oauth2'], int(opt['oauth2_port']),
|
|
187
|
+
opt['oauth2'], int(opt['oauth2_port']),
|
|
188
|
+
opt['oauth2_tenant_id'], opt['oauth2_client_id'], opt['oauth2_client_secret'],
|
|
185
189
|
int(opt['oauth2_timeout']))
|
|
186
190
|
if status != 0:
|
|
187
191
|
return msg
|
|
@@ -244,7 +248,7 @@ class Edge(object):
|
|
|
244
248
|
resq:queue.Queue = pipe_cmd['resq']
|
|
245
249
|
del pipe_cmd['resq']
|
|
246
250
|
tool = Tool(self.logger, self.appcls, self.ver)
|
|
247
|
-
tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info)
|
|
251
|
+
tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
248
252
|
feat:feature.Feature = self.options.get_cmd_attr(pipe_cmd['mode'], pipe_cmd['cmd'], 'feature')
|
|
249
253
|
while not thevent.is_set():
|
|
250
254
|
prevres = None if prevq is None else prevq.get(pipe_cmd['timeout'])
|
|
@@ -301,7 +305,7 @@ class Edge(object):
|
|
|
301
305
|
def mkcmd(opt):
|
|
302
306
|
def _ex():
|
|
303
307
|
tool = Tool(self.logger, self.appcls, self.ver)
|
|
304
|
-
tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info)
|
|
308
|
+
tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
305
309
|
feat:feature.Feature = self.options.get_cmd_attr(opt['mode'], opt['cmd'], 'feature')
|
|
306
310
|
for status, ret in feat.edgerun(opt, tool, self.logger, self.timeout):
|
|
307
311
|
pass
|
|
@@ -348,7 +352,7 @@ class Edge(object):
|
|
|
348
352
|
return status, json.loads(res)
|
|
349
353
|
|
|
350
354
|
def signin(self, auth_type:str, user:str, password:str, apikey:str,
|
|
351
|
-
oauth2:str, oauth2_port:int, oauth2_client_id:str, oauth2_client_secret:str,
|
|
355
|
+
oauth2:str, oauth2_port:int, oauth2_tenant_id:str, oauth2_client_id:str, oauth2_client_secret:str,
|
|
352
356
|
oauth2_timeout:int) -> Tuple[int, Dict[str, Any]]:
|
|
353
357
|
"""
|
|
354
358
|
サインインを行います
|
|
@@ -360,6 +364,7 @@ class Edge(object):
|
|
|
360
364
|
apikey (str): APIキー
|
|
361
365
|
oauth2 (str): OAuth2
|
|
362
366
|
oauth2_port (int): OAuth2ポート
|
|
367
|
+
oauth2_tenant_id (str): OAuth2テナントID
|
|
363
368
|
oauth2_client_id (str): OAuth2クライアントID
|
|
364
369
|
oauth2_client_secret (str): OAuth2クライアントシークレット
|
|
365
370
|
oauth2_timeout (int): OAuth2タイムアウト
|
|
@@ -369,13 +374,14 @@ class Edge(object):
|
|
|
369
374
|
"""
|
|
370
375
|
self.session = requests.Session()
|
|
371
376
|
self.signed_in = False
|
|
377
|
+
self.oauth2 = oauth2
|
|
372
378
|
if auth_type == "noauth":
|
|
373
379
|
status, res, _ = self.site_request(self.session.get, "/gui")
|
|
374
380
|
if status != 0: return status, res
|
|
375
381
|
status, self.user_info = self.load_user_info()
|
|
376
382
|
self.user_info['auth_type'] = auth_type
|
|
377
383
|
if status != 0: return status, res
|
|
378
|
-
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info)
|
|
384
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
379
385
|
return 0, dict(success="No auth.")
|
|
380
386
|
|
|
381
387
|
# ID/PW認証を使用する場合
|
|
@@ -392,7 +398,7 @@ class Edge(object):
|
|
|
392
398
|
self.user_info['auth_type'] = auth_type
|
|
393
399
|
self.user_info['password'] = password
|
|
394
400
|
if status != 0: return status, res
|
|
395
|
-
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info)
|
|
401
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
396
402
|
return 0, dict(success="Signin Success.")
|
|
397
403
|
|
|
398
404
|
# APIKEY認証を使用する場合
|
|
@@ -407,7 +413,7 @@ class Edge(object):
|
|
|
407
413
|
self.user_info['auth_type'] = auth_type
|
|
408
414
|
self.user_info['apikey'] = apikey
|
|
409
415
|
if status != 0: return status, res
|
|
410
|
-
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info)
|
|
416
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
411
417
|
return 0, dict(success="Signin Success.")
|
|
412
418
|
|
|
413
419
|
# OAuth2認証を使用する場合
|
|
@@ -449,7 +455,7 @@ class Edge(object):
|
|
|
449
455
|
self.user_info['access_token'] = access_token
|
|
450
456
|
if status != 0: return status, res
|
|
451
457
|
self.signed_in = True
|
|
452
|
-
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info)
|
|
458
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
453
459
|
return dict(success="Signin success. Please close your browser.")
|
|
454
460
|
except Exception as e:
|
|
455
461
|
raise HTTPException(status_code=500, detail=f'Failed to get token. {e}')
|
|
@@ -515,7 +521,7 @@ class Edge(object):
|
|
|
515
521
|
self.user_info['access_token'] = access_token
|
|
516
522
|
if status != 0: return status, res
|
|
517
523
|
self.signed_in = True
|
|
518
|
-
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info)
|
|
524
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
519
525
|
return dict(success="Signin success. Please close your browser.")
|
|
520
526
|
except Exception as e:
|
|
521
527
|
raise HTTPException(status_code=500, detail=f'Failed to get token. {e}')
|
|
@@ -543,6 +549,79 @@ class Edge(object):
|
|
|
543
549
|
time.sleep(1)
|
|
544
550
|
return 0, dict(success="Signin success.")
|
|
545
551
|
|
|
552
|
+
|
|
553
|
+
# Azure OAuth2を使用する場合
|
|
554
|
+
elif oauth2 == "azure":
|
|
555
|
+
if oauth2_tenant_id is None:
|
|
556
|
+
return 1, dict(warn="Please specify the --oauth2_tenant_id option.")
|
|
557
|
+
if oauth2_client_id is None:
|
|
558
|
+
return 1, dict(warn="Please specify the --oauth2_client_id option.")
|
|
559
|
+
if oauth2_client_secret is None:
|
|
560
|
+
return 1, dict(warn="Please specify the --oauth2_client_secret option.")
|
|
561
|
+
if oauth2_timeout is None:
|
|
562
|
+
return 1, dict(warn="Please specify the --oauth2_timeout option.")
|
|
563
|
+
|
|
564
|
+
redirect_uri = f'http://localhost:{oauth2_port}/oauth2/azure/callback'
|
|
565
|
+
# OAuth2認証のコールバックを受けるFastAPIサーバーを起動
|
|
566
|
+
fastapi = FastAPI()
|
|
567
|
+
@fastapi.get('/oauth2/azure/callback')
|
|
568
|
+
async def oauth2_azure_callback(req:Request):
|
|
569
|
+
if req.query_params['state'] != 'edge':
|
|
570
|
+
return dict(warn="Invalid state.")
|
|
571
|
+
# アクセストークン取得
|
|
572
|
+
headers = {'Content-Type': 'application/x-www-form-urlencoded',
|
|
573
|
+
'Accept': 'application/json'}
|
|
574
|
+
data = {'tenant': oauth2_tenant_id,
|
|
575
|
+
'code': req.query_params['code'],
|
|
576
|
+
'scope': " ".join(['openid', 'profile', 'email']),
|
|
577
|
+
'client_id': oauth2_client_id,
|
|
578
|
+
#'client_secret': oauth2_client_secret,
|
|
579
|
+
'redirect_uri': redirect_uri,
|
|
580
|
+
'grant_type': 'authorization_code'}
|
|
581
|
+
query = '&'.join([f'{k}={urllib.parse.quote(v)}' for k, v in data.items()])
|
|
582
|
+
try:
|
|
583
|
+
token_resp = self.session.post(url=f'https://login.microsoftonline.com/{oauth2_tenant_id}/oauth2/v2.0/token', headers=headers, data=query,
|
|
584
|
+
verify=not self.svcert_no_verify)
|
|
585
|
+
token_resp.raise_for_status()
|
|
586
|
+
token_json = token_resp.json()
|
|
587
|
+
access_token = token_json['access_token']
|
|
588
|
+
status, res, headers = self.site_request(self.session.get, f"/oauth2/azure/session/{access_token}/gui", ok_status=[200, 307])
|
|
589
|
+
if status != 0 or headers.get('signin') is None:
|
|
590
|
+
return dict(warn=f"Signin failed.")
|
|
591
|
+
status, self.user_info = self.load_user_info()
|
|
592
|
+
self.user_info['auth_type'] = auth_type
|
|
593
|
+
self.user_info['access_token'] = access_token
|
|
594
|
+
if status != 0: return status, res
|
|
595
|
+
self.signed_in = True
|
|
596
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
597
|
+
return dict(success="Signin success. Please close your browser.")
|
|
598
|
+
except Exception as e:
|
|
599
|
+
raise HTTPException(status_code=500, detail=f'Failed to get token. {e}')
|
|
600
|
+
|
|
601
|
+
if not hasattr(self, 'thUvicorn') or not self.thUvicorn.is_alive():
|
|
602
|
+
self.thUvicorn = web.ThreadedUvicorn(self.logger, Config(app=fastapi, host='localhost', port=oauth2_port), {})
|
|
603
|
+
self.thUvicorn.start()
|
|
604
|
+
time.sleep(1)
|
|
605
|
+
|
|
606
|
+
# OAuth2認証のリクエストを送信
|
|
607
|
+
data = {'scope': " ".join(['openid', 'profile', 'email']),
|
|
608
|
+
'access_type': 'offline',
|
|
609
|
+
'response_type': 'code',
|
|
610
|
+
'redirect_uri': redirect_uri,
|
|
611
|
+
'client_id': oauth2_client_id,
|
|
612
|
+
'response_mode': 'query',
|
|
613
|
+
'state': 'edge'}
|
|
614
|
+
query = '&'.join([f'{k}={urllib.parse.quote(v)}' for k, v in data.items()])
|
|
615
|
+
webbrowser.open(f'https://login.microsoftonline.com/{oauth2_tenant_id}/oauth2/v2.0/authorize?{query}')
|
|
616
|
+
|
|
617
|
+
# 認証完了まで指定秒数待つ
|
|
618
|
+
tm = time.time()
|
|
619
|
+
while not self.signed_in:
|
|
620
|
+
if time.time() - tm > oauth2_timeout:
|
|
621
|
+
return 1, dict(warn="Signin Timeout.")
|
|
622
|
+
time.sleep(1)
|
|
623
|
+
return 0, dict(success="Signin success.")
|
|
624
|
+
|
|
546
625
|
return 1, dict(warn="unsupported auth_type.")
|
|
547
626
|
|
|
548
627
|
class Tool(object):
|
|
@@ -578,7 +657,7 @@ class Tool(object):
|
|
|
578
657
|
except Exception as e:
|
|
579
658
|
self.logger.error(f"notify error. {e}", exc_info=True)
|
|
580
659
|
|
|
581
|
-
def set_session(self, session:requests.Session, svcert_no_verify:bool, endpoint:str, icon_path:Path, user_info:Dict[str, Any]):
|
|
660
|
+
def set_session(self, session:requests.Session, svcert_no_verify:bool, endpoint:str, icon_path:Path, user_info:Dict[str, Any], oauth2:str):
|
|
582
661
|
"""
|
|
583
662
|
セッションを設定します
|
|
584
663
|
|
|
@@ -588,12 +667,14 @@ class Tool(object):
|
|
|
588
667
|
endpoint (str): エンドポイント
|
|
589
668
|
icon_path (Path): アイコン画像のパス
|
|
590
669
|
user_info (Dict[str, Any]): ユーザー情報
|
|
670
|
+
oauth2 (str): OAuth2
|
|
591
671
|
"""
|
|
592
672
|
self.session = session
|
|
593
673
|
self.svcert_no_verify = svcert_no_verify
|
|
594
674
|
self.endpoint = endpoint
|
|
595
675
|
self.icon_path = icon_path
|
|
596
676
|
self.user = user_info
|
|
677
|
+
self.oauth2 = oauth2
|
|
597
678
|
|
|
598
679
|
def exec_cmd(self, opt:Dict[str, Any], logger:logging.Logger, timeout:int, prevres:Any=None) -> Tuple[int, Dict[str, Any]]:
|
|
599
680
|
"""
|
|
@@ -694,9 +775,12 @@ class Tool(object):
|
|
|
694
775
|
webbrowser.open(f"{self.endpoint}/dosignin_token/{token}{path}")
|
|
695
776
|
return 0, dict(success="Open browser.")
|
|
696
777
|
elif self.user['auth_type'] == "oauth2" and self.oauth2 == 'google':
|
|
697
|
-
webbrowser.open(f"{self.endpoint}/oauth2/google/session/{self.user['access_token']}
|
|
778
|
+
webbrowser.open(f"{self.endpoint}/oauth2/google/session/{self.user['access_token']}{path}")
|
|
698
779
|
return 0, dict(success="Open browser.")
|
|
699
780
|
elif self.user['auth_type'] == "oauth2" and self.oauth2 == 'github':
|
|
700
|
-
webbrowser.open(f"{self.endpoint}/oauth2/github/session/{self.user['access_token']}
|
|
781
|
+
webbrowser.open(f"{self.endpoint}/oauth2/github/session/{self.user['access_token']}{path}")
|
|
782
|
+
return 0, dict(success="Open browser.")
|
|
783
|
+
elif self.user['auth_type'] == "oauth2" and self.oauth2 == 'azure':
|
|
784
|
+
webbrowser.open(f"{self.endpoint}/oauth2/azure/session/{self.user['access_token']}{path}")
|
|
701
785
|
return 0, dict(success="Open browser.")
|
|
702
786
|
return 1, dict(warn="unsupported auth_type.")
|
|
@@ -49,7 +49,7 @@ class EdgeConfig(feature.UnsupportEdgeFeature):
|
|
|
49
49
|
discription_en="Specifies the authentication method for endpoint connections.",
|
|
50
50
|
choice_show=dict(idpw=["user","password"],
|
|
51
51
|
apikey=["apikey"],
|
|
52
|
-
oauth2=["oauth2","oauth2_port"
|
|
52
|
+
oauth2=["oauth2","oauth2_port"]),),
|
|
53
53
|
dict(opt="user", type=Options.T_STR, default="user", required=False, multi=False, hide=False, choice=None,
|
|
54
54
|
discription_ja="エンドポイントへの接続ユーザーを指定します。",
|
|
55
55
|
discription_en="Specifies the user connecting to the endpoint."),
|
|
@@ -59,12 +59,18 @@ class EdgeConfig(feature.UnsupportEdgeFeature):
|
|
|
59
59
|
dict(opt="apikey", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
60
60
|
discription_ja="エンドポイントへの接続するためのAPIKEYを指定します。",
|
|
61
61
|
discription_en="Specify the APIKEY to connect to the endpoint."),
|
|
62
|
-
dict(opt="oauth2", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=["", "google", "github"],
|
|
62
|
+
dict(opt="oauth2", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=["", "google", "github", "azure"],
|
|
63
63
|
discription_ja="OAuth2認証を使用してエンドポイントに接続します。",
|
|
64
|
-
discription_en="Connect to the endpoint using OAuth2 authentication."
|
|
64
|
+
discription_en="Connect to the endpoint using OAuth2 authentication.",
|
|
65
|
+
choice_show=dict(google=["oauth2_client_id","oauth2_client_secret"],
|
|
66
|
+
github=["oauth2_client_id","oauth2_client_secret"],
|
|
67
|
+
azure=["oauth2_tenant_id","oauth2_client_id","oauth2_client_secret"])),
|
|
65
68
|
dict(opt="oauth2_port", type=Options.T_INT, default="8091", required=False, multi=False, hide=False, choice=None,
|
|
66
69
|
discription_ja="OAuth2認証を使用する場合のコールバックポートを指定します。省略した時は `8091` を使用します。",
|
|
67
70
|
discription_en="Specifies the callback port when OAuth2 authentication is used. If omitted, `8091` is used."),
|
|
71
|
+
dict(opt="oauth2_tenant_id", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
72
|
+
discription_ja="OAuth2認証を使用するときのテナントIDを指定します。",
|
|
73
|
+
discription_en="Specifies the tenant ID when OAuth2 authentication is used."),
|
|
68
74
|
dict(opt="oauth2_client_id", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
69
75
|
discription_ja="OAuth2認証を使用するときのクライアントIDを指定します。",
|
|
70
76
|
discription_en="Specifies the client ID when OAuth2 authentication is used."),
|
|
@@ -86,7 +86,7 @@ class GuiStart(feature.UnsupportEdgeFeature):
|
|
|
86
86
|
dict(opt="session_secure", type=Options.T_BOOL, default=False, required=False, multi=False, hide=True, choice=[True, False],
|
|
87
87
|
discription_ja="サインインしたユーザーのセッションにSecureフラグを設定します。",
|
|
88
88
|
discription_en="Set the Secure flag for the signed-in user's session."),
|
|
89
|
-
dict(opt="session_timeout", type=Options.T_INT, default="
|
|
89
|
+
dict(opt="session_timeout", type=Options.T_INT, default="900", required=False, multi=False, hide=True, choice=None,
|
|
90
90
|
discription_ja="サインインしたユーザーのセッションタイムアウトの時間を秒で指定します。",
|
|
91
91
|
discription_en="Specify the session timeout in seconds for signed-in users."),
|
|
92
92
|
dict(opt="guvicorn_workers", type=Options.T_INT, default=multiprocessing.cpu_count()*2, required=False, multi=False, hide=True, choice=None,
|
|
@@ -86,7 +86,7 @@ class WebStart(feature.UnsupportEdgeFeature):
|
|
|
86
86
|
dict(opt="session_secure", type=Options.T_BOOL, default=False, required=False, multi=False, hide=True, choice=[True, False],
|
|
87
87
|
discription_ja="サインインしたユーザーのセッションにSecureフラグを設定します。",
|
|
88
88
|
discription_en="Set the Secure flag for the signed-in user's session."),
|
|
89
|
-
dict(opt="session_timeout", type=Options.T_INT, default="
|
|
89
|
+
dict(opt="session_timeout", type=Options.T_INT, default="900", required=False, multi=False, hide=True, choice=None,
|
|
90
90
|
discription_ja="サインインしたユーザーのセッションタイムアウトの時間を秒で指定します。",
|
|
91
91
|
discription_en="Specify the session timeout in seconds for signed-in users."),
|
|
92
92
|
dict(opt="guvicorn_workers", type=Options.T_INT, default=multiprocessing.cpu_count()*2, required=False, multi=False, hide=True, choice=None,
|
|
@@ -171,6 +171,7 @@ class WebStart(feature.UnsupportEdgeFeature):
|
|
|
171
171
|
common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
|
|
172
172
|
return 0, msg, w
|
|
173
173
|
except Exception as e:
|
|
174
|
+
logger.error(f"Web server start error. {e}", exc_info=True)
|
|
174
175
|
msg = dict(warn=f"Web server start error. {e}")
|
|
175
176
|
common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
|
|
176
177
|
return 1, msg, w
|
|
@@ -15,7 +15,7 @@ class BbforceCmd(feature.WebFeature):
|
|
|
15
15
|
"""
|
|
16
16
|
@app.get('/bbforce_cmd')
|
|
17
17
|
async def del_cmd(req:Request, res:Response):
|
|
18
|
-
signin = web.check_signin(req, res)
|
|
18
|
+
signin = web.signin.check_signin(req, res)
|
|
19
19
|
if signin is not None:
|
|
20
20
|
raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
|
|
21
21
|
if web.logger.level == logging.DEBUG:
|
|
@@ -15,7 +15,7 @@ class Copyright(feature.WebFeature):
|
|
|
15
15
|
"""
|
|
16
16
|
@app.get('/copyright', response_class=PlainTextResponse)
|
|
17
17
|
async def copyright(req:Request, res:Response):
|
|
18
|
-
signin = web.check_signin(req, res)
|
|
18
|
+
signin = web.signin.check_signin(req, res)
|
|
19
19
|
if signin is not None:
|
|
20
20
|
raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
|
|
21
21
|
return self.ver.__copyright__
|
|
@@ -14,7 +14,7 @@ class DelCmd(feature.WebFeature):
|
|
|
14
14
|
"""
|
|
15
15
|
@app.post('/gui/del_cmd')
|
|
16
16
|
async def del_cmd(req:Request, res:Response):
|
|
17
|
-
signin = web.check_signin(req, res)
|
|
17
|
+
signin = web.signin.check_signin(req, res)
|
|
18
18
|
if signin is not None:
|
|
19
19
|
raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
|
|
20
20
|
form = await req.form()
|
|
@@ -14,7 +14,7 @@ class DelPipe(feature.WebFeature):
|
|
|
14
14
|
"""
|
|
15
15
|
@app.post('/gui/del_pipe')
|
|
16
16
|
async def del_pipe(req:Request, res:Response):
|
|
17
|
-
signin = web.check_signin(req, res)
|
|
17
|
+
signin = web.signin.check_signin(req, res)
|
|
18
18
|
if signin is not None:
|
|
19
19
|
raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
|
|
20
20
|
form = await req.form()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from cmdbox.app import common
|
|
1
|
+
from cmdbox.app import common
|
|
2
|
+
from cmdbox.app.auth.signin import Signin
|
|
2
3
|
from cmdbox.app.commons import convert
|
|
3
4
|
from cmdbox.app.features.web import cmdbox_web_signin
|
|
4
5
|
from cmdbox.app.web import Web
|
|
@@ -33,6 +34,7 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
33
34
|
name = form.get('name')
|
|
34
35
|
passwd = form.get('password')
|
|
35
36
|
# edgeからtokenによる認証の場合
|
|
37
|
+
signin_data = web.signin.get_data()
|
|
36
38
|
token_ok = False
|
|
37
39
|
if token is not None:
|
|
38
40
|
if web.logger.level == logging.DEBUG:
|
|
@@ -40,7 +42,7 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
40
42
|
token = convert.b64str2str(token)
|
|
41
43
|
token = json.loads(token)
|
|
42
44
|
name = token['user']
|
|
43
|
-
user = [u for u in
|
|
45
|
+
user = [u for u in signin_data['users'] if u['name'] == name]
|
|
44
46
|
if len(user) <= 0:
|
|
45
47
|
raise HTTPException(status_code=401, detail='Unauthorized')
|
|
46
48
|
user = user[0]
|
|
@@ -57,7 +59,7 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
57
59
|
if not token_ok:
|
|
58
60
|
if name == '' or passwd == '':
|
|
59
61
|
return RedirectResponse(url=f'/signin/{next}?error=1')
|
|
60
|
-
user = [u for u in
|
|
62
|
+
user = [u for u in signin_data['users'] if u['name'] == name and u['hash'] != 'oauth2']
|
|
61
63
|
if len(user) <= 0:
|
|
62
64
|
return RedirectResponse(url=f'/signin/{next}?error=1')
|
|
63
65
|
user = user[0]
|
|
@@ -67,9 +69,9 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
67
69
|
# ロックアウトチェック
|
|
68
70
|
pass_miss_count = web.user_data(None, uid, name, 'password', 'pass_miss_count')
|
|
69
71
|
pass_miss_count = 0 if pass_miss_count is None else int(pass_miss_count)
|
|
70
|
-
if 'password' in
|
|
71
|
-
threshold =
|
|
72
|
-
reset =
|
|
72
|
+
if 'password' in signin_data and signin_data['password']['lockout']['enabled']:
|
|
73
|
+
threshold = signin_data['password']['lockout']['threshold']
|
|
74
|
+
reset = signin_data['password']['lockout']['reset']
|
|
73
75
|
pass_miss_last = web.user_data(None, uid, name, 'password', 'pass_miss_last')
|
|
74
76
|
if pass_miss_last is None:
|
|
75
77
|
pass_miss_last = web.user_data(None, uid, name, 'password', 'pass_miss_last', datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S'))
|
|
@@ -95,17 +97,17 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
95
97
|
web.user_data(None, uid, name, 'password', 'pass_miss_count', pass_miss_count+1)
|
|
96
98
|
web.logger.warning(f'Failed to signin. name={name}, pass_miss_count={pass_miss_count+1}')
|
|
97
99
|
return RedirectResponse(url=f'/signin/{next}?error=1')
|
|
98
|
-
group_names = list(set(web.correct_group(user['groups'])))
|
|
99
|
-
gids = [g['gid'] for g in
|
|
100
|
+
group_names = list(set(web.signin.__class__.correct_group(signin_data, user['groups'], None)))
|
|
101
|
+
gids = [g['gid'] for g in signin_data['groups'] if g['name'] in group_names]
|
|
100
102
|
email = user.get('email', '')
|
|
101
103
|
# パスワード最終更新日時取得
|
|
102
104
|
last_update = web.user_data(None, uid, name, 'password', 'last_update')
|
|
103
105
|
notify_passchange = True if last_update is None else False
|
|
104
106
|
# パスワード認証の場合はパスワード有効期限チェック
|
|
105
|
-
if user['hash']!='oauth2' and 'password' in
|
|
107
|
+
if user['hash']!='oauth2' and 'password' in signin_data and not notify_passchange:
|
|
106
108
|
last_update = datetime.datetime.strptime(last_update, '%Y-%m-%dT%H:%M:%S')
|
|
107
109
|
# パスワード有効期限
|
|
108
|
-
expiration =
|
|
110
|
+
expiration = signin_data['password']['expiration']
|
|
109
111
|
if expiration['enabled']:
|
|
110
112
|
period = expiration['period']
|
|
111
113
|
notify = expiration['notify']
|
|
@@ -122,7 +124,7 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
122
124
|
next = f"../{next}" if token_ok else next
|
|
123
125
|
return RedirectResponse(url=f'../{next}{"?warn=passchange" if notify_passchange else ""}', headers=dict(signin="success")) # nginxのリバプロ対応のための相対パス
|
|
124
126
|
|
|
125
|
-
def _load_signin(signin_module:str, appcls, ver):
|
|
127
|
+
def _load_signin(web:Web, signin_module:str, appcls, ver):
|
|
126
128
|
"""
|
|
127
129
|
サインインオブジェクトを読込む
|
|
128
130
|
|
|
@@ -138,26 +140,31 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
138
140
|
try:
|
|
139
141
|
mod = importlib.import_module(signin_module)
|
|
140
142
|
members = inspect.getmembers(mod, inspect.isclass)
|
|
143
|
+
signin_data = web.signin.get_data()
|
|
141
144
|
for name, cls in members:
|
|
142
|
-
if cls is
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return sobj
|
|
145
|
+
if cls is Signin or issubclass(cls, Signin):
|
|
146
|
+
sobj = cls(web.logger, web.signin_file, signin_data, appcls, ver)
|
|
147
|
+
return sobj
|
|
146
148
|
return None
|
|
147
149
|
except Exception as e:
|
|
148
150
|
web.logger.error(f'Failed to load signin. {e}', exc_info=True)
|
|
149
151
|
raise e
|
|
150
152
|
|
|
151
|
-
|
|
152
|
-
self.
|
|
153
|
-
|
|
153
|
+
signin_data = web.signin.get_data()
|
|
154
|
+
self.google_signin = Signin(web.logger, web.signin_file, signin_data, self.appcls, self.ver)
|
|
155
|
+
self.github_signin = Signin(web.logger, web.signin_file, signin_data, self.appcls, self.ver)
|
|
156
|
+
self.azure_signin = Signin(web.logger, web.signin_file, signin_data, self.appcls, self.ver)
|
|
157
|
+
if signin_data is not None:
|
|
154
158
|
# signinオブジェクトの指定があった場合読込む
|
|
155
|
-
if 'signin_module' in
|
|
156
|
-
sobj = _load_signin(web
|
|
159
|
+
if 'signin_module' in signin_data['oauth2']['providers']['google']:
|
|
160
|
+
sobj = _load_signin(web, signin_data['oauth2']['providers']['google']['signin_module'], self.appcls, self.ver)
|
|
157
161
|
self.google_signin = sobj if sobj is not None else self.google_signin
|
|
158
|
-
if 'signin_module' in
|
|
159
|
-
sobj = _load_signin(web
|
|
162
|
+
if 'signin_module' in signin_data['oauth2']['providers']['github']:
|
|
163
|
+
sobj = _load_signin(web, signin_data['oauth2']['providers']['github']['signin_module'], self.appcls, self.ver)
|
|
160
164
|
self.github_signin = sobj if sobj is not None else self.github_signin
|
|
165
|
+
if 'signin_module' in signin_data['oauth2']['providers']['azure']:
|
|
166
|
+
sobj = _load_signin(web, signin_data['oauth2']['providers']['azure']['signin_module'], self.appcls, self.ver)
|
|
167
|
+
self.azure_signin = sobj if sobj is not None else self.azure_signin
|
|
161
168
|
|
|
162
169
|
def _set_session(req:Request, user:dict, email:str, hashed_password:str, access_token:str, group_names:list, gids:list):
|
|
163
170
|
"""
|
|
@@ -191,7 +198,7 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
191
198
|
|
|
192
199
|
@app.get('/oauth2/google/callback')
|
|
193
200
|
async def oauth2_google_callback(req:Request, res:Response):
|
|
194
|
-
conf = web.
|
|
201
|
+
conf = web.signin.get_data()['oauth2']['providers']['google']
|
|
195
202
|
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
|
|
196
203
|
next = req.query_params['state']
|
|
197
204
|
data = {'code': req.query_params['code'],
|
|
@@ -206,7 +213,7 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
206
213
|
token_resp.raise_for_status()
|
|
207
214
|
token_json = token_resp.json()
|
|
208
215
|
access_token = token_json['access_token']
|
|
209
|
-
return await oauth2_google_session(
|
|
216
|
+
return await oauth2_google_session(access_token, next, req, res)
|
|
210
217
|
except Exception as e:
|
|
211
218
|
web.logger.warning(f'Failed to get token. {e}', exc_info=True)
|
|
212
219
|
raise HTTPException(status_code=500, detail=f'Failed to get token. {e}')
|
|
@@ -223,12 +230,11 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
223
230
|
user_info_json = user_info_resp.json()
|
|
224
231
|
email = user_info_json['email']
|
|
225
232
|
# サインイン判定
|
|
226
|
-
|
|
227
|
-
jadge, user = self.google_signin.jadge(access_token, email, copy_signin_data)
|
|
233
|
+
jadge, user = self.google_signin.jadge(access_token, email)
|
|
228
234
|
if not jadge:
|
|
229
235
|
return RedirectResponse(url=f'/signin/{next}?error=appdeny')
|
|
230
236
|
# グループ取得
|
|
231
|
-
group_names, gids = self.google_signin.get_groups(access_token, user
|
|
237
|
+
group_names, gids = self.google_signin.get_groups(access_token, user)
|
|
232
238
|
# セッションに保存
|
|
233
239
|
_set_session(req, user, email, None, access_token, group_names, gids)
|
|
234
240
|
return RedirectResponse(url=f'../../{next}', headers=dict(signin="success")) # nginxのリバプロ対応のための相対パス
|
|
@@ -238,7 +244,7 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
238
244
|
|
|
239
245
|
@app.get('/oauth2/github/callback')
|
|
240
246
|
async def oauth2_github_callback(req:Request, res:Response):
|
|
241
|
-
conf = web.
|
|
247
|
+
conf = web.signin.get_data()['oauth2']['providers']['github']
|
|
242
248
|
headers = {'Content-Type': 'application/x-www-form-urlencoded',
|
|
243
249
|
'Accept': 'application/json'}
|
|
244
250
|
next = req.query_params['state']
|
|
@@ -253,7 +259,7 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
253
259
|
token_resp.raise_for_status()
|
|
254
260
|
token_json = token_resp.json()
|
|
255
261
|
access_token = token_json['access_token']
|
|
256
|
-
return await oauth2_github_session(
|
|
262
|
+
return await oauth2_github_session(access_token, next, req, res)
|
|
257
263
|
except Exception as e:
|
|
258
264
|
web.logger.warning(f'Failed to get token. {e}', exc_info=True)
|
|
259
265
|
raise HTTPException(status_code=500, detail=f'Failed to get token. {e}')
|
|
@@ -275,12 +281,62 @@ class DoSignin(cmdbox_web_signin.Signin):
|
|
|
275
281
|
email = u['email']
|
|
276
282
|
break
|
|
277
283
|
# サインイン判定
|
|
278
|
-
|
|
279
|
-
jadge, user = self.github_signin.jadge(access_token, email, copy_signin_data)
|
|
284
|
+
jadge, user = self.github_signin.jadge(access_token, email)
|
|
280
285
|
if not jadge:
|
|
281
286
|
return RedirectResponse(url=f'/signin/{next}?error=appdeny')
|
|
282
287
|
# グループ取得
|
|
283
|
-
group_names, gids = self.github_signin.get_groups(access_token, user
|
|
288
|
+
group_names, gids = self.github_signin.get_groups(access_token, user)
|
|
289
|
+
# セッションに保存
|
|
290
|
+
_set_session(req, user, email, None, access_token, group_names, gids)
|
|
291
|
+
return RedirectResponse(url=f'../../{next}', headers=dict(signin="success")) # nginxのリバプロ対応のための相対パス
|
|
292
|
+
except Exception as e:
|
|
293
|
+
web.logger.warning(f'Failed to get token. {e}', exc_info=True)
|
|
294
|
+
raise HTTPException(status_code=500, detail=f'Failed to get token. {e}')
|
|
295
|
+
|
|
296
|
+
@app.get('/oauth2/azure/callback')
|
|
297
|
+
async def oauth2_azure_callback(req:Request, res:Response):
|
|
298
|
+
conf = web.signin.get_data()['oauth2']['providers']['azure']
|
|
299
|
+
headers = {'Content-Type': 'application/x-www-form-urlencoded',
|
|
300
|
+
'Accept': 'application/json'}
|
|
301
|
+
next = req.query_params['state']
|
|
302
|
+
data = {'tenant': conf['tenant_id'],
|
|
303
|
+
'code': req.query_params['code'],
|
|
304
|
+
'scope': " ".join(conf['scope']),
|
|
305
|
+
'client_id': conf['client_id'],
|
|
306
|
+
#'client_secret': conf['client_secret'],
|
|
307
|
+
'redirect_uri': conf['redirect_uri'],
|
|
308
|
+
'grant_type': 'authorization_code'}
|
|
309
|
+
query = '&'.join([f'{k}={urllib.parse.quote(v)}' for k, v in data.items()])
|
|
310
|
+
try:
|
|
311
|
+
# アクセストークン取得
|
|
312
|
+
token_resp = requests.post(url=f'https://login.microsoftonline.com/{conf["tenant_id"]}/oauth2/v2.0/token', headers=headers, data=query)
|
|
313
|
+
token_resp.raise_for_status()
|
|
314
|
+
token_json = token_resp.json()
|
|
315
|
+
access_token = token_json['access_token']
|
|
316
|
+
return await oauth2_azure_session(access_token, next, req, res)
|
|
317
|
+
except Exception as e:
|
|
318
|
+
web.logger.warning(f'Failed to get token. {e}', exc_info=True)
|
|
319
|
+
raise HTTPException(status_code=500, detail=f'Failed to get token. {e}')
|
|
320
|
+
|
|
321
|
+
@app.get('/oauth2/azure/session/{access_token}/{next}')
|
|
322
|
+
async def oauth2_azure_session(access_token:str, next:str, req:Request, res:Response):
|
|
323
|
+
try:
|
|
324
|
+
# ユーザー情報取得(email)
|
|
325
|
+
user_info_resp = requests.get(
|
|
326
|
+
url='https://graph.microsoft.com/v1.0/me',
|
|
327
|
+
#url='https://graph.microsoft.com/v1.0/me/transitiveMemberOf?$Top=999',
|
|
328
|
+
headers={'Authorization': f'Bearer {access_token}'}
|
|
329
|
+
)
|
|
330
|
+
user_info_resp.raise_for_status()
|
|
331
|
+
user_info_json = user_info_resp.json()
|
|
332
|
+
if isinstance(user_info_json, dict):
|
|
333
|
+
email = user_info_json.get('mail', 'notfound')
|
|
334
|
+
# サインイン判定
|
|
335
|
+
jadge, user = self.azure_signin.jadge(access_token, email)
|
|
336
|
+
if not jadge:
|
|
337
|
+
return RedirectResponse(url=f'/signin/{next}?error=appdeny')
|
|
338
|
+
# グループ取得
|
|
339
|
+
group_names, gids = self.azure_signin.get_groups(access_token, user)
|
|
284
340
|
# セッションに保存
|
|
285
341
|
_set_session(req, user, email, None, access_token, group_names, gids)
|
|
286
342
|
return RedirectResponse(url=f'../../{next}', headers=dict(signin="success")) # nginxのリバプロ対応のための相対パス
|
|
@@ -26,7 +26,7 @@ class ExecCmd(cmdbox_web_load_cmd.LoadCmd):
|
|
|
26
26
|
@app.post('/exec_cmd/{title}')
|
|
27
27
|
async def exec_cmd(req:Request, res:Response, title:str=None):
|
|
28
28
|
try:
|
|
29
|
-
signin = web.check_signin(req, res)
|
|
29
|
+
signin = web.signin.check_signin(req, res)
|
|
30
30
|
if signin is not None:
|
|
31
31
|
raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
|
|
32
32
|
opt = None
|
|
@@ -114,7 +114,7 @@ class ExecCmd(cmdbox_web_load_cmd.LoadCmd):
|
|
|
114
114
|
appcls = app.CmdBoxApp if appcls is None else appcls
|
|
115
115
|
web.container['cmdbox_app'] = ap = appcls.getInstance(appcls=appcls, ver=self.ver)
|
|
116
116
|
if 'mode' in opt and 'cmd' in opt:
|
|
117
|
-
if not web.check_cmd(req, res, opt['mode'], opt['cmd']):
|
|
117
|
+
if not web.signin.check_cmd(req, res, opt['mode'], opt['cmd']):
|
|
118
118
|
return dict(warn=f'Command "{title}" failed. Execute command denyed. mode={opt["mode"]}, cmd={opt["cmd"]}')
|
|
119
119
|
if 'host' in opt: opt['host'] = web.redis_host
|
|
120
120
|
if 'port' in opt: opt['port'] = web.redis_port
|
|
@@ -29,7 +29,7 @@ class ExecPipe(cmdbox_web_load_pipe.LoadPipe, cmdbox_web_raw_pipe.RawPipe):
|
|
|
29
29
|
async def exec_pipe(req:Request, res:Response, title:str=None):
|
|
30
30
|
upfiles = dict()
|
|
31
31
|
try:
|
|
32
|
-
signin = web.check_signin(req, res)
|
|
32
|
+
signin = web.signin.check_signin(req, res)
|
|
33
33
|
if signin is not None:
|
|
34
34
|
raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
|
|
35
35
|
opt = None
|
|
@@ -71,7 +71,7 @@ class ExecPipe(cmdbox_web_load_pipe.LoadPipe, cmdbox_web_raw_pipe.RawPipe):
|
|
|
71
71
|
msg = f'Command "{cmd_title}" failed. This command is not available in web mode.'
|
|
72
72
|
self.callback_return_pipe_exec_func(web, title, dict(warn=msg))
|
|
73
73
|
raise HTTPException(401, detail=msg)
|
|
74
|
-
if not web.check_cmd(req, res, cmd_opt['mode'], cmd_opt['cmd']):
|
|
74
|
+
if not web.signin.check_cmd(req, res, cmd_opt['mode'], cmd_opt['cmd']):
|
|
75
75
|
msg = f'Command "{cmd_title}" failed. Execute command denyed. mode={cmd_opt["mode"]}, cmd={cmd_opt["cmd"]}'
|
|
76
76
|
self.callback_return_pipe_exec_func(web, title, dict(warn=msg))
|
|
77
77
|
raise HTTPException(401, detail=msg)
|
|
@@ -3,9 +3,8 @@ from cmdbox.app.commons import convert
|
|
|
3
3
|
from cmdbox.app.features.web import cmdbox_web_exec_cmd
|
|
4
4
|
from cmdbox.app.web import Web
|
|
5
5
|
from fastapi import FastAPI, Request, Response, HTTPException
|
|
6
|
-
from fastapi.responses import
|
|
6
|
+
from fastapi.responses import StreamingResponse
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Dict, Any
|
|
9
8
|
import io
|
|
10
9
|
import urllib.parse
|
|
11
10
|
|
|
@@ -21,7 +20,7 @@ class FilerDownload(cmdbox_web_exec_cmd.ExecCmd):
|
|
|
21
20
|
"""
|
|
22
21
|
@app.get('/filer/download/{constr:str}', response_class=StreamingResponse)
|
|
23
22
|
async def filer_download(constr:str, req:Request, res:Response):
|
|
24
|
-
signin = web.check_signin(req, res)
|
|
23
|
+
signin = web.signin.check_signin(req, res)
|
|
25
24
|
if signin is not None:
|
|
26
25
|
raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
|
|
27
26
|
try:
|