enricher_template.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. """Pydantic schemas for enricher templates."""
  2. from datetime import datetime
  3. from typing import Any, Dict, Optional
  4. from pydantic import UUID4, BaseModel, Field, field_validator
  5. from .base import ORMBase
  6. class EnricherTemplateCreate(BaseModel):
  7. """Schema for creating a new enricher template."""
  8. name: str = Field(
  9. ..., min_length=1, max_length=255, description="Name of the template"
  10. )
  11. description: Optional[str] = Field(
  12. None, max_length=1000, description="Description of the template"
  13. )
  14. category: str = Field(
  15. ..., min_length=1, max_length=100, description="Category (e.g., Ip, Domain)"
  16. )
  17. version: float = Field(default=1.0, ge=0, description="Template version")
  18. content: Dict[str, Any] = Field(
  19. ..., description="Template content as parsed YAML/JSON"
  20. )
  21. is_public: bool = Field(
  22. default=False, description="Whether the template is publicly visible"
  23. )
  24. @field_validator("content")
  25. @classmethod
  26. def validate_content(cls, v: Dict[str, Any]) -> Dict[str, Any]:
  27. """Validate that content has required template fields."""
  28. required_fields = [
  29. "name",
  30. "category",
  31. "version",
  32. "input",
  33. "request",
  34. "output",
  35. "response",
  36. ]
  37. missing = [f for f in required_fields if f not in v]
  38. if missing:
  39. raise ValueError(
  40. f"Missing required fields in content: {', '.join(missing)}"
  41. )
  42. # Validate input
  43. if "input" in v and "type" not in v.get("input", {}):
  44. raise ValueError("input.type is required")
  45. # Validate request
  46. request = v.get("request", {})
  47. if "method" not in request:
  48. raise ValueError("request.method is required")
  49. if request.get("method") not in ["GET", "POST"]:
  50. raise ValueError("request.method must be GET or POST")
  51. if "url" not in request:
  52. raise ValueError("request.url is required")
  53. # Validate output
  54. if "output" in v and "type" not in v.get("output", {}):
  55. raise ValueError("output.type is required")
  56. # Validate response
  57. response = v.get("response", {})
  58. if "expect" not in response:
  59. raise ValueError("response.expect is required")
  60. if response.get("expect") not in ["json", "xml", "text"]:
  61. raise ValueError("response.expect must be json, xml, or text")
  62. return v
  63. class EnricherTemplateUpdate(BaseModel):
  64. """Schema for updating an existing enricher template."""
  65. name: Optional[str] = Field(None, min_length=1, max_length=255)
  66. description: Optional[str] = Field(None, max_length=1000)
  67. category: Optional[str] = Field(None, min_length=1, max_length=100)
  68. version: Optional[float] = Field(None, ge=0)
  69. content: Optional[Dict[str, Any]] = None
  70. is_public: Optional[bool] = None
  71. @field_validator("content")
  72. @classmethod
  73. def validate_content(cls, v: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
  74. """Validate content if provided."""
  75. if v is None:
  76. return v
  77. required_fields = [
  78. "name",
  79. "category",
  80. "version",
  81. "input",
  82. "request",
  83. "output",
  84. "response",
  85. ]
  86. missing = [f for f in required_fields if f not in v]
  87. if missing:
  88. raise ValueError(
  89. f"Missing required fields in content: {', '.join(missing)}"
  90. )
  91. return v
  92. class EnricherTemplateRead(ORMBase):
  93. """Schema for reading an enricher template."""
  94. id: UUID4
  95. name: str
  96. description: Optional[str]
  97. category: str
  98. version: float
  99. content: Dict[str, Any]
  100. is_public: bool
  101. owner_id: UUID4
  102. created_at: datetime
  103. updated_at: datetime
  104. class EnricherTemplateList(ORMBase):
  105. """Schema for listing enricher templates (minimal fields)."""
  106. id: UUID4
  107. name: str
  108. description: Optional[str]
  109. category: str
  110. version: float
  111. is_public: bool
  112. owner_id: UUID4
  113. created_at: datetime
  114. updated_at: datetime
  115. class EnricherTemplateTestRequest(BaseModel):
  116. """Schema for testing an enricher template by ID."""
  117. input_value: str = Field(
  118. ..., min_length=1, description="The value to test the template with"
  119. )
  120. class EnricherTemplateTestContentRequest(BaseModel):
  121. """Schema for testing template content directly (without saving)."""
  122. input_value: str = Field(
  123. ..., min_length=1, description="The value to test the template with"
  124. )
  125. content: Dict[str, Any] = Field(..., description="Template content to test")
  126. class EnricherTemplateTestResponse(BaseModel):
  127. """Schema for test response."""
  128. success: bool
  129. data: Optional[Dict[str, Any]] = None
  130. error: Optional[str] = None
  131. status_code: Optional[int] = None
  132. url: str
  133. class EnricherTemplateGenerateRequest(BaseModel):
  134. """Schema for AI-assisted template generation."""
  135. prompt: str = Field(
  136. ...,
  137. min_length=10,
  138. max_length=16000,
  139. description="Free-text description of the desired enricher template",
  140. )
  141. input_type: Optional[str] = Field(
  142. None, description="Flowsint input type name (e.g. 'Ip', 'Domain')"
  143. )
  144. output_type: Optional[str] = Field(
  145. None, description="Flowsint output type name (e.g. 'Ip', 'SocialAccount')"
  146. )
  147. class EnricherTemplateGenerateResponse(BaseModel):
  148. """Schema for the generated template response."""
  149. yaml_content: str = Field(
  150. ..., description="Raw YAML string of the generated template"
  151. )