docs: rebuild architecture and taskplans for role-site model
This commit is contained in:
@@ -1,190 +1,38 @@
|
||||
# Internal API Handoff
|
||||
# Internal API Handoff(新模型)
|
||||
|
||||
## Base URL
|
||||
- Local: `http://127.0.0.1:8000`
|
||||
- Prod: 由部署環境提供
|
||||
|
||||
## Auth Headers(每支 `/internal/*` 都必帶)
|
||||
## Auth Headers(`/internal/*`)
|
||||
- `X-Client-Key: <client_key>`
|
||||
- `X-API-Key: <api_key>`
|
||||
|
||||
## Common Error Response
|
||||
```json
|
||||
{
|
||||
"detail": "error_code"
|
||||
}
|
||||
{ "detail": "error_code" }
|
||||
```
|
||||
|
||||
常見 `detail`:
|
||||
- `invalid_client`(401)
|
||||
- `invalid_api_key`(401)
|
||||
- `client_expired`(401)
|
||||
- `origin_not_allowed`(403)
|
||||
- `ip_not_allowed`(403)
|
||||
- `path_not_allowed`(403)
|
||||
## 資源模型(重點)
|
||||
- `company`: `id`, `company_key`, `display_name`, `legal_name`, `status`
|
||||
- `site`: `id`, `site_key`, `company_id`, `display_name`, `domain`, `status`
|
||||
- `system`: `id`, `system_key`, `name`, `idp_client_id`, `status`
|
||||
- `role`: `id`, `role_key`, `system_id`, `name`, `description`, `idp_role_name`, `status`
|
||||
- `user`: `id`, `user_sub`, `username`, `email`, `display_name`, `is_active`, `status`
|
||||
|
||||
## Endpoints
|
||||
## 主要端點(目標)
|
||||
1. `GET /internal/companies`
|
||||
2. `GET /internal/sites`
|
||||
3. `GET /internal/systems`
|
||||
4. `GET /internal/roles`
|
||||
5. `GET /internal/users`
|
||||
6. `GET /internal/users/{user_sub}/roles`
|
||||
- 回傳該 user 透過 site 推導出的最終 roles。
|
||||
|
||||
### GET `/internal/systems`
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{ "id": "uuid", "system_key": "ST20260331X1234", "name": "Marketing", "status": "active" }
|
||||
],
|
||||
"total": 1,
|
||||
"limit": 200,
|
||||
"offset": 0
|
||||
}
|
||||
```
|
||||
## 關聯端點(目標)
|
||||
1. `POST /internal/site-roles` / `DELETE /internal/site-roles/{id}`
|
||||
2. `POST /internal/user-sites` / `DELETE /internal/user-sites/{id}`
|
||||
|
||||
### GET `/internal/modules`
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"module_key": "MD20260331X5678",
|
||||
"system_key": "ST20260331X1234",
|
||||
"name": "Campaign",
|
||||
"status": "active"
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"limit": 500,
|
||||
"offset": 0
|
||||
}
|
||||
```
|
||||
|
||||
### GET `/internal/companies`
|
||||
Query:
|
||||
- `keyword`(optional)
|
||||
- `limit`(default 500)
|
||||
- `offset`(default 0)
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{ "id": "uuid", "company_key": "CP20260331X9999", "name": "OSE", "status": "active" }
|
||||
],
|
||||
"total": 1,
|
||||
"limit": 500,
|
||||
"offset": 0
|
||||
}
|
||||
```
|
||||
|
||||
### GET `/internal/sites`
|
||||
Query:
|
||||
- `company_key`(optional)
|
||||
- `limit`(default 500)
|
||||
- `offset`(default 0)
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"site_key": "ST20260331X1111",
|
||||
"company_key": "CP20260331X9999",
|
||||
"name": "main-site",
|
||||
"status": "active"
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"limit": 500,
|
||||
"offset": 0
|
||||
}
|
||||
```
|
||||
|
||||
### GET `/internal/members`
|
||||
Query:
|
||||
- `keyword`(optional)
|
||||
- `limit`(default 500)
|
||||
- `offset`(default 0)
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"user_sub": "idp-uid",
|
||||
"username": "chris",
|
||||
"email": "chris@ose.tw",
|
||||
"display_name": "Chris",
|
||||
"is_active": true
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"limit": 500,
|
||||
"offset": 0
|
||||
}
|
||||
```
|
||||
|
||||
### POST `/internal/users/upsert-by-sub`
|
||||
Request:
|
||||
```json
|
||||
{
|
||||
"user_sub": "idp-uid",
|
||||
"username": "chris",
|
||||
"email": "chris@ose.tw",
|
||||
"display_name": "Chris",
|
||||
"is_active": true
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"user_sub": "idp-uid",
|
||||
"idp_user_id": "idp-user-id-or-uuid",
|
||||
"username": "chris",
|
||||
"email": "chris@ose.tw",
|
||||
"display_name": "Chris",
|
||||
"is_active": true
|
||||
}
|
||||
```
|
||||
|
||||
### GET `/internal/permissions/{user_sub}/snapshot`
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"user_sub": "idp-uid",
|
||||
"permissions": [
|
||||
{
|
||||
"scope_type": "site",
|
||||
"scope_id": "ST20260331X1111",
|
||||
"system": "ST20260331X1234",
|
||||
"module": "MD20260331X5678",
|
||||
"actions": ["view", "edit"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### POST `/internal/idp/users/ensure`
|
||||
(相容路徑:`/internal/idp/users/ensure`)
|
||||
Request:
|
||||
```json
|
||||
{
|
||||
"user_sub": "idp-uid",
|
||||
"email": "user@example.com",
|
||||
"username": "user1",
|
||||
"display_name": "User One",
|
||||
"is_active": true
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"idp_user_id": "idp-user-id-or-uuid",
|
||||
"action": "created"
|
||||
}
|
||||
```
|
||||
|
||||
`action` 可能值:`created` / `updated`
|
||||
## 注意事項
|
||||
- 不提供 user direct role 寫入 API。
|
||||
- 若其他系統需要判斷某 user 可否做某事,請吃 `users/{user_sub}/roles` 聚合結果。
|
||||
|
||||
Reference in New Issue
Block a user