first commit
This commit is contained in:
97
schemas.py
Normal file
97
schemas.py
Normal file
@@ -0,0 +1,97 @@
|
||||
from pydantic import BaseModel, field_serializer, field_validator, Field
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
import re
|
||||
import html
|
||||
|
||||
# Message schemas
|
||||
class MessageBase(BaseModel):
|
||||
message: str = Field(..., min_length=1, max_length=1000, description="Message content")
|
||||
sender: str = Field(..., min_length=1, max_length=255, description="Sender name")
|
||||
item_id: Optional[int] = Field(None, ge=0, description="Item ID")
|
||||
amount: Optional[int] = Field(None, ge=0, description="Item amount")
|
||||
|
||||
# No validators on base class - they will be added to Create classes only
|
||||
|
||||
class MessageCreate(MessageBase):
|
||||
@field_validator('message', 'sender')
|
||||
@classmethod
|
||||
def sanitize_text(cls, v):
|
||||
"""Sanitize text input to prevent XSS and other attacks"""
|
||||
if not v:
|
||||
return v
|
||||
# HTML escape to prevent XSS
|
||||
v = html.escape(v.strip())
|
||||
# Remove any remaining script tags or dangerous patterns
|
||||
v = re.sub(r'<script.*?</script>', '', v, flags=re.IGNORECASE | re.DOTALL)
|
||||
v = re.sub(r'javascript:', '', v, flags=re.IGNORECASE)
|
||||
return v
|
||||
|
||||
@field_validator('sender')
|
||||
@classmethod
|
||||
def validate_sender(cls, v):
|
||||
"""Validate sender name format"""
|
||||
if not v:
|
||||
return v
|
||||
# Allow only alphanumeric, spaces, and common characters
|
||||
if not re.match(r'^[a-zA-Z0-9\s\-_\.]+$', v):
|
||||
raise ValueError('Sender name contains invalid characters')
|
||||
return v
|
||||
|
||||
class Message(MessageBase):
|
||||
id: int
|
||||
created_at: datetime
|
||||
|
||||
@field_serializer('created_at')
|
||||
def serialize_created_at(self, value: datetime) -> str:
|
||||
"""Format datetime to match plugin expectations: 'u-M-d H:m:s' (no leading zeros)"""
|
||||
return value.strftime("%Y-%-m-%-d %-H:%M:%S")
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
# Transaction schemas
|
||||
class TransactionBase(BaseModel):
|
||||
item_id: int = Field(..., ge=0, description="Item ID")
|
||||
item: str = Field(..., min_length=1, max_length=255, description="Item name")
|
||||
user: str = Field(..., min_length=1, max_length=255, description="User name")
|
||||
amount: int = Field(..., description="Transaction amount")
|
||||
|
||||
# No validators on base class - they will be added to Create classes only
|
||||
|
||||
class TransactionCreate(TransactionBase):
|
||||
@field_validator('item', 'user')
|
||||
@classmethod
|
||||
def sanitize_text(cls, v):
|
||||
"""Sanitize text input to prevent XSS and other attacks"""
|
||||
if not v:
|
||||
return v
|
||||
# HTML escape to prevent XSS
|
||||
v = html.escape(v.strip())
|
||||
# Remove any remaining script tags or dangerous patterns
|
||||
v = re.sub(r'<script.*?</script>', '', v, flags=re.IGNORECASE | re.DOTALL)
|
||||
v = re.sub(r'javascript:', '', v, flags=re.IGNORECASE)
|
||||
return v
|
||||
|
||||
@field_validator('user')
|
||||
@classmethod
|
||||
def validate_user(cls, v):
|
||||
"""Validate user name format"""
|
||||
if not v:
|
||||
return v
|
||||
# Allow only alphanumeric, spaces, and common characters
|
||||
if not re.match(r'^[a-zA-Z0-9\s\-_\.]+$', v):
|
||||
raise ValueError('User name contains invalid characters')
|
||||
return v
|
||||
|
||||
class Transaction(TransactionBase):
|
||||
id: int
|
||||
created_at: datetime
|
||||
|
||||
@field_serializer('created_at')
|
||||
def serialize_created_at(self, value: datetime) -> str:
|
||||
"""Format datetime to match plugin expectations: 'u-M-d H:m:s' (no leading zeros)"""
|
||||
return value.strftime("%Y-%-m-%-d %-H:%M:%S")
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
Reference in New Issue
Block a user