aiteamutils 0.2.87__py3-none-any.whl → 0.2.89__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,6 +1,6 @@
1
1
  #기본 라이브러리
2
2
  from fastapi import Request
3
- from typing import TypeVar, Generic, Type, Dict, Any, Union, List, Optional
3
+ from typing import TypeVar, Generic, Type, Dict, Any, Union, List, Optional, Literal
4
4
  from sqlalchemy.orm import DeclarativeBase
5
5
  from sqlalchemy.ext.asyncio import AsyncSession
6
6
  from datetime import datetime
@@ -13,12 +13,12 @@ from .database import (
13
13
  process_response,
14
14
  validate_unique_fields
15
15
  )
16
- from .security import hash_password
16
+ from .security import hash_password, verify_jwt_token, verify_role_permission
17
17
  ModelType = TypeVar("ModelType", bound=DeclarativeBase)
18
18
 
19
19
  class BaseService(Generic[ModelType]):
20
20
  ##################
21
- # 1. 초기화 영역 #
21
+ # 초기화 영역 #
22
22
  ##################
23
23
  def __init__(
24
24
  self,
@@ -37,12 +37,16 @@ class BaseService(Generic[ModelType]):
37
37
  #######################
38
38
  async def create(
39
39
  self,
40
+ request: Request,
40
41
  entity_data: Dict[str, Any],
41
42
  response_model: Any = None,
42
43
  exclude_entities: List[str] | None = None,
43
44
  unique_check: List[Dict[str, Any]] | None = None,
44
45
  fk_check: List[Dict[str, Any]] | None = None,
46
+ org_ulid_position: str = "organization_ulid",
47
+ role_permission: str = "create"
45
48
  ) -> ModelType:
49
+ await verify_role_permission(request, role_permission)
46
50
 
47
51
  try:
48
52
  async with self.db_session.begin():
@@ -77,12 +81,15 @@ class BaseService(Generic[ModelType]):
77
81
 
78
82
  async def update(
79
83
  self,
84
+ request: Request,
80
85
  ulid: str | None = None,
81
86
  update_data: Dict[str, Any] | None = None,
82
87
  conditions: Dict[str, Any] | None = None,
83
88
  unique_check: List[Dict[str, Any]] | None = None,
84
89
  exclude_entities: List[str] | None = None,
85
- response_model: Any = None
90
+ response_model: Any = None,
91
+ org_ulid_position: str = "organization_ulid",
92
+ role_permission: str = "update"
86
93
  ) -> ModelType:
87
94
  try:
88
95
  async with self.db_session.begin():
@@ -130,8 +137,11 @@ class BaseService(Generic[ModelType]):
130
137
 
131
138
  async def delete(
132
139
  self,
140
+ request: Request,
133
141
  ulid: str | None = None,
134
- conditions: Dict[str, Any] | None = None
142
+ conditions: Dict[str, Any] | None = None,
143
+ org_ulid_position: str = "organization_ulid",
144
+ role_permission: str = "delete"
135
145
  ) -> bool:
136
146
  try:
137
147
  if not ULID.from_str(ulid):
@@ -172,13 +182,16 @@ class BaseService(Generic[ModelType]):
172
182
  #########################
173
183
  async def list(
174
184
  self,
185
+ request: Request,
175
186
  skip: int = 0,
176
187
  limit: int = 100,
177
188
  filters: List[Dict[str, Any]] | None = None,
189
+ org_ulid_position: str = "organization_ulid",
178
190
  response_model: Any = None,
179
191
  explicit_joins: Optional[List[Any]] = None,
180
192
  loading_joins: Optional[List[Any]] = None,
181
- order: Optional[str] = None
193
+ order: Optional[str] = None,
194
+ role_permission: str = "list"
182
195
  ) -> List[Dict[str, Any]]:
183
196
  try:
184
197
  if order is None:
@@ -208,12 +221,15 @@ class BaseService(Generic[ModelType]):
208
221
 
209
222
  async def get(
210
223
  self,
224
+ request: Request,
211
225
  ulid: str,
212
226
  model_name: str | None = None,
213
227
  response_model: Any = None,
214
228
  conditions: Dict[str, Any] | None = None,
215
229
  explicit_joins: Optional[List[Any]] = None,
216
- loading_joins: Optional[List[Any]] = None
230
+ loading_joins: Optional[List[Any]] = None,
231
+ org_ulid_position: str = "organization_ulid",
232
+ role_permission: str = "get"
217
233
  ):
218
234
  try:
219
235
  if not ulid and not conditions:
aiteamutils/exceptions.py CHANGED
@@ -25,6 +25,7 @@ class ErrorCode(Enum):
25
25
  FORBIDDEN = ErrorResponse(1005, "AUTH_FORBIDDEN", 403, "접근 권한이 없습니다")
26
26
  RATE_LIMIT_EXCEEDED = ErrorResponse(1006, "AUTH_RATE_LIMIT_EXCEEDED", 429, "너무 많은 요청이 발생했습니다")
27
27
  INVALID_PASSWORD = ErrorResponse(1007, "AUTH_INVALID_PASSWORD", 401, "잘못된 비밀번호입니다")
28
+ INVALID_ROLE_PERMISSION = ErrorResponse(1008, "AUTH_INVALID_ROLE_PERMISSION", 401, "접근 권한이 없습니다")
28
29
 
29
30
  # User 관련 에러: 2000번대
30
31
  USER_NOT_FOUND = ErrorResponse(2001, "USER_NOT_FOUND", 404, "사용자를 찾을 수 없습니다")
aiteamutils/security.py CHANGED
@@ -203,7 +203,6 @@ async def create_jwt_token(
203
203
  original_error=str(e)
204
204
  )
205
205
 
206
-
207
206
  async def verify_jwt_token(
208
207
  token: str,
209
208
  expected_type: Optional[Literal["access", "refresh"]] = None,
@@ -283,22 +282,25 @@ async def verify_jwt_token(
283
282
  original_error=e
284
283
  )
285
284
 
286
- def validate_token(
287
- token: str,
288
- token_settings: Dict[str, Any] = None
289
- ) -> Dict[str, Any]:
290
- """JWT 토큰을 검증하고 페이로드를 반환합니다."""
291
- try:
292
- payload = jwt.decode(
293
- token,
294
- token_settings["JWT_SECRET"],
295
- algorithms=[token_settings["JWT_ALGORITHM"]]
296
- )
297
- return payload
298
- except JWTError as e:
285
+ async def verify_role_permission(
286
+ request: Request,
287
+ permission: str,
288
+ ) -> bool:
289
+ token = request.headers.get("Authorization")
290
+
291
+ if not token:
299
292
  raise CustomException(
300
- ErrorCode.INVALID_TOKEN,
301
- detail=token,
302
- source_function="security.validate_token",
303
- original_error=e
304
- )
293
+ ErrorCode.UNAUTHORIZED,
294
+ detail="Authorization header is missing",
295
+ source_function="security.verify_role_permission"
296
+ )
297
+
298
+ token = token.split(" ")[1]
299
+
300
+ payload = await verify_jwt_token(token)
301
+
302
+ organization_ulid = payload.get("organization_ulid")
303
+ role_ulid = payload.get("role_ulid")
304
+ user_ulid = payload.get("user_ulid")
305
+
306
+ return True
aiteamutils/version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  """버전 정보"""
2
- __version__ = "0.2.87"
2
+ __version__ = "0.2.89"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiteamutils
3
- Version: 0.2.87
3
+ Version: 0.2.89
4
4
  Summary: AI Team Utilities
5
5
  Project-URL: Homepage, https://github.com/yourusername/aiteamutils
6
6
  Project-URL: Issues, https://github.com/yourusername/aiteamutils/issues
@@ -1,15 +1,15 @@
1
1
  aiteamutils/__init__.py,sha256=kRBpRjark0M8ZwFfmKiMFol6CbIILN3WE4f6_P6iIq0,1089
2
2
  aiteamutils/base_model.py,sha256=bnRJJaGXGS3TKxfCWWV3arFjdG0qLsPFDXuguYsDyVM,3008
3
3
  aiteamutils/base_repository.py,sha256=HKcgYyEb0JypojoXBFcIT39hPC5CqnjBkHT__GV-lfQ,4615
4
- aiteamutils/base_service.py,sha256=7DXjEn3e_dve_ZfNwUP1_WD7QnucWRXBq-bYuxVmyXI,8694
4
+ aiteamutils/base_service.py,sha256=TlGIY4mkSmGq7Pqjz5ybGDCwpXicrSrs2LIFfjNKJqo,9404
5
5
  aiteamutils/cache.py,sha256=07xBGlgAwOTAdY5mnMOQJ5EBxVwe8glVD7DkGEkxCtw,1373
6
6
  aiteamutils/config.py,sha256=YdalpJb70-txhGJAS4aaKglEZAFVWgfzw5BXSWpkUz4,3232
7
7
  aiteamutils/database.py,sha256=b4fN0XHNWxMJeS5M95JcJ7tujAJ1x3SPTAfDvJdB4sE,19696
8
8
  aiteamutils/enums.py,sha256=Z9wzR3H4XLpA4U3urR5e4eDnEY3Qhne34nLXsKXiL64,2177
9
- aiteamutils/exceptions.py,sha256=5yREcEUbJPzq2404pFJ4J9047I9_qx2QG5iBND1PjDI,15901
10
- aiteamutils/security.py,sha256=tS7gdkCvL0hfgC_FWDSWaCVrzy3zUFpw-PyiFn9yXMM,10839
9
+ aiteamutils/exceptions.py,sha256=wls-R8qbD7fWzEgDDY1Eiy1vXl59R5IsCXTRkZpBiGU,16021
10
+ aiteamutils/security.py,sha256=scyPjVAKXTlu7peGKtUgX-PhcteNWgDt-pDF46PLPy8,10850
11
11
  aiteamutils/validators.py,sha256=PvI9hbMEAqTawgxPbiWRyx2r9yTUrpNBQs1AD3w4F2U,7726
12
- aiteamutils/version.py,sha256=V9nxm2F0tF5ex_r5HRYpS3-KH6vQYMx6bBbIeLl-UfI,42
13
- aiteamutils-0.2.87.dist-info/METADATA,sha256=j9DXkfNdy_4flnY5CKKTg5t8WcKRHBO5boG5Lo5FAP0,1718
14
- aiteamutils-0.2.87.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
15
- aiteamutils-0.2.87.dist-info/RECORD,,
12
+ aiteamutils/version.py,sha256=qp3nB-yWKyYCX8Ttv3g_SDaDwxV5ldrepC0S131QqUg,42
13
+ aiteamutils-0.2.89.dist-info/METADATA,sha256=VLvXEYylcdpRHXATtaAFH0DyW5IKLcBHvnwxageKAcU,1718
14
+ aiteamutils-0.2.89.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
15
+ aiteamutils-0.2.89.dist-info/RECORD,,