diff --git a/server/app/controller/user/user_controller.py b/server/app/controller/user/user_controller.py index 30345645..9f75d74b 100644 --- a/server/app/controller/user/user_controller.py +++ b/server/app/controller/user/user_controller.py @@ -77,7 +77,7 @@ def get_privacy(session: Session = Depends(session), auth: Auth = Depends(auth_m return UserPrivacySettings.default_settings() logger.debug("Privacy settings retrieved", extra={"user_id": user_id}) - return model.pricacy_setting + return UserPrivacySettings(**model.pricacy_setting).to_response() @router.put("/user/privacy", name="update user privacy") @@ -97,7 +97,7 @@ def put_privacy(data: UserPrivacySettings, session: Session = Depends(session), model.save(session) logger.info("Privacy settings created", extra={"user_id": user_id}) - return model.pricacy_setting + return UserPrivacySettings(**model.pricacy_setting).to_response() @router.get("/user/current_credits", name="get user current credits") diff --git a/server/app/model/user/privacy.py b/server/app/model/user/privacy.py index d4fed768..d38e9c67 100644 --- a/server/app/model/user/privacy.py +++ b/server/app/model/user/privacy.py @@ -1,16 +1,18 @@ -# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. ========= -# 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 -# -# http://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. # ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. ========= +# 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 +# +# http://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. +# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. ========= + +from typing import ClassVar from pydantic import BaseModel from sqlalchemy import JSON @@ -31,6 +33,21 @@ class UserPrivacySettings(BaseModel): access_your_address: bool | None = False password_storage: bool | None = False + # Fields that must all be True for the user to proceed + REQUIRED_FIELDS: ClassVar[list[str]] = [ + 'take_screenshot', + 'access_local_software', + 'access_your_address', + 'password_storage', + ] + @classmethod def default_settings(cls) -> dict: - return cls().model_dump() + instance = cls() + return {**instance.model_dump(), "all_required_granted": instance.all_required_granted()} + + def all_required_granted(self) -> bool: + return all(getattr(self, f) for f in self.REQUIRED_FIELDS) + + def to_response(self) -> dict: + return {**self.model_dump(), "all_required_granted": self.all_required_granted()} diff --git a/server/tests/user.http b/server/tests/user.http new file mode 100644 index 00000000..f518e970 --- /dev/null +++ b/server/tests/user.http @@ -0,0 +1,80 @@ +### ============================================ +### Eigent Server API Tests +### ============================================ +### VSCode Extension: "REST Client" by Huachao Mao +### Extension ID: humao.rest-client +### ============================================ + +@baseUrl = http://localhost:3001/api +@token = YOUR_TOKEN_HERE + +### ────────────────────────────────────────── +### Auth (no token required) +### ────────────────────────────────────────── + +### Register a new user +POST {{baseUrl}}/register +Content-Type: application/json + +{ + "email": "test@example.com", + "password": "testpassword123" +} + +### Login +# @name login +POST {{baseUrl}}/login +Content-Type: application/json + +{ + "email": "test@example.com", + "password": "testpassword123" +} + +### Save token from login response (use this after running login) +@authToken = {{login.response.body.token}} + +### ────────────────────────────────────────── +### User +### ────────────────────────────────────────── + +### Get current user info +GET {{baseUrl}}/user +Authorization: Bearer {{authToken}} + +### ────────────────────────────────────────── +### Privacy Settings +### ────────────────────────────────────────── + +### Get privacy settings +GET {{baseUrl}}/user/privacy +Authorization: Bearer {{authToken}} + +### Update privacy settings +PUT {{baseUrl}}/user/privacy +Authorization: Bearer {{authToken}} +Content-Type: application/json + +{ + "take_screenshot": true, + "access_local_software": false, + "access_your_address": false, + "password_storage": false +} + +### Update only help_improve +PUT {{baseUrl}}/user/privacy +Authorization: Bearer {{authToken}} +Content-Type: application/json + +{ + "help_improve": true +} + +### ────────────────────────────────────────── +### User Stats +### ────────────────────────────────────────── + +### Get user stats +GET {{baseUrl}}/user/stat +Authorization: Bearer {{authToken}} diff --git a/src/components/ChatBox/index.tsx b/src/components/ChatBox/index.tsx index cacee7cd..5ebe08ef 100644 --- a/src/components/ChatBox/index.tsx +++ b/src/components/ChatBox/index.tsx @@ -74,7 +74,10 @@ export default function ChatBox(): JSX.Element { useEffect(() => { proxyFetchGet('/api/user/privacy') .then((res) => { - const allEnabled = isPrivacyAllEnabled(res || {}); + const allEnabled = + res && typeof res.all_required_granted === 'boolean' + ? res.all_required_granted + : isPrivacyAllEnabled(res || {}); setPrivacy(allEnabled); setStoredPrivacyEnabled(email, allEnabled); }) diff --git a/src/pages/Setting/Privacy.tsx b/src/pages/Setting/Privacy.tsx index 7343853f..00e4c239 100644 --- a/src/pages/Setting/Privacy.tsx +++ b/src/pages/Setting/Privacy.tsx @@ -63,11 +63,14 @@ export default function SettingPrivacy() { useEffect(() => { proxyFetchGet('/api/user/privacy') .then((res) => { - const allEnabled = isPrivacyAllEnabled(res || {}); + const allEnabled = + res && typeof res.all_required_granted === 'boolean' + ? res.all_required_granted + : isPrivacyAllEnabled(res || {}); setSettings((prev) => prev.map((item, index) => ({ ...item, - checked: !!res?.[API_FIELDS[index]], + checked: res?.[API_FIELDS[index]] || false, })) ); setPrivacy(allEnabled);