+18


![dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>](/assets/img/avatar_default.png)

![autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>](/assets/img/avatar_default.png)




FFXN
GitHub
yyh
盐粒 Yanli
autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Tianle
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Yunlu Wen
zyssyz123
Claude Opus 4.7
chariri
Asuka Minato
Copilot Autofix powered by AI
Nian
非法操作
Carmen Fernández Ruiz
wangxiaolei
QuantumGhost
L1nSn0w
Evan
Escape0707
Jingyi
Amr Sherif
ZHOU ZHICHEN
unknown
JzoNg
Xiyuan Chen
-LAN-
107bba0116
Signed-off-by: dependabot[bot] <[email protected]> Signed-off-by: EvanYao826 <[email protected]> Co-authored-by: yyh <[email protected]> Co-authored-by: 盐粒 Yanli <[email protected]> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Tianle <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Yunlu Wen <[email protected]> Co-authored-by: zyssyz123 <[email protected]> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]> Co-authored-by: chariri <[email protected]> Co-authored-by: Asuka Minato <[email protected]> Co-authored-by: Copilot Autofix powered by AI <[email protected]> Co-authored-by: Nian <[email protected]> Co-authored-by: 非法操作 <[email protected]> Co-authored-by: Carmen Fernández Ruiz <[email protected]> Co-authored-by: wangxiaolei <[email protected]> Co-authored-by: QuantumGhost <[email protected]> Co-authored-by: L1nSn0w <[email protected]> Co-authored-by: Evan <[email protected]> Co-authored-by: Escape0707 <[email protected]> Co-authored-by: Jingyi <[email protected]> Co-authored-by: Amr Sherif <[email protected]> Co-authored-by: ZHOU ZHICHEN <[email protected]> Co-authored-by: unknown <[email protected]> Co-authored-by: JzoNg <[email protected]> Co-authored-by: Xiyuan Chen <[email protected]> Co-authored-by: -LAN- <[email protected]>
85 lines
3.2 KiB
Python
85 lines
3.2 KiB
Python
from flask_restx import Resource
|
|
from werkzeug.exceptions import Unauthorized
|
|
|
|
from controllers.common.schema import register_response_schema_models
|
|
from libs.login import current_user, login_required
|
|
from services.feature_service import FeatureModel, FeatureService, LimitationModel, SystemFeatureModel
|
|
|
|
from . import console_ns
|
|
from .wraps import account_initialization_required, cloud_utm_record, setup_required, with_current_tenant_id
|
|
|
|
register_response_schema_models(console_ns, FeatureModel, LimitationModel, SystemFeatureModel)
|
|
|
|
|
|
@console_ns.route("/features")
|
|
class FeatureApi(Resource):
|
|
@console_ns.doc("get_tenant_features")
|
|
@console_ns.doc(description="Get feature configuration for current tenant")
|
|
@console_ns.response(
|
|
200,
|
|
"Success",
|
|
console_ns.models[FeatureModel.__name__],
|
|
)
|
|
@setup_required
|
|
@login_required
|
|
@account_initialization_required
|
|
@cloud_utm_record
|
|
@with_current_tenant_id
|
|
def get(self, current_tenant_id: str):
|
|
"""Get feature configuration for current tenant"""
|
|
payload = FeatureService.get_features(
|
|
current_tenant_id,
|
|
exclude_vector_space=True,
|
|
).model_dump()
|
|
payload.pop("vector_space", None)
|
|
return payload
|
|
|
|
|
|
@console_ns.route("/features/vector-space")
|
|
class FeatureVectorSpaceApi(Resource):
|
|
@console_ns.doc("get_tenant_feature_vector_space")
|
|
@console_ns.doc(description="Get vector-space usage and limit for current tenant")
|
|
@console_ns.response(
|
|
200,
|
|
"Success",
|
|
console_ns.models[LimitationModel.__name__],
|
|
)
|
|
@setup_required
|
|
@login_required
|
|
@account_initialization_required
|
|
@cloud_utm_record
|
|
@with_current_tenant_id
|
|
def get(self, current_tenant_id: str):
|
|
"""Get vector-space usage and limit for current tenant"""
|
|
return FeatureService.get_vector_space(current_tenant_id).model_dump()
|
|
|
|
|
|
@console_ns.route("/system-features")
|
|
class SystemFeatureApi(Resource):
|
|
@console_ns.doc("get_system_features")
|
|
@console_ns.doc(description="Get system-wide feature configuration")
|
|
@console_ns.response(
|
|
200,
|
|
"Success",
|
|
console_ns.models[SystemFeatureModel.__name__],
|
|
)
|
|
def get(self):
|
|
"""Get system-wide feature configuration
|
|
|
|
NOTE: This endpoint is unauthenticated by design, as it provides system features
|
|
data required for dashboard initialization.
|
|
|
|
Authentication would create circular dependency (can't login without dashboard loading).
|
|
|
|
Only non-sensitive configuration data should be returned by this endpoint.
|
|
"""
|
|
# NOTE(QuantumGhost): ideally we should access `current_user.is_authenticated`
|
|
# without a try-catch. However, due to the implementation of user loader (the `load_user_from_request`
|
|
# in api/extensions/ext_login.py), accessing `current_user.is_authenticated` will
|
|
# raise `Unauthorized` exception if authentication token is not provided.
|
|
try:
|
|
is_authenticated = current_user.is_authenticated
|
|
except Unauthorized:
|
|
is_authenticated = False
|
|
return FeatureService.get_system_features(is_authenticated=is_authenticated).model_dump()
|