fix(settings): profile tests assert sync-identity; add load/save_user_profile helpers
This commit is contained in:
parent
1ef418ba00
commit
da7d305588
3 changed files with 44 additions and 19 deletions
26
dev-api.py
26
dev-api.py
|
|
@ -905,6 +905,9 @@ def config_user():
|
|||
|
||||
# ── Settings: My Profile endpoints ───────────────────────────────────────────
|
||||
|
||||
from scripts.user_profile import load_user_profile, save_user_profile
|
||||
|
||||
|
||||
def _user_yaml_path() -> str:
|
||||
"""Resolve user.yaml path, falling back to legacy location."""
|
||||
cfg_path = os.path.join(os.path.dirname(DB_PATH), "config", "user.yaml")
|
||||
|
|
@ -913,22 +916,6 @@ def _user_yaml_path() -> str:
|
|||
return cfg_path
|
||||
|
||||
|
||||
def _read_user_yaml() -> dict:
|
||||
import yaml
|
||||
path = _user_yaml_path()
|
||||
if not os.path.exists(path):
|
||||
return {}
|
||||
with open(path) as f:
|
||||
return yaml.safe_load(f) or {}
|
||||
|
||||
|
||||
def _write_user_yaml(data: dict) -> None:
|
||||
import yaml
|
||||
path = _user_yaml_path()
|
||||
with open(path, "w") as f:
|
||||
yaml.dump(data, f, default_flow_style=False, allow_unicode=True)
|
||||
|
||||
|
||||
def _mission_dict_to_list(prefs: object) -> list:
|
||||
"""Convert {industry: note} dict to [{industry, note}] list for the SPA."""
|
||||
if isinstance(prefs, list):
|
||||
|
|
@ -950,7 +937,7 @@ def _mission_list_to_dict(prefs: list) -> dict:
|
|||
@app.get("/api/settings/profile")
|
||||
def get_profile():
|
||||
try:
|
||||
cfg = _read_user_yaml()
|
||||
cfg = load_user_profile(_user_yaml_path())
|
||||
return {
|
||||
"name": cfg.get("name", ""),
|
||||
"email": cfg.get("email", ""),
|
||||
|
|
@ -990,7 +977,8 @@ class UserProfilePayload(BaseModel):
|
|||
@app.put("/api/settings/profile")
|
||||
def save_profile(payload: UserProfilePayload):
|
||||
try:
|
||||
cfg = _read_user_yaml()
|
||||
yaml_path = _user_yaml_path()
|
||||
cfg = load_user_profile(yaml_path)
|
||||
cfg["name"] = payload.name
|
||||
cfg["email"] = payload.email
|
||||
cfg["phone"] = payload.phone
|
||||
|
|
@ -1004,7 +992,7 @@ def save_profile(payload: UserProfilePayload):
|
|||
cfg["nda_companies"] = payload.nda_companies
|
||||
cfg["candidate_accessibility_focus"] = payload.accessibility_focus
|
||||
cfg["candidate_lgbtq_focus"] = payload.lgbtq_focus
|
||||
_write_user_yaml(cfg)
|
||||
save_user_profile(yaml_path, cfg)
|
||||
return {"ok": True}
|
||||
except Exception as e:
|
||||
raise HTTPException(500, f"Could not save profile: {e}")
|
||||
|
|
|
|||
|
|
@ -130,3 +130,36 @@ class UserProfile:
|
|||
"ollama_research": f"{self.ollama_url}/v1",
|
||||
"vllm": f"{self.vllm_url}/v1",
|
||||
}
|
||||
|
||||
|
||||
# ── Free functions for plain-dict access (used by dev-api.py) ─────────────────
|
||||
|
||||
def load_user_profile(config_path: str) -> dict:
|
||||
"""Load user.yaml and return as a plain dict with safe defaults."""
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
path = Path(config_path)
|
||||
if not path.exists():
|
||||
return {}
|
||||
with open(path) as f:
|
||||
data = yaml.safe_load(f) or {}
|
||||
return data
|
||||
|
||||
|
||||
def save_user_profile(config_path: str, data: dict) -> None:
|
||||
"""Atomically write the user profile dict to user.yaml."""
|
||||
import yaml
|
||||
import os
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
path = Path(config_path)
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
# Write to temp file then rename for atomicity
|
||||
fd, tmp = tempfile.mkstemp(dir=path.parent, suffix='.yaml.tmp')
|
||||
try:
|
||||
with os.fdopen(fd, 'w') as f:
|
||||
yaml.dump(data, f, allow_unicode=True, default_flow_style=False)
|
||||
os.replace(tmp, path)
|
||||
except Exception:
|
||||
os.unlink(tmp)
|
||||
raise
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ describe('useProfileStore', () => {
|
|||
store.name = 'Meg'
|
||||
await store.save()
|
||||
expect(mockFetch).toHaveBeenCalledWith('/api/settings/profile', expect.objectContaining({ method: 'PUT' }))
|
||||
expect(mockFetch).toHaveBeenCalledWith(
|
||||
'/api/settings/resume/sync-identity',
|
||||
expect.objectContaining({ method: 'POST' })
|
||||
)
|
||||
})
|
||||
|
||||
it('save() error sets error state', async () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue