현재 작업 전체 반영

This commit is contained in:
Yun Chan 2026-06-27 16:08:41 +09:00
parent 5560638e54
commit c0dddab594
85 changed files with 11322 additions and 539 deletions

View file

@ -70,10 +70,19 @@ def user_id_from_email(email: str) -> str:
return str(uuid.uuid5(uuid.NAMESPACE_URL, f"vignette:user:{email.strip().lower()}"))
def user_id_from_external_id(external_id: str) -> str:
return str(uuid.uuid5(uuid.NAMESPACE_URL, f"vignette:user-external:{external_id.strip().lower()}"))
def _normalize_email(email: str) -> str:
return email.strip().lower()
def _normalize_external_id(external_id: str | None, email: str) -> str:
value = (external_id or "").strip().lower()
return value or f"email:{_normalize_email(email)}"
def _db_role(role: str) -> str:
return DB_ROLE_BY_APP.get(role, role)
@ -309,6 +318,24 @@ async def ensure_runtime_tables() -> None:
)
"""
)
await conn.execute(
"""
DROP POLICY IF EXISTS p_case_insert ON app.case_profile;
DROP POLICY IF EXISTS p_case_update ON app.case_profile;
CREATE POLICY p_case_insert ON app.case_profile FOR INSERT WITH CHECK (
app.is_ai_context() OR app.current_role_name() IN ('admin','instructor')
OR learner_id = app.current_uid()
);
CREATE POLICY p_case_update ON app.case_profile FOR UPDATE USING (
app.is_ai_context() OR app.current_role_name() IN ('admin','instructor')
OR learner_id = app.current_uid()
) WITH CHECK (
app.is_ai_context() OR app.current_role_name() IN ('admin','instructor')
OR learner_id = app.current_uid()
)
"""
)
await conn.execute(
"""
DROP POLICY IF EXISTS p_turns_modify ON app.turns;
@ -412,10 +439,12 @@ async def upsert_managed_user(
role: str,
cohort_ids: list[str] | None = None,
user_id: str | None = None,
external_id: str | None = None,
affiliation: str | None = None,
reactivate: bool = False,
) -> ManagedUser:
normalized_email = _normalize_email(email)
normalized_external_id = _normalize_external_id(external_id, normalized_email)
try:
pool = get_pool()
async with pool.acquire() as conn:
@ -437,7 +466,7 @@ async def upsert_managed_user(
WHERE app.app_user.is_active OR $7
RETURNING user_id, email, display_name, role, cohort, affiliation, created_at, last_seen_at
""",
f"email:{normalized_email}",
normalized_external_id,
normalized_email,
(display_name.strip() if display_name else normalized_email),
_db_role(role),
@ -468,7 +497,7 @@ async def upsert_managed_user(
display_name=display_name,
role=role,
cohort_ids=cohort_ids,
user_id=user_id,
user_id=user_id or user_id_from_external_id(normalized_external_id),
affiliation=affiliation,
reactivate=reactivate,
)
@ -669,6 +698,7 @@ async def create_session(
role: str,
cohort_ids: list[str] | None = None,
user_id: str | None = None,
external_id: str | None = None,
) -> tuple[str, SessionUser]:
raw_sid = secrets.token_urlsafe(32)
normalized_email = _normalize_email(email)
@ -678,6 +708,7 @@ async def create_session(
role=role,
cohort_ids=cohort_ids,
user_id=user_id,
external_id=external_id,
reactivate=False,
)
expires_at = time.time() + settings.session_ttl_seconds