增加了激活页面
This commit is contained in:
parent
c3f9693ee9
commit
69650ee030
15
backend/activation_request_W10-D13710C7BD317C29.json
Normal file
15
backend/activation_request_W10-D13710C7BD317C29.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"product": "BodyBalanceEvaluation",
|
||||
"version": "1.0.0",
|
||||
"machine_id": "W10-D13710C7BD317C29",
|
||||
"platform": "Windows",
|
||||
"request_time": "2025-11-02T03:42:26.592503+00:00",
|
||||
"hardware_info": {
|
||||
"system": "Windows",
|
||||
"machine": "AMD64",
|
||||
"processor": "Intel64 Family 6 Model 165 Stepping 2, GenuineIntel",
|
||||
"node": "MSI"
|
||||
},
|
||||
"company_name": "北京天宏博科技有限公司",
|
||||
"contact_info": "thb@163.com"
|
||||
}
|
||||
@ -393,11 +393,20 @@ class AppServer:
|
||||
company_name=company_name,
|
||||
contact_info=contact_info
|
||||
)
|
||||
# 读取文件内容返回给前端便于直接下载
|
||||
content_text = None
|
||||
try:
|
||||
with open(request_file, 'r', encoding='utf-8') as f:
|
||||
content_text = f.read()
|
||||
except Exception as e:
|
||||
self.logger.warning(f'读取激活请求文件失败: {e}')
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'data': {
|
||||
'request_file': request_file,
|
||||
'content': content_text,
|
||||
'machine_id': self.license_manager.get_machine_id() if self.license_manager else None,
|
||||
'message': f'激活请求文件已生成: {request_file}'
|
||||
}
|
||||
})
|
||||
@ -488,6 +497,64 @@ class AppServer:
|
||||
self.logger.error(f'验证授权文件失败: {e}')
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
@self.app.route('/api/license/activate-package', methods=['POST'])
|
||||
def activate_license_package():
|
||||
"""上传授权包ZIP,解压到配置指定目录并刷新授权"""
|
||||
try:
|
||||
if not self.license_manager:
|
||||
return jsonify({'success': False, 'error': '授权管理器未初始化'}), 500
|
||||
|
||||
if 'package_zip' not in flask_request.files:
|
||||
return jsonify({'success': False, 'error': '未找到授权包压缩文件'}), 400
|
||||
|
||||
file = flask_request.files['package_zip']
|
||||
if file.filename == '':
|
||||
return jsonify({'success': False, 'error': '未选择文件'}), 400
|
||||
|
||||
import tempfile, zipfile, shutil
|
||||
with tempfile.NamedTemporaryFile(suffix='.zip', delete=False) as temp_file:
|
||||
file.save(temp_file.name)
|
||||
temp_path = temp_file.name
|
||||
|
||||
try:
|
||||
# 目标目录:LICENSE.path 的目录
|
||||
license_path_cfg = self.config_manager.get_config_value('LICENSE', 'path', 'data/license.json') if self.config_manager else 'data/license.json'
|
||||
if not os.path.isabs(license_path_cfg):
|
||||
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
license_path_cfg = os.path.join(base_dir, license_path_cfg)
|
||||
target_dir = os.path.dirname(license_path_cfg)
|
||||
os.makedirs(target_dir, exist_ok=True)
|
||||
|
||||
# 安全解压,防止路径遍历
|
||||
with zipfile.ZipFile(temp_path, 'r') as zip_ref:
|
||||
for member in zip_ref.namelist():
|
||||
safe_member = os.path.normpath(member)
|
||||
if ('..' in safe_member) or safe_member.startswith('/') or safe_member.startswith('\\') or os.path.isabs(safe_member):
|
||||
return jsonify({'success': False, 'error': '压缩包包含非法路径'}), 400
|
||||
zip_ref.extractall(target_dir)
|
||||
|
||||
# 刷新授权
|
||||
self.license_status = self.license_manager.get_license_status(force_reload=True)
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'data': {
|
||||
'message': '激活包已安装,请重启系统生效',
|
||||
'valid': self.license_status.valid,
|
||||
'license_type': self.license_status.license_type,
|
||||
'expires_at': self.license_status.expires_at.isoformat() if self.license_status.expires_at else None
|
||||
}
|
||||
})
|
||||
finally:
|
||||
try:
|
||||
os.unlink(temp_path)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f'激活包安装失败: {e}')
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
# ==================== 静态文件服务 ====================
|
||||
|
||||
@self.app.route('/<path:filename>', methods=['GET'])
|
||||
|
||||
41
config.ini
Normal file
41
config.ini
Normal file
@ -0,0 +1,41 @@
|
||||
[APP]
|
||||
name = Body Balance Evaluation System
|
||||
version = 1.0.0
|
||||
debug = false
|
||||
log_level = INFO
|
||||
|
||||
[SERVER]
|
||||
host = 0.0.0.0
|
||||
port = 5000
|
||||
cors_origins = *
|
||||
|
||||
[DATABASE]
|
||||
path = backend/data/body_balance.db
|
||||
backup_interval = 24
|
||||
max_backups = 7
|
||||
|
||||
[DEVICES]
|
||||
camera_index = 0
|
||||
camera_width = 640
|
||||
camera_height = 480
|
||||
camera_fps = 30
|
||||
imu_port = COM3
|
||||
pressure_port = COM4
|
||||
|
||||
[DETECTION]
|
||||
default_duration = 60
|
||||
sampling_rate = 30
|
||||
balance_threshold = 0.2
|
||||
posture_threshold = 5.0
|
||||
|
||||
[DATA_PROCESSING]
|
||||
filter_window = 5
|
||||
outlier_threshold = 2.0
|
||||
chart_dpi = 300
|
||||
export_format = csv
|
||||
|
||||
[SECURITY]
|
||||
secret_key = f50c705c26a963701a4832ae3d69a091674f587a4b02da8b1c59909c0bd312fe
|
||||
session_timeout = 3600
|
||||
max_login_attempts = 5
|
||||
|
||||
@ -0,0 +1 @@
|
||||
pip
|
||||
@ -0,0 +1,139 @@
|
||||
Metadata-Version: 2.4
|
||||
Name: cryptography
|
||||
Version: 46.0.3
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Natural Language :: English
|
||||
Classifier: Operating System :: MacOS :: MacOS X
|
||||
Classifier: Operating System :: POSIX
|
||||
Classifier: Operating System :: POSIX :: BSD
|
||||
Classifier: Operating System :: POSIX :: Linux
|
||||
Classifier: Operating System :: Microsoft :: Windows
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3 :: Only
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Programming Language :: Python :: 3.13
|
||||
Classifier: Programming Language :: Python :: 3.14
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Programming Language :: Python :: Free Threading :: 3 - Stable
|
||||
Classifier: Topic :: Security :: Cryptography
|
||||
Requires-Dist: cffi>=1.14 ; python_full_version == '3.8.*' and platform_python_implementation != 'PyPy'
|
||||
Requires-Dist: cffi>=2.0.0 ; python_full_version >= '3.9' and platform_python_implementation != 'PyPy'
|
||||
Requires-Dist: typing-extensions>=4.13.2 ; python_full_version < '3.11'
|
||||
Requires-Dist: bcrypt>=3.1.5 ; extra == 'ssh'
|
||||
Requires-Dist: nox[uv]>=2024.4.15 ; extra == 'nox'
|
||||
Requires-Dist: cryptography-vectors==46.0.3 ; extra == 'test'
|
||||
Requires-Dist: pytest>=7.4.0 ; extra == 'test'
|
||||
Requires-Dist: pytest-benchmark>=4.0 ; extra == 'test'
|
||||
Requires-Dist: pytest-cov>=2.10.1 ; extra == 'test'
|
||||
Requires-Dist: pytest-xdist>=3.5.0 ; extra == 'test'
|
||||
Requires-Dist: pretend>=0.7 ; extra == 'test'
|
||||
Requires-Dist: certifi>=2024 ; extra == 'test'
|
||||
Requires-Dist: pytest-randomly ; extra == 'test-randomorder'
|
||||
Requires-Dist: sphinx>=5.3.0 ; extra == 'docs'
|
||||
Requires-Dist: sphinx-rtd-theme>=3.0.0 ; extra == 'docs'
|
||||
Requires-Dist: sphinx-inline-tabs ; extra == 'docs'
|
||||
Requires-Dist: pyenchant>=3 ; extra == 'docstest'
|
||||
Requires-Dist: readme-renderer>=30.0 ; extra == 'docstest'
|
||||
Requires-Dist: sphinxcontrib-spelling>=7.3.1 ; extra == 'docstest'
|
||||
Requires-Dist: build>=1.0.0 ; extra == 'sdist'
|
||||
Requires-Dist: ruff>=0.11.11 ; extra == 'pep8test'
|
||||
Requires-Dist: mypy>=1.14 ; extra == 'pep8test'
|
||||
Requires-Dist: check-sdist ; extra == 'pep8test'
|
||||
Requires-Dist: click>=8.0.1 ; extra == 'pep8test'
|
||||
Provides-Extra: ssh
|
||||
Provides-Extra: nox
|
||||
Provides-Extra: test
|
||||
Provides-Extra: test-randomorder
|
||||
Provides-Extra: docs
|
||||
Provides-Extra: docstest
|
||||
Provides-Extra: sdist
|
||||
Provides-Extra: pep8test
|
||||
License-File: LICENSE
|
||||
License-File: LICENSE.APACHE
|
||||
License-File: LICENSE.BSD
|
||||
Summary: cryptography is a package which provides cryptographic recipes and primitives to Python developers.
|
||||
Author-email: The Python Cryptographic Authority and individual contributors <cryptography-dev@python.org>
|
||||
License-Expression: Apache-2.0 OR BSD-3-Clause
|
||||
Requires-Python: >=3.8, !=3.9.0, !=3.9.1
|
||||
Description-Content-Type: text/x-rst; charset=UTF-8
|
||||
Project-URL: homepage, https://github.com/pyca/cryptography
|
||||
Project-URL: documentation, https://cryptography.io/
|
||||
Project-URL: source, https://github.com/pyca/cryptography/
|
||||
Project-URL: issues, https://github.com/pyca/cryptography/issues
|
||||
Project-URL: changelog, https://cryptography.io/en/latest/changelog/
|
||||
|
||||
pyca/cryptography
|
||||
=================
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/cryptography.svg
|
||||
:target: https://pypi.org/project/cryptography/
|
||||
:alt: Latest Version
|
||||
|
||||
.. image:: https://readthedocs.org/projects/cryptography/badge/?version=latest
|
||||
:target: https://cryptography.io
|
||||
:alt: Latest Docs
|
||||
|
||||
.. image:: https://github.com/pyca/cryptography/actions/workflows/ci.yml/badge.svg
|
||||
:target: https://github.com/pyca/cryptography/actions/workflows/ci.yml?query=branch%3Amain
|
||||
|
||||
``cryptography`` is a package which provides cryptographic recipes and
|
||||
primitives to Python developers. Our goal is for it to be your "cryptographic
|
||||
standard library". It supports Python 3.8+ and PyPy3 7.3.11+.
|
||||
|
||||
``cryptography`` includes both high level recipes and low level interfaces to
|
||||
common cryptographic algorithms such as symmetric ciphers, message digests, and
|
||||
key derivation functions. For example, to encrypt something with
|
||||
``cryptography``'s high level symmetric encryption recipe:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from cryptography.fernet import Fernet
|
||||
>>> # Put this somewhere safe!
|
||||
>>> key = Fernet.generate_key()
|
||||
>>> f = Fernet(key)
|
||||
>>> token = f.encrypt(b"A really secret message. Not for prying eyes.")
|
||||
>>> token
|
||||
b'...'
|
||||
>>> f.decrypt(token)
|
||||
b'A really secret message. Not for prying eyes.'
|
||||
|
||||
You can find more information in the `documentation`_.
|
||||
|
||||
You can install ``cryptography`` with:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install cryptography
|
||||
|
||||
For full details see `the installation documentation`_.
|
||||
|
||||
Discussion
|
||||
~~~~~~~~~~
|
||||
|
||||
If you run into bugs, you can file them in our `issue tracker`_.
|
||||
|
||||
We maintain a `cryptography-dev`_ mailing list for development discussion.
|
||||
|
||||
You can also join ``#pyca`` on ``irc.libera.chat`` to ask questions or get
|
||||
involved.
|
||||
|
||||
Security
|
||||
~~~~~~~~
|
||||
|
||||
Need to report a security issue? Please consult our `security reporting`_
|
||||
documentation.
|
||||
|
||||
|
||||
.. _`documentation`: https://cryptography.io/
|
||||
.. _`the installation documentation`: https://cryptography.io/en/latest/installation/
|
||||
.. _`issue tracker`: https://github.com/pyca/cryptography/issues
|
||||
.. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev
|
||||
.. _`security reporting`: https://cryptography.io/en/latest/security/
|
||||
|
||||
@ -0,0 +1,181 @@
|
||||
cryptography-46.0.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
cryptography-46.0.3.dist-info/METADATA,sha256=bx2LyCEmOVUC8FH5hsGEZewWPiZoIIYTq0hM9mu9r4s,5748
|
||||
cryptography-46.0.3.dist-info/RECORD,,
|
||||
cryptography-46.0.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
cryptography-46.0.3.dist-info/WHEEL,sha256=8hEf8NzM1FnmM77AjVt5h8nDuYkN3UqZ79LoIAHXeRE,95
|
||||
cryptography-46.0.3.dist-info/licenses/LICENSE,sha256=Pgx8CRqUi4JTO6mP18u0BDLW8amsv4X1ki0vmak65rs,197
|
||||
cryptography-46.0.3.dist-info/licenses/LICENSE.APACHE,sha256=qsc7MUj20dcRHbyjIJn2jSbGRMaBOuHk8F9leaomY_4,11360
|
||||
cryptography-46.0.3.dist-info/licenses/LICENSE.BSD,sha256=YCxMdILeZHndLpeTzaJ15eY9dz2s0eymiSMqtwCPtPs,1532
|
||||
cryptography/__about__.py,sha256=QCLxNH_Abbygdc9RQGpUmrK14Wp3Cl_SEiB2byLwyxo,445
|
||||
cryptography/__init__.py,sha256=mthuUrTd4FROCpUYrTIqhjz6s6T9djAZrV7nZ1oMm2o,364
|
||||
cryptography/__pycache__/__about__.cpython-313.pyc,,
|
||||
cryptography/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/__pycache__/exceptions.cpython-313.pyc,,
|
||||
cryptography/__pycache__/fernet.cpython-313.pyc,,
|
||||
cryptography/__pycache__/utils.cpython-313.pyc,,
|
||||
cryptography/exceptions.py,sha256=835EWILc2fwxw-gyFMriciC2SqhViETB10LBSytnDIc,1087
|
||||
cryptography/fernet.py,sha256=3Cvxkh0KJSbX8HbnCHu4wfCW7U0GgfUA3v_qQ8a8iWc,6963
|
||||
cryptography/hazmat/__init__.py,sha256=5IwrLWrVp0AjEr_4FdWG_V057NSJGY_W4egNNsuct0g,455
|
||||
cryptography/hazmat/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/__pycache__/_oid.cpython-313.pyc,,
|
||||
cryptography/hazmat/_oid.py,sha256=p8ThjwJB56Ci_rAIrjyJ1f8VjgD6e39es2dh8JIUBOw,17240
|
||||
cryptography/hazmat/asn1/__init__.py,sha256=hS_EWx3wVvZzfbCcNV8hzcDnyMM8H-BhIoS1TipUosk,293
|
||||
cryptography/hazmat/asn1/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/asn1/__pycache__/asn1.cpython-313.pyc,,
|
||||
cryptography/hazmat/asn1/asn1.py,sha256=eMEThEXa19LQjcyVofgHsW6tsZnjp3ddH7bWkkcxfLM,3860
|
||||
cryptography/hazmat/backends/__init__.py,sha256=O5jvKFQdZnXhKeqJ-HtulaEL9Ni7mr1mDzZY5kHlYhI,361
|
||||
cryptography/hazmat/backends/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/backends/openssl/__init__.py,sha256=p3jmJfnCag9iE5sdMrN6VvVEu55u46xaS_IjoI0SrmA,305
|
||||
cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-313.pyc,,
|
||||
cryptography/hazmat/backends/openssl/backend.py,sha256=tV5AxBoFJ2GfA0DMWSY-0TxQJrpQoexzI9R4Kybb--4,10215
|
||||
cryptography/hazmat/bindings/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
|
||||
cryptography/hazmat/bindings/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/bindings/_rust.pyd,sha256=kvWLtPAadaDvTdlCXcKpbd_iX8k_2dwR6o8NBbek8IU,9245696
|
||||
cryptography/hazmat/bindings/_rust/__init__.pyi,sha256=KhqLhXFPArPzzJ7DYO9Fl8FoXB_BagAd_r4Dm_Ze9Xo,1257
|
||||
cryptography/hazmat/bindings/_rust/_openssl.pyi,sha256=mpNJLuYLbCVrd5i33FBTmWwL_55Dw7JPkSLlSX9Q7oI,230
|
||||
cryptography/hazmat/bindings/_rust/asn1.pyi,sha256=BrGjC8J6nwuS-r3EVcdXJB8ndotfY9mbQYOfpbPG0HA,354
|
||||
cryptography/hazmat/bindings/_rust/declarative_asn1.pyi,sha256=2ECFmYue1EPkHEE2Bm7aLwkjB0mSUTpr23v9MN4pri4,892
|
||||
cryptography/hazmat/bindings/_rust/exceptions.pyi,sha256=exXr2xw_0pB1kk93cYbM3MohbzoUkjOms1ZMUi0uQZE,640
|
||||
cryptography/hazmat/bindings/_rust/ocsp.pyi,sha256=VPVWuKHI9EMs09ZLRYAGvR0Iz0mCMmEzXAkgJHovpoM,4020
|
||||
cryptography/hazmat/bindings/_rust/openssl/__init__.pyi,sha256=iOAMDyHoNwwCSZfZzuXDr64g4GpGUeDgEN-LjXqdrBM,1522
|
||||
cryptography/hazmat/bindings/_rust/openssl/aead.pyi,sha256=4Nddw6-ynzIB3w2W86WvkGKTLlTDk_6F5l54RHCuy3E,2688
|
||||
cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi,sha256=LhPzHWSXJq4grAJXn6zSvSSdV-aYIIscHDwIPlJGGPs,1315
|
||||
cryptography/hazmat/bindings/_rust/openssl/cmac.pyi,sha256=nPH0X57RYpsAkRowVpjQiHE566ThUTx7YXrsadmrmHk,564
|
||||
cryptography/hazmat/bindings/_rust/openssl/dh.pyi,sha256=Z3TC-G04-THtSdAOPLM1h2G7ml5bda1ElZUcn5wpuhk,1564
|
||||
cryptography/hazmat/bindings/_rust/openssl/dsa.pyi,sha256=qBtkgj2albt2qFcnZ9UDrhzoNhCVO7HTby5VSf1EXMI,1299
|
||||
cryptography/hazmat/bindings/_rust/openssl/ec.pyi,sha256=zJy0pRa5n-_p2dm45PxECB_-B6SVZyNKfjxFDpPqT38,1691
|
||||
cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi,sha256=VXfXd5G6hUivg399R1DYdmW3eTb0EebzDTqjRC2gaRw,532
|
||||
cryptography/hazmat/bindings/_rust/openssl/ed448.pyi,sha256=Yx49lqdnjsD7bxiDV1kcaMrDktug5evi5a6zerMiy2s,514
|
||||
cryptography/hazmat/bindings/_rust/openssl/hashes.pyi,sha256=OWZvBx7xfo_HJl41Nc--DugVyCVPIprZ3HlOPTSWH9g,984
|
||||
cryptography/hazmat/bindings/_rust/openssl/hmac.pyi,sha256=BXZn7NDjL3JAbYW0SQ8pg1iyC5DbQXVhUAiwsi8DFR8,702
|
||||
cryptography/hazmat/bindings/_rust/openssl/kdf.pyi,sha256=xXfFBb9QehHfDtEaxV_65Z0YK7NquOVIChpTLkgAs_k,2029
|
||||
cryptography/hazmat/bindings/_rust/openssl/keys.pyi,sha256=teIt8M6ZEMJrn4s3W0UnW0DZ-30Jd68WnSsKKG124l0,912
|
||||
cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi,sha256=_SW9NtQ5FDlAbdclFtWpT4lGmxKIKHpN-4j8J2BzYfQ,585
|
||||
cryptography/hazmat/bindings/_rust/openssl/rsa.pyi,sha256=2OQCNSXkxgc-3uw1xiCCloIQTV6p9_kK79Yu0rhZgPc,1364
|
||||
cryptography/hazmat/bindings/_rust/openssl/x25519.pyi,sha256=ewn4GpQyb7zPwE-ni7GtyQgMC0A1mLuqYsSyqv6nI_s,523
|
||||
cryptography/hazmat/bindings/_rust/openssl/x448.pyi,sha256=juTZTmli8jO_5Vcufg-vHvx_tCyezmSLIh_9PU3TczI,505
|
||||
cryptography/hazmat/bindings/_rust/pkcs12.pyi,sha256=vEEd5wDiZvb8ZGFaziLCaWLzAwoG_tvPUxLQw5_uOl8,1605
|
||||
cryptography/hazmat/bindings/_rust/pkcs7.pyi,sha256=txGBJijqZshEcqra6byPNbnisIdlxzOSIHP2hl9arPs,1601
|
||||
cryptography/hazmat/bindings/_rust/test_support.pyi,sha256=PPhld-WkO743iXFPebeG0LtgK0aTzGdjcIsay1Gm5GE,757
|
||||
cryptography/hazmat/bindings/_rust/x509.pyi,sha256=n9X0IQ6ICbdIi-ExdCFZoBgeY6njm3QOVAVZwDQdnbk,9784
|
||||
cryptography/hazmat/bindings/openssl/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
|
||||
cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-313.pyc,,
|
||||
cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-313.pyc,,
|
||||
cryptography/hazmat/bindings/openssl/_conditional.py,sha256=DMOpA_XN4l70zTc5_J9DpwlbQeUBRTWpfIJ4yRIn1-U,5791
|
||||
cryptography/hazmat/bindings/openssl/binding.py,sha256=x8eocEmukO4cm7cHqfVmOoYY7CCXdoF1v1WhZQt9neo,4610
|
||||
cryptography/hazmat/decrepit/__init__.py,sha256=wHCbWfaefa-fk6THSw9th9fJUsStJo7245wfFBqmduA,216
|
||||
cryptography/hazmat/decrepit/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/decrepit/ciphers/__init__.py,sha256=wHCbWfaefa-fk6THSw9th9fJUsStJo7245wfFBqmduA,216
|
||||
cryptography/hazmat/decrepit/ciphers/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/decrepit/ciphers/__pycache__/algorithms.cpython-313.pyc,,
|
||||
cryptography/hazmat/decrepit/ciphers/algorithms.py,sha256=YrKgHS4MfwWaMmPBYRymRRlC0phwWp9ycICFezeJPGk,2595
|
||||
cryptography/hazmat/primitives/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
|
||||
cryptography/hazmat/primitives/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/__pycache__/_serialization.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/__pycache__/cmac.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/__pycache__/constant_time.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/__pycache__/hashes.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/__pycache__/hmac.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/__pycache__/keywrap.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/__pycache__/padding.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/__pycache__/poly1305.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/_asymmetric.py,sha256=RhgcouUB6HTiFDBrR1LxqkMjpUxIiNvQ1r_zJjRG6qQ,532
|
||||
cryptography/hazmat/primitives/_cipheralgorithm.py,sha256=Eh3i7lwedHfi0eLSsH93PZxQKzY9I6lkK67vL4V5tOc,1522
|
||||
cryptography/hazmat/primitives/_serialization.py,sha256=chgPCSF2jxI2Cr5gB-qbWXOvOfupBh4CARS0KAhv9AM,5123
|
||||
cryptography/hazmat/primitives/asymmetric/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/asymmetric/dh.py,sha256=0v_vEFFz5pQ1QG-FkWDyvgv7IfuVZSH5Q6LyFI5A8rg,3645
|
||||
cryptography/hazmat/primitives/asymmetric/dsa.py,sha256=Ld_bbbqQFz12dObHxIkzEQzX0SWWP41RLSWkYSaKhqE,4213
|
||||
cryptography/hazmat/primitives/asymmetric/ec.py,sha256=Vf5ig2PcS3PVnsb5N49Kx1uIkFBJyhg4BWXThDz5cug,12999
|
||||
cryptography/hazmat/primitives/asymmetric/ed25519.py,sha256=jZW5cs472wXXV3eB0sE1b8w64gdazwwU0_MT5UOTiXs,3700
|
||||
cryptography/hazmat/primitives/asymmetric/ed448.py,sha256=yAetgn2f2JYf0BO8MapGzXeThsvSMG5LmUCrxVOidAA,3729
|
||||
cryptography/hazmat/primitives/asymmetric/padding.py,sha256=vQ6l6gOg9HqcbOsvHrSiJRVLdEj9L4m4HkRGYziTyFA,2854
|
||||
cryptography/hazmat/primitives/asymmetric/rsa.py,sha256=ZnKOo2f34MCCOupC03Y1uR-_jiSG5IrelHEmxaME3D4,8303
|
||||
cryptography/hazmat/primitives/asymmetric/types.py,sha256=LnsOJym-wmPUJ7Knu_7bCNU3kIiELCd6krOaW_JU08I,2996
|
||||
cryptography/hazmat/primitives/asymmetric/utils.py,sha256=DPTs6T4F-UhwzFQTh-1fSEpQzazH2jf2xpIro3ItF4o,790
|
||||
cryptography/hazmat/primitives/asymmetric/x25519.py,sha256=_4nQeZ3yJ3Lg0RpXnaqA-1yt6vbx1F-wzLcaZHwSpeE,3613
|
||||
cryptography/hazmat/primitives/asymmetric/x448.py,sha256=WKBLtuVfJqiBRro654fGaQAlvsKbqbNkK7c4A_ZCdV0,3642
|
||||
cryptography/hazmat/primitives/ciphers/__init__.py,sha256=eyEXmjk6_CZXaOPYDr7vAYGXr29QvzgWL2-4CSolLFs,680
|
||||
cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/ciphers/aead.py,sha256=Fzlyx7w8KYQakzDp1zWgJnIr62zgZrgVh1u2h4exB54,634
|
||||
cryptography/hazmat/primitives/ciphers/algorithms.py,sha256=Q7ZJwcsx83Mgxv5y7r6CyJKSdsOwC-my-5A67-ma2vw,3407
|
||||
cryptography/hazmat/primitives/ciphers/base.py,sha256=aBC7HHBBoixebmparVr0UlODs3VD0A7B6oz_AaRjDv8,4253
|
||||
cryptography/hazmat/primitives/ciphers/modes.py,sha256=20stpwhDtbAvpH0SMf9EDHIciwmTF-JMBUOZ9bU8WiQ,8318
|
||||
cryptography/hazmat/primitives/cmac.py,sha256=sz_s6H_cYnOvx-VNWdIKhRhe3Ymp8z8J0D3CBqOX3gg,338
|
||||
cryptography/hazmat/primitives/constant_time.py,sha256=xdunWT0nf8OvKdcqUhhlFKayGp4_PgVJRU2W1wLSr_A,422
|
||||
cryptography/hazmat/primitives/hashes.py,sha256=M8BrlKB3U6DEtHvWTV5VRjpteHv1kS3Zxm_Bsk04cr8,5184
|
||||
cryptography/hazmat/primitives/hmac.py,sha256=RpB3z9z5skirCQrm7zQbtnp9pLMnAjrlTUvKqF5aDDc,423
|
||||
cryptography/hazmat/primitives/kdf/__init__.py,sha256=4XibZnrYq4hh5xBjWiIXzaYW6FKx8hPbVaa_cB9zS64,750
|
||||
cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/kdf/__pycache__/argon2.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/kdf/argon2.py,sha256=UFDNXG0v-rw3DqAQTB1UQAsQC2M5Ejg0k_6OCyhLKus,460
|
||||
cryptography/hazmat/primitives/kdf/concatkdf.py,sha256=Ua8KoLXXnzgsrAUmHpyKymaPt8aPRP0EHEaBz7QCQ9I,3737
|
||||
cryptography/hazmat/primitives/kdf/hkdf.py,sha256=M0lAEfRoc4kpp4-nwDj9yB-vNZukIOYEQrUlWsBNn9o,543
|
||||
cryptography/hazmat/primitives/kdf/kbkdf.py,sha256=oZepvo4evhKkkJQWRDwaPoIbyTaFmDc5NPimxg6lfKg,9165
|
||||
cryptography/hazmat/primitives/kdf/pbkdf2.py,sha256=1WIwhELR0w8ztTpTu8BrFiYWmK3hUfJq08I79TxwieE,1957
|
||||
cryptography/hazmat/primitives/kdf/scrypt.py,sha256=XyWUdUUmhuI9V6TqAPOvujCSMGv1XQdg0a21IWCmO-U,590
|
||||
cryptography/hazmat/primitives/kdf/x963kdf.py,sha256=zLTcF665QFvXX2f8TS7fmBZTteXpFjKahzfjjQcCJyw,1999
|
||||
cryptography/hazmat/primitives/keywrap.py,sha256=XV4Pj2fqSeD-RqZVvY2cA3j5_7RwJSFygYuLfk2ujCo,5650
|
||||
cryptography/hazmat/primitives/padding.py,sha256=QT-U-NvV2eQGO1wVPbDiNGNSc9keRDS-ig5cQOrLz0E,1865
|
||||
cryptography/hazmat/primitives/poly1305.py,sha256=P5EPQV-RB_FJPahpg01u0Ts4S_PnAmsroxIGXbGeRRo,355
|
||||
cryptography/hazmat/primitives/serialization/__init__.py,sha256=Q7uTgDlt7n3WfsMT6jYwutC6DIg_7SEeoAm1GHZ5B5E,1705
|
||||
cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/serialization/base.py,sha256=ikq5MJIwp_oUnjiaBco_PmQwOTYuGi-XkYUYHKy8Vo0,615
|
||||
cryptography/hazmat/primitives/serialization/pkcs12.py,sha256=mS9cFNG4afzvseoc5e1MWoY2VskfL8N8Y_OFjl67luY,5104
|
||||
cryptography/hazmat/primitives/serialization/pkcs7.py,sha256=5OR_Tkysxaprn4FegvJIfbep9rJ9wok6FLWvWwQ5-Mg,13943
|
||||
cryptography/hazmat/primitives/serialization/ssh.py,sha256=hPV5obFznz0QhFfXFPOeQ8y6MsurA0xVMQiLnLESEs8,53700
|
||||
cryptography/hazmat/primitives/twofactor/__init__.py,sha256=tmMZGB-g4IU1r7lIFqASU019zr0uPp_wEBYcwdDCKCA,258
|
||||
cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-313.pyc,,
|
||||
cryptography/hazmat/primitives/twofactor/hotp.py,sha256=ivZo5BrcCGWLsqql4nZV0XXCjyGPi_iHfDFltGlOJwk,3256
|
||||
cryptography/hazmat/primitives/twofactor/totp.py,sha256=m5LPpRL00kp4zY8gTjr55Hfz9aMlPS53kHmVkSQCmdY,1652
|
||||
cryptography/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
cryptography/utils.py,sha256=bZAjFC5KVpfmF29qS_18vvpW3mKxmdiRALcusHhTTkg,4301
|
||||
cryptography/x509/__init__.py,sha256=xloN0swseNx-m2WFZmCA17gOoxQWqeU82UVjEdJBePQ,8257
|
||||
cryptography/x509/__pycache__/__init__.cpython-313.pyc,,
|
||||
cryptography/x509/__pycache__/base.cpython-313.pyc,,
|
||||
cryptography/x509/__pycache__/certificate_transparency.cpython-313.pyc,,
|
||||
cryptography/x509/__pycache__/extensions.cpython-313.pyc,,
|
||||
cryptography/x509/__pycache__/general_name.cpython-313.pyc,,
|
||||
cryptography/x509/__pycache__/name.cpython-313.pyc,,
|
||||
cryptography/x509/__pycache__/ocsp.cpython-313.pyc,,
|
||||
cryptography/x509/__pycache__/oid.cpython-313.pyc,,
|
||||
cryptography/x509/__pycache__/verification.cpython-313.pyc,,
|
||||
cryptography/x509/base.py,sha256=OrmTw3y8B6AE_nGXQPN8x9kq-d7rDWeH13gCq6T6D6U,27997
|
||||
cryptography/x509/certificate_transparency.py,sha256=JqoOIDhlwInrYMFW6IFn77WJ0viF-PB_rlZV3vs9MYc,797
|
||||
cryptography/x509/extensions.py,sha256=QxYrqR6SF1qzR9ZraP8wDiIczlEVlAFuwDRVcltB6Tk,77724
|
||||
cryptography/x509/general_name.py,sha256=sP_rV11Qlpsk4x3XXGJY_Mv0Q_s9dtjeLckHsjpLQoQ,7836
|
||||
cryptography/x509/name.py,sha256=ty0_xf0LnHwZAdEf-d8FLO1K4hGqx_7DsD3CHwoLJiY,15101
|
||||
cryptography/x509/ocsp.py,sha256=Yey6NdFV1MPjop24Mj_VenjEpg3kUaMopSWOK0AbeBs,12699
|
||||
cryptography/x509/oid.py,sha256=BUzgXXGVWilkBkdKPTm9R4qElE9gAGHgdYPMZAp7PJo,931
|
||||
cryptography/x509/verification.py,sha256=gR2C2c-XZQtblZhT5T5vjSKOtCb74ef2alPVmEcwFlM,958
|
||||
@ -0,0 +1,4 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: maturin (1.9.4)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp311-abi3-win_amd64
|
||||
@ -0,0 +1,3 @@
|
||||
This software is made available under the terms of *either* of the licenses
|
||||
found in LICENSE.APACHE or LICENSE.BSD. Contributions to cryptography are made
|
||||
under the terms of *both* these licenses.
|
||||
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@ -0,0 +1,27 @@
|
||||
Copyright (c) Individual contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of PyCA Cryptography nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
Binary file not shown.
@ -35,7 +35,7 @@ chart_dpi = 300
|
||||
export_format = csv
|
||||
|
||||
[SECURITY]
|
||||
secret_key = c4939b252df4fff97f62644697ab798d7c0ccff8a8d9a592d0ffeb7675a44f92
|
||||
secret_key = 5e3de79da9a48e8cf9d37a9320b07cf0eba9c37f35a6f6cdec8ff0ba9fa77ee9
|
||||
session_timeout = 3600
|
||||
max_login_attempts = 5
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ import PatientCreate from '../views/PatientCreate.vue'
|
||||
import PatientProfile from '../views/PatientProfile.vue'
|
||||
import Detection from '../views/Detection.vue'
|
||||
import Recording from '../views/Recording.vue'
|
||||
import License from '../views/License.vue'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
@ -50,6 +51,13 @@ const routes = [
|
||||
component: Recording,
|
||||
meta: { title: '检测回放 - 平衡体态检测系统', requiresAuth: true }
|
||||
}
|
||||
,
|
||||
{
|
||||
path: '/license',
|
||||
name: 'License',
|
||||
component: License,
|
||||
meta: { title: '授权激活 - 平衡体态检测系统', requiresAuth: true }
|
||||
}
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
|
||||
@ -16,10 +16,13 @@ api.interceptors.request.use(
|
||||
config.baseURL = 'http://localhost:5000'
|
||||
}
|
||||
|
||||
// 只为需要发送数据的请求设置Content-Type
|
||||
if (['post', 'put', 'patch'].includes(config.method.toLowerCase())) {
|
||||
// 为需要发送数据的请求设置Content-Type(避免覆盖FormData)
|
||||
if (['post', 'put', 'patch'].includes((config.method || '').toLowerCase())) {
|
||||
const isFormData = typeof FormData !== 'undefined' && config.data instanceof FormData
|
||||
if (!isFormData && !config.headers['Content-Type']) {
|
||||
config.headers['Content-Type'] = 'application/json'
|
||||
}
|
||||
}
|
||||
|
||||
// 添加认证token
|
||||
const token = localStorage.getItem('authToken')
|
||||
@ -265,6 +268,26 @@ export const detectionAPI = {
|
||||
}
|
||||
}
|
||||
|
||||
// 授权API
|
||||
export const licenseAPI = {
|
||||
info() {
|
||||
return api.get('/api/license/info')
|
||||
},
|
||||
generateActivationRequest(company_name, contact_info) {
|
||||
return api.post('/api/license/activation-request', { company_name, contact_info })
|
||||
},
|
||||
verifyLicense(licenseFile) {
|
||||
const formData = new FormData()
|
||||
formData.append('license_file', licenseFile)
|
||||
return api.post('/api/license/verify', formData)
|
||||
},
|
||||
activatePackage(zipFile) {
|
||||
const formData = new FormData()
|
||||
formData.append('package_zip', zipFile)
|
||||
return api.post('/api/license/activate-package', formData)
|
||||
}
|
||||
}
|
||||
|
||||
// 录制API
|
||||
export const recordingAPI = {
|
||||
// 创建录制
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
<div class="system-title">
|
||||
平衡体态检测系统
|
||||
<span v-if="licenseBadge" :class="['license-badge', licenseClass]">{{ licenseBadge }}</span>
|
||||
<button v-if="showActivateButton" class="activate-btn" @click="goActivate">激活</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
@ -72,6 +73,8 @@
|
||||
})
|
||||
const licenseBadge = ref('')
|
||||
const licenseClass = ref('')
|
||||
const licenseType = ref('')
|
||||
const showActivateButton = ref(false)
|
||||
|
||||
|
||||
const handleUserCommand = (command) => {
|
||||
@ -150,6 +153,8 @@
|
||||
if (!json || json.success !== true) {
|
||||
licenseBadge.value = '未授权'
|
||||
licenseClass.value = 'badge-invalid'
|
||||
licenseType.value = 'invalid'
|
||||
showActivateButton.value = true
|
||||
return
|
||||
}
|
||||
const data = json.data || {}
|
||||
@ -159,21 +164,33 @@
|
||||
const expStr = exp ? `${exp.getFullYear()}-${String(exp.getMonth()+1).padStart(2,'0')}-${String(exp.getDate()).padStart(2,'0')}` : ''
|
||||
licenseBadge.value = expStr ? `试用版(截止 ${expStr})` : '试用版'
|
||||
licenseClass.value = 'badge-trial'
|
||||
licenseType.value = 'trial'
|
||||
showActivateButton.value = true
|
||||
} else {
|
||||
licenseBadge.value = '已授权'
|
||||
licenseClass.value = 'badge-valid'
|
||||
licenseType.value = 'full'
|
||||
showActivateButton.value = false
|
||||
}
|
||||
} else {
|
||||
licenseBadge.value = '未授权'
|
||||
licenseClass.value = 'badge-invalid'
|
||||
licenseType.value = 'invalid'
|
||||
showActivateButton.value = true
|
||||
}
|
||||
} catch (e) {
|
||||
// 网络或后端错误时,显示未授权
|
||||
licenseBadge.value = '未授权'
|
||||
licenseClass.value = 'badge-invalid'
|
||||
licenseType.value = 'invalid'
|
||||
showActivateButton.value = true
|
||||
}
|
||||
})()
|
||||
})
|
||||
|
||||
const goActivate = () => {
|
||||
router.push('/license')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -261,6 +278,20 @@
|
||||
.badge-invalid { background-color: #8b0000; color: #fff; }
|
||||
.badge-trial { background-color: #ff8c00; color: #fff; }
|
||||
.badge-valid { background-color: #2e8b57; color: #fff; }
|
||||
.activate-btn {
|
||||
margin-left: 8px;
|
||||
padding: 2px 10px;
|
||||
font-size: 12px;
|
||||
border: 1px solid #409EFF;
|
||||
background-color: #409EFF;
|
||||
color: #fff;
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.activate-btn:hover {
|
||||
background-color: #66b1ff;
|
||||
border-color: #66b1ff;
|
||||
}
|
||||
.userInfoviewDialog{
|
||||
background-color: #323232 !important;
|
||||
}
|
||||
|
||||
184
frontend/src/renderer/src/views/License.vue
Normal file
184
frontend/src/renderer/src/views/License.vue
Normal file
@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<div class="license-container">
|
||||
<div class="page-header">
|
||||
<h2>授权中心</h2>
|
||||
<div class="desc">在此申请激活文件或上传授权包激活。</div>
|
||||
</div>
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane label="授权申请" name="request">
|
||||
<div class="tab-content">
|
||||
<el-form :model="form" label-width="120px" class="license-form">
|
||||
<el-form-item label="公司名称">
|
||||
<el-input v-model="form.company_name" placeholder="请输入公司名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系方式">
|
||||
<el-input v-model="form.contact_info" placeholder="请输入联系方式" />
|
||||
</el-form-item>
|
||||
<el-divider>软件信息</el-divider>
|
||||
<el-form-item label="产品">
|
||||
<el-input :model-value="software.product" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="版本">
|
||||
<el-input :model-value="software.version" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="机器码">
|
||||
<el-input :model-value="software.machine_id" disabled />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="actions">
|
||||
<el-button type="primary" @click="exportActivationFile" :loading="exporting">导出激活文件</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="激活授权" name="activate">
|
||||
<div class="tab-content">
|
||||
<el-upload
|
||||
:auto-upload="false"
|
||||
:show-file-list="true"
|
||||
:on-change="onZipChange"
|
||||
accept=".zip"
|
||||
>
|
||||
<el-button type="primary">选择授权包(.zip)</el-button>
|
||||
</el-upload>
|
||||
<div class="actions">
|
||||
<el-button type="success" :disabled="!zipFile" @click="activatePackage" :loading="activating">上传激活包并安装</el-button>
|
||||
</div>
|
||||
<div class="hint">安装完成后,请重启系统生效。</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { systemAPI } from '../services/api.js'
|
||||
import { licenseAPI } from '../services/api.js'
|
||||
|
||||
const activeTab = ref('request')
|
||||
|
||||
const form = reactive({
|
||||
company_name: '北京天宏博科技有限公司',
|
||||
contact_info: 'thb@163.com'
|
||||
})
|
||||
|
||||
const software = reactive({
|
||||
product: 'BodyBalanceEvaluation',
|
||||
version: '1.0.0',
|
||||
machine_id: ''
|
||||
})
|
||||
|
||||
const exporting = ref(false)
|
||||
const activating = ref(false)
|
||||
const zipFile = ref(null)
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
// 获取机器码
|
||||
const lic = await licenseAPI.info()
|
||||
if (lic && lic.success && lic.data) {
|
||||
software.machine_id = lic.data.machine_id || ''
|
||||
}
|
||||
// 获取版本
|
||||
const health = await systemAPI.health()
|
||||
if (health && health.version) {
|
||||
software.version = health.version
|
||||
} else if (health && health.data && health.data.version) {
|
||||
software.version = health.data.version
|
||||
}
|
||||
} catch (e) {
|
||||
// 忽略错误,保留默认值
|
||||
}
|
||||
})
|
||||
|
||||
const downloadTextFile = (filename, content) => {
|
||||
try {
|
||||
const blob = new Blob([content], { type: 'application/json;charset=utf-8' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = filename
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
window.URL.revokeObjectURL(url)
|
||||
} catch (e) {
|
||||
console.error('下载文件失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
const exportActivationFile = async () => {
|
||||
exporting.value = true
|
||||
try {
|
||||
const res = await licenseAPI.generateActivationRequest(form.company_name, form.contact_info)
|
||||
if (res && res.success) {
|
||||
const data = res.data || {}
|
||||
let content = data.content
|
||||
const machineId = data.machine_id || software.machine_id || 'UNKNOWN'
|
||||
const filename = `activation_request_${machineId}.json`
|
||||
|
||||
// 如果后端未返回content,使用前端合成内容作为兜底
|
||||
if (!content) {
|
||||
const requestData = {
|
||||
product: software.product,
|
||||
version: software.version,
|
||||
machine_id: software.machine_id,
|
||||
request_time: new Date().toISOString(),
|
||||
company_name: form.company_name,
|
||||
contact_info: form.contact_info
|
||||
}
|
||||
content = JSON.stringify(requestData, null, 2)
|
||||
}
|
||||
|
||||
downloadTextFile(filename, content)
|
||||
ElMessage.success('激活请求文件已导出')
|
||||
} else {
|
||||
throw new Error(res && res.error ? res.error : '生成激活文件失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error(e.message || '导出激活文件失败')
|
||||
} finally {
|
||||
exporting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const onZipChange = (file) => {
|
||||
zipFile.value = file && file.raw ? file.raw : null
|
||||
}
|
||||
|
||||
const activatePackage = async () => {
|
||||
if (!zipFile.value) {
|
||||
ElMessage.warning('请先选择授权包压缩文件(.zip)')
|
||||
return
|
||||
}
|
||||
activating.value = true
|
||||
try {
|
||||
const res = await licenseAPI.activatePackage(zipFile.value)
|
||||
if (res && res.success) {
|
||||
ElMessageBox.alert('激活包已安装,请重启系统生效。', '激活成功', { type: 'success' })
|
||||
} else {
|
||||
throw new Error(res && res.error ? res.error : '激活包安装失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error(e.message || '上传并安装授权包失败')
|
||||
} finally {
|
||||
activating.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.license-container {
|
||||
padding: 16px;
|
||||
color: #fff;
|
||||
}
|
||||
.page-header { margin-bottom: 12px; }
|
||||
.page-header h2 { margin: 0 0 4px 0; font-size: 20px; }
|
||||
.desc { color: #bbb; font-size: 12px; }
|
||||
.tab-content { padding: 12px 0; }
|
||||
.actions { margin-top: 12px; }
|
||||
.hint { margin-top: 8px; color: #bbb; font-size: 12px; }
|
||||
.license-form { max-width: 560px; }
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user