mirror of
https://github.com/EZ-Api/ez-api.git
synced 2026-01-13 17:47:51 +00:00
feat(api): add /auth/whoami endpoint and build automation
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -30,3 +30,4 @@ go.work.sum
|
|||||||
# Editor/IDE
|
# Editor/IDE
|
||||||
# .idea/
|
# .idea/
|
||||||
# .vscode/
|
# .vscode/
|
||||||
|
ez-api
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
FROM golang:1.24-alpine AS builder
|
FROM golang:1.24-alpine AS builder
|
||||||
|
|
||||||
|
# Install make for Makefile support
|
||||||
|
RUN apk add --no-cache make
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN go build -o ez-api ./cmd/server
|
|
||||||
|
# Use Makefile to generate swagger and build
|
||||||
|
RUN make build
|
||||||
|
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
|
|||||||
58
Makefile
Normal file
58
Makefile
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
.PHONY: all build swagger test clean dev
|
||||||
|
|
||||||
|
# Default target
|
||||||
|
all: swagger build
|
||||||
|
|
||||||
|
# Generate swagger documentation using go run (no install needed)
|
||||||
|
swagger:
|
||||||
|
@echo "Generating Swagger documentation..."
|
||||||
|
go run github.com/swaggo/swag/cmd/swag@latest init -g cmd/server/main.go -o docs --parseDependency --parseInternal
|
||||||
|
|
||||||
|
# Build the binary
|
||||||
|
build: swagger
|
||||||
|
@echo "Building ez-api..."
|
||||||
|
go build -o ez-api ./cmd/server
|
||||||
|
|
||||||
|
# Build without swagger regeneration (for quick iteration)
|
||||||
|
build-fast:
|
||||||
|
go build -o ez-api ./cmd/server
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
test:
|
||||||
|
go test -v ./...
|
||||||
|
|
||||||
|
# Clean build artifacts
|
||||||
|
clean:
|
||||||
|
rm -f ez-api
|
||||||
|
rm -rf docs/
|
||||||
|
|
||||||
|
# Run in development mode
|
||||||
|
dev: swagger
|
||||||
|
go run ./cmd/server
|
||||||
|
|
||||||
|
# Format code
|
||||||
|
fmt:
|
||||||
|
go fmt ./...
|
||||||
|
|
||||||
|
# Lint code
|
||||||
|
lint:
|
||||||
|
@which golangci-lint > /dev/null || go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
|
||||||
|
golangci-lint run
|
||||||
|
|
||||||
|
# Generate swagger only (alias)
|
||||||
|
docs: swagger
|
||||||
|
|
||||||
|
# Help
|
||||||
|
help:
|
||||||
|
@echo "Available targets:"
|
||||||
|
@echo " all - Generate swagger docs and build (default)"
|
||||||
|
@echo " build - Generate swagger and build binary"
|
||||||
|
@echo " build-fast - Build binary without swagger regeneration"
|
||||||
|
@echo " swagger - Generate Swagger documentation"
|
||||||
|
@echo " docs - Alias for swagger"
|
||||||
|
@echo " test - Run tests"
|
||||||
|
@echo " dev - Run in development mode"
|
||||||
|
@echo " clean - Remove build artifacts"
|
||||||
|
@echo " fmt - Format code"
|
||||||
|
@echo " lint - Run linter"
|
||||||
|
@echo " help - Show this help"
|
||||||
25
docs/api.md
25
docs/api.md
@@ -17,8 +17,30 @@
|
|||||||
| :--- | :--- | :--- | :--- |
|
| :--- | :--- | :--- | :--- |
|
||||||
| **Admin** | `Authorization: Bearer <admin_token>` | 环境变量 `EZ_ADMIN_TOKEN` | 全局管理权限,可管理所有租户、供应商和模型。 |
|
| **Admin** | `Authorization: Bearer <admin_token>` | 环境变量 `EZ_ADMIN_TOKEN` | 全局管理权限,可管理所有租户、供应商和模型。 |
|
||||||
| **Master** | `Authorization: Bearer <master_key>` | 创建 Master 时返回 | 租户级权限,仅能管理所属的子 Key、查看自身统计和日志。 |
|
| **Master** | `Authorization: Bearer <master_key>` | 创建 Master 时返回 | 租户级权限,仅能管理所属的子 Key、查看自身统计和日志。 |
|
||||||
|
| **Key** | `Authorization: Bearer <child_key>` | Master 或 Admin 签发 | 用于调用 AI API,可通过 `/auth/whoami` 查询身份信息。 |
|
||||||
| **Internal** | `X-Internal-Token: <token>` | 环境变量 `EZ_INTERNAL_STATS_TOKEN` | 内部组件(如 Data Plane)同步指标使用。 |
|
| **Internal** | `X-Internal-Token: <token>` | 环境变量 `EZ_INTERNAL_STATS_TOKEN` | 内部组件(如 Data Plane)同步指标使用。 |
|
||||||
|
|
||||||
|
### 1.4 身份识别接口
|
||||||
|
使用 `GET /auth/whoami` 可根据 Authorization header 中的 Token 识别当前身份类型:
|
||||||
|
|
||||||
|
| Token 类型 | 返回 `type` | 说明 |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| Admin Token | `"admin"` | 进入管理员面板 |
|
||||||
|
| Master Key | `"master"` | 进入租户自服务面板 |
|
||||||
|
| Child Key | `"key"` | 显示 Key 信息页,包含 `issued_by` 字段标识签发者 |
|
||||||
|
|
||||||
|
**示例响应**:
|
||||||
|
```json
|
||||||
|
// Admin Token
|
||||||
|
{"type": "admin", "role": "admin"}
|
||||||
|
|
||||||
|
// Master Key
|
||||||
|
{"type": "master", "id": 1, "name": "研发团队", "group": "default", ...}
|
||||||
|
|
||||||
|
// Child Key
|
||||||
|
{"type": "key", "id": 5, "master_id": 1, "issued_by": "master", ...}
|
||||||
|
```
|
||||||
|
|
||||||
### 1.3 通用约定
|
### 1.3 通用约定
|
||||||
- **分页处理**:
|
- **分页处理**:
|
||||||
- 管理端列表 (`GET /admin/*`):使用 `page` (从 1 开始) 和 `limit` (默认 50,最大 200)。
|
- 管理端列表 (`GET /admin/*`):使用 `page` (从 1 开始) 和 `limit` (默认 50,最大 200)。
|
||||||
@@ -106,6 +128,9 @@ graph TD
|
|||||||
|
|
||||||
## 4. API 模块概览
|
## 4. API 模块概览
|
||||||
|
|
||||||
|
### 4.0 公开接口 (Auth API) - 无需中间件
|
||||||
|
- **身份识别**:`GET /auth/whoami` - 根据 Token 返回身份类型和详细信息。
|
||||||
|
|
||||||
### 4.1 管理端 (Admin API) - 需 Admin Token
|
### 4.1 管理端 (Admin API) - 需 Admin Token
|
||||||
- **租户管理**:创建 Master、签发子 Key、实时 QPS 监控、冻结/解冻。
|
- **租户管理**:创建 Master、签发子 Key、实时 QPS 监控、冻结/解冻。
|
||||||
- **上游管理**:ProviderGroup + APIKey 的 CRUD 与批量操作。
|
- **上游管理**:ProviderGroup + APIKey 的 CRUD 与批量操作。
|
||||||
|
|||||||
111
docs/docs.go
111
docs/docs.go
@@ -2859,6 +2859,40 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/auth/whoami": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"AdminAuth": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MasterAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Returns the identity of the authenticated user based on the Authorization header.\nSupports Admin Token, Master Key, and Child Key (API Key) authentication.\n\nResponse varies by token type:\n- Admin Token: {\"type\": \"admin\", \"role\": \"admin\"}\n- Master Key: {\"type\": \"master\", \"id\": 1, \"name\": \"...\", ...}\n- Child Key: {\"type\": \"key\", \"id\": 5, \"master_id\": 1, \"issued_by\": \"master\", ...}",
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"auth"
|
||||||
|
],
|
||||||
|
"summary": "Get current identity",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/internal_api.WhoamiResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Invalid or missing token",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/gin.H"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/internal/stats/flush": {
|
"/internal/stats/flush": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "Internal endpoint for flushing accumulated key usage stats from DP to CP database",
|
"description": "Internal endpoint for flushing accumulated key usage stats from DP to CP database",
|
||||||
@@ -4620,6 +4654,83 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"internal_api.WhoamiResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"created_at": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1703505600
|
||||||
|
},
|
||||||
|
"default_namespace": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "default"
|
||||||
|
},
|
||||||
|
"epoch": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1
|
||||||
|
},
|
||||||
|
"global_qps": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 100
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "default"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"description": "Master fields (only present when type is \"master\")",
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1
|
||||||
|
},
|
||||||
|
"issued_at_epoch": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1
|
||||||
|
},
|
||||||
|
"issued_by": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "master"
|
||||||
|
},
|
||||||
|
"master_id": {
|
||||||
|
"description": "Key fields (only present when type is \"key\")",
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1
|
||||||
|
},
|
||||||
|
"max_child_keys": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 5
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "tenant-a"
|
||||||
|
},
|
||||||
|
"namespaces": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "default,ns1"
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"description": "Admin fields (only present when type is \"admin\")",
|
||||||
|
"type": "string",
|
||||||
|
"example": "admin"
|
||||||
|
},
|
||||||
|
"scopes": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "chat:write"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "active"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"description": "Type of the authenticated identity: \"admin\", \"master\", or \"key\"",
|
||||||
|
"type": "string",
|
||||||
|
"example": "master"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1703505600
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"internal_api.refreshModelRegistryRequest": {
|
"internal_api.refreshModelRegistryRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -2853,6 +2853,40 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/auth/whoami": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"AdminAuth": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MasterAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Returns the identity of the authenticated user based on the Authorization header.\nSupports Admin Token, Master Key, and Child Key (API Key) authentication.\n\nResponse varies by token type:\n- Admin Token: {\"type\": \"admin\", \"role\": \"admin\"}\n- Master Key: {\"type\": \"master\", \"id\": 1, \"name\": \"...\", ...}\n- Child Key: {\"type\": \"key\", \"id\": 5, \"master_id\": 1, \"issued_by\": \"master\", ...}",
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"auth"
|
||||||
|
],
|
||||||
|
"summary": "Get current identity",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/internal_api.WhoamiResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Invalid or missing token",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/gin.H"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/internal/stats/flush": {
|
"/internal/stats/flush": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "Internal endpoint for flushing accumulated key usage stats from DP to CP database",
|
"description": "Internal endpoint for flushing accumulated key usage stats from DP to CP database",
|
||||||
@@ -4614,6 +4648,83 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"internal_api.WhoamiResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"created_at": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1703505600
|
||||||
|
},
|
||||||
|
"default_namespace": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "default"
|
||||||
|
},
|
||||||
|
"epoch": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1
|
||||||
|
},
|
||||||
|
"global_qps": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 100
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "default"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"description": "Master fields (only present when type is \"master\")",
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1
|
||||||
|
},
|
||||||
|
"issued_at_epoch": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1
|
||||||
|
},
|
||||||
|
"issued_by": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "master"
|
||||||
|
},
|
||||||
|
"master_id": {
|
||||||
|
"description": "Key fields (only present when type is \"key\")",
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1
|
||||||
|
},
|
||||||
|
"max_child_keys": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 5
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "tenant-a"
|
||||||
|
},
|
||||||
|
"namespaces": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "default,ns1"
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"description": "Admin fields (only present when type is \"admin\")",
|
||||||
|
"type": "string",
|
||||||
|
"example": "admin"
|
||||||
|
},
|
||||||
|
"scopes": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "chat:write"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "active"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"description": "Type of the authenticated identity: \"admin\", \"master\", or \"key\"",
|
||||||
|
"type": "string",
|
||||||
|
"example": "master"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"type": "integer",
|
||||||
|
"example": 1703505600
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"internal_api.refreshModelRegistryRequest": {
|
"internal_api.refreshModelRegistryRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -731,6 +731,64 @@ definitions:
|
|||||||
description: active/suspended
|
description: active/suspended
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
internal_api.WhoamiResponse:
|
||||||
|
properties:
|
||||||
|
created_at:
|
||||||
|
example: 1703505600
|
||||||
|
type: integer
|
||||||
|
default_namespace:
|
||||||
|
example: default
|
||||||
|
type: string
|
||||||
|
epoch:
|
||||||
|
example: 1
|
||||||
|
type: integer
|
||||||
|
global_qps:
|
||||||
|
example: 100
|
||||||
|
type: integer
|
||||||
|
group:
|
||||||
|
example: default
|
||||||
|
type: string
|
||||||
|
id:
|
||||||
|
description: Master fields (only present when type is "master")
|
||||||
|
example: 1
|
||||||
|
type: integer
|
||||||
|
issued_at_epoch:
|
||||||
|
example: 1
|
||||||
|
type: integer
|
||||||
|
issued_by:
|
||||||
|
example: master
|
||||||
|
type: string
|
||||||
|
master_id:
|
||||||
|
description: Key fields (only present when type is "key")
|
||||||
|
example: 1
|
||||||
|
type: integer
|
||||||
|
max_child_keys:
|
||||||
|
example: 5
|
||||||
|
type: integer
|
||||||
|
name:
|
||||||
|
example: tenant-a
|
||||||
|
type: string
|
||||||
|
namespaces:
|
||||||
|
example: default,ns1
|
||||||
|
type: string
|
||||||
|
role:
|
||||||
|
description: Admin fields (only present when type is "admin")
|
||||||
|
example: admin
|
||||||
|
type: string
|
||||||
|
scopes:
|
||||||
|
example: chat:write
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
example: active
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: 'Type of the authenticated identity: "admin", "master", or "key"'
|
||||||
|
example: master
|
||||||
|
type: string
|
||||||
|
updated_at:
|
||||||
|
example: 1703505600
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
internal_api.refreshModelRegistryRequest:
|
internal_api.refreshModelRegistryRequest:
|
||||||
properties:
|
properties:
|
||||||
ref:
|
ref:
|
||||||
@@ -2612,6 +2670,33 @@ paths:
|
|||||||
summary: Test dependency connectivity
|
summary: Test dependency connectivity
|
||||||
tags:
|
tags:
|
||||||
- system
|
- system
|
||||||
|
/auth/whoami:
|
||||||
|
get:
|
||||||
|
description: |-
|
||||||
|
Returns the identity of the authenticated user based on the Authorization header.
|
||||||
|
Supports Admin Token, Master Key, and Child Key (API Key) authentication.
|
||||||
|
|
||||||
|
Response varies by token type:
|
||||||
|
- Admin Token: {"type": "admin", "role": "admin"}
|
||||||
|
- Master Key: {"type": "master", "id": 1, "name": "...", ...}
|
||||||
|
- Child Key: {"type": "key", "id": 5, "master_id": 1, "issued_by": "master", ...}
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/internal_api.WhoamiResponse'
|
||||||
|
"401":
|
||||||
|
description: Invalid or missing token
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/gin.H'
|
||||||
|
security:
|
||||||
|
- AdminAuth: []
|
||||||
|
- MasterAuth: []
|
||||||
|
summary: Get current identity
|
||||||
|
tags:
|
||||||
|
- auth
|
||||||
/internal/stats/flush:
|
/internal/stats/flush:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
|
|||||||
Reference in New Issue
Block a user