huace-aigc-auth-client 1.1.3__py3-none-any.whl → 1.1.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -68,6 +68,11 @@ from .legacy_adapter import (
68
68
  create_default_field_mappings,
69
69
  )
70
70
 
71
+ from .webhook import (
72
+ register_webhook_router,
73
+ verify_webhook_signature,
74
+ )
75
+
71
76
  __all__ = [
72
77
  # 核心类
73
78
  "AigcAuthClient",
@@ -89,5 +94,8 @@ __all__ = [
89
94
  "SyncResult",
90
95
  "create_sync_config",
91
96
  "create_default_field_mappings",
97
+ # Webhook 接收
98
+ "register_webhook_router",
99
+ "verify_webhook_signature",
92
100
  ]
93
- __version__ = "1.1.3"
101
+ __version__ = "1.1.5"
@@ -577,7 +577,7 @@ class AuthMiddleware:
577
577
  return None
578
578
  return authorization[7:]
579
579
 
580
- async def fastapi_middleware(self, request, call_next):
580
+ async def fastapi_middleware(self, request, call_next, user_info_callback: Callable = None):
581
581
  """
582
582
  FastAPI 中间件
583
583
 
@@ -613,22 +613,23 @@ class AuthMiddleware:
613
613
  forwarded_proto = request.headers.get("x-forwarded-proto")
614
614
  if forwarded_proto:
615
615
  request.scope["scheme"] = forwarded_proto
616
+ if user_info_callback:
617
+ await user_info_callback(request, user_info)
616
618
  except AigcAuthError as e:
617
619
  return JSONResponse(
618
620
  status_code=401,
619
621
  content={"code": e.code, "message": e.message, "data": None}
620
622
  )
621
-
622
623
  return await call_next(request)
623
624
 
624
- def flask_before_request(self):
625
+ def flask_before_request(self, user_info_callback: Callable = None):
625
626
  """
626
627
  Flask before_request 处理器
627
628
 
628
629
  使用方法:
629
630
  @app.before_request
630
631
  def before_request():
631
- return auth_middleware.flask_before_request()
632
+ return auth_middleware.flask_before_request(user_info_callback=user_info_callback)
632
633
  """
633
634
  from flask import request, jsonify, g
634
635
 
@@ -654,6 +655,8 @@ class AuthMiddleware:
654
655
  user_info = self.client.get_user_info(token)
655
656
  # 将用户信息存储到 flask.g
656
657
  g.user_info = user_info
658
+ if user_info_callback:
659
+ user_info_callback(request, user_info)
657
660
  except AigcAuthError as e:
658
661
  return jsonify({
659
662
  "code": e.code,
@@ -0,0 +1,128 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Webhook 接收模块
4
+
5
+ 提供通用的 webhook 接收功能,用于接收 aigc-auth 的用户变更通知
6
+ """
7
+
8
+ import hmac
9
+ import hashlib
10
+ import os
11
+ import logging
12
+ from typing import Callable, Awaitable, Dict, Any, Optional
13
+ from fastapi import APIRouter, Request, HTTPException
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool:
19
+ """
20
+ 验证 webhook 签名
21
+
22
+ Args:
23
+ payload: 请求体(bytes)
24
+ signature: 签名字符串
25
+ secret: 密钥
26
+
27
+ Returns:
28
+ bool: 签名是否有效
29
+ """
30
+ if not secret or not signature:
31
+ return False # 如果未配置密钥,则签名无效
32
+
33
+ expected = hmac.new(
34
+ secret.encode('utf-8'),
35
+ payload, # payload 已经是 bytes 类型
36
+ hashlib.sha256
37
+ ).hexdigest()
38
+
39
+ return hmac.compare_digest(expected, signature)
40
+
41
+
42
+ def register_webhook_router(
43
+ api_router: APIRouter,
44
+ handler: Callable[[Dict[str, Any]], Awaitable[Dict[str, Any]]],
45
+ prefix: str = "/webhook",
46
+ secret_env_key: str = "AIGC_AUTH_WEBHOOK_SECRET",
47
+ tags: Optional[list] = None
48
+ ) -> APIRouter:
49
+ """
50
+ 注册 webhook 路由到现有的 API Router
51
+
52
+ Args:
53
+ api_router: FastAPI APIRouter 实例
54
+ handler: 异步处理函数,接收 webhook 数据并返回结果
55
+ 函数签名: async def handler(data: Dict[str, Any]) -> Dict[str, Any]
56
+ prefix: webhook 路由前缀,默认 "/webhook"
57
+ secret_env_key: webhook 密钥的环境变量名,默认 "AIGC_AUTH_WEBHOOK_SECRET"
58
+ tags: OpenAPI 标签列表,默认 ["Webhook"]
59
+
60
+ Returns:
61
+ APIRouter: 创建的 webhook router
62
+
63
+ 使用示例:
64
+ from fastapi import APIRouter
65
+ from huace_aigc_auth_client.webhook import register_webhook_router
66
+
67
+ api_router = APIRouter()
68
+
69
+ async def my_webhook_handler(data: dict) -> dict:
70
+ event = data.get("event")
71
+ if event == "user.created":
72
+ # 处理用户创建事件
73
+ pass
74
+ return {"status": "ok"}
75
+
76
+ register_webhook_router(api_router, my_webhook_handler)
77
+ """
78
+ if tags is None:
79
+ tags = ["Webhook"]
80
+
81
+ webhook_router = APIRouter()
82
+
83
+ @webhook_router.post("/auth")
84
+ async def receive_auth_webhook(request: Request):
85
+ """
86
+ 接收 aigc-auth 用户变更通知
87
+
88
+ 当 aigc-auth 中创建或更新用户时,会发送 webhook 通知到此端点,
89
+ 本系统接收后会调用自定义的处理函数进行处理。
90
+
91
+ 支持的事件:
92
+ - user.created: 用户创建
93
+ - user.updated: 用户更新
94
+ """
95
+ # 获取请求体
96
+ body = await request.body()
97
+
98
+ # 验证签名
99
+ signature = request.headers.get("X-Webhook-Signature", "")
100
+ secret = os.getenv(secret_env_key, "")
101
+
102
+ if not verify_webhook_signature(body, signature, secret):
103
+ logger.warning("Webhook signature verification failed")
104
+ raise HTTPException(status_code=401, detail="Invalid signature")
105
+
106
+ # 解析请求数据
107
+ try:
108
+ data = await request.json()
109
+ except Exception as e:
110
+ logger.error(f"Failed to parse webhook payload: {e}")
111
+ raise HTTPException(status_code=400, detail="Invalid JSON payload")
112
+
113
+ # 记录日志
114
+ event = data.get("event", "unknown")
115
+ logger.info(f"Received webhook event: {event}")
116
+
117
+ # 调用用户提供的处理函数
118
+ try:
119
+ result = await handler(data)
120
+ return result
121
+ except Exception as e:
122
+ logger.exception(f"Failed to handle webhook: {e}")
123
+ raise HTTPException(status_code=500, detail=str(e))
124
+
125
+ # 将 webhook router 注册到主 router
126
+ api_router.include_router(webhook_router, prefix=prefix, tags=tags)
127
+
128
+ return webhook_router
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: huace-aigc-auth-client
3
- Version: 1.1.3
3
+ Version: 1.1.5
4
4
  Summary: 华策AIGC Auth Client - 提供 Token 验证、用户信息获取、权限检查、旧系统接入等功能
5
5
  Author-email: Huace <support@huace.com>
6
6
  License: MIT
@@ -0,0 +1,9 @@
1
+ huace_aigc_auth_client/__init__.py,sha256=IEHy6LKacmhQnnaUHIKg5YyUf2aNCYMj4_0p3NNOU90,2332
2
+ huace_aigc_auth_client/legacy_adapter.py,sha256=lCxpwROHZd0RG0dVp6AidQQRpFv6H8DvVzjrYHRDZFg,21515
3
+ huace_aigc_auth_client/sdk.py,sha256=4Azj2TPOCLWv6dTaAqw--_Uh-Gzpp0KhpxOEBGONG48,22749
4
+ huace_aigc_auth_client/webhook.py,sha256=m-mjXNNqrUClrNpOHRBzty0XKFDBuZp4e_PgLd2t0aA,4070
5
+ huace_aigc_auth_client-1.1.5.dist-info/licenses/LICENSE,sha256=z7dgC7KljhBLNvKjN15391nMj3aLt0gbud8-Yf1F8EQ,1063
6
+ huace_aigc_auth_client-1.1.5.dist-info/METADATA,sha256=d8z-VO8lkrZO7JYuSqHyfezrJzOxlYaYqwPfk9zijao,20084
7
+ huace_aigc_auth_client-1.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ huace_aigc_auth_client-1.1.5.dist-info/top_level.txt,sha256=kbv0nQ6PQ0JVneWPH7O2AbtlJnP7AjvFJ6JjM6ZEBxo,23
9
+ huace_aigc_auth_client-1.1.5.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- huace_aigc_auth_client/__init__.py,sha256=WwdgR8RP5SkueieSv6HCjIirIZdwTDpyGTaBzpENK5g,2163
2
- huace_aigc_auth_client/legacy_adapter.py,sha256=lCxpwROHZd0RG0dVp6AidQQRpFv6H8DvVzjrYHRDZFg,21515
3
- huace_aigc_auth_client/sdk.py,sha256=46kkNDmWcce4BkSAT9zn5n8XdURDns3YtXIIfe8TGDU,22453
4
- huace_aigc_auth_client-1.1.3.dist-info/licenses/LICENSE,sha256=z7dgC7KljhBLNvKjN15391nMj3aLt0gbud8-Yf1F8EQ,1063
5
- huace_aigc_auth_client-1.1.3.dist-info/METADATA,sha256=nATeZZKa_zxe1vVU5KF6jNiASCWPwbDS3yWqpv7FtzE,20084
6
- huace_aigc_auth_client-1.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
- huace_aigc_auth_client-1.1.3.dist-info/top_level.txt,sha256=kbv0nQ6PQ0JVneWPH7O2AbtlJnP7AjvFJ6JjM6ZEBxo,23
8
- huace_aigc_auth_client-1.1.3.dist-info/RECORD,,