Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
All services: admin-v2, studio-v2, website, ai-compliance-sdk, consent-service, klausur-service, voice-service, and infrastructure. Large PDFs and compiled binaries excluded via .gitignore.
192 lines
4.8 KiB
Python
192 lines
4.8 KiB
Python
"""
|
|
Pydantic Schemas für Content Service API
|
|
"""
|
|
from pydantic import BaseModel, Field, validator
|
|
from typing import Optional, List
|
|
from datetime import datetime
|
|
from models import ContentType, CCLicense, ContentCategory, ContentStatus
|
|
|
|
# ============= REQUEST SCHEMAS =============
|
|
|
|
class ContentCreate(BaseModel):
|
|
"""Schema für Content Creation"""
|
|
title: str = Field(..., min_length=3, max_length=500)
|
|
description: Optional[str] = Field(None, max_length=5000)
|
|
content_type: ContentType
|
|
category: ContentCategory
|
|
license: CCLicense = CCLicense.CC_BY_SA
|
|
|
|
age_min: int = Field(6, ge=3, le=18)
|
|
age_max: int = Field(18, ge=3, le=18)
|
|
|
|
embed_url: Optional[str] = None
|
|
tags: List[str] = []
|
|
|
|
@validator('age_max')
|
|
def age_max_must_be_greater(cls, v, values):
|
|
if 'age_min' in values and v < values['age_min']:
|
|
raise ValueError('age_max must be >= age_min')
|
|
return v
|
|
|
|
class ContentUpdate(BaseModel):
|
|
"""Schema für Content Update"""
|
|
title: Optional[str] = Field(None, min_length=3, max_length=500)
|
|
description: Optional[str] = Field(None, max_length=5000)
|
|
category: Optional[ContentCategory] = None
|
|
license: Optional[CCLicense] = None
|
|
age_min: Optional[int] = Field(None, ge=3, le=18)
|
|
age_max: Optional[int] = Field(None, ge=3, le=18)
|
|
embed_url: Optional[str] = None
|
|
tags: Optional[List[str]] = None
|
|
status: Optional[ContentStatus] = None
|
|
|
|
class RatingCreate(BaseModel):
|
|
"""Schema für Rating Creation"""
|
|
stars: int = Field(..., ge=1, le=5)
|
|
comment: Optional[str] = Field(None, max_length=2000)
|
|
|
|
# ============= RESPONSE SCHEMAS =============
|
|
|
|
class TagResponse(BaseModel):
|
|
"""Tag Response"""
|
|
id: str
|
|
name: str
|
|
category: Optional[str]
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class RatingResponse(BaseModel):
|
|
"""Rating Response"""
|
|
id: str
|
|
user_id: str
|
|
user_name: Optional[str]
|
|
stars: int
|
|
comment: Optional[str]
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class ContentResponse(BaseModel):
|
|
"""Content Response (Full)"""
|
|
id: str
|
|
creator_id: str
|
|
creator_name: str
|
|
creator_email: Optional[str]
|
|
|
|
title: str
|
|
description: Optional[str]
|
|
content_type: ContentType
|
|
category: ContentCategory
|
|
license: CCLicense
|
|
|
|
age_min: int
|
|
age_max: int
|
|
|
|
files: List[str]
|
|
thumbnail_url: Optional[str]
|
|
embed_url: Optional[str]
|
|
h5p_content_id: Optional[str]
|
|
|
|
matrix_room_id: Optional[str]
|
|
matrix_event_id: Optional[str]
|
|
|
|
status: ContentStatus
|
|
|
|
downloads: int
|
|
views: int
|
|
avg_rating: float
|
|
rating_count: int
|
|
impact_score: float
|
|
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
published_at: Optional[datetime]
|
|
|
|
tags: List[TagResponse] = []
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class ContentListItem(BaseModel):
|
|
"""Content Response (List View - simplified)"""
|
|
id: str
|
|
creator_name: str
|
|
title: str
|
|
description: Optional[str]
|
|
content_type: ContentType
|
|
category: ContentCategory
|
|
license: CCLicense
|
|
thumbnail_url: Optional[str]
|
|
avg_rating: float
|
|
rating_count: int
|
|
downloads: int
|
|
created_at: datetime
|
|
tags: List[str] = []
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class ContentWithRatings(ContentResponse):
|
|
"""Content with ratings included"""
|
|
ratings: List[RatingResponse] = []
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
# ============= FILTER SCHEMAS =============
|
|
|
|
class ContentFilter(BaseModel):
|
|
"""Search/Filter Parameters"""
|
|
search: Optional[str] = None
|
|
category: Optional[ContentCategory] = None
|
|
content_type: Optional[ContentType] = None
|
|
license: Optional[CCLicense] = None
|
|
age_min: Optional[int] = None
|
|
age_max: Optional[int] = None
|
|
tags: Optional[List[str]] = None
|
|
min_rating: Optional[float] = None
|
|
status: Optional[ContentStatus] = ContentStatus.PUBLISHED
|
|
creator_id: Optional[str] = None
|
|
|
|
# Pagination
|
|
skip: int = Field(0, ge=0)
|
|
limit: int = Field(20, ge=1, le=100)
|
|
|
|
# Sorting
|
|
sort_by: str = Field("created_at", pattern="^(created_at|avg_rating|downloads|title)$")
|
|
sort_desc: bool = True
|
|
|
|
# ============= ANALYTICS SCHEMAS =============
|
|
|
|
class ContentStats(BaseModel):
|
|
"""Content Statistics"""
|
|
total_contents: int
|
|
total_downloads: int
|
|
total_views: int
|
|
avg_rating: float
|
|
by_category: dict
|
|
by_type: dict
|
|
by_license: dict
|
|
|
|
class CreatorStats(BaseModel):
|
|
"""Creator Statistics"""
|
|
creator_id: str
|
|
creator_name: str
|
|
total_contents: int
|
|
total_downloads: int
|
|
total_views: int
|
|
avg_rating: float
|
|
impact_score: float
|
|
content_breakdown: dict
|
|
|
|
# ============= UPLOAD SCHEMAS =============
|
|
|
|
class FileUploadResponse(BaseModel):
|
|
"""File Upload Response"""
|
|
file_url: str
|
|
file_name: str
|
|
file_size: int
|
|
content_type: str
|