sharedkernel 1.0.0__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.
- sharedkernel/common.py +29 -0
- sharedkernel/config.py +12 -0
- sharedkernel/database/adapter.py +6 -0
- sharedkernel/database/repository_base.py +82 -0
- sharedkernel/enum/error_code.py +12 -0
- sharedkernel/exception/__init__.py +5 -0
- sharedkernel/exception/exception.py +39 -0
- sharedkernel/exception/exception_handlers.py +74 -0
- sharedkernel/jwt_service.py +38 -0
- sharedkernel/objects/__init__.py +3 -0
- sharedkernel/objects/base_document.py +8 -0
- sharedkernel/objects/jwt_model.py +7 -0
- sharedkernel/objects/result.py +28 -0
- sharedkernel/string_extentions.py +4 -0
- sharedkernel-1.0.0.dist-info/METADATA +11 -0
- sharedkernel-1.0.0.dist-info/RECORD +18 -0
- sharedkernel-1.0.0.dist-info/WHEEL +5 -0
- sharedkernel-1.0.0.dist-info/top_level.txt +1 -0
sharedkernel/common.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import yaml
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
def yaml2json(yaml_data:yaml) -> json:
|
|
5
|
+
|
|
6
|
+
output = json.dumps(yaml.safe_load(yaml_data), indent=2)
|
|
7
|
+
|
|
8
|
+
return json.loads(output)
|
|
9
|
+
|
|
10
|
+
def json2yaml(data) -> yaml:
|
|
11
|
+
|
|
12
|
+
data=json.dumps(data,default=lambda o: del_none(o.__dict__))
|
|
13
|
+
|
|
14
|
+
data=json.loads(data)
|
|
15
|
+
output = yaml.dump(data)
|
|
16
|
+
|
|
17
|
+
return output
|
|
18
|
+
|
|
19
|
+
def del_none(d):
|
|
20
|
+
"""
|
|
21
|
+
Delete keys with the value ``None`` in a dictionary, recursively.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
for key, value in list(d.items()):
|
|
25
|
+
if value is None:
|
|
26
|
+
del d[key]
|
|
27
|
+
elif isinstance(value, dict):
|
|
28
|
+
del_none(value)
|
|
29
|
+
return d
|
sharedkernel/config.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
# MONGO CONFIG
|
|
3
|
+
|
|
4
|
+
# MONGO_CONNECTION_STRING = "mongodb://localhost:27017"
|
|
5
|
+
MONGO_CONNECTION_STRING = "mongodb://admin:Xp!j1h73ALrD@188.121.112.202:27017"
|
|
6
|
+
|
|
7
|
+
# AUTHENTICATION
|
|
8
|
+
|
|
9
|
+
JWT_ISSURE = "enterprise-identity"
|
|
10
|
+
JWT_AUDIENCE = "AdminPortal"
|
|
11
|
+
JWT_SECRETKEY = "ThereR_10_Project$@$milinnoBut50%OfThemRPublished"
|
|
12
|
+
JWT_ALGORITHM= "HS256"
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from typing import (Optional,
|
|
2
|
+
List
|
|
3
|
+
)
|
|
4
|
+
from bson.objectid import ObjectId
|
|
5
|
+
from typing import Generic, TypeVar
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
from pydantic import parse_obj_as
|
|
8
|
+
|
|
9
|
+
from sharedkernel.string_extentions import camel_to_snake
|
|
10
|
+
from .adapter import MongoDBClient
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
from sharedkernel.exception.exception import BusinessException
|
|
14
|
+
from sharedkernel.enum.error_code import ErrorCode
|
|
15
|
+
|
|
16
|
+
mongo_client= MongoDBClient()
|
|
17
|
+
|
|
18
|
+
ResultT = TypeVar("ResultT")
|
|
19
|
+
|
|
20
|
+
T = TypeVar("T", bound=BaseModel)
|
|
21
|
+
|
|
22
|
+
class RepositoryBase(Generic[T]):
|
|
23
|
+
|
|
24
|
+
def __init__(self,model):
|
|
25
|
+
self.model = model
|
|
26
|
+
self.model_name= camel_to_snake(self.model.__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def find(self,id: str) -> T:
|
|
30
|
+
if (not ObjectId.is_valid(id)):
|
|
31
|
+
raise BusinessException(ErrorCode.Item_NotFound)
|
|
32
|
+
|
|
33
|
+
query = {"_id": ObjectId(id),"is_deleted":False}
|
|
34
|
+
|
|
35
|
+
item = mongo_client.domain[self.model_name].find_one(query)
|
|
36
|
+
|
|
37
|
+
if (not item):
|
|
38
|
+
raise BusinessException(ErrorCode.Item_NotFound)
|
|
39
|
+
|
|
40
|
+
item['_id']=str(item['_id'])
|
|
41
|
+
item['id']= item['_id']
|
|
42
|
+
item.pop('_id')
|
|
43
|
+
|
|
44
|
+
return self.model.parse_obj(item) if item else None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def get_all(self,query:dict = None) -> Optional[List]:
|
|
48
|
+
if query:
|
|
49
|
+
query["is_deleted"]= False
|
|
50
|
+
else:
|
|
51
|
+
query= {"is_deleted":False}
|
|
52
|
+
items = list(mongo_client.domain[self.model_name].find(query))
|
|
53
|
+
|
|
54
|
+
for item in items:
|
|
55
|
+
item['_id'] = str(item['_id'])
|
|
56
|
+
item['id']= item['_id']
|
|
57
|
+
item.pop('_id')
|
|
58
|
+
|
|
59
|
+
return parse_obj_as(List[self.model],items)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def insert(self, insert_data: T) -> str:
|
|
63
|
+
delattr(insert_data, "id")
|
|
64
|
+
inserted_data= mongo_client.domain[self.model_name].insert_one(insert_data.dict())
|
|
65
|
+
|
|
66
|
+
return str(inserted_data.inserted_id)
|
|
67
|
+
|
|
68
|
+
def bulk_insert(self, insert_data: List[T]):
|
|
69
|
+
insert_data=[delattr(data, "id") for data in insert_data]
|
|
70
|
+
mongo_client.domain[self.model_name].insert_many(insert_data)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def update(self,id:str,update_data: T):
|
|
75
|
+
query = {"_id": ObjectId(id)}
|
|
76
|
+
delattr(update_data, "id")
|
|
77
|
+
mongo_client.domain[self.model_name].update_one(query, {"$set": update_data.dict()}, upsert=False)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def query(self):
|
|
81
|
+
return mongo_client.domain[self.model_name]
|
|
82
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
class ErrorCode(str, Enum):
|
|
4
|
+
Item_NotFound= "یافت نشد"
|
|
5
|
+
|
|
6
|
+
Internal_Server= "خطایی در سیستم رخ داده است"
|
|
7
|
+
|
|
8
|
+
UnAuthorized= "توکن دسترسی معتبر نمی باشد"
|
|
9
|
+
|
|
10
|
+
Success= "با موفقیت انجام شد"
|
|
11
|
+
|
|
12
|
+
Intents_Count_Should_Equal_One= "فقط یک اینتنت میتوانید وارد نمایید"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from typing import Any, Dict, Optional
|
|
2
|
+
from fastapi import HTTPException, status
|
|
3
|
+
|
|
4
|
+
from sharedkernel.enum.error_code import ErrorCode
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CustomException(HTTPException):
|
|
8
|
+
def __init__(
|
|
9
|
+
self,
|
|
10
|
+
status_code:int,
|
|
11
|
+
error_code: str,
|
|
12
|
+
detail: Any = None,
|
|
13
|
+
headers: Optional[Dict[str, Any]] = None,
|
|
14
|
+
) -> None:
|
|
15
|
+
super().__init__(status_code= status_code,detail= detail)
|
|
16
|
+
self.headers = headers
|
|
17
|
+
self.error_code = error_code
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class BusinessException(HTTPException):
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
error_code: ErrorCode,
|
|
24
|
+
headers: Optional[Dict[str, Any]] = None,
|
|
25
|
+
) -> None:
|
|
26
|
+
super().__init__(status.HTTP_400_BAD_REQUEST,detail=error_code.value)
|
|
27
|
+
self.headers = headers
|
|
28
|
+
self.error_code = error_code.name
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class UnAuthorizedException(HTTPException):
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
headers: Optional[Dict[str, Any]] = None) -> None:
|
|
35
|
+
super().__init__(status.HTTP_401_UNAUTHORIZED, headers)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
|
|
2
|
+
from fastapi import Request,status
|
|
3
|
+
import requests
|
|
4
|
+
from fastapi.responses import JSONResponse
|
|
5
|
+
from fastapi.exceptions import HTTPException
|
|
6
|
+
|
|
7
|
+
from sharedkernel.exception import (
|
|
8
|
+
BusinessException,
|
|
9
|
+
UnAuthorizedException,
|
|
10
|
+
CustomException
|
|
11
|
+
)
|
|
12
|
+
from sharedkernel.objects import Result
|
|
13
|
+
from sharedkernel.enum.error_code import ErrorCode
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
async def http_exception_handler(request: Request, exc: HTTPException):
|
|
18
|
+
if type(exc)==UnAuthorizedException :
|
|
19
|
+
return await custom_http_exception_handler(
|
|
20
|
+
request,
|
|
21
|
+
CustomException
|
|
22
|
+
(
|
|
23
|
+
status_code= exc.status_code,
|
|
24
|
+
error_code= ErrorCode.UnAuthorized.name,
|
|
25
|
+
detail= ErrorCode.UnAuthorized.value
|
|
26
|
+
)
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
return await custom_http_exception_handler(
|
|
30
|
+
request,
|
|
31
|
+
CustomException
|
|
32
|
+
(
|
|
33
|
+
status_code= exc.status_code,
|
|
34
|
+
error_code= requests.status_codes._codes[exc.status_code][0].title(),
|
|
35
|
+
detail= exc.detail
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
async def business_http_exception_handler(request: Request, exc: BusinessException):
|
|
42
|
+
return await custom_http_exception_handler(
|
|
43
|
+
request,
|
|
44
|
+
CustomException
|
|
45
|
+
(
|
|
46
|
+
status_code= status.HTTP_400_BAD_REQUEST,
|
|
47
|
+
error_code= exc.error_code,
|
|
48
|
+
detail= exc.detail
|
|
49
|
+
),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
async def custom_http_exception_handler(request: Request, exc: CustomException):
|
|
53
|
+
return JSONResponse(
|
|
54
|
+
status_code=exc.status_code,
|
|
55
|
+
content= Result( isSucceed= False,
|
|
56
|
+
data= None,
|
|
57
|
+
message= exc.detail,
|
|
58
|
+
errorCode= exc.error_code
|
|
59
|
+
).__dict__
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
async def exception_handler(request: Request, exc: Exception):
|
|
64
|
+
|
|
65
|
+
return await custom_http_exception_handler(
|
|
66
|
+
request,
|
|
67
|
+
CustomException(
|
|
68
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
69
|
+
error_code=ErrorCode.Internal_Server.name,
|
|
70
|
+
detail=ErrorCode.Internal_Server.value
|
|
71
|
+
),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import jwt
|
|
2
|
+
import time
|
|
3
|
+
from fastapi import Request
|
|
4
|
+
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
|
5
|
+
|
|
6
|
+
from sharedkernel.exception.exception import UnAuthorizedException
|
|
7
|
+
from sharedkernel.objects import JwtModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class JWTBearer(HTTPBearer):
|
|
11
|
+
|
|
12
|
+
def __init__(self,jwt_config:JwtModel, auto_error: bool = True):
|
|
13
|
+
self.jwt_config=jwt_config
|
|
14
|
+
super(JWTBearer, self).__init__(auto_error=auto_error)
|
|
15
|
+
|
|
16
|
+
async def __call__(self, request: Request):
|
|
17
|
+
try:
|
|
18
|
+
credentials: HTTPAuthorizationCredentials = await super(
|
|
19
|
+
JWTBearer, self
|
|
20
|
+
).__call__(request)
|
|
21
|
+
|
|
22
|
+
self.verify(credentials.credentials)
|
|
23
|
+
|
|
24
|
+
except:
|
|
25
|
+
raise UnAuthorizedException()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def verify(self, token: str) -> bool:
|
|
29
|
+
decoded_token = jwt.decode(
|
|
30
|
+
jwt= token.replace("Bearer","").strip(),
|
|
31
|
+
key= self.jwt_config.secret_key,
|
|
32
|
+
algorithms= self.jwt_config.algorithms,
|
|
33
|
+
audience= self.jwt_config.audience,
|
|
34
|
+
issuer= self.jwt_config.issuer
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if decoded_token["exp"] < time.time():
|
|
38
|
+
raise UnAuthorizedException()
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
from typing import Generic, TypeVar
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
from pydantic.generics import GenericModel
|
|
7
|
+
|
|
8
|
+
from sharedkernel.enum.error_code import ErrorCode
|
|
9
|
+
|
|
10
|
+
ResultT = TypeVar("ResultT")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BaseResult(BaseModel):
|
|
14
|
+
isSucceed:bool = True
|
|
15
|
+
message: str = ErrorCode.Success.value
|
|
16
|
+
errorCode: str = None
|
|
17
|
+
|
|
18
|
+
class Result(BaseResult,GenericModel, Generic[ResultT]):
|
|
19
|
+
data: ResultT =None
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
isSucceed:bool = True,
|
|
24
|
+
data: object = None,
|
|
25
|
+
message: str = ErrorCode.Success.value,
|
|
26
|
+
errorCode: str = None
|
|
27
|
+
)-> None:
|
|
28
|
+
super().__init__(isSucceed= isSucceed, data= data, message= message, errorCode= errorCode)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: sharedkernel
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: sharekernel is an shared package between all python projects
|
|
5
|
+
Author: Smilinno
|
|
6
|
+
Requires-Dist: numpy
|
|
7
|
+
Requires-Dist: requests
|
|
8
|
+
Requires-Dist: pymongo
|
|
9
|
+
Requires-Dist: fastapi ==0.89.1
|
|
10
|
+
Requires-Dist: PyJWT
|
|
11
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
sharedkernel/common.py,sha256=HL5vsuJBaIeBcoXA8Hbe6jnYAv4danIszo5Y7G2gGDA,622
|
|
2
|
+
sharedkernel/config.py,sha256=e77EbMSv-gTmtXklh1mYNHWuY-ztE7RKGv_sL6XS-Qo,326
|
|
3
|
+
sharedkernel/jwt_service.py,sha256=MzlfGROiNhUGDtCPNrpN5T0IgK_bn8M7tAJ9lnCUD9M,1178
|
|
4
|
+
sharedkernel/string_extentions.py,sha256=ld02W06gd0Ql80GQU6nlqPAeUSfOe2Yr8cCzf3lJgQY,98
|
|
5
|
+
sharedkernel/database/adapter.py,sha256=hxCRusICwWyNopG5rQ8lDHgaTc_-XbkUfugI67ccDm4,190
|
|
6
|
+
sharedkernel/database/repository_base.py,sha256=f0Lqn3aVmtuRSslMuV16hOTBq7A9X4G2QED4Far_OO4,2412
|
|
7
|
+
sharedkernel/enum/error_code.py,sha256=xGR0hGj4rbkBKvQQ_GOEInRay_f8yw6gs-GOsYmrX7w,387
|
|
8
|
+
sharedkernel/exception/__init__.py,sha256=VvWkai1Biz4KVYS58aS_xUdhhphS6WbxB2-lH05UiZs,319
|
|
9
|
+
sharedkernel/exception/exception.py,sha256=TOxnymWJfhsrMmuLsG-amqJlDxmzznEfRnqDBe1vizk,1016
|
|
10
|
+
sharedkernel/exception/exception_handlers.py,sha256=81b0sp_QL2TZJMplyZkFnh8tWmGzDdd7230EBcL1UOA,3176
|
|
11
|
+
sharedkernel/objects/__init__.py,sha256=7s5P9I3JQOrAhEWVyTPEHoQ7Xz_56UubfFJ-WEcHXTU,100
|
|
12
|
+
sharedkernel/objects/base_document.py,sha256=BLK_16ji_1BkahqZj9HAnju5pbI99PekcyMaPFAQ1NE,186
|
|
13
|
+
sharedkernel/objects/jwt_model.py,sha256=XQHQhTbg7PT8XiUh5fd9MwRH4ldPsesI_hfbjaSqdKg,134
|
|
14
|
+
sharedkernel/objects/result.py,sha256=zKGONnS9ctEE2XgegdWWhptIZhFvEF3qyz-me7nO_qo,721
|
|
15
|
+
sharedkernel-1.0.0.dist-info/METADATA,sha256=23XFIBvBTlD7-_ZXenHYgg4G8gxcrIlRQz9dYEIu3lc,276
|
|
16
|
+
sharedkernel-1.0.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
17
|
+
sharedkernel-1.0.0.dist-info/top_level.txt,sha256=TVTOnV1MItSSlpSjqkiijuHkoVsGHS4CArpsM-lylkE,13
|
|
18
|
+
sharedkernel-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sharedkernel
|