huace-aigc-auth-client 1.1.20__py3-none-any.whl → 1.1.28__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.
@@ -172,4 +172,4 @@ __all__ = [
172
172
  # 用户上下文
173
173
  "get_current_user",
174
174
  ]
175
- __version__ = "1.1.20"
175
+ __version__ = "1.1.28"
@@ -16,9 +16,9 @@ class ApiStatsCollector:
16
16
  def __init__(
17
17
  self,
18
18
  api_url: str,
19
+ app_id: str,
19
20
  app_secret: str,
20
- token: str,
21
- batch_size: int = 10,
21
+ batch_size: int = 50,
22
22
  flush_interval: float = 5.0,
23
23
  enabled: bool = True
24
24
  ):
@@ -27,15 +27,15 @@ class ApiStatsCollector:
27
27
 
28
28
  Args:
29
29
  api_url: 统计接口 URL(如:http://auth.example.com/api/sdk/stats/report/batch)
30
+ app_id: 应用 ID
30
31
  app_secret: 应用密钥
31
- token: 用户访问令牌
32
32
  batch_size: 批量提交大小
33
33
  flush_interval: 刷新间隔(秒)
34
34
  enabled: 是否启用
35
35
  """
36
36
  self.api_url = api_url.rstrip('/')
37
+ self.app_id = app_id
37
38
  self.app_secret = app_secret
38
- self.token = token
39
39
  self.batch_size = batch_size
40
40
  self.flush_interval = flush_interval
41
41
  self.enabled = enabled
@@ -66,6 +66,7 @@ class ApiStatsCollector:
66
66
  api_method: str,
67
67
  status_code: int,
68
68
  response_time: float,
69
+ token: str,
69
70
  error_message: Optional[str] = None,
70
71
  request_params: Optional[Dict[str, Any]] = None
71
72
  ):
@@ -77,21 +78,26 @@ class ApiStatsCollector:
77
78
  api_method: 请求方法
78
79
  status_code: 状态码
79
80
  response_time: 响应时间(秒)
81
+ token: 用户访问令牌
80
82
  error_message: 错误信息
81
83
  request_params: 请求参数(包含 headers, query_params, view_params, request_body, form_params)
82
84
  """
83
85
  if not self.enabled:
84
86
  return
85
87
 
88
+ # 过滤重定向请求(3xx 状态码),这些通常是框架自动处理的,不应统计
89
+ if 300 <= status_code < 400:
90
+ return
91
+
86
92
  try:
87
93
  stat_data = {
88
94
  'api_path': api_path,
89
95
  'api_method': api_method,
90
96
  'status_code': status_code,
91
97
  'response_time': response_time,
98
+ 'token': token,
92
99
  'error_message': error_message,
93
- 'request_params': request_params,
94
- 'timestamp': datetime.utcnow().isoformat()
100
+ 'request_params': request_params
95
101
  }
96
102
  self.queue.put_nowait(stat_data)
97
103
  except queue.Full:
@@ -132,18 +138,50 @@ class ApiStatsCollector:
132
138
  self._flush_buffer(buffer)
133
139
 
134
140
  def _flush_buffer(self, buffer: List[Dict[str, Any]]):
135
- """刷新缓冲区:批量提交统计数据"""
141
+ """刷新缓冲区:按token分组批量提交统计数据"""
136
142
  if not buffer:
137
143
  return
138
144
 
145
+ try:
146
+ # 按token分组
147
+ token_groups: Dict[str, List[Dict[str, Any]]] = {}
148
+ for stat in buffer:
149
+ token = stat.get('token')
150
+ if not token:
151
+ continue
152
+
153
+ if token not in token_groups:
154
+ token_groups[token] = []
155
+
156
+ # 移除token字段后添加到分组
157
+ stat_copy = stat.copy()
158
+ stat_copy.pop('token', None)
159
+ token_groups[token].append(stat_copy)
160
+
161
+ # 对每个token分组分别提交
162
+ for token, stats in token_groups.items():
163
+ self._submit_stats(token, stats)
164
+
165
+ except Exception:
166
+ pass # 静默失败,不影响主流程
167
+
168
+ def _submit_stats(self, token: str, stats: List[Dict[str, Any]]):
169
+ """
170
+ 提交统计数据到服务端
171
+
172
+ Args:
173
+ token: 用户访问令牌
174
+ stats: 统计数据列表(已移除token字段)
175
+ """
139
176
  try:
140
177
  headers = {
178
+ 'X-App-Id': self.app_id,
141
179
  'X-App-Secret': self.app_secret,
142
- 'Authorization': f'Bearer {self.token}',
180
+ 'Authorization': f'Bearer {token}',
143
181
  'Content-Type': 'application/json'
144
182
  }
145
183
 
146
- payload = {'stats': buffer}
184
+ payload = {'stats': stats}
147
185
 
148
186
  response = requests.post(
149
187
  f'{self.api_url}/stats/report/batch',
@@ -167,8 +205,8 @@ _global_collector: Optional[ApiStatsCollector] = None
167
205
 
168
206
  def init_api_stats_collector(
169
207
  api_url: str,
208
+ app_id: str,
170
209
  app_secret: str,
171
- token: str,
172
210
  batch_size: int = 10,
173
211
  flush_interval: float = 5.0,
174
212
  enabled: bool = True
@@ -178,8 +216,8 @@ def init_api_stats_collector(
178
216
 
179
217
  Args:
180
218
  api_url: 统计接口 URL
219
+ app_id: 应用 ID
181
220
  app_secret: 应用密钥
182
- token: 用户访问令牌
183
221
  batch_size: 批量提交大小
184
222
  flush_interval: 刷新间隔(秒)
185
223
  enabled: 是否启用
@@ -190,8 +228,8 @@ def init_api_stats_collector(
190
228
  global _global_collector
191
229
  _global_collector = ApiStatsCollector(
192
230
  api_url=api_url,
231
+ app_id=app_id,
193
232
  app_secret=app_secret,
194
- token=token,
195
233
  batch_size=batch_size,
196
234
  flush_interval=flush_interval,
197
235
  enabled=enabled
@@ -217,6 +255,7 @@ def collect_api_stat(
217
255
  api_method: str,
218
256
  status_code: int,
219
257
  response_time: float,
258
+ token: str,
220
259
  error_message: Optional[str] = None,
221
260
  request_params: Optional[Dict[str, Any]] = None
222
261
  ):
@@ -224,7 +263,21 @@ def collect_api_stat(
224
263
  快捷方法:收集接口统计数据
225
264
 
226
265
  使用全局收集器实例
266
+ 注意:会自动过滤 3xx 重定向状态码的请求
267
+
268
+ Args:
269
+ api_path: 接口路径
270
+ api_method: 请求方法
271
+ status_code: 状态码
272
+ response_time: 响应时间(秒)
273
+ token: 用户访问令牌
274
+ error_message: 错误信息
275
+ request_params: 请求参数
227
276
  """
277
+ # 过滤重定向请求(3xx 状态码),这些通常是框架自动处理的,不应统计
278
+ if 300 <= status_code < 400:
279
+ return
280
+
228
281
  collector = get_api_stats_collector()
229
282
  if collector:
230
283
  collector.collect(
@@ -232,6 +285,7 @@ def collect_api_stat(
232
285
  api_method=api_method,
233
286
  status_code=status_code,
234
287
  response_time=response_time,
288
+ token=token,
235
289
  error_message=error_message,
236
290
  request_params=request_params
237
291
  )
@@ -570,23 +570,28 @@ class AuthMiddleware:
570
570
  self.exclude_paths = exclude_paths or []
571
571
  self.exclude_prefixes = exclude_prefixes or []
572
572
  self.enable_stats = enable_stats
573
- self.stats_collector = None
574
573
 
575
- # 如果启用统计,设置统计接口 URL(默认使用 client 的 base_url)
574
+ # 如果启用统计,初始化全局统计收集器
576
575
  if self.enable_stats:
577
576
  self.stats_api_url = stats_api_url or f"{self.client.base_url}/sdk"
577
+ self._init_global_stats_collector()
578
578
 
579
- def _init_stats_collector(self, token: str):
580
- """初始化统计收集器(延迟初始化)"""
581
- if not self.enable_stats or self.stats_collector is not None:
579
+ def _init_global_stats_collector(self):
580
+ """初始化全局统计收集器(只初始化一次)"""
581
+ if not self.enable_stats:
582
582
  return
583
583
 
584
584
  try:
585
- from .api_stats_collector import init_api_stats_collector
586
- self.stats_collector = init_api_stats_collector(
585
+ from .api_stats_collector import init_api_stats_collector, get_api_stats_collector
586
+
587
+ # 检查是否已经初始化
588
+ if get_api_stats_collector() is not None:
589
+ return
590
+
591
+ init_api_stats_collector(
587
592
  api_url=self.stats_api_url,
593
+ app_id=self.client.app_id,
588
594
  app_secret=self.client.app_secret,
589
- token=token,
590
595
  batch_size=10,
591
596
  flush_interval=5.0,
592
597
  enabled=True
@@ -614,21 +619,31 @@ class AuthMiddleware:
614
619
  "form_params": None
615
620
  }
616
621
 
617
- # 获取请求体(JSON 或文本)
622
+ # 获取 content-type
623
+ content_type = request.headers.get('Content-Type', '').lower()
624
+
625
+ # 获取请求体(使用白名单方式,只处理已知安全的内容类型)
618
626
  if request.is_json:
619
627
  try:
620
628
  params["request_body"] = request.get_json(silent=True)
621
629
  except Exception:
622
630
  pass
623
- elif request.data:
631
+ elif 'application/x-www-form-urlencoded' in content_type:
632
+ # 表单数据
633
+ if request.form:
634
+ params["form_params"] = request.form.to_dict(flat=False)
635
+ elif 'multipart/form-data' in content_type:
636
+ # 文件上传请求,不读取 request.data,避免损坏文件流
637
+ # 只收集表单字段(非文件字段)
638
+ if request.form:
639
+ params["form_params"] = request.form.to_dict(flat=False)
640
+ elif content_type.startswith('text/') and request.data and len(request.data) < 10240:
641
+ # 只读取文本类型的请求体,且限制大小避免内存问题
624
642
  try:
625
643
  params["request_body"] = request.data.decode('utf-8')
626
644
  except Exception:
627
- params["request_body"] = str(request.data)
628
-
629
- # 获取表单数据
630
- if request.form:
631
- params["form_params"] = request.form.to_dict(flat=False)
645
+ pass
646
+ # 其他类型(如 application/octet-stream 等二进制流)直接跳过,不读取
632
647
 
633
648
  return params
634
649
  except Exception as e:
@@ -655,28 +670,32 @@ class AuthMiddleware:
655
670
  "form_params": None
656
671
  }
657
672
 
658
- # 获取请求体
659
- content_type = request.headers.get("content-type", "")
673
+ # 获取请求体(使用白名单方式,只处理已知安全的内容类型)
674
+ content_type = request.headers.get("content-type", "").lower()
675
+ # 读取请求体(需要特殊处理以避免消耗流)
676
+ body = b""
677
+ if request.method in ["POST", "PUT", "PATCH"]:
678
+ try:
679
+ body = await request.body()
680
+ except:
681
+ pass
682
+ params["request_body"] = body.decode('utf-8', errors='ignore')
660
683
 
661
684
  if "application/json" in content_type:
662
685
  try:
663
686
  params["request_body"] = await request.json()
664
687
  except Exception:
665
688
  pass
666
- elif "application/x-www-form-urlencoded" in content_type or "multipart/form-data" in content_type:
689
+ elif "application/x-www-form-urlencoded" in content_type:
667
690
  try:
668
691
  form = await request.form()
669
692
  params["form_params"] = {k: v for k, v in form.items()}
670
693
  except Exception:
671
694
  pass
672
- else:
673
- # 尝试读取原始body
674
- try:
675
- body = await request.body()
676
- if body:
677
- params["request_body"] = body.decode('utf-8')
678
- except Exception:
679
- pass
695
+ elif "multipart/form-data" in content_type:
696
+ # 文件上传请求,不读取 body,避免损坏文件流
697
+ params["form_params"] = {"skipped_multipart": True}
698
+ # 其他类型(如 application/octet-stream 等二进制流)直接跳过,不读取
680
699
 
681
700
  return params
682
701
  except Exception as e:
@@ -689,22 +708,27 @@ class AuthMiddleware:
689
708
  api_method: str,
690
709
  status_code: int,
691
710
  response_time: float,
711
+ token: str,
692
712
  error_message: Optional[str] = None,
693
713
  request_params: Optional[Dict[str, Any]] = None
694
714
  ):
695
715
  """收集接口统计"""
696
- if not self.enable_stats or not self.stats_collector:
716
+ if not self.enable_stats:
697
717
  return
698
718
 
699
719
  try:
700
- self.stats_collector.collect(
701
- api_path=api_path,
702
- api_method=api_method,
703
- status_code=status_code,
704
- response_time=response_time,
705
- error_message=error_message,
706
- request_params=request_params
707
- )
720
+ from .api_stats_collector import get_api_stats_collector
721
+ collector = get_api_stats_collector()
722
+ if collector:
723
+ collector.collect(
724
+ api_path=api_path,
725
+ api_method=api_method,
726
+ status_code=status_code,
727
+ response_time=response_time,
728
+ token=token,
729
+ error_message=error_message,
730
+ request_params=request_params
731
+ )
708
732
  except Exception:
709
733
  pass # 静默失败
710
734
 
@@ -725,9 +749,83 @@ class AuthMiddleware:
725
749
  return None
726
750
  return authorization[7:]
727
751
 
752
+ def get_fastapi_middleware_class(self, user_info_callback: Callable = None):
753
+ """
754
+ 获取 FastAPI 中间件类(推荐使用,避免请求体读取问题)
755
+
756
+ 使用方法:
757
+ from starlette.middleware.base import BaseHTTPMiddleware
758
+ app.add_middleware(auth_middleware.get_fastapi_middleware_class())
759
+
760
+ Returns:
761
+ 继承于 BaseHTTPMiddleware 的中间件类
762
+ """
763
+ from fastapi.responses import JSONResponse
764
+ from starlette.middleware.base import BaseHTTPMiddleware
765
+
766
+ auth_middleware_instance = self
767
+
768
+ class AuthHTTPMiddleware(BaseHTTPMiddleware):
769
+ async def dispatch(self, request, call_next):
770
+ path = request.url.path
771
+ start_time = time.time()
772
+
773
+ # 收集请求参数
774
+ request_params = await auth_middleware_instance._collect_fastapi_request_params(request) if auth_middleware_instance.enable_stats else None
775
+
776
+ # 检查是否跳过
777
+ if auth_middleware_instance._should_skip(path):
778
+ return await call_next(request)
779
+
780
+ # 获取 Authorization header
781
+ authorization = request.headers.get("Authorization")
782
+ token = auth_middleware_instance._extract_token(authorization)
783
+
784
+ if not token:
785
+ logger.warning("AuthMiddleware未提供认证信息")
786
+ response_time = time.time() - start_time
787
+ auth_middleware_instance._collect_stats(path, request.method, 401, response_time, "", "未提供认证信息", request_params)
788
+ return JSONResponse(
789
+ status_code=401,
790
+ content={"code": 401, "message": "未提供认证信息", "data": None}
791
+ )
792
+
793
+ # 验证 token
794
+ try:
795
+ user_info = auth_middleware_instance.client.get_user_info(token)
796
+ # 将用户信息存储到 request.state
797
+ request.state.user_info = user_info
798
+ # 设置上下文
799
+ set_current_user(dataclasses.asdict(user_info))
800
+ if user_info_callback:
801
+ await user_info_callback(request, user_info)
802
+ except AigcAuthError as e:
803
+ logger.error(f"AuthMiddleware认证失败: {e.message}")
804
+ response_time = time.time() - start_time
805
+ auth_middleware_instance._collect_stats(path, request.method, 401, response_time, token, e.message, request_params)
806
+ return JSONResponse(
807
+ status_code=401,
808
+ content={"code": e.code, "message": e.message, "data": None}
809
+ )
810
+
811
+ # 处理请求
812
+ try:
813
+ response = await call_next(request)
814
+ response_time = time.time() - start_time
815
+ auth_middleware_instance._collect_stats(path, request.method, response.status_code, response_time, token, None, request_params)
816
+ return response
817
+ except Exception as e:
818
+ response_time = time.time() - start_time
819
+ auth_middleware_instance._collect_stats(path, request.method, 500, response_time, token, str(e), request_params)
820
+ raise
821
+ finally:
822
+ clear_current_user()
823
+
824
+ return AuthHTTPMiddleware
825
+
728
826
  async def fastapi_middleware(self, request, call_next, user_info_callback: Callable = None):
729
827
  """
730
- FastAPI 中间件
828
+ FastAPI 中间件(旧方法,推荐使用 get_fastapi_middleware_class)
731
829
 
732
830
  使用方法:
733
831
  @app.middleware("http")
@@ -735,12 +833,14 @@ class AuthMiddleware:
735
833
  return await auth_middleware.fastapi_middleware(request, call_next)
736
834
  """
737
835
  from fastapi.responses import JSONResponse
836
+
837
+ # 处理代理头部,确保重定向(如果有)使用正确的协议
838
+ forwarded_proto = request.headers.get("x-forwarded-proto")
839
+ if forwarded_proto:
840
+ request.scope["scheme"] = forwarded_proto
738
841
 
739
842
  path = request.url.path
740
843
  start_time = time.time()
741
-
742
- # 收集请求参数
743
- request_params = await self._collect_fastapi_request_params(request) if self.enable_stats else None
744
844
 
745
845
  # 检查是否跳过
746
846
  if self._should_skip(path):
@@ -753,7 +853,9 @@ class AuthMiddleware:
753
853
  if not token:
754
854
  logger.warning("AuthMiddleware未提供认证信息")
755
855
  response_time = time.time() - start_time
756
- self._collect_stats(path, request.method, 401, response_time, "未提供认证信息", request_params)
856
+ # 收集请求参数
857
+ request_params = await self._collect_fastapi_request_params(request) if self.enable_stats else None
858
+ self._collect_stats(path, request.method, 401, response_time, "", "未提供认证信息", request_params)
757
859
  return JSONResponse(
758
860
  status_code=401,
759
861
  content={"code": 401, "message": "未提供认证信息", "data": None}
@@ -762,24 +864,18 @@ class AuthMiddleware:
762
864
  # 验证 token
763
865
  try:
764
866
  user_info = self.client.get_user_info(token)
765
- # 初始化统计收集器(第一次有token时)
766
- if self.enable_stats and self.stats_collector is None:
767
- self._init_stats_collector(token)
768
867
  # 将用户信息存储到 request.state
769
868
  request.state.user_info = user_info
770
869
  # 设置上下文
771
870
  set_current_user(dataclasses.asdict(user_info))
772
-
773
- # 处理代理头部,确保重定向(如果有)使用正确的协议
774
- forwarded_proto = request.headers.get("x-forwarded-proto")
775
- if forwarded_proto:
776
- request.scope["scheme"] = forwarded_proto
777
871
  if user_info_callback:
778
872
  await user_info_callback(request, user_info)
779
873
  except AigcAuthError as e:
780
874
  logger.error(f"AuthMiddleware认证失败: {e.message}")
781
875
  response_time = time.time() - start_time
782
- self._collect_stats(path, request.method, 401, response_time, e.message, request_params)
876
+ # 收集请求参数
877
+ request_params = await self._collect_fastapi_request_params(request) if self.enable_stats else None
878
+ self._collect_stats(path, request.method, 401, response_time, token, e.message, request_params)
783
879
  return JSONResponse(
784
880
  status_code=401,
785
881
  content={"code": e.code, "message": e.message, "data": None}
@@ -789,11 +885,15 @@ class AuthMiddleware:
789
885
  try:
790
886
  response = await call_next(request)
791
887
  response_time = time.time() - start_time
792
- self._collect_stats(path, request.method, response.status_code, response_time, None, request_params)
888
+ # 收集请求参数
889
+ request_params = await self._collect_fastapi_request_params(request) if self.enable_stats else None
890
+ self._collect_stats(path, request.method, response.status_code, response_time, token, None, request_params)
793
891
  return response
794
892
  except Exception as e:
893
+ # 收集请求参数
894
+ request_params = await self._collect_fastapi_request_params(request) if self.enable_stats else None
795
895
  response_time = time.time() - start_time
796
- self._collect_stats(path, request.method, 500, response_time, str(e), request_params)
896
+ self._collect_stats(path, request.method, 500, response_time, token, str(e), request_params)
797
897
  raise
798
898
  finally:
799
899
  clear_current_user()
@@ -827,7 +927,7 @@ class AuthMiddleware:
827
927
  if not token:
828
928
  logger.warning("AuthMiddleware未提供认证信息")
829
929
  response_time = time.time() - g.start_time
830
- self._collect_stats(path, request.method, 401, response_time, "未提供认证信息", g.request_params)
930
+ self._collect_stats(path, request.method, 401, response_time, "", "未提供认证信息", g.request_params)
831
931
  return jsonify({
832
932
  "code": 401,
833
933
  "message": "未提供认证信息",
@@ -837,9 +937,6 @@ class AuthMiddleware:
837
937
  # 验证 token
838
938
  try:
839
939
  user_info = self.client.get_user_info(token)
840
- # 初始化统计收集器(第一次有token时)
841
- if self.enable_stats and self.stats_collector is None:
842
- self._init_stats_collector(token)
843
940
  # 将用户信息存储到 flask.g
844
941
  g.user_info = user_info
845
942
  # 设置上下文
@@ -849,7 +946,7 @@ class AuthMiddleware:
849
946
  except AigcAuthError as e:
850
947
  logger.error(f"AuthMiddleware认证失败: {e.message}")
851
948
  response_time = time.time() - g.start_time
852
- self._collect_stats(path, request.method, 401, response_time, e.message, g.request_params)
949
+ self._collect_stats(path, request.method, 401, response_time, token, e.message, g.request_params)
853
950
  return jsonify({
854
951
  "code": e.code,
855
952
  "message": e.message,
@@ -875,11 +972,15 @@ class AuthMiddleware:
875
972
  if hasattr(g, 'start_time'):
876
973
  response_time = time.time() - g.start_time
877
974
  request_params = getattr(g, 'request_params', None)
975
+ # 从 request 的 Authorization header 获取 token
976
+ authorization = request.headers.get("Authorization")
977
+ token = self._extract_token(authorization) or ""
878
978
  self._collect_stats(
879
979
  request.path,
880
980
  request.method,
881
981
  response.status_code,
882
982
  response_time,
983
+ token,
883
984
  None,
884
985
  request_params
885
986
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: huace-aigc-auth-client
3
- Version: 1.1.20
3
+ Version: 1.1.28
4
4
  Summary: 华策AIGC Auth Client - 提供 Token 验证、用户信息获取、权限检查、旧系统接入等功能
5
5
  Author-email: Huace <support@huace.com>
6
6
  License: MIT
@@ -0,0 +1,12 @@
1
+ huace_aigc_auth_client/__init__.py,sha256=nCpT58WU83NkEpdyMiq35t4Zd261cdp45N_07NRoisY,4630
2
+ huace_aigc_auth_client/api_stats_collector.py,sha256=UCUu2CHWsJyiAM58-XLQtfxWK0fjZ8TTdw90gv_Gx04,10347
3
+ huace_aigc_auth_client/legacy_adapter.py,sha256=TVCBAKejE2z2HQFsEwDW8LMiaIkXNfz3Mxv6_E-UJFY,24102
4
+ huace_aigc_auth_client/sdk.py,sha256=49UrQnS96a_m-FM9KVSqmE8x4J-R4qpYsE4KgzasvFE,36742
5
+ huace_aigc_auth_client/user_context.py,sha256=KzevYLsLv1hv8rlvRw83FT-HugeoBJSJ1Pi56iLWyTE,5592
6
+ huace_aigc_auth_client/webhook.py,sha256=XQZYEbMoqIdqZWCGSTcedeDKJpDbUVSq5g08g-6Qucg,4124
7
+ huace_aigc_auth_client/webhook_flask.py,sha256=Iosu4dBtRhQZM_ytn-bn82MpVsyOiV28FBnt7Tfh31U,7225
8
+ huace_aigc_auth_client-1.1.28.dist-info/licenses/LICENSE,sha256=z7dgC7KljhBLNvKjN15391nMj3aLt0gbud8-Yf1F8EQ,1063
9
+ huace_aigc_auth_client-1.1.28.dist-info/METADATA,sha256=9TkNkzidAbMP7nb2drl1FfSOAumh6ngs7ueiik40mnE,23629
10
+ huace_aigc_auth_client-1.1.28.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
11
+ huace_aigc_auth_client-1.1.28.dist-info/top_level.txt,sha256=kbv0nQ6PQ0JVneWPH7O2AbtlJnP7AjvFJ6JjM6ZEBxo,23
12
+ huace_aigc_auth_client-1.1.28.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- huace_aigc_auth_client/__init__.py,sha256=e-Y0M75DKW4t-hhipxgH_UDhoVSdH1uKFmJKyacyRJo,4630
2
- huace_aigc_auth_client/api_stats_collector.py,sha256=VL_z-3WUWhEkAKDhGnKX0H-nNUn3x2IO_1FASsFA-Ss,8511
3
- huace_aigc_auth_client/legacy_adapter.py,sha256=TVCBAKejE2z2HQFsEwDW8LMiaIkXNfz3Mxv6_E-UJFY,24102
4
- huace_aigc_auth_client/sdk.py,sha256=0E0EmfLVxpOI5rOiVdAGcFzajdNZnDgjwrmOX7aYzGc,31303
5
- huace_aigc_auth_client/user_context.py,sha256=KzevYLsLv1hv8rlvRw83FT-HugeoBJSJ1Pi56iLWyTE,5592
6
- huace_aigc_auth_client/webhook.py,sha256=XQZYEbMoqIdqZWCGSTcedeDKJpDbUVSq5g08g-6Qucg,4124
7
- huace_aigc_auth_client/webhook_flask.py,sha256=Iosu4dBtRhQZM_ytn-bn82MpVsyOiV28FBnt7Tfh31U,7225
8
- huace_aigc_auth_client-1.1.20.dist-info/licenses/LICENSE,sha256=z7dgC7KljhBLNvKjN15391nMj3aLt0gbud8-Yf1F8EQ,1063
9
- huace_aigc_auth_client-1.1.20.dist-info/METADATA,sha256=NkVUBXJLpANzcTh_VpBm2Lm1UquzxgjCK_2l-Xj6Kfo,23629
10
- huace_aigc_auth_client-1.1.20.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
11
- huace_aigc_auth_client-1.1.20.dist-info/top_level.txt,sha256=kbv0nQ6PQ0JVneWPH7O2AbtlJnP7AjvFJ6JjM6ZEBxo,23
12
- huace_aigc_auth_client-1.1.20.dist-info/RECORD,,