pixelarraythirdparty 1.2.1__py3-none-any.whl → 1.2.3__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.
- pixelarraythirdparty/__init__.py +1 -1
- pixelarraythirdparty/unified_login/unified_login.py +230 -66
- {pixelarraythirdparty-1.2.1.dist-info → pixelarraythirdparty-1.2.3.dist-info}/METADATA +1 -1
- {pixelarraythirdparty-1.2.1.dist-info → pixelarraythirdparty-1.2.3.dist-info}/RECORD +7 -7
- {pixelarraythirdparty-1.2.1.dist-info → pixelarraythirdparty-1.2.3.dist-info}/WHEEL +0 -0
- {pixelarraythirdparty-1.2.1.dist-info → pixelarraythirdparty-1.2.3.dist-info}/licenses/LICENSE +0 -0
- {pixelarraythirdparty-1.2.1.dist-info → pixelarraythirdparty-1.2.3.dist-info}/top_level.txt +0 -0
pixelarraythirdparty/__init__.py
CHANGED
|
@@ -15,7 +15,21 @@ class OAuth2Login(AsyncClient):
|
|
|
15
15
|
|
|
16
16
|
使用示例:
|
|
17
17
|
```
|
|
18
|
-
#
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
-
|
|
282
|
+
# 1. 获取授权URL
|
|
283
|
+
auth_data, success = await google.get_auth_url()
|
|
255
284
|
if success:
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
#
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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,4 +1,4 @@
|
|
|
1
|
-
pixelarraythirdparty/__init__.py,sha256=
|
|
1
|
+
pixelarraythirdparty/__init__.py,sha256=zQsr327IH9uZgfbsXIpwvP6B_KJltOQFfaWJ5NqGHAo,582
|
|
2
2
|
pixelarraythirdparty/client.py,sha256=Ym_IZ6cdoZJoMKW61ZRTfQ81-Hay5dpLTgExoANZwI4,3171
|
|
3
3
|
pixelarraythirdparty/cron/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
pixelarraythirdparty/cron/cron.py,sha256=nv4e2hX_UkEJ-kbEARbInU2J6aREyYZ61dZ-4b9UWJI,3146
|
|
@@ -11,11 +11,11 @@ pixelarraythirdparty/product/product.py,sha256=5fgv2Ck860epYXxipY83vePziubCIlocF
|
|
|
11
11
|
pixelarraythirdparty/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
pixelarraythirdparty/project/project.py,sha256=a8swjckyn4y3NlIx0-tMbcRwDY9woOijGi7lb1wN7Ok,2455
|
|
13
13
|
pixelarraythirdparty/unified_login/__init__.py,sha256=tzy3nmRv-qZID-6kYRFarqQVrmkUsEI7D6de_PFu7Tg,327
|
|
14
|
-
pixelarraythirdparty/unified_login/unified_login.py,sha256=
|
|
14
|
+
pixelarraythirdparty/unified_login/unified_login.py,sha256=A1Sl0g0s9MrBdSmrFiui2r15sA0Xd17iTQIUfJsZEFQ,41483
|
|
15
15
|
pixelarraythirdparty/user/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
pixelarraythirdparty/user/user.py,sha256=SqufSAVMxQElz-NqtlOZs_dG7UtbuE-ygLAyml9oKpY,5761
|
|
17
|
-
pixelarraythirdparty-1.2.
|
|
18
|
-
pixelarraythirdparty-1.2.
|
|
19
|
-
pixelarraythirdparty-1.2.
|
|
20
|
-
pixelarraythirdparty-1.2.
|
|
21
|
-
pixelarraythirdparty-1.2.
|
|
17
|
+
pixelarraythirdparty-1.2.3.dist-info/licenses/LICENSE,sha256=O-g1dUr0U50rSIvmWE9toiVkSgFpVt72_MHITbWvAqA,1067
|
|
18
|
+
pixelarraythirdparty-1.2.3.dist-info/METADATA,sha256=_TNjpH-NiF7st_CYAxM9Gz8LWs01m-Prlzjw7vZ4708,993
|
|
19
|
+
pixelarraythirdparty-1.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
20
|
+
pixelarraythirdparty-1.2.3.dist-info/top_level.txt,sha256=dzG2Ut8j7noUqj_0ZQjcIDAeHYCh_9WtlxjAxtoyufo,21
|
|
21
|
+
pixelarraythirdparty-1.2.3.dist-info/RECORD,,
|
|
File without changes
|
{pixelarraythirdparty-1.2.1.dist-info → pixelarraythirdparty-1.2.3.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|