Compare commits

...

11 Commits

Author SHA1 Message Date
GareArc
50eef41cf7 chore: remove list controller 2025-02-11 15:35:39 -05:00
GareArc
51e948b89c fix: remove list api 2025-02-11 15:32:17 -05:00
GareArc
4305c778d8 chore: increase rate limit to 4 2025-02-10 01:09:12 -05:00
GareArc
eff559291f fix: bad method call 2025-02-06 00:10:57 -05:00
GareArc
58bf08111a feat: add rate limiter to report download api 2025-02-05 22:59:43 -05:00
GareArc
7dfd6a95ab fix: bad req parser 2025-01-25 20:42:45 -05:00
GareArc
981e497489 fix: wrong api path url 2025-01-25 20:31:26 -05:00
GareArc
478aaeba8e Merge branch 'main' into feat/compliance 2025-01-25 20:16:08 -05:00
GareArc
68f0a903a8 feat: add compliance api 2025-01-24 22:10:19 -05:00
GareArc
db04cc2922 Merge branch 'main' into feat/compliance 2025-01-24 21:38:47 -05:00
GareArc
34c3dd20eb feat: init controller 2025-01-08 01:47:00 -05:00
4 changed files with 71 additions and 1 deletions

View File

@@ -70,7 +70,7 @@ from .app import (
from .auth import activate, data_source_bearer_auth, data_source_oauth, forgot_password, login, oauth
# Import billing controllers
from .billing import billing
from .billing import billing, compliance
# Import datasets controllers
from .datasets import (

View File

@@ -0,0 +1,35 @@
from flask import request
from flask_login import current_user # type: ignore
from flask_restful import Resource, reqparse # type: ignore
from libs.helper import extract_remote_ip
from libs.login import login_required
from services.billing_service import BillingService
from .. import api
from ..wraps import account_initialization_required, only_edition_cloud, setup_required
class ComplianceApi(Resource):
@setup_required
@login_required
@account_initialization_required
@only_edition_cloud
def get(self):
parser = reqparse.RequestParser()
parser.add_argument("doc_name", type=str, required=True, location="args")
args = parser.parse_args()
ip_address = extract_remote_ip(request)
device_info = request.headers.get("User-Agent", "Unknown device")
return BillingService.get_compliance_download_link(
doc_name=args.doc_name,
account_id=current_user.id,
tenant_id=current_user.current_tenant_id,
ip=ip_address,
device_info=device_info,
)
api.add_resource(ComplianceApi, "/compliance/download")

View File

@@ -101,3 +101,9 @@ class AccountInFreezeError(BaseHTTPException):
"This email account has been deleted within the past 30 days"
"and is temporarily unavailable for new account registration."
)
class CompilanceRateLimitError(BaseHTTPException):
error_code = "compilance_rate_limit"
description = "Rate limit exceeded for downloading compliance report."
code = 429

View File

@@ -5,6 +5,7 @@ import httpx
from tenacity import retry, retry_if_exception_type, stop_before_delay, wait_fixed
from extensions.ext_database import db
from libs.helper import RateLimiter
from models.account import TenantAccountJoin, TenantAccountRole
@@ -12,6 +13,8 @@ class BillingService:
base_url = os.environ.get("BILLING_API_URL", "BILLING_API_URL")
secret_key = os.environ.get("BILLING_API_SECRET_KEY", "BILLING_API_SECRET_KEY")
compliance_download_rate_limiter = RateLimiter("compliance_download_rate_limiter", 4, 60)
@classmethod
def get_info(cls, tenant_id: str):
params = {"tenant_id": tenant_id}
@@ -91,3 +94,29 @@ class BillingService:
"""Update account deletion feedback."""
json = {"email": email, "feedback": feedback}
return cls._send_request("POST", "/account/delete-feedback", json=json)
@classmethod
def get_compliance_download_link(
cls,
doc_name: str,
account_id: str,
tenant_id: str,
ip: str,
device_info: str,
):
limiter_key = f"{account_id}:{tenant_id}"
if cls.compliance_download_rate_limiter.is_rate_limited(limiter_key):
from controllers.console.error import CompilanceRateLimitError
raise CompilanceRateLimitError()
json = {
"doc_name": doc_name,
"account_id": account_id,
"tenant_id": tenant_id,
"ip_address": ip,
"device_info": device_info,
}
res = cls._send_request("POST", "/compliance/download", json=json)
cls.compliance_download_rate_limiter.increment_rate_limit(limiter_key)
return res