pixelarraythirdparty 1.2.1__tar.gz → 1.2.3__tar.gz

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.
Files changed (26) hide show
  1. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/PKG-INFO +1 -1
  2. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/__init__.py +1 -1
  3. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/unified_login/unified_login.py +230 -66
  4. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty.egg-info/PKG-INFO +1 -1
  5. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pyproject.toml +1 -1
  6. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/LICENSE +0 -0
  7. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/MANIFEST.in +0 -0
  8. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/client.py +0 -0
  9. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/cron/__init__.py +0 -0
  10. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/cron/cron.py +0 -0
  11. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/feedback/__init__.py +0 -0
  12. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/feedback/feedback.py +0 -0
  13. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/order/__init__.py +0 -0
  14. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/order/order.py +0 -0
  15. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/product/__init__.py +0 -0
  16. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/product/product.py +0 -0
  17. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/project/__init__.py +0 -0
  18. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/project/project.py +0 -0
  19. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/unified_login/__init__.py +0 -0
  20. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/user/__init__.py +0 -0
  21. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty/user/user.py +0 -0
  22. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty.egg-info/SOURCES.txt +0 -0
  23. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty.egg-info/dependency_links.txt +0 -0
  24. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty.egg-info/requires.txt +0 -0
  25. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/pixelarraythirdparty.egg-info/top_level.txt +0 -0
  26. {pixelarraythirdparty-1.2.1 → pixelarraythirdparty-1.2.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pixelarraythirdparty
3
- Version: 1.2.1
3
+ Version: 1.2.3
4
4
  Summary: PixelArray 第三方微服务客户端
5
5
  Author-email: Lu qi <qi.lu@pixelarrayai.com>
6
6
  License-Expression: MIT
@@ -13,7 +13,7 @@ PixelArray 第三方微服务客户端
13
13
  - project: 项目管理模块
14
14
  """
15
15
 
16
- __version__ = "1.2.1"
16
+ __version__ = "1.2.3"
17
17
  __author__ = "Lu qi"
18
18
  __email__ = "qi.lu@pixelarrayai.com"
19
19
 
@@ -15,7 +15,21 @@ class OAuth2Login(AsyncClient):
15
15
 
16
16
  使用示例:
17
17
  ```
18
- # Google登录
18
+ # 服务端使用场景(推荐)
19
+ google = OAuth2Login(
20
+ api_key="your_api_key",
21
+ provider="google"
22
+ )
23
+ # 1. 获取授权URL
24
+ auth_data, success = await google.get_auth_url()
25
+ if success:
26
+ auth_url = auth_data.get("auth_url")
27
+ state = auth_data.get("state")
28
+ # 将auth_url返回给前端,让用户点击授权
29
+ # 2. 等待登录结果(在服务端轮询)
30
+ user_info, success = await google.wait_for_login(state, timeout=180)
31
+
32
+ # 测试场景(仅用于本地测试,会打开浏览器)
19
33
  google = OAuth2Login(
20
34
  api_key="your_api_key",
21
35
  provider="google"
@@ -123,10 +137,13 @@ class OAuth2Login(AsyncClient):
123
137
  )
124
138
  return endpoint
125
139
 
126
- async def _get_auth_url(self) -> Tuple[Optional[Dict[str, str]], bool]:
140
+ async def get_auth_url(self) -> Tuple[Optional[Dict[str, str]], bool]:
127
141
  """
128
142
  description:
129
- 获取OAuth授权URL
143
+ 获取OAuth授权URL(公共方法,供服务端调用)
144
+
145
+ 服务端应该调用此方法获取授权URL,然后将URL返回给前端让用户点击授权。
146
+ 获取到state后,使用wait_for_login方法等待登录结果。
130
147
  return:
131
148
  auth_data(dict, optional): 授权数据字典,包含auth_url和state
132
149
  success(bool): 是否成功
@@ -161,15 +178,18 @@ class OAuth2Login(AsyncClient):
161
178
  return None
162
179
  return None
163
180
 
164
- async def _wait_for_login(
165
- self, state: str, timeout: int
181
+ async def wait_for_login(
182
+ self, state: str, timeout: int = 180
166
183
  ) -> Tuple[Dict, bool]:
167
184
  """
168
185
  description:
169
- 等待登录结果,轮询检查登录状态
186
+ 等待登录结果,轮询检查登录状态(公共方法,供服务端调用)
187
+
188
+ 服务端在用户点击授权后,调用此方法轮询等待登录结果。
189
+ 此方法会持续轮询直到登录成功或超时。
170
190
  parameters:
171
- state(str): 登录状态标识
172
- timeout(int): 超时时间(秒)
191
+ state(str): 登录状态标识,从get_auth_url返回的auth_data中获取
192
+ timeout(int, optional): 超时时间(秒),默认为180
173
193
  return:
174
194
  user_info(dict): 用户信息字典
175
195
  success(bool): 是否成功
@@ -199,13 +219,16 @@ class OAuth2Login(AsyncClient):
199
219
  """
200
220
  description:
201
221
  仿 Supabase CLI 的一键登录流程:打开浏览器完成授权,终端端轮询等待登录结果
222
+
223
+ 注意:此方法仅用于本地测试场景,会自动打开浏览器。
224
+ 在生产环境的服务端场景中,应该使用get_auth_url和wait_for_login方法。
202
225
  parameters:
203
226
  timeout(int, optional): 等待用户完成授权的超时时间(秒),默认为180
204
227
  return:
205
228
  user_info(dict): 用户信息字典
206
229
  success(bool): 是否成功
207
230
  """
208
- auth_data, success = await self._get_auth_url()
231
+ auth_data, success = await self.get_auth_url()
209
232
  if not success or not auth_data:
210
233
  return {}, False
211
234
 
@@ -217,12 +240,16 @@ class OAuth2Login(AsyncClient):
217
240
 
218
241
  webbrowser.open(auth_url, new=2)
219
242
 
220
- return await self._wait_for_login(state, timeout)
243
+ return await self.wait_for_login(state, timeout)
221
244
 
222
245
  async def refresh_access_token(self, refresh_token: str) -> Tuple[Dict, bool]:
223
246
  """
224
247
  description:
225
248
  使用refresh_token刷新access_token(仅支持Google和GitLab)
249
+
250
+ 注意:GitLab 采用 token rotation(令牌轮换)机制,每次刷新时会返回新的 refresh_token,
251
+ 旧的 refresh_token 会立即失效。必须保存新的 refresh_token 并替换旧的。
252
+ Google 也可能在某些情况下返回新的 refresh_token。
226
253
  parameters:
227
254
  refresh_token(str): OAuth refresh_token
228
255
  return:
@@ -250,27 +277,42 @@ class GoogleLogin(AsyncClient):
250
277
 
251
278
  使用示例:
252
279
  ```
280
+ # 服务端使用场景(推荐)
253
281
  google = GoogleLogin(api_key="your_api_key")
254
- user_info, success = await google.login()
282
+ # 1. 获取授权URL
283
+ auth_data, success = await google.get_auth_url()
255
284
  if success:
256
- access_token = user_info.get("access_token")
257
- refresh_token = user_info.get("refresh_token")
258
-
259
- # 使用refresh_token刷新access_token
260
- if refresh_token:
261
- token_data, success = await google.refresh_access_token(refresh_token)
262
- if success:
263
- new_access_token = token_data.get("access_token")
285
+ auth_url = auth_data.get("auth_url")
286
+ state = auth_data.get("state")
287
+ # 将auth_url返回给前端,让用户点击授权
288
+ # 2. 等待登录结果(在服务端轮询)
289
+ user_info, success = await google.wait_for_login(state, timeout=180)
290
+ if success:
291
+ access_token = user_info.get("access_token")
292
+ refresh_token = user_info.get("refresh_token")
293
+
294
+ # 使用refresh_token刷新access_token
295
+ if refresh_token:
296
+ token_data, success = await google.refresh_access_token(refresh_token)
297
+ if success:
298
+ new_access_token = token_data.get("access_token")
299
+
300
+ # 测试场景(仅用于本地测试,会打开浏览器)
301
+ google = GoogleLogin(api_key="your_api_key")
302
+ user_info, success = await google.login()
264
303
  ```
265
304
  """
266
305
 
267
306
  def __init__(self, api_key: str):
268
307
  super().__init__(api_key)
269
308
 
270
- async def _get_auth_url(self) -> Tuple[Optional[Dict[str, str]], bool]:
309
+ async def get_auth_url(self) -> Tuple[Optional[Dict[str, str]], bool]:
271
310
  """
272
311
  description:
273
- 获取Google OAuth授权URL
312
+ 获取Google OAuth授权URL(公共方法,供服务端调用)
313
+
314
+ 服务端应该调用此方法获取授权URL,然后将URL返回给前端让用户点击授权。
315
+ 获取到state后,使用wait_for_login方法等待登录结果。
274
316
  return:
275
317
  auth_data(dict, optional): 授权数据字典,包含auth_url和state
276
318
  success(bool): 是否成功
@@ -289,13 +331,16 @@ class GoogleLogin(AsyncClient):
289
331
  """
290
332
  description:
291
333
  仿 Supabase CLI 的一键登录流程:打开浏览器完成授权,终端端轮询等待登录结果
334
+
335
+ 注意:此方法仅用于本地测试场景,会自动打开浏览器。
336
+ 在生产环境的服务端场景中,应该使用get_auth_url和wait_for_login方法。
292
337
  parameters:
293
338
  timeout(int, optional): 等待用户完成授权的超时时间(秒),默认为180
294
339
  return:
295
340
  user_info(dict): 用户信息字典
296
341
  success(bool): 是否成功
297
342
  """
298
- auth_data, success = await self._get_auth_url()
343
+ auth_data, success = await self.get_auth_url()
299
344
  if not success or not auth_data:
300
345
  return {}, False
301
346
 
@@ -307,7 +352,7 @@ class GoogleLogin(AsyncClient):
307
352
 
308
353
  webbrowser.open(auth_url, new=2)
309
354
 
310
- return await self._wait_for_google_login(state, timeout)
355
+ return await self.wait_for_login(state, timeout)
311
356
 
312
357
  def _extract_state(self, auth_url: Optional[str]) -> Optional[str]:
313
358
  if not auth_url:
@@ -322,15 +367,18 @@ class GoogleLogin(AsyncClient):
322
367
  return None
323
368
  return None
324
369
 
325
- async def _wait_for_google_login(
326
- self, state: str, timeout: int
370
+ async def wait_for_login(
371
+ self, state: str, timeout: int = 180
327
372
  ) -> Tuple[Dict, bool]:
328
373
  """
329
374
  description:
330
- 等待Google登录结果,轮询检查登录状态
375
+ 等待Google登录结果,轮询检查登录状态(公共方法,供服务端调用)
376
+
377
+ 服务端在用户点击授权后,调用此方法轮询等待登录结果。
378
+ 此方法会持续轮询直到登录成功或超时。
331
379
  parameters:
332
- state(str): 登录状态标识
333
- timeout(int): 超时时间(秒)
380
+ state(str): 登录状态标识,从get_auth_url返回的auth_data中获取
381
+ timeout(int, optional): 超时时间(秒),默认为180
334
382
  return:
335
383
  user_info(dict): 用户信息字典
336
384
  success(bool): 是否成功
@@ -385,21 +433,42 @@ class WechatLogin(AsyncClient):
385
433
 
386
434
  使用示例:
387
435
  ```
436
+ # 服务端使用场景(推荐)
388
437
  wechat = WechatLogin(api_key="your_api_key")
389
438
  # PC端扫码登录
390
- user_info, success = await wechat.login(login_type="desktop")
439
+ auth_data, success = await wechat.get_auth_url(login_type="desktop")
440
+ if success:
441
+ auth_url = auth_data.get("auth_url")
442
+ state = auth_data.get("state")
443
+ # 将auth_url返回给前端,让用户扫码授权
444
+ # 等待登录结果
445
+ user_info, success = await wechat.wait_for_login(state, timeout=180, login_type="desktop")
446
+
391
447
  # 微信公众号登录(手机端)
392
- user_info, success = await wechat.login(login_type="mobile")
448
+ auth_data, success = await wechat.get_auth_url(login_type="mobile")
449
+ if success:
450
+ auth_url = auth_data.get("auth_url")
451
+ state = auth_data.get("state")
452
+ # 将auth_url返回给前端,让用户在微信内打开授权
453
+ # 等待登录结果
454
+ user_info, success = await wechat.wait_for_login(state, timeout=180, login_type="mobile")
455
+
456
+ # 测试场景(仅用于本地测试,会打开浏览器)
457
+ wechat = WechatLogin(api_key="your_api_key")
458
+ user_info, success = await wechat.login(login_type="desktop")
393
459
  ```
394
460
  """
395
461
 
396
462
  def __init__(self, api_key: str):
397
463
  super().__init__(api_key)
398
464
 
399
- async def _get_auth_url(self, login_type: str = "desktop") -> Tuple[Optional[Dict[str, str]], bool]:
465
+ async def get_auth_url(self, login_type: str = "desktop") -> Tuple[Optional[Dict[str, str]], bool]:
400
466
  """
401
467
  description:
402
- 获取微信授权URL
468
+ 获取微信授权URL(公共方法,供服务端调用)
469
+
470
+ 服务端应该调用此方法获取授权URL,然后将URL返回给前端让用户点击授权。
471
+ 获取到state后,使用wait_for_login方法等待登录结果。
403
472
  parameters:
404
473
  login_type(str, optional): 登录类型,desktop表示PC端扫码登录,mobile表示微信公众号登录,默认为desktop
405
474
  return:
@@ -425,6 +494,9 @@ class WechatLogin(AsyncClient):
425
494
  """
426
495
  description:
427
496
  仿 Supabase CLI 的一键登录流程:打开浏览器完成授权,终端端轮询等待登录结果
497
+
498
+ 注意:此方法仅用于本地测试场景,会自动打开浏览器。
499
+ 在生产环境的服务端场景中,应该使用get_auth_url和wait_for_login方法。
428
500
  parameters:
429
501
  login_type(str, optional): 登录类型,desktop表示PC端扫码登录,mobile表示微信公众号登录,默认为desktop
430
502
  timeout(int, optional): 等待用户完成授权的超时时间(秒),默认为180
@@ -432,7 +504,7 @@ class WechatLogin(AsyncClient):
432
504
  user_info(dict): 用户信息字典
433
505
  success(bool): 是否成功
434
506
  """
435
- auth_data, success = await self._get_auth_url(login_type)
507
+ auth_data, success = await self.get_auth_url(login_type)
436
508
  if not success or not auth_data:
437
509
  return {}, False
438
510
 
@@ -444,7 +516,7 @@ class WechatLogin(AsyncClient):
444
516
 
445
517
  webbrowser.open(auth_url, new=2)
446
518
 
447
- return await self._wait_for_wechat_login(state, timeout, login_type)
519
+ return await self.wait_for_login(state, timeout, login_type)
448
520
 
449
521
  def _extract_state(self, auth_url: Optional[str]) -> Optional[str]:
450
522
  """
@@ -467,15 +539,18 @@ class WechatLogin(AsyncClient):
467
539
  return None
468
540
  return None
469
541
 
470
- async def _wait_for_wechat_login(
471
- self, state: str, timeout: int, login_type: str = "desktop"
542
+ async def wait_for_login(
543
+ self, state: str, timeout: int = 180, login_type: str = "desktop"
472
544
  ) -> Tuple[Dict, bool]:
473
545
  """
474
546
  description:
475
- 等待微信登录结果,轮询检查登录状态
547
+ 等待微信登录结果,轮询检查登录状态(公共方法,供服务端调用)
548
+
549
+ 服务端在用户点击授权后,调用此方法轮询等待登录结果。
550
+ 此方法会持续轮询直到登录成功或超时。
476
551
  parameters:
477
- state(str): 登录状态标识
478
- timeout(int): 超时时间(秒)
552
+ state(str): 登录状态标识,从get_auth_url返回的auth_data中获取
553
+ timeout(int, optional): 超时时间(秒),默认为180
479
554
  login_type(str, optional): 登录类型,desktop表示PC端扫码登录,mobile表示微信公众号登录,默认为desktop
480
555
  return:
481
556
  user_info(dict): 用户信息字典
@@ -514,6 +589,18 @@ class GitHubLogin(AsyncClient):
514
589
 
515
590
  使用示例:
516
591
  ```
592
+ # 服务端使用场景(推荐)
593
+ github = GitHubLogin(api_key="your_api_key")
594
+ # 1. 获取授权URL
595
+ auth_data, success = await github.get_auth_url()
596
+ if success:
597
+ auth_url = auth_data.get("auth_url")
598
+ state = auth_data.get("state")
599
+ # 将auth_url返回给前端,让用户点击授权
600
+ # 2. 等待登录结果(在服务端轮询)
601
+ user_info, success = await github.wait_for_login(state, timeout=180)
602
+
603
+ # 测试场景(仅用于本地测试,会打开浏览器)
517
604
  github = GitHubLogin(api_key="your_api_key")
518
605
  user_info, success = await github.login()
519
606
  ```
@@ -522,10 +609,13 @@ class GitHubLogin(AsyncClient):
522
609
  def __init__(self, api_key: str):
523
610
  super().__init__(api_key)
524
611
 
525
- async def _get_auth_url(self) -> Tuple[Optional[Dict[str, str]], bool]:
612
+ async def get_auth_url(self) -> Tuple[Optional[Dict[str, str]], bool]:
526
613
  """
527
614
  description:
528
- 获取GitHub OAuth授权URL
615
+ 获取GitHub OAuth授权URL(公共方法,供服务端调用)
616
+
617
+ 服务端应该调用此方法获取授权URL,然后将URL返回给前端让用户点击授权。
618
+ 获取到state后,使用wait_for_login方法等待登录结果。
529
619
  return:
530
620
  auth_data(dict, optional): 授权数据字典,包含auth_url和state
531
621
  success(bool): 是否成功
@@ -544,13 +634,16 @@ class GitHubLogin(AsyncClient):
544
634
  """
545
635
  description:
546
636
  仿 Supabase CLI 的一键登录流程:打开浏览器完成授权,终端端轮询等待登录结果
637
+
638
+ 注意:此方法仅用于本地测试场景,会自动打开浏览器。
639
+ 在生产环境的服务端场景中,应该使用get_auth_url和wait_for_login方法。
547
640
  parameters:
548
641
  timeout(int, optional): 等待用户完成授权的超时时间(秒),默认为180
549
642
  return:
550
643
  user_info(dict): 用户信息字典
551
644
  success(bool): 是否成功
552
645
  """
553
- auth_data, success = await self._get_auth_url()
646
+ auth_data, success = await self.get_auth_url()
554
647
  if not success or not auth_data:
555
648
  return {}, False
556
649
 
@@ -562,7 +655,7 @@ class GitHubLogin(AsyncClient):
562
655
 
563
656
  webbrowser.open(auth_url, new=2)
564
657
 
565
- return await self._wait_for_github_login(state, timeout)
658
+ return await self.wait_for_login(state, timeout)
566
659
 
567
660
  def _extract_state(self, auth_url: Optional[str]) -> Optional[str]:
568
661
  """
@@ -585,15 +678,18 @@ class GitHubLogin(AsyncClient):
585
678
  return None
586
679
  return None
587
680
 
588
- async def _wait_for_github_login(
589
- self, state: str, timeout: int
681
+ async def wait_for_login(
682
+ self, state: str, timeout: int = 180
590
683
  ) -> Tuple[Dict, bool]:
591
684
  """
592
685
  description:
593
- 等待GitHub登录结果,轮询检查登录状态
686
+ 等待GitHub登录结果,轮询检查登录状态(公共方法,供服务端调用)
687
+
688
+ 服务端在用户点击授权后,调用此方法轮询等待登录结果。
689
+ 此方法会持续轮询直到登录成功或超时。
594
690
  parameters:
595
- state(str): 登录状态标识
596
- timeout(int): 超时时间(秒)
691
+ state(str): 登录状态标识,从get_auth_url返回的auth_data中获取
692
+ timeout(int, optional): 超时时间(秒),默认为180
597
693
  return:
598
694
  user_info(dict): 用户信息字典
599
695
  success(bool): 是否成功
@@ -625,6 +721,18 @@ class DouyinLogin(AsyncClient):
625
721
 
626
722
  使用示例:
627
723
  ```
724
+ # 服务端使用场景(推荐)
725
+ douyin = DouyinLogin(api_key="your_api_key")
726
+ # 1. 获取授权URL
727
+ auth_data, success = await douyin.get_auth_url()
728
+ if success:
729
+ auth_url = auth_data.get("auth_url")
730
+ state = auth_data.get("state")
731
+ # 将auth_url返回给前端,让用户点击授权
732
+ # 2. 等待登录结果(在服务端轮询)
733
+ user_info, success = await douyin.wait_for_login(state, timeout=180)
734
+
735
+ # 测试场景(仅用于本地测试,会打开浏览器)
628
736
  douyin = DouyinLogin(api_key="your_api_key")
629
737
  user_info, success = await douyin.login()
630
738
  ```
@@ -633,10 +741,13 @@ class DouyinLogin(AsyncClient):
633
741
  def __init__(self, api_key: str):
634
742
  super().__init__(api_key)
635
743
 
636
- async def _get_auth_url(self) -> Tuple[Optional[Dict[str, str]], bool]:
744
+ async def get_auth_url(self) -> Tuple[Optional[Dict[str, str]], bool]:
637
745
  """
638
746
  description:
639
- 获取抖音OAuth授权URL
747
+ 获取抖音OAuth授权URL(公共方法,供服务端调用)
748
+
749
+ 服务端应该调用此方法获取授权URL,然后将URL返回给前端让用户点击授权。
750
+ 获取到state后,使用wait_for_login方法等待登录结果。
640
751
  return:
641
752
  auth_data(dict, optional): 授权数据字典,包含auth_url和state
642
753
  success(bool): 是否成功
@@ -655,13 +766,16 @@ class DouyinLogin(AsyncClient):
655
766
  """
656
767
  description:
657
768
  仿 Supabase CLI 的一键登录流程:打开浏览器完成授权,终端端轮询等待登录结果
769
+
770
+ 注意:此方法仅用于本地测试场景,会自动打开浏览器。
771
+ 在生产环境的服务端场景中,应该使用get_auth_url和wait_for_login方法。
658
772
  parameters:
659
773
  timeout(int, optional): 等待用户完成授权的超时时间(秒),默认为180
660
774
  return:
661
775
  user_info(dict): 用户信息字典
662
776
  success(bool): 是否成功
663
777
  """
664
- auth_data, success = await self._get_auth_url()
778
+ auth_data, success = await self.get_auth_url()
665
779
  if not success or not auth_data:
666
780
  return {}, False
667
781
 
@@ -673,7 +787,7 @@ class DouyinLogin(AsyncClient):
673
787
 
674
788
  webbrowser.open(auth_url, new=2)
675
789
 
676
- return await self._wait_for_douyin_login(state, timeout)
790
+ return await self.wait_for_login(state, timeout)
677
791
 
678
792
  def _extract_state(self, auth_url: Optional[str]) -> Optional[str]:
679
793
  """
@@ -696,15 +810,18 @@ class DouyinLogin(AsyncClient):
696
810
  return None
697
811
  return None
698
812
 
699
- async def _wait_for_douyin_login(
700
- self, state: str, timeout: int
813
+ async def wait_for_login(
814
+ self, state: str, timeout: int = 180
701
815
  ) -> Tuple[Dict, bool]:
702
816
  """
703
817
  description:
704
- 等待抖音登录结果,轮询检查登录状态
818
+ 等待抖音登录结果,轮询检查登录状态(公共方法,供服务端调用)
819
+
820
+ 服务端在用户点击授权后,调用此方法轮询等待登录结果。
821
+ 此方法会持续轮询直到登录成功或超时。
705
822
  parameters:
706
- state(str): 登录状态标识
707
- timeout(int): 超时时间(秒)
823
+ state(str): 登录状态标识,从get_auth_url返回的auth_data中获取
824
+ timeout(int, optional): 超时时间(秒),默认为180
708
825
  return:
709
826
  user_info(dict): 用户信息字典
710
827
  success(bool): 是否成功
@@ -736,6 +853,21 @@ class GitLabLogin(AsyncClient):
736
853
 
737
854
  使用示例:
738
855
  ```
856
+ # 服务端使用场景(推荐)
857
+ gitlab = GitLabLogin(api_key="your_api_key")
858
+ # 1. 获取授权URL
859
+ auth_data, success = await gitlab.get_auth_url()
860
+ if success:
861
+ auth_url = auth_data.get("auth_url")
862
+ state = auth_data.get("state")
863
+ # 将auth_url返回给前端,让用户点击授权
864
+ # 2. 等待登录结果(在服务端轮询)
865
+ user_info, success = await gitlab.wait_for_login(state, timeout=180)
866
+ if success and user_info.get("refresh_token"):
867
+ # 使用refresh_token刷新access_token
868
+ token_data, success = await gitlab.refresh_access_token(user_info.get("refresh_token"))
869
+
870
+ # 测试场景(仅用于本地测试,会打开浏览器)
739
871
  gitlab = GitLabLogin(api_key="your_api_key")
740
872
  user_info, success = await gitlab.login()
741
873
  ```
@@ -744,7 +876,17 @@ class GitLabLogin(AsyncClient):
744
876
  def __init__(self, api_key: str):
745
877
  super().__init__(api_key)
746
878
 
747
- async def _get_auth_url(self) -> Tuple[Optional[Dict[str, str]], bool]:
879
+ async def get_auth_url(self) -> Tuple[Optional[Dict[str, str]], bool]:
880
+ """
881
+ description:
882
+ 获取GitLab OAuth授权URL(公共方法,供服务端调用)
883
+
884
+ 服务端应该调用此方法获取授权URL,然后将URL返回给前端让用户点击授权。
885
+ 获取到state后,使用wait_for_login方法等待登录结果。
886
+ return:
887
+ auth_data(dict, optional): 授权数据字典,包含auth_url和state
888
+ success(bool): 是否成功
889
+ """
748
890
  data, success = await self._request(
749
891
  "POST", "/api/unified-login/gitlab/auth-url"
750
892
  )
@@ -757,12 +899,18 @@ class GitLabLogin(AsyncClient):
757
899
 
758
900
  async def login(self, timeout: int = 180) -> Tuple[Dict, bool]:
759
901
  """
760
- 仿 Supabase CLI 的一键登录流程:打开浏览器完成授权,
761
- 终端端轮询等待登录结果
762
-
763
- :param timeout: 等待用户完成授权的超时时间(秒)
902
+ description:
903
+ 仿 Supabase CLI 的一键登录流程:打开浏览器完成授权,终端端轮询等待登录结果
904
+
905
+ 注意:此方法仅用于本地测试场景,会自动打开浏览器。
906
+ 在生产环境的服务端场景中,应该使用get_auth_url和wait_for_login方法。
907
+ parameters:
908
+ timeout(int, optional): 等待用户完成授权的超时时间(秒),默认为180
909
+ return:
910
+ user_info(dict): 用户信息字典
911
+ success(bool): 是否成功
764
912
  """
765
- auth_data, success = await self._get_auth_url()
913
+ auth_data, success = await self.get_auth_url()
766
914
  if not success or not auth_data:
767
915
  return {}, False
768
916
 
@@ -774,7 +922,7 @@ class GitLabLogin(AsyncClient):
774
922
 
775
923
  webbrowser.open(auth_url, new=2)
776
924
 
777
- return await self._wait_for_gitlab_login(state, timeout)
925
+ return await self.wait_for_login(state, timeout)
778
926
 
779
927
  def _extract_state(self, auth_url: Optional[str]) -> Optional[str]:
780
928
  if not auth_url:
@@ -789,9 +937,22 @@ class GitLabLogin(AsyncClient):
789
937
  return None
790
938
  return None
791
939
 
792
- async def _wait_for_gitlab_login(
793
- self, state: str, timeout: int
940
+ async def wait_for_login(
941
+ self, state: str, timeout: int = 180
794
942
  ) -> Tuple[Dict, bool]:
943
+ """
944
+ description:
945
+ 等待GitLab登录结果,轮询检查登录状态(公共方法,供服务端调用)
946
+
947
+ 服务端在用户点击授权后,调用此方法轮询等待登录结果。
948
+ 此方法会持续轮询直到登录成功或超时。
949
+ parameters:
950
+ state(str): 登录状态标识,从get_auth_url返回的auth_data中获取
951
+ timeout(int, optional): 超时时间(秒),默认为180
952
+ return:
953
+ user_info(dict): 用户信息字典
954
+ success(bool): 是否成功
955
+ """
795
956
  interval = 2
796
957
  total_checks = max(1, timeout // interval) if timeout > 0 else 1
797
958
 
@@ -816,6 +977,9 @@ class GitLabLogin(AsyncClient):
816
977
  """
817
978
  description:
818
979
  使用refresh_token刷新access_token
980
+
981
+ 注意:GitLab 采用 token rotation(令牌轮换)机制,每次刷新时会返回新的 refresh_token,
982
+ 旧的 refresh_token 会立即失效。必须保存新的 refresh_token 并替换旧的。
819
983
  parameters:
820
984
  refresh_token(str): GitLab OAuth refresh_token
821
985
  return:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pixelarraythirdparty
3
- Version: 1.2.1
3
+ Version: 1.2.3
4
4
  Summary: PixelArray 第三方微服务客户端
5
5
  Author-email: Lu qi <qi.lu@pixelarrayai.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pixelarraythirdparty"
7
- version = "1.2.1"
7
+ version = "1.2.3"
8
8
  authors = [
9
9
  {name = "Lu qi", email = "qi.lu@pixelarrayai.com"},
10
10
  ]