nc-user-terminator 0.1.5__py3-none-any.whl → 0.1.17__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.
nc_user_manager/client.py CHANGED
@@ -1,10 +1,10 @@
1
1
  import asyncio
2
2
  from typing import Optional, Dict, Any
3
3
 
4
- from cache import MemoryCache, BaseCache, AsyncRedisCache
5
- from models import UserResponse, OAuth2AuthorizeResponse, CallbackResponse
6
- from exceptions import OAuthError
7
- from utils import request
4
+ from nc_user_manager.cache import MemoryCache, BaseCache, AsyncRedisCache
5
+ from nc_user_manager.models import UserResponse, OAuth2AuthorizeResponse, CallbackResponse
6
+ from nc_user_manager.exceptions import OAuthError
7
+ from nc_user_manager.utils import request
8
8
 
9
9
 
10
10
  PRODUCT_HEADER = "X-Product-Code"
@@ -14,8 +14,8 @@ DEFAULT_TTL = 3600
14
14
  class OAuthClient:
15
15
  def __init__(
16
16
  self,
17
- base_url: str,
18
17
  product_code: str,
18
+ base_url: Optional[str] = None,
19
19
  redirect_url: Optional[str] = None,
20
20
  single_session: bool = False,
21
21
  cache: Optional[BaseCache] = None,
@@ -28,6 +28,8 @@ class OAuthClient:
28
28
  :param redirect_url: 可选,重定向地址
29
29
  :param single_session: 是否单会话登录
30
30
  """
31
+ if not base_url:
32
+ base_url = "http://172.27.92.74"
31
33
  self._base_url = base_url.rstrip("/")
32
34
  self._product_code = product_code
33
35
  self._redirect_url = redirect_url
@@ -43,7 +45,13 @@ class OAuthClient:
43
45
  return await asyncio.to_thread(request, *args, **kwargs)
44
46
 
45
47
  def _headers(self, extra: Optional[Dict[str, str]] = None) -> Dict[str, str]:
46
- headers = {PRODUCT_HEADER: self._product_code}
48
+ headers = {
49
+ PRODUCT_HEADER: self._product_code,
50
+ }
51
+ if self._base_url == 'http://172.27.92.74':
52
+ headers.update({
53
+ "Host": "auth.nc.com"
54
+ })
47
55
  if extra:
48
56
  headers.update(extra)
49
57
  return headers
@@ -214,19 +222,23 @@ class OAuthClient:
214
222
  return UserResponse(res_dict)
215
223
 
216
224
  async def say_my_name_async(self, token: str) -> UserResponse:
217
- if not self._async_cache:
218
- raise RuntimeError("异步方法只支持异步缓存,请传入 async_cache")
219
-
220
225
  """异步获取当前用户"""
221
226
  key = f"user:{token}"
222
- data = await self._cache.get(key)
227
+ if self._async_cache:
228
+ data = await self._cache.get(key)
229
+ else:
230
+ data = self._cache.get(key)
231
+
223
232
  if data:
224
233
  return UserResponse(data)
225
234
 
226
235
  headers = self._headers({"Authorization": f"Bearer {token}"})
227
236
  res_dict = await self._arequest("GET", f"{self._base_url}/api/me", headers=headers)
228
237
  if res_dict.get("success", True):
229
- await self._cache_user_async(token, res_dict)
238
+ if self._async_cache:
239
+ await self._cache_user_async(token, res_dict)
240
+ else:
241
+ self._cache_user(token, res_dict)
230
242
 
231
243
  return UserResponse(res_dict)
232
244
 
@@ -262,10 +274,125 @@ class OAuthClient:
262
274
  headers = self._headers({"Authorization": f"Bearer {token}"})
263
275
  resp = await self._arequest("POST", f"{self._base_url}/api/auth/logout", headers=headers)
264
276
 
265
- data = await self._cache.get(f"user:{token}")
266
- await self._uncache_user_async(token, data)
277
+ if self._async_cache:
278
+ data = await self._cache.get(f"user:{token}")
279
+ await self._uncache_user_async(token, data)
280
+ else:
281
+ data = self._cache.get(f"user:{token}")
282
+ self._uncache_user(token, data)
267
283
  return resp
268
284
 
285
+ # 密码学登录
286
+ def open_sesame(self, user_name:str, password: str) -> CallbackResponse:
287
+ params = {"single_session": str(self._single_session).lower()}
288
+
289
+ form = {
290
+ "username": user_name,
291
+ "password": password,
292
+ }
293
+
294
+ res_dict = request("POST", f"{self._base_url}/api/auth/login", headers=self._headers(), params=params, form_body=form)
295
+
296
+ return CallbackResponse(res_dict)
297
+
298
+
299
+ async def open_sesame_async(self, user_name:str, password: str) -> CallbackResponse:
300
+ params = {"single_session": str(self._single_session).lower()}
301
+
302
+ form = {
303
+ "username": user_name,
304
+ "password": password,
305
+ }
306
+
307
+ res_dict = await self._arequest(
308
+ "POST",
309
+ f"{self._base_url}/api/auth/login",
310
+ params=params,
311
+ form_body=form,
312
+ headers={
313
+ "Content-Type": "application/x-www-form-urlencoded",
314
+ **self._headers(),
315
+ }
316
+ )
317
+ return CallbackResponse(res_dict)
318
+
319
+ def forget_me_not(self, user_email: str, redirect_url: str):
320
+ """
321
+ 忘记密码
322
+ :param user_email:
323
+ :param redirect_url:
324
+ :return:
325
+ """
326
+ headers = self._headers()
327
+ json_data = {
328
+ "email": user_email,
329
+ "redirect_url": redirect_url
330
+ }
331
+ return request("POST", f"{self._base_url}/api/auth/forgot-password", headers=headers, json_body=json_data)
332
+
333
+ def lily_of_the_valley(self, password_token: str, password: str):
334
+ """
335
+ 找回密码
336
+ :param password_token: forgot_password获取的验证token
337
+ :param password: 新密码
338
+ :return:
339
+ """
340
+ json_data = {
341
+ "token": password_token,
342
+ "password": password
343
+ }
344
+ return request("POST", f"{self._base_url}/api/auth/reset-password", headers=self._headers(), json_body=json_data)
345
+
346
+ def register_apply(self, ip_address: str, email: str, password: str, full_name: str = None, redirect_url: str = None) -> dict:
347
+ """
348
+ 邮件注册申请
349
+ :param ip_address:
350
+ :param redirect_url: 不填默认为系统配置的回调地址
351
+ :param password: 用户的密码
352
+ :param full_name: 用户的名称
353
+ :param email: 用户的邮箱
354
+ :return:
355
+ """
356
+ json_data = {
357
+ "email": email,
358
+ "password": password,
359
+ "full_name": full_name,
360
+ }
361
+ params = {"redirect_url": redirect_url, "ip_address": ip_address}
362
+ return request("POST", f"{self._base_url}/api/auth/register-apply", params=params, headers=self._headers(),
363
+ json_body=json_data)
364
+
365
+ def register(self, register_token: str, full_name: str = None) -> dict:
366
+ """
367
+ 邮箱注册
368
+ :param register_token:
369
+ :param full_name: 可不填, 填写后会修改名称
370
+ :return:
371
+ """
372
+ json_data = {
373
+ "token": register_token,
374
+ "full_name": full_name,
375
+ }
376
+ return request("POST", f"{self._base_url}/api/auth/register", headers=self._headers(),
377
+ json_body=json_data)
378
+
379
+ def lycoris(self, token: str, password: str):
380
+ """
381
+ 账户注销
382
+ :param password: 用户密码 用来确认用户是否正确
383
+ :param token: 用户token
384
+ :return:
385
+ """
386
+ user = self.say_my_name(token=token)
387
+ user_id = user.user_id
388
+
389
+ headers = self._headers({"Authorization": f"Bearer {token}"})
390
+ form_data = {
391
+ "username": user.email,
392
+ "password": password
393
+ }
394
+ return request("POST", f"{self._base_url}/api/users/{ user_id }/remove", headers=headers, form_body=form_data)
395
+
269
396
  async def main():
270
397
  def get_redis_url() -> str:
271
398
  return f'redis://default:1q2w3e@localhost:6379/1'
@@ -276,18 +403,19 @@ async def main():
276
403
  _redis = redis.from_url(get_redis_url(), decode_responses=True)
277
404
 
278
405
  redis_cache = AsyncRedisCache(_redis)
406
+ import socket
407
+ print(socket.gethostbyname("dev.ncuser.com"))
408
+
409
+ client = OAuthClient("kode", "http://dev.ncuser.com", "http://localhost:8000/auth/google/custom_callback", single_session=True, cache=redis_cache)
410
+ authorize = await client.say_my_name_async("QtbMAqXNwrsy-7dr-D_lIVvUu88gjhPM0fBXeJTaOiA")
279
411
 
280
- client = OAuthClient("http://localhost:8000/", "bankgpt", "http://localhost:8000/auth/google/custom_callback", single_session=True, cache=redis_cache)
281
- # authorize = client.authorize("google")
282
- # print(authorize)
412
+ client.open_sesame_async("glztestvt1@zingfront.com", "123456789")
413
+ # res = client.forgot_password("QtbMAqXNwrsy-7dr-D_lIVvUu88gjhPM0fBXeJTaOiA")
283
414
 
415
+ token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1IiwicGFzc3dvcmRfZmdwdCI6IiRhcmdvbjJpZCR2PTE5JG09NjU1MzYsdD0zLHA9NCRYUlQ1K1p3Uk5sbjhKQzQrZW94TFlnJERadnFKb29xUDNMUGVJbEV6OVR5TjZIdm1LYW9yYnpvdGxGRlB5SlBKZE0iLCJhdWQiOiJmYXN0YXBpLXVzZXJzOnJlc2V0IiwiZXhwIjoxNzYxNTU4MTUxfQ.rSr8tRql4ZsE2k-WGHzhq9aT387E9jXGJ_bNomC4LKA"
416
+ print(client.logout_async(token, "965965965"))
417
+ print(authorize)
284
418
 
285
- name = await client.say_my_name_async("Tu72u4SVue4ezadi1v5Ui9r9HjxH7YqbkY_yf5jFtPQ")
286
- print(name)
287
- name = await client.say_my_name_async("Tu72u4SVue4ezadi1v5Ui9r9HjxH7YqbkY_yf5jFtPQ")
288
- print(name)
289
- name = await client.logout_async("Tu72u4SVue4ezadi1v5Ui9r9HjxH7YqbkY_yf5jFtPQ")
290
- print(name)
291
419
 
292
420
 
293
421
  if __name__ == '__main__':
nc_user_manager/models.py CHANGED
@@ -15,8 +15,8 @@ class UserResponse(dict):
15
15
  return self.get("email")
16
16
 
17
17
  @property
18
- def picture(self) -> Optional[str]:
19
- return self.get("picture")
18
+ def avatar(self) -> Optional[str]:
19
+ return self.get("avatar")
20
20
 
21
21
  @property
22
22
  def full_name(self) -> Optional[str]:
@@ -26,6 +26,10 @@ class UserResponse(dict):
26
26
  def role(self) -> Optional[str]:
27
27
  return self.get("role")
28
28
 
29
+ @property
30
+ def user_id(self) -> Optional[str]:
31
+ return self.get("user_id")
32
+
29
33
  class CallbackResponse(dict):
30
34
  @property
31
35
  def token(self) -> str:
@@ -44,5 +48,5 @@ class CallbackResponse(dict):
44
48
  return self.get("email")
45
49
 
46
50
  @property
47
- def user_picture(self) -> str:
48
- return self.get("user_picture")
51
+ def avatar(self) -> str:
52
+ return self.get("avatar")
nc_user_manager/utils.py CHANGED
@@ -10,7 +10,8 @@ def request(
10
10
  url: str,
11
11
  params: Optional[Dict[str, Any]] = None,
12
12
  headers: Optional[Dict[str, str]] = None,
13
- json_body: Optional[dict] = None
13
+ json_body: Optional[dict] = None,
14
+ form_body: Optional[dict] = None,
14
15
  ) -> dict:
15
16
  """
16
17
  发送 HTTP 请求并返回统一结果,不抛异常
@@ -28,12 +29,20 @@ def request(
28
29
  url = f"{url}?{query}"
29
30
 
30
31
  data = None
32
+
33
+ # JSON 请求
31
34
  if json_body is not None:
32
35
  data = json.dumps(json_body).encode("utf-8")
33
36
  if headers is None:
34
37
  headers = {}
35
38
  headers["Content-Type"] = "application/json"
36
39
 
40
+ # Form 表单请求
41
+ if form_body is not None:
42
+ data = urllib.parse.urlencode(form_body).encode("utf-8")
43
+ headers = headers or {}
44
+ headers["Content-Type"] = "application/x-www-form-urlencoded"
45
+
37
46
  req = urllib.request.Request(url, method=method.upper(), data=data)
38
47
  if headers:
39
48
  for k, v in headers.items():
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.4
2
+ Name: nc-user-terminator
3
+ Version: 0.1.17
4
+ Summary: OAuth client wrapper for multi-tenant projects
5
+ Author: bw_song
6
+ Author-email: m132777096902@gmail.com
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: cachetools==6.2.0
10
+ Dynamic: author-email
11
+ Dynamic: requires-python
12
+
13
+ # 更新
14
+ + V0.1.5
15
+ - 新增本地缓存机制
16
+ + v0.1.6
17
+ - 默认连接地址
18
+ + v0.1.7
19
+ - 映射host
20
+ + v0.1.8
21
+ - 调整相对路径
22
+ + v0.1.9
23
+ - 修改缓存配置
24
+ + v0.1.10
25
+ - 获取用户信息,本地缓存配置
26
+ + v0.1.11
27
+ - 用户头像字段调整
28
+ + v0.1.12
29
+ - 新增密码学登录
30
+ - 新增修改密码
31
+ - 支持重置社媒账号密码
32
+ + v0.1.13
33
+ - 包路径调整
34
+ + v0.1.14
35
+ - 新增facebook第三方登录
36
+ - 新增邮箱注册功能
37
+ + v0.1.15
38
+ - 新增忘记密码
39
+ - 新增找回密码
40
+ - 新增账户注销
41
+ + v0.1.16
42
+ - 修改接口返回数据
43
+ + v0.1.17
44
+ - 用户注销调整
@@ -0,0 +1,10 @@
1
+ nc_user_manager/__init__.py,sha256=fF3FZD0XUW5YCfTbBeJs3RK-Mnm3IQ7lns6Eb_tMqPU,238
2
+ nc_user_manager/cache.py,sha256=u9ioXDwHmEJHRB4VKI4JU_pp-8Y5O4bLPm8-pwqiMVc,2273
3
+ nc_user_manager/client.py,sha256=r8M-HXaku8D_x4zp4fxVY5avjjr3TKqmHd6ILQXl-cc,16055
4
+ nc_user_manager/exceptions.py,sha256=yUMDrh1HHZF36UUadQNHvJlDgEYSYoYOObs8Q11fjrE,351
5
+ nc_user_manager/models.py,sha256=WgNC7z7Xy9fok5tA6CawxvBmEhGM6J0KCD3bk2MMUWU,1166
6
+ nc_user_manager/utils.py,sha256=zn0ds3UftTaEnrTVDn0YL9N-EkVWpbJtowFzAotU80E,2608
7
+ nc_user_terminator-0.1.17.dist-info/METADATA,sha256=pfxhwK_sbiC6quB-jO8u-_XwfYsvsN1VajsGkG9Lze8,967
8
+ nc_user_terminator-0.1.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
+ nc_user_terminator-0.1.17.dist-info/top_level.txt,sha256=kOAUtl6RYo-x3vMJL8It3KCJLoIFPvMUiAAyXjPQTYA,16
10
+ nc_user_terminator-0.1.17.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: nc-user-terminator
3
- Version: 0.1.5
4
- Summary: OAuth client wrapper for multi-tenant projects
5
- Author: bw_song
6
- Author-email: m132777096902@gmail.com
7
- Requires-Python: >=3.8
8
- Description-Content-Type: text/markdown
9
- Requires-Dist: cachetools==6.2.0
10
- Dynamic: author-email
11
- Dynamic: requires-python
12
-
13
- # 更新
14
- + V0.1.5
15
- - 新增本地缓存机制
@@ -1,10 +0,0 @@
1
- nc_user_manager/__init__.py,sha256=fF3FZD0XUW5YCfTbBeJs3RK-Mnm3IQ7lns6Eb_tMqPU,238
2
- nc_user_manager/cache.py,sha256=u9ioXDwHmEJHRB4VKI4JU_pp-8Y5O4bLPm8-pwqiMVc,2273
3
- nc_user_manager/client.py,sha256=71pQ_4YZy1f_BJ9Pc2Md1r57SStqI1qRxnXU9IGAm5Y,11276
4
- nc_user_manager/exceptions.py,sha256=yUMDrh1HHZF36UUadQNHvJlDgEYSYoYOObs8Q11fjrE,351
5
- nc_user_manager/models.py,sha256=mDK7zskIcaThxvUUTWVf6eMasw7YaA3hDGVVSd1ZJgo,1088
6
- nc_user_manager/utils.py,sha256=gxFSaUq0oiymIlvHITu2L7EkU2ZYQmW2q_okmUxGBeU,2319
7
- nc_user_terminator-0.1.5.dist-info/METADATA,sha256=1uCPVZ-m6nHokYebpNHDAdgJbtNxxJxugWNvzmqxm1U,378
8
- nc_user_terminator-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
- nc_user_terminator-0.1.5.dist-info/top_level.txt,sha256=kOAUtl6RYo-x3vMJL8It3KCJLoIFPvMUiAAyXjPQTYA,16
10
- nc_user_terminator-0.1.5.dist-info/RECORD,,