forked from baron/baron-sso
Implement tenant import and RP auto login policies
This commit is contained in:
121
docs/custom-field-jsonb-index-policy.md
Normal file
121
docs/custom-field-jsonb-index-policy.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Custom Field JSONB 및 인덱스 정책
|
||||
|
||||
## 현재 구조
|
||||
|
||||
- Tenant custom schema는 `tenants.config.userSchema` JSONB에 저장한다.
|
||||
- Tenant custom value는 backend DB의 `users.metadata` JSONB에 저장한다.
|
||||
- `isLoginId=true`인 Tenant field 값은 로그인 식별자 처리를 위해 `user_login_ids`에도 동기화한다.
|
||||
- Ory Kratos traits에는 인증/식별에 필요한 최소 값만 동기화하는 방향으로 정리한다.
|
||||
- RP custom value는 backend DB의 `rp_user_metadata.metadata` JSONB에 별도 저장한다.
|
||||
|
||||
## Tenant Custom Field
|
||||
|
||||
Tenant schema field는 다음 속성을 기준으로 한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "employeeNo",
|
||||
"label": "사번",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"indexed": true,
|
||||
"isLoginId": true,
|
||||
"adminOnly": false,
|
||||
"validation": "^[A-Z0-9]+$"
|
||||
}
|
||||
```
|
||||
|
||||
- `indexed=true`는 검색/필터 최적화 대상이라는 의미다.
|
||||
- `isLoginId=true`이면 backend와 adminfront 모두 `indexed=true`를 강제한다.
|
||||
- `isLoginId=true`는 값 필수를 의미하지 않는다. 값 필수 여부는 `required=true`로 별도 제어한다.
|
||||
- `isLoginId=true`인 field는 `type=text`만 허용한다.
|
||||
- JSONB 통합 정책에서는 `varchar` 크기 지정 의미를 두지 않는다.
|
||||
|
||||
## RP Custom Field
|
||||
|
||||
RP custom schema는 client metadata의 `customUserSchema`에 저장한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"customUserSchema": [
|
||||
{
|
||||
"key": "approvalLevel",
|
||||
"label": "승인 등급",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"indexed": true,
|
||||
"claimEnabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
RP custom value는 `rp_user_metadata` 테이블에 저장한다.
|
||||
|
||||
```text
|
||||
client_id text
|
||||
user_id uuid
|
||||
metadata jsonb
|
||||
created_at timestamptz
|
||||
updated_at timestamptz
|
||||
primary key (client_id, user_id)
|
||||
foreign key (user_id) references users(id)
|
||||
```
|
||||
|
||||
Backend API 초안:
|
||||
|
||||
```text
|
||||
GET /api/v1/dev/clients/:id/users/:userId/metadata
|
||||
PUT /api/v1/dev/clients/:id/users/:userId/metadata
|
||||
```
|
||||
|
||||
PUT payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"approvalLevel": "A",
|
||||
"preferences": {
|
||||
"theme": "dark"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 검색 및 인덱스
|
||||
|
||||
- `indexed=true` field만 검색 UI/API 후보로 노출한다.
|
||||
- 기본 검색은 exact match, exists, JSON containment 중심으로 제한한다.
|
||||
- RP custom field의 LIKE/fuzzy 검색은 기본 제공하지 않는다.
|
||||
- GIN 인덱스는 backend index manager가 별도 상태로 관리하는 방향을 원칙으로 한다.
|
||||
- API 요청 처리 중 `CREATE INDEX`를 동기 실행하지 않는다.
|
||||
|
||||
## Claim Projection
|
||||
|
||||
JWT 또는 userinfo 응답에서는 custom field를 top-level에 풀지 않는다.
|
||||
Tenant/RP 단위로 묶어서 전달한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"tenant_profiles": [
|
||||
{
|
||||
"tenant_id": "tenant-uuid",
|
||||
"tenant_slug": "hanmac-family",
|
||||
"fields": {
|
||||
"employeeNo": "E1001"
|
||||
}
|
||||
}
|
||||
],
|
||||
"rp_profiles": [
|
||||
{
|
||||
"client_id": "sample-rp",
|
||||
"fields": {
|
||||
"approvalLevel": "A"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `claimEnabled=true` field만 RP claim 후보로 포함한다.
|
||||
- 긴 JSON 값은 기본적으로 token claim보다 userinfo/profile API 응답에 싣는 방향을 우선한다.
|
||||
Reference in New Issue
Block a user