From 033ba649974aa77aa3dbbd66457ba6097ca15128 Mon Sep 17 00:00:00 2001 From: kyy Date: Fri, 6 Feb 2026 11:25:16 +0900 Subject: [PATCH] =?UTF-8?q?=EB=8F=99=EC=9D=98=20=EB=82=B4=EC=97=AD=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EB=AA=85=EC=84=B8=20?= =?UTF-8?q?=EB=B0=8F=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A0=80=EC=9E=A5=20?= =?UTF-8?q?=ED=9D=90=EB=A6=84=20=EB=AC=B8=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/consent_listing_flow.md | 74 ++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 docs/consent_listing_flow.md diff --git a/docs/consent_listing_flow.md b/docs/consent_listing_flow.md new file mode 100644 index 00000000..1ede6486 --- /dev/null +++ b/docs/consent_listing_flow.md @@ -0,0 +1,74 @@ +# [Flow] 사용자 동의 내역 조회 및 동기화 흐름 + +이 문서는 DevFront(개발자 포털)에서 클라이언트별 사용자 동의 내역을 조회하는 기능의 전체적인 데이터 흐름과 백엔드 로직을 설명합니다. 이 기능의 핵심은 Ory Hydra의 API 제약을 우회하고 멀티 테넌트 환경에서 데이터를 격리하기 위해 Baron SSO 자체 DB를 활용하는 것입니다. + +## 1. 데이터 동기화 (자체 DB에 저장) + +사용자의 동의 상태가 변경될 때마다 Baron SSO의 `client_consents` 테이블에 실시간으로 데이터가 동기화됩니다. + +### 1.1. 사용자가 최초로 동의할 때 + +- **시작점**: 사용자가 로그인 후 동의 화면에서 "허용" 버튼을 클릭합니다. +- **파일**: `backend/internal/handler/auth_handler.go` +- **함수**: `AcceptConsentRequest` +- **로직**: + 1. 프론트엔드로부터 `consent_challenge`와 사용자가 선택한 `scopes`를 전달받습니다. + 2. `h.Hydra.AcceptConsentRequest`를 호출하여 Ory Hydra에 동의를 최종 승인합니다. + 3. Hydra 요청이 성공하면, `domain.ClientConsent` 모델 객체를 생성합니다. + 4. `h.ConsentRepo.Upsert` 함수를 호출하여 `client_consents` 테이블에 해당 동의 내역을 저장(INSERT 또는 UPDATE)합니다. + +### 1.2. 사용자가 이미 동의하여 자동으로 승인될 때 + +- **시작점**: 이미 동의한 사용자가 다시 로그인을 시도하여 동의 화면이 생략(`skip: true`)될 때. +- **파일**: `backend/internal/handler/auth_handler.go` +- **함수**: `GetConsentRequest` +- **로직**: + 1. Ory Hydra로부터 `skip: true` 응답을 받습니다. + 2. 백엔드는 이 요청을 자동으로 수락하기 위해 `h.Hydra.AcceptConsentRequest`를 내부적으로 호출합니다. + 3. 자동 승인이 성공하면, **마찬가지로 `h.ConsentRepo.Upsert`를 호출하여 `client_consents` 테이블의 데이터를 최신 상태로 동기화합니다.** 이는 동의 내역의 일관성을 보장합니다. + +## 2. 데이터 조회 (DevFront 목록 표시) + +관리자가 DevFront에서 동의 내역을 조회할 때의 흐름입니다. + +- **시작점**: 관리자가 DevFront의 `Consent & Users` 페이지에 진입합니다. +- **파일**: `devfront/src/features/clients/ClientConsentsPage.tsx` +- **로직**: + 1. React Query의 `useQuery` 훅이 실행되면서 백엔드 API `GET /api/v1/dev/consents?client_id=`를 호출합니다. + 2. (보안) 이때 axios interceptor 등을 통해 현재 관리자의 **테넌트 ID가 담긴 `X-Tenant-ID` 헤더**를 함께 전송합니다. + +- **파일**: `backend/internal/handler/dev_handler.go` +- **함수**: `ListConsents` +- **로직**: + 1. `client_id`와 `X-Tenant-ID` 헤더 값을 파라미터로 받습니다. + 2. **테넌트 ID 유무에 따라 분기합니다**: + - `X-Tenant-ID`가 있으면, `h.ConsentRepo.ListByTenant`를 호출합니다. + - `X-Tenant-ID`가 없으면 (e.g., 슈퍼 관리자), `h.ConsentRepo.List`를 호출합니다. + +- **파일**: `backend/internal/repository/client_consent_repository.go` +- **함수**: `ListByTenant` +- **로직**: + 1. **가장 핵심적인 데이터 격리 로직이 실행됩니다.** + 2. GORM을 사용하여 `client_consents` 테이블과 `users` 테이블을 `JOIN`합니다. + 3. `WHERE` 절을 통해 `client_id`와 **관리자의 `tenant_id`**를 동시에 조건으로 사용하여, 해당 테넌트에 속한 사용자들의 동의 내역만 안전하게 필터링합니다. + 4. 조회된 결과를 `DevHandler`로 반환합니다. + +- **파일**: `backend/internal/handler/dev_handler.go` +- **함수**: `ListConsents` (계속) +- **로직**: + 1. Repository로부터 필터링된 동의 목록을 전달받습니다. + 2. 목록의 각 항목(사용자 `subject`)에 대해 `h.KratosAdmin.GetIdentity`를 호출하여 Kratos로부터 사용자 이름, 이메일 등 추가 정보를 가져와 응답 데이터를 보강합니다. + 3. 최종적으로 보강된 데이터를 JSON 형태로 프론트엔드에 반환합니다. + +- **파일**: `devfront/src/features/clients/ClientConsentsPage.tsx` (계속) +- **로직**: + 1. `useQuery`가 성공적으로 데이터를 받아오면, 상태가 업데이트되고 화면에 테이블 형태로 동의 내역이 렌더링됩니다. + +## 3. 데이터 철회 (동의 취소) + +- **시작점**: 관리자가 DevFront의 동의 목록에서 "Revoke" 버튼을 클릭합니다. +- **파일**: `backend/internal/handler/dev_handler.go` +- **함수**: `RevokeConsents` +- **로직**: + 1. `h.Hydra.RevokeConsentSessions`를 호출하여 Ory Hydra에서 실제 OIDC 세션을 무효화합니다. + 2. 성공 시, `h.ConsentRepo.Delete`를 호출하여 `client_consents` 테이블에서도 해당 동의 내역을 삭제하여 상태를 일치시킵니다.