fix: fix the invalid id format issues
This commit is contained in:
parent
1823a33d45
commit
ba63e1b7a8
@ -132,9 +132,9 @@ class PermissionHandler:
|
|||||||
"""Query permissions with pagination and fuzzy search"""
|
"""Query permissions with pagination and fuzzy search"""
|
||||||
query = {}
|
query = {}
|
||||||
if permission_key:
|
if permission_key:
|
||||||
query[str(PermissionDoc.permission_key)] = {"$regex": permission_key, "$options": "i"}
|
query["permission_key"] = {"$regex": permission_key, "$options": "i"}
|
||||||
if permission_name:
|
if permission_name:
|
||||||
query[str(PermissionDoc.permission_name)] = {"$regex": permission_name, "$options": "i"}
|
query["permission_name"] = {"$regex": permission_name, "$options": "i"}
|
||||||
cursor = PermissionDoc.find(query)
|
cursor = PermissionDoc.find(query)
|
||||||
total = await cursor.count()
|
total = await cursor.count()
|
||||||
docs = await cursor.skip(skip).limit(limit).to_list()
|
docs = await cursor.skip(skip).limit(limit).to_list()
|
||||||
@ -150,13 +150,14 @@ class PermissionHandler:
|
|||||||
query = {}
|
query = {}
|
||||||
if permission_id:
|
if permission_id:
|
||||||
try:
|
try:
|
||||||
query[str(PermissionDoc.id)] = permission_id
|
ObjectId(permission_id) # Validate ObjectId format
|
||||||
|
query["_id"] = permission_id # Use MongoDB's _id field directly
|
||||||
except Exception:
|
except Exception:
|
||||||
raise RequestValidationError("Invalid permission_id format. Must be a valid ObjectId.")
|
raise RequestValidationError("Invalid permission_id format. Must be a valid ObjectId.")
|
||||||
if permission_key:
|
if permission_key:
|
||||||
query[str(PermissionDoc.permission_key)] = {"$regex": permission_key, "$options": "i"}
|
query["permission_key"] = {"$regex": permission_key, "$options": "i"}
|
||||||
if permission_name:
|
if permission_name:
|
||||||
query[str(PermissionDoc.permission_name)] = {"$regex": permission_name, "$options": "i"}
|
query["permission_name"] = {"$regex": permission_name, "$options": "i"}
|
||||||
cursor = PermissionDoc.find(query)
|
cursor = PermissionDoc.find(query)
|
||||||
total = await cursor.count()
|
total = await cursor.count()
|
||||||
docs = await cursor.to_list()
|
docs = await cursor.to_list()
|
||||||
|
|||||||
@ -126,9 +126,9 @@ class RoleHandler:
|
|||||||
"""Query roles with pagination and fuzzy search by role_key and role_name"""
|
"""Query roles with pagination and fuzzy search by role_key and role_name"""
|
||||||
query = {}
|
query = {}
|
||||||
if role_key:
|
if role_key:
|
||||||
query[str(RoleDoc.role_key)] = {"$regex": role_key, "$options": "i"}
|
query["role_key"] = {"$regex": role_key, "$options": "i"}
|
||||||
if role_name:
|
if role_name:
|
||||||
query[str(RoleDoc.role_name)] = {"$regex": role_name, "$options": "i"}
|
query["role_name"] = {"$regex": role_name, "$options": "i"}
|
||||||
cursor = RoleDoc.find(query)
|
cursor = RoleDoc.find(query)
|
||||||
total = await cursor.count()
|
total = await cursor.count()
|
||||||
docs = await cursor.skip(skip).limit(limit).to_list()
|
docs = await cursor.skip(skip).limit(limit).to_list()
|
||||||
@ -144,13 +144,14 @@ class RoleHandler:
|
|||||||
query = {}
|
query = {}
|
||||||
if role_id:
|
if role_id:
|
||||||
try:
|
try:
|
||||||
query[str(RoleDoc.id)] = role_id
|
ObjectId(role_id) # Validate ObjectId format
|
||||||
|
query["_id"] = role_id # Use MongoDB's _id field directly
|
||||||
except Exception:
|
except Exception:
|
||||||
raise RequestValidationError("Invalid role_id format. Must be a valid ObjectId.")
|
raise RequestValidationError("Invalid role_id format. Must be a valid ObjectId.")
|
||||||
if role_key:
|
if role_key:
|
||||||
query[str(RoleDoc.role_key)] = {"$regex": role_key, "$options": "i"}
|
query["role_key"] = {"$regex": role_key, "$options": "i"}
|
||||||
if role_name:
|
if role_name:
|
||||||
query[str(RoleDoc.role_name)] = {"$regex": role_name, "$options": "i"}
|
query["role_name"] = {"$regex": role_name, "$options": "i"}
|
||||||
cursor = RoleDoc.find(query)
|
cursor = RoleDoc.find(query)
|
||||||
total = await cursor.count()
|
total = await cursor.count()
|
||||||
docs = await cursor.to_list()
|
docs = await cursor.to_list()
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from datetime import datetime, timezone
|
|||||||
from typing import Optional, List, Dict, Any, Type, Union
|
from typing import Optional, List, Dict, Any, Type, Union
|
||||||
from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase
|
from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
from pydantic._internal._model_construction import ModelMetaclass
|
||||||
from common.config.app_settings import app_settings
|
from common.config.app_settings import app_settings
|
||||||
|
|
||||||
|
|
||||||
@ -14,27 +15,27 @@ class QueryExpression:
|
|||||||
def __init__(self, field_name: str):
|
def __init__(self, field_name: str):
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
|
|
||||||
def __eq__(self, other) -> dict:
|
def __eq__(self, other: Any) -> Dict[str, Any]:
|
||||||
"""Handle field == value comparisons"""
|
"""Handle field == value comparisons"""
|
||||||
return {self.field_name: other}
|
return {self.field_name: other}
|
||||||
|
|
||||||
def __ne__(self, other) -> dict:
|
def __ne__(self, other: Any) -> Dict[str, Any]:
|
||||||
"""Handle field != value comparisons"""
|
"""Handle field != value comparisons"""
|
||||||
return {self.field_name: {"$ne": other}}
|
return {self.field_name: {"$ne": other}}
|
||||||
|
|
||||||
def __gt__(self, other) -> dict:
|
def __gt__(self, other: Any) -> Dict[str, Any]:
|
||||||
"""Handle field > value comparisons"""
|
"""Handle field > value comparisons"""
|
||||||
return {self.field_name: {"$gt": other}}
|
return {self.field_name: {"$gt": other}}
|
||||||
|
|
||||||
def __lt__(self, other) -> dict:
|
def __lt__(self, other: Any) -> Dict[str, Any]:
|
||||||
"""Handle field < value comparisons"""
|
"""Handle field < value comparisons"""
|
||||||
return {self.field_name: {"$lt": other}}
|
return {self.field_name: {"$lt": other}}
|
||||||
|
|
||||||
def __ge__(self, other) -> dict:
|
def __ge__(self, other: Any) -> Dict[str, Any]:
|
||||||
"""Handle field >= value comparisons"""
|
"""Handle field >= value comparisons"""
|
||||||
return {self.field_name: {"$gte": other}}
|
return {self.field_name: {"$gte": other}}
|
||||||
|
|
||||||
def __le__(self, other) -> dict:
|
def __le__(self, other: Any) -> Dict[str, Any]:
|
||||||
"""Handle field <= value comparisons"""
|
"""Handle field <= value comparisons"""
|
||||||
return {self.field_name: {"$lte": other}}
|
return {self.field_name: {"$lte": other}}
|
||||||
|
|
||||||
@ -80,13 +81,13 @@ import contextvars
|
|||||||
_tenant_db_context: contextvars.ContextVar[Optional[AsyncIOMotorDatabase]] = contextvars.ContextVar('tenant_db', default=None)
|
_tenant_db_context: contextvars.ContextVar[Optional[AsyncIOMotorDatabase]] = contextvars.ContextVar('tenant_db', default=None)
|
||||||
|
|
||||||
|
|
||||||
class QueryModelMeta(type(BaseModel)):
|
class QueryModelMeta(ModelMetaclass):
|
||||||
"""Metaclass: automatically create FieldDescriptor for model fields"""
|
"""Metaclass: automatically create FieldDescriptor for model fields"""
|
||||||
def __new__(cls, name: str, bases: tuple, namespace: dict):
|
def __new__(cls, name: str, bases: tuple, namespace: dict):
|
||||||
# Get model field annotations (like name: str -> "name" and str)
|
# Get model field annotations (like name: str -> "name" and str)
|
||||||
annotations = namespace.get("__annotations__", {})
|
annotations = namespace.get("__annotations__", {})
|
||||||
|
|
||||||
# Create the class first
|
# Create the class first using Pydantic's metaclass
|
||||||
new_class = super().__new__(cls, name, bases, namespace)
|
new_class = super().__new__(cls, name, bases, namespace)
|
||||||
|
|
||||||
# After Pydantic processes the fields, add the descriptors as class attributes
|
# After Pydantic processes the fields, add the descriptors as class attributes
|
||||||
@ -97,6 +98,13 @@ class QueryModelMeta(type(BaseModel)):
|
|||||||
|
|
||||||
return new_class
|
return new_class
|
||||||
|
|
||||||
|
def __getattr__(cls, name: str):
|
||||||
|
"""Handle field access like Doc.field_name for query building"""
|
||||||
|
# Check if this is a field that exists in the model
|
||||||
|
if hasattr(cls, 'model_fields') and name in cls.model_fields:
|
||||||
|
return QueryExpression(name)
|
||||||
|
raise AttributeError(f"'{cls.__name__}' object has no attribute '{name}'")
|
||||||
|
|
||||||
class BaseDoc(BaseModel, metaclass=QueryModelMeta):
|
class BaseDoc(BaseModel, metaclass=QueryModelMeta):
|
||||||
"""
|
"""
|
||||||
Base document class that provides Beanie-like interface using direct MongoDB operations.
|
Base document class that provides Beanie-like interface using direct MongoDB operations.
|
||||||
@ -118,8 +126,10 @@ class BaseDoc(BaseModel, metaclass=QueryModelMeta):
|
|||||||
|
|
||||||
return filtered_result
|
return filtered_result
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def field(cls, field_name: str) -> QueryExpression:
|
||||||
|
"""Get a field expression for query building"""
|
||||||
|
return QueryExpression(field_name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def _get_database(cls) -> AsyncIOMotorDatabase:
|
async def _get_database(cls) -> AsyncIOMotorDatabase:
|
||||||
@ -344,8 +354,8 @@ class QueryBuilder:
|
|||||||
def __init__(self, model_class: Type[BaseDoc], conditions: tuple):
|
def __init__(self, model_class: Type[BaseDoc], conditions: tuple):
|
||||||
self.model_class = model_class
|
self.model_class = model_class
|
||||||
self.conditions = conditions
|
self.conditions = conditions
|
||||||
self._limit_value = None
|
self._limit_value: Optional[int] = None
|
||||||
self._skip_value = None
|
self._skip_value: Optional[int] = None
|
||||||
|
|
||||||
def limit(self, n: int) -> 'QueryBuilder':
|
def limit(self, n: int) -> 'QueryBuilder':
|
||||||
"""Limit number of results"""
|
"""Limit number of results"""
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user