diff --git a/api/controllers/console/workspace/account.py b/api/controllers/console/workspace/account.py index f1ec0f3d29..bcfdb388f8 100644 --- a/api/controllers/console/workspace/account.py +++ b/api/controllers/console/workspace/account.py @@ -15,7 +15,12 @@ from controllers.console.workspace.error import ( InvalidInvitationCodeError, RepeatPasswordNotMatchError, ) -from controllers.console.wraps import account_initialization_required, enterprise_license_required, setup_required +from controllers.console.wraps import ( + account_initialization_required, + enterprise_license_required, + only_edition_cloud, + setup_required, +) from extensions.ext_database import db from fields.member_fields import account_fields from libs.helper import TimestampField, timezone @@ -292,6 +297,51 @@ class AccountDeleteUpdateFeedbackApi(Resource): return {"result": "success"} +class EducationVerifyApi(Resource): + verify_fields = { + "token": fields.String, + } + + @setup_required + @login_required + @account_initialization_required + @only_edition_cloud + @marshal_with(verify_fields) + def get(self): + account = current_user + + return BillingService.EducationIdentity.verify(account.id) + + +class EducationApi(Resource): + status_fields = { + "verified": fields.Boolean, + } + + @setup_required + @login_required + @account_initialization_required + @only_edition_cloud + def post(self): + account = current_user + + parser = reqparse.RequestParser() + parser.add_argument("token", type=str, required=True, location="json") + args = parser.parse_args() + + return BillingService.EducationIdentity.activate(account, args["token"]) + + @setup_required + @login_required + @account_initialization_required + @only_edition_cloud + @marshal_with(status_fields) + def get(self): + account = current_user + + return BillingService.EducationIdentity.is_active(account.id) + + # Register API resources api.add_resource(AccountInitApi, "/account/init") api.add_resource(AccountProfileApi, "/account/profile") @@ -305,5 +355,7 @@ api.add_resource(AccountIntegrateApi, "/account/integrates") api.add_resource(AccountDeleteVerifyApi, "/account/delete/verify") api.add_resource(AccountDeleteApi, "/account/delete") api.add_resource(AccountDeleteUpdateFeedbackApi, "/account/delete/feedback") +api.add_resource(EducationVerifyApi, "/account/education/verify") +api.add_resource(EducationApi, "/account/education") # api.add_resource(AccountEmailApi, '/account/email') # api.add_resource(AccountEmailVerifyApi, '/account/email-verify') diff --git a/api/services/billing_service.py b/api/services/billing_service.py index 0d50a2aa8c..4cb514616a 100644 --- a/api/services/billing_service.py +++ b/api/services/billing_service.py @@ -5,7 +5,7 @@ import httpx from tenacity import retry, retry_if_exception_type, stop_before_delay, wait_fixed from extensions.ext_database import db -from models.account import TenantAccountJoin, TenantAccountRole +from models.account import Account, TenantAccountJoin, TenantAccountRole class BillingService: @@ -91,3 +91,23 @@ class BillingService: """Update account deletion feedback.""" json = {"email": email, "feedback": feedback} return cls._send_request("POST", "/account/delete-feedback", json=json) + + class EducationIdentity: + @classmethod + def verify(cls, account_id: str): + params = {"account_id": account_id} + return BillingService._send_request("GET", "/education/verify", params=params) + + @classmethod + def is_active(cls, account_id: str): + params = {"account_id": account_id} + return BillingService._send_request("GET", "/education/status", params=params) + + @classmethod + def activate(cls, account: Account, token: str): + json = { + "account_id": account.id, + "email": account.email, + "token": token, + } + return BillingService._send_request("POST", "/education/", json=json)