nlbone 0.7.23__py3-none-any.whl → 0.7.25__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.
@@ -1,7 +1,8 @@
1
1
  import enum
2
2
  import uuid
3
+ from dataclasses import dataclass
3
4
  from datetime import datetime, timedelta, timezone
4
- from typing import Any, Dict, Optional
5
+ from typing import Any, Dict, Optional, List
5
6
 
6
7
  from sqlalchemy import JSON, DateTime, Index, Integer, String, Text
7
8
  from sqlalchemy import JSON as SA_JSON
@@ -22,6 +23,35 @@ except Exception:
22
23
  UUIDType = String(36)
23
24
 
24
25
 
26
+ @dataclass
27
+ class CurrentUserData:
28
+ active: bool
29
+ id: int
30
+ email: str
31
+ exp: int
32
+ iat: int
33
+ preferred_username: str
34
+ name: str
35
+ phone_number: str
36
+ verifications: List[str]
37
+ allowed_permissions: List[str]
38
+
39
+ @classmethod
40
+ def from_dict(cls, data: dict) -> "CurrentUserData":
41
+ return cls(
42
+ active=data.get("active"),
43
+ id=data.get("sub"),
44
+ email=data.get("email"),
45
+ exp=data.get("exp"),
46
+ iat=data.get("iat"),
47
+ preferred_username=data.get("preferred_username"),
48
+ name=data.get("name"),
49
+ phone_number=data.get("phone_number"),
50
+ verifications=data.get("verifications", []),
51
+ allowed_permissions=data.get("allowed_permissions", []),
52
+ )
53
+
54
+
25
55
  class AuditLog(Base):
26
56
  __tablename__ = "audit_logs"
27
57
 
@@ -1,5 +1,6 @@
1
1
  import functools
2
2
 
3
+ from nlbone.core.domain.models import CurrentUserData
3
4
  from nlbone.adapters.auth import KeycloakAuthService
4
5
  from nlbone.adapters.auth.keycloak import get_auth_service
5
6
  from nlbone.config.settings import get_settings
@@ -21,6 +22,13 @@ def current_user_id() -> int:
21
22
  raise UnauthorizedException()
22
23
 
23
24
 
25
+ def current_user() -> CurrentUserData:
26
+ user = current_request().state.user
27
+ if user.id is None:
28
+ raise UnauthorizedException()
29
+ return user
30
+
31
+
24
32
  def current_client_id() -> str:
25
33
  request = current_request()
26
34
  if client_id := KeycloakAuthService().get_client_id(request.state.token):
@@ -1,4 +1,4 @@
1
- from typing import Any, Iterable
1
+ from typing import Any, Iterable, Dict, List
2
2
 
3
3
  from fastapi import HTTPException, status
4
4
 
@@ -83,9 +83,14 @@ class UnprocessableEntityException(BaseHttpException):
83
83
  )
84
84
 
85
85
 
86
- class LogicalValidationException(UnprocessableEntityException):
87
- def __init__(self, detail: str, loc: Iterable[Any] | None = None, type_: str = "logical_error"):
88
- super().__init__(detail=detail, loc=loc, type_=type_)
86
+ class LogicalValidationException(HTTPException):
87
+ def __init__(self, detail: str = None, loc: Iterable[Any] | None = None, type_: str = "logical_error",
88
+ errors: List[Dict[str, Any]] = None):
89
+ self.errors = errors
90
+ if errors:
91
+ super().__init__(detail=errors, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,)
92
+ else:
93
+ super().__init__(detail=_errors(loc, detail, type_), status_code=status.HTTP_422_UNPROCESSABLE_ENTITY)
89
94
 
90
95
 
91
96
  class GoneException(BaseHttpException):
@@ -3,6 +3,7 @@ from typing import Callable, Optional, Union
3
3
  from fastapi import Request
4
4
  from starlette.middleware.base import BaseHTTPMiddleware
5
5
 
6
+ from nlbone.core.domain.models import CurrentUserData
6
7
  from nlbone.adapters.auth.auth_service import AuthService
7
8
  from nlbone.config.settings import get_settings
8
9
 
@@ -53,7 +54,8 @@ def authenticate_admin_user(request, auth_service):
53
54
 
54
55
  def authenticate_user(request):
55
56
  token = (
56
- request.cookies.get("access_token") or request.cookies.get("j_token") or request.headers.get("Authorization")
57
+ request.cookies.get("access_token") or request.cookies.get("j_token") or request.headers.get(
58
+ "Authorization")
57
59
  )
58
60
  if request.headers.get("Authorization"):
59
61
  scheme, token = request.headers.get("Authorization").split(" ", 1)
@@ -64,6 +66,7 @@ def authenticate_user(request):
64
66
  service: BaseAuthService = AuthService()
65
67
  data = service.verify_token(token)
66
68
  if data:
69
+ request.state.user = CurrentUserData.from_dict(data)
67
70
  request.state.user_id = data.get("sub")
68
71
  except Exception:
69
72
  pass
@@ -78,6 +81,7 @@ class AuthenticationMiddleware(BaseHTTPMiddleware):
78
81
  request.state.client_id = None
79
82
  request.state.user_id = None
80
83
  request.state.token = None
84
+ request.state.user = None
81
85
  if request.headers.get("X-Client-Id") and request.headers.get("X-Api-Key"):
82
86
  if request.headers.get("X-Api-Key") == get_settings().PRICING_API_SECRET:
83
87
  request.state.client_id = request.headers.get("X-Client-Id")
@@ -0,0 +1,26 @@
1
+ from typing import List, Any
2
+ from sqlalchemy import Row
3
+
4
+
5
+ def flatten_sqlalchemy_result(items: List[Any]) -> List[Any]:
6
+ """
7
+ Converts a list of SQLAlchemy Rows (tuples) into a flat list of entities
8
+ with extra fields injected as attributes.
9
+ """
10
+ if not items:
11
+ return []
12
+
13
+ if not isinstance(items[0], Row):
14
+ return items
15
+
16
+ normalized = []
17
+ for row in items:
18
+ entity = row[0]
19
+
20
+ for key, value in row._mapping.items():
21
+ if not isinstance(value, type(entity)):
22
+ setattr(entity, key, value)
23
+
24
+ normalized.append(entity)
25
+
26
+ return normalized
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nlbone
3
- Version: 0.7.23
3
+ Version: 0.7.25
4
4
  Summary: Backbone package for interfaces and infrastructure in Python projects
5
5
  Author-email: Amir Hosein Kahkbazzadeh <a.khakbazzadeh@gmail.com>
6
6
  License: MIT
@@ -58,7 +58,7 @@ nlbone/core/application/use_case.py,sha256=3GMQZ3CFK5cbLoBNBgohPft6GBq2j9_wr8iKR
58
58
  nlbone/core/application/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  nlbone/core/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
60
  nlbone/core/domain/base.py,sha256=dz3gwNnOk048zLghbNNM_Wa0qPXLoRmH5w72fwtXNFM,2592
61
- nlbone/core/domain/models.py,sha256=uCxdHqD8AJM-iq78bJ-nqAnGxtRiNK-5oFbkunXa7qc,3298
61
+ nlbone/core/domain/models.py,sha256=_euaxgiZ8NZUrkvyc6jSMn0A_3m_mW1RIHcQ8o550Hg,4126
62
62
  nlbone/core/ports/__init__.py,sha256=syJg3fAjQALD5Rjfm9wi9bQpkIvNTWjE9AURBmy587o,132
63
63
  nlbone/core/ports/auth.py,sha256=C-GmUqHNx4bAku6KbW_OTpPXCEfurBWWyDi9KxpTi9M,553
64
64
  nlbone/core/ports/cache.py,sha256=8pP_z4ta7PNNG8UiSrEF4xMZRm2wLPxISZvdPt7QnxQ,2351
@@ -71,7 +71,7 @@ nlbone/core/ports/uow.py,sha256=VhqSc-Ryt9m-rlNMiXTzD3dPGz6mM_JxND8D0UJGRu4,962
71
71
  nlbone/interfaces/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
72
  nlbone/interfaces/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
73
  nlbone/interfaces/api/exception_handlers.py,sha256=vxNEBgAaQygLgAz1UNt3wHj0SdCJOwtLOv_BwTfir3o,4050
74
- nlbone/interfaces/api/exceptions.py,sha256=jshNmu6tqPEjUelTdHKByI3n5CX5jDErB8fEwn3X1oo,2696
74
+ nlbone/interfaces/api/exceptions.py,sha256=Phv0nXaEHCgJVEAuQ2q8QHxpn_diXahKarupSHOATY0,2964
75
75
  nlbone/interfaces/api/routers.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
76
  nlbone/interfaces/api/schemas.py,sha256=NIEKeTdJtwwIkIxL7WURNZF8g34I4TlRAqs-x1Uq7YI,108
77
77
  nlbone/interfaces/api/additional_filed/__init__.py,sha256=BWemliLSQV9iq1vdUaF733q0FOSipSWBOQk9eYj732Q,318
@@ -82,14 +82,14 @@ nlbone/interfaces/api/additional_filed/default_field_rules/__init__.py,sha256=LU
82
82
  nlbone/interfaces/api/additional_filed/default_field_rules/image_field_rules.py,sha256=ecKqPeXZ-YiF14RK9PmK7ln3PCzpCUc18S5zm5IF3fw,339
83
83
  nlbone/interfaces/api/dependencies/__init__.py,sha256=rnYRrFVZCfICQrp_PVFlzNg3BeC57yM08wn2DbOHCfk,359
84
84
  nlbone/interfaces/api/dependencies/async_auth.py,sha256=s8qbMWuvHkS_9xnOmoO5kLLfKrZrOkvhKFfS9kQb51Y,1711
85
- nlbone/interfaces/api/dependencies/auth.py,sha256=u5XRn08Pn4MEAwrkWc6DayKwN6_vd_pRMhaCj-rXWDM,3085
85
+ nlbone/interfaces/api/dependencies/auth.py,sha256=yre1ny3nRKDOmYP5Qto0wjbuEZF2Y53RyNW0xAR_a6g,3298
86
86
  nlbone/interfaces/api/dependencies/client_credential.py,sha256=Bo4dYx75Qw0JzTKD9ZfV5EXDEOuwndJk2D-V37K2ePg,1293
87
87
  nlbone/interfaces/api/dependencies/db.py,sha256=-UD39J_86UU7ZJs2ZncpdND0yhAG0NeeeALrgSDuuFw,466
88
88
  nlbone/interfaces/api/dependencies/uow.py,sha256=QfLEvLYLNWZJQN1k-0q0hBVtUld3D75P4j39q_RjcnE,1181
89
89
  nlbone/interfaces/api/middleware/__init__.py,sha256=zbX2vaEAfxRMIYwO2MVY_2O6bqG5H9o7HqGpX14U3Is,158
90
90
  nlbone/interfaces/api/middleware/access_log.py,sha256=vIkxxxfy2HcjqqKb8XCfGCcSrivAC8u6ie75FMq5x-U,1032
91
91
  nlbone/interfaces/api/middleware/add_request_context.py,sha256=rfqbXvteFPzd8DLg3V_69fVR_kP-FSzezs91wb1DvPM,1905
92
- nlbone/interfaces/api/middleware/authentication.py,sha256=EtzG9EAspF4CMPMcGM-5EYi1-mlnufxtvZHxN_NScdE,3129
92
+ nlbone/interfaces/api/middleware/authentication.py,sha256=Bt6sYu4KtXAyUQnSIp-Z2Z1yKNNtfRy9Y3rOZcYTFhw,3299
93
93
  nlbone/interfaces/api/pagination/__init__.py,sha256=pA1uC4rK6eqDI5IkLVxmgO2B6lExnOm8Pje2-hifJZw,431
94
94
  nlbone/interfaces/api/pagination/offset_base.py,sha256=60X8a9uDOSd3qG45M49dqNG_FUjSxEDrgEyb9JD9V-o,4113
95
95
  nlbone/interfaces/api/schema/__init__.py,sha256=LAqgynfupeqOQ6u0I5ucrcYnojRMZUg9yW8IjKSQTNI,119
@@ -109,12 +109,13 @@ nlbone/utils/cache_keys.py,sha256=Y2YSellHTbUOcoaNbl1jaD4r485VU_e4KXsfBWhYTBo,10
109
109
  nlbone/utils/cache_registry.py,sha256=3FWYyhujW8oPBiVUPzk1CqJ3jJfxs9729Sbb1pQ5Fag,707
110
110
  nlbone/utils/context.py,sha256=TXZtORxyWcBiZozNzmXeZhXxDCXXuM91JfrQj-SkFK8,1851
111
111
  nlbone/utils/crypto.py,sha256=PX0Tlf2nqXcGbuv16J26MoUPzo2c4xcD4sZBXxhBXgQ,746
112
+ nlbone/utils/flatten_sqlalchemy_result.py,sha256=JGwQEauoJVjhzvXrOtqabj3wQ7zp2-OPwhuh44sUdUE,625
112
113
  nlbone/utils/http.py,sha256=0yeI34j5FfelqvX3PJnKknSXji1jl15VYbVIIvrSbXg,997
113
114
  nlbone/utils/normalize_mobile.py,sha256=sGH4tV9gX-6eVKozviNWJhm1DN1J28Nj-ERldCYkS_E,732
114
115
  nlbone/utils/redactor.py,sha256=-V4HrHmHwPi3Kez587Ek1uJlgK35qGSrwBOvcbw8Jas,1279
115
116
  nlbone/utils/time.py,sha256=DjjyQ9GLsfXoT6NK8RDW2rOlJg3e6sF04Jw6PBUrSvg,1268
116
- nlbone-0.7.23.dist-info/METADATA,sha256=485NZAzhMrUYkYuFkQa5ZlANQCtfHLHVJAf6BYHuwFg,2295
117
- nlbone-0.7.23.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
118
- nlbone-0.7.23.dist-info/entry_points.txt,sha256=CpIL45t5nbhl1dGQPhfIIDfqqak3teK0SxPGBBr7YCk,59
119
- nlbone-0.7.23.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
120
- nlbone-0.7.23.dist-info/RECORD,,
117
+ nlbone-0.7.25.dist-info/METADATA,sha256=HUsDtSuUlRm9QCdUx_W0TV0pGHG8Dykh06paMC3d90g,2295
118
+ nlbone-0.7.25.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
119
+ nlbone-0.7.25.dist-info/entry_points.txt,sha256=CpIL45t5nbhl1dGQPhfIIDfqqak3teK0SxPGBBr7YCk,59
120
+ nlbone-0.7.25.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
121
+ nlbone-0.7.25.dist-info/RECORD,,