Initial commit: MCP Hub Community Edition v3.0.0
Community edition generated from private repo via sync pipeline. Includes 9 plugins (WordPress, WooCommerce, WP Advanced, Gitea, n8n, Supabase, OpenPanel, Appwrite, Directus) with ~587 tools. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
127
plugins/gitea/schemas/__init__.py
Normal file
127
plugins/gitea/schemas/__init__.py
Normal file
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
Gitea Plugin Pydantic Schemas
|
||||
|
||||
All validation schemas for Gitea plugin operations.
|
||||
"""
|
||||
|
||||
from .common import (
|
||||
ErrorResponse,
|
||||
GiteaPermissions,
|
||||
GiteaTimestamps,
|
||||
GiteaUser,
|
||||
PaginationParams,
|
||||
Site,
|
||||
SuccessResponse,
|
||||
)
|
||||
from .issue import (
|
||||
Comment,
|
||||
CreateCommentRequest,
|
||||
CreateIssueRequest,
|
||||
CreateLabelRequest,
|
||||
CreateMilestoneRequest,
|
||||
Issue,
|
||||
IssueListFilters,
|
||||
Label,
|
||||
Milestone,
|
||||
UpdateIssueRequest,
|
||||
)
|
||||
from .pull_request import (
|
||||
CreatePullRequestRequest,
|
||||
CreateReviewRequest,
|
||||
MergePullRequestRequest,
|
||||
PRBranchInfo,
|
||||
PRCommit,
|
||||
PRFile,
|
||||
PRListFilters,
|
||||
PRReview,
|
||||
PullRequest,
|
||||
RequestReviewersRequest,
|
||||
UpdatePullRequestRequest,
|
||||
)
|
||||
from .repository import (
|
||||
Branch,
|
||||
CreateBranchRequest,
|
||||
CreateFileRequest,
|
||||
CreateRepositoryRequest,
|
||||
CreateTagRequest,
|
||||
FileContent,
|
||||
Repository,
|
||||
Tag,
|
||||
UpdateFileRequest,
|
||||
UpdateRepositoryRequest,
|
||||
)
|
||||
from .user import (
|
||||
Email,
|
||||
Organization,
|
||||
SearchOrgsRequest,
|
||||
SearchUsersRequest,
|
||||
Team,
|
||||
TeamMember,
|
||||
User,
|
||||
)
|
||||
from .webhook import (
|
||||
CreateWebhookRequest,
|
||||
UpdateWebhookRequest,
|
||||
Webhook,
|
||||
WebhookConfig,
|
||||
WebhookTestResult,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# Common
|
||||
"Site",
|
||||
"PaginationParams",
|
||||
"ErrorResponse",
|
||||
"SuccessResponse",
|
||||
"GiteaUser",
|
||||
"GiteaPermissions",
|
||||
"GiteaTimestamps",
|
||||
# Repository
|
||||
"Repository",
|
||||
"Branch",
|
||||
"Tag",
|
||||
"FileContent",
|
||||
"CreateRepositoryRequest",
|
||||
"UpdateRepositoryRequest",
|
||||
"CreateBranchRequest",
|
||||
"CreateTagRequest",
|
||||
"CreateFileRequest",
|
||||
"UpdateFileRequest",
|
||||
# Issue
|
||||
"Label",
|
||||
"Milestone",
|
||||
"Issue",
|
||||
"Comment",
|
||||
"CreateIssueRequest",
|
||||
"UpdateIssueRequest",
|
||||
"CreateCommentRequest",
|
||||
"CreateLabelRequest",
|
||||
"CreateMilestoneRequest",
|
||||
"IssueListFilters",
|
||||
# Pull Request
|
||||
"PRBranchInfo",
|
||||
"PullRequest",
|
||||
"PRReview",
|
||||
"PRCommit",
|
||||
"PRFile",
|
||||
"CreatePullRequestRequest",
|
||||
"UpdatePullRequestRequest",
|
||||
"MergePullRequestRequest",
|
||||
"CreateReviewRequest",
|
||||
"RequestReviewersRequest",
|
||||
"PRListFilters",
|
||||
# User
|
||||
"User",
|
||||
"Organization",
|
||||
"Team",
|
||||
"TeamMember",
|
||||
"Email",
|
||||
"SearchUsersRequest",
|
||||
"SearchOrgsRequest",
|
||||
# Webhook
|
||||
"Webhook",
|
||||
"WebhookConfig",
|
||||
"CreateWebhookRequest",
|
||||
"UpdateWebhookRequest",
|
||||
"WebhookTestResult",
|
||||
]
|
||||
73
plugins/gitea/schemas/common.py
Normal file
73
plugins/gitea/schemas/common.py
Normal file
@@ -0,0 +1,73 @@
|
||||
"""
|
||||
Common Pydantic Schemas for Gitea Plugin
|
||||
|
||||
Shared validation schemas used across Gitea handlers.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
class Site(BaseModel):
|
||||
"""Gitea site configuration"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
site_id: str = Field(..., description="Site identifier (e.g., 'site1')")
|
||||
url: str = Field(..., description="Gitea instance URL")
|
||||
token: str | None = Field(None, description="Personal access token")
|
||||
alias: str | None = Field(None, description="Site alias")
|
||||
oauth_enabled: bool = Field(default=False, description="Whether OAuth is enabled")
|
||||
|
||||
class PaginationParams(BaseModel):
|
||||
"""Pagination parameters for list endpoints"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
page: int = Field(default=1, ge=1, description="Page number (starts at 1)")
|
||||
limit: int = Field(default=30, ge=1, le=100, description="Number of items per page (1-100)")
|
||||
|
||||
class ErrorResponse(BaseModel):
|
||||
"""Standard error response"""
|
||||
|
||||
error: bool = Field(default=True)
|
||||
message: str = Field(..., description="Error message")
|
||||
code: str | None = Field(None, description="Error code")
|
||||
details: dict[str, Any] | None = Field(None, description="Additional error details")
|
||||
|
||||
class SuccessResponse(BaseModel):
|
||||
"""Standard success response"""
|
||||
|
||||
success: bool = Field(default=True)
|
||||
message: str = Field(..., description="Success message")
|
||||
data: dict[str, Any] | None = Field(None, description="Response data")
|
||||
|
||||
class GiteaUser(BaseModel):
|
||||
"""Gitea user information"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
login: str
|
||||
full_name: str | None = None
|
||||
email: str | None = None
|
||||
avatar_url: str | None = None
|
||||
is_admin: bool = False
|
||||
|
||||
class GiteaPermissions(BaseModel):
|
||||
"""Repository permissions"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
admin: bool = False
|
||||
push: bool = False
|
||||
pull: bool = False
|
||||
|
||||
class GiteaTimestamps(BaseModel):
|
||||
"""Common timestamp fields"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
184
plugins/gitea/schemas/issue.py
Normal file
184
plugins/gitea/schemas/issue.py
Normal file
@@ -0,0 +1,184 @@
|
||||
"""
|
||||
Issue Pydantic Schemas
|
||||
|
||||
Validation schemas for Gitea issue operations.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
|
||||
from .common import GiteaUser
|
||||
|
||||
class Label(BaseModel):
|
||||
"""Issue/PR label"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
name: str
|
||||
color: str
|
||||
description: str | None = None
|
||||
url: str | None = None
|
||||
|
||||
class Milestone(BaseModel):
|
||||
"""Issue/PR milestone"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
title: str
|
||||
description: str | None = None
|
||||
state: str # "open" or "closed"
|
||||
open_issues: int = 0
|
||||
closed_issues: int = 0
|
||||
created_at: datetime
|
||||
updated_at: datetime | None = None
|
||||
closed_at: datetime | None = None
|
||||
due_on: datetime | None = None
|
||||
|
||||
class Issue(BaseModel):
|
||||
"""Gitea issue model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
number: int
|
||||
user: GiteaUser
|
||||
original_author: str | None = None
|
||||
original_author_id: int | None = None
|
||||
title: str
|
||||
body: str | None = None
|
||||
ref: str | None = None
|
||||
labels: list[Label] = []
|
||||
milestone: Milestone | None = None
|
||||
assignee: GiteaUser | None = None
|
||||
assignees: list[GiteaUser] = []
|
||||
state: str # "open" or "closed"
|
||||
is_locked: bool = False
|
||||
comments: int = 0
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
closed_at: datetime | None = None
|
||||
due_date: datetime | None = None
|
||||
pull_request: dict | None = None # Non-null if this is a PR
|
||||
repository: dict | None = None
|
||||
html_url: str
|
||||
url: str
|
||||
|
||||
class Comment(BaseModel):
|
||||
"""Issue/PR comment"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
html_url: str
|
||||
pull_request_url: str | None = None
|
||||
issue_url: str | None = None
|
||||
user: GiteaUser
|
||||
original_author: str | None = None
|
||||
original_author_id: int | None = None
|
||||
body: str
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class CreateIssueRequest(BaseModel):
|
||||
"""Request to create an issue"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
title: str = Field(..., min_length=1, max_length=255, description="Issue title")
|
||||
body: str | None = Field(None, description="Issue body/description")
|
||||
assignee: str | None = Field(None, description="Username of assignee")
|
||||
assignees: list[str] | None = Field(None, description="List of assignee usernames")
|
||||
closed: bool | None = Field(False, description="Create as closed")
|
||||
due_date: datetime | None = Field(None, description="Due date")
|
||||
labels: list[int] | None = Field(None, description="List of label IDs")
|
||||
milestone: int | None = Field(None, description="Milestone ID")
|
||||
ref: str | None = Field(None, description="Issue ref")
|
||||
|
||||
class UpdateIssueRequest(BaseModel):
|
||||
"""Request to update an issue"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
title: str | None = Field(None, min_length=1, max_length=255, description="Issue title")
|
||||
body: str | None = Field(None, description="Issue body/description")
|
||||
assignee: str | None = Field(None, description="Username of assignee")
|
||||
assignees: list[str] | None = Field(None, description="List of assignee usernames")
|
||||
state: str | None = Field(None, description="State (open/closed)")
|
||||
due_date: datetime | None = Field(None, description="Due date")
|
||||
labels: list[int] | None = Field(None, description="List of label IDs")
|
||||
milestone: int | None = Field(None, description="Milestone ID")
|
||||
ref: str | None = Field(None, description="Issue ref")
|
||||
unset_due_date: bool | None = Field(None, description="Unset due date")
|
||||
|
||||
@classmethod
|
||||
@field_validator("state")
|
||||
def validate_state(cls, v):
|
||||
if v and v not in ["open", "closed"]:
|
||||
raise ValueError("State must be 'open' or 'closed'")
|
||||
return v
|
||||
|
||||
class CreateCommentRequest(BaseModel):
|
||||
"""Request to create a comment"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
body: str = Field(..., min_length=1, description="Comment body")
|
||||
|
||||
class CreateLabelRequest(BaseModel):
|
||||
"""Request to create a label"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
name: str = Field(..., min_length=1, max_length=50, description="Label name")
|
||||
color: str = Field(..., pattern=r"^[0-9A-Fa-f]{6}$", description="Label color (hex without #)")
|
||||
description: str | None = Field(None, max_length=200, description="Label description")
|
||||
|
||||
class CreateMilestoneRequest(BaseModel):
|
||||
"""Request to create a milestone"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
title: str = Field(..., min_length=1, max_length=255, description="Milestone title")
|
||||
description: str | None = Field(None, description="Milestone description")
|
||||
due_on: datetime | None = Field(None, description="Due date")
|
||||
state: str | None = Field("open", description="State (open/closed)")
|
||||
|
||||
@classmethod
|
||||
@field_validator("state")
|
||||
def validate_state(cls, v):
|
||||
if v not in ["open", "closed"]:
|
||||
raise ValueError("State must be 'open' or 'closed'")
|
||||
return v
|
||||
|
||||
class IssueListFilters(BaseModel):
|
||||
"""Filters for listing issues"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
state: str | None = Field("open", description="Filter by state (open/closed/all)")
|
||||
labels: str | None = Field(None, description="Comma-separated label IDs")
|
||||
q: str | None = Field(None, description="Search query")
|
||||
type: str | None = Field(None, description="Filter by type (issues/pulls)")
|
||||
milestones: str | None = Field(None, description="Comma-separated milestone names")
|
||||
since: datetime | None = Field(None, description="Only show items updated after this time")
|
||||
before: datetime | None = Field(None, description="Only show items updated before this time")
|
||||
created_by: str | None = Field(None, description="Filter by creator username")
|
||||
assigned_by: str | None = Field(None, description="Filter by assignee username")
|
||||
mentioned_by: str | None = Field(None, description="Filter by mentioned username")
|
||||
|
||||
@classmethod
|
||||
@field_validator("state")
|
||||
def validate_state(cls, v):
|
||||
if v and v not in ["open", "closed", "all"]:
|
||||
raise ValueError("State must be 'open', 'closed', or 'all'")
|
||||
return v
|
||||
|
||||
@classmethod
|
||||
@field_validator("type")
|
||||
def validate_type(cls, v):
|
||||
if v and v not in ["issues", "pulls"]:
|
||||
raise ValueError("Type must be 'issues' or 'pulls'")
|
||||
return v
|
||||
215
plugins/gitea/schemas/pull_request.py
Normal file
215
plugins/gitea/schemas/pull_request.py
Normal file
@@ -0,0 +1,215 @@
|
||||
"""
|
||||
Pull Request Pydantic Schemas
|
||||
|
||||
Validation schemas for Gitea pull request operations.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
|
||||
from .common import GiteaUser
|
||||
from .issue import Label, Milestone
|
||||
|
||||
class PRBranchInfo(BaseModel):
|
||||
"""Pull request branch information"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
label: str
|
||||
ref: str
|
||||
sha: str
|
||||
repo_id: int
|
||||
repository: dict | None = None
|
||||
|
||||
class PullRequest(BaseModel):
|
||||
"""Gitea pull request model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
number: int
|
||||
user: GiteaUser
|
||||
title: str
|
||||
body: str | None = None
|
||||
labels: list[Label] = []
|
||||
milestone: Milestone | None = None
|
||||
assignee: GiteaUser | None = None
|
||||
assignees: list[GiteaUser] = []
|
||||
requested_reviewers: list[GiteaUser] = []
|
||||
state: str # "open" or "closed"
|
||||
is_locked: bool = False
|
||||
comments: int = 0
|
||||
html_url: str
|
||||
diff_url: str
|
||||
patch_url: str
|
||||
mergeable: bool = False
|
||||
merged: bool = False
|
||||
merged_at: datetime | None = None
|
||||
merge_commit_sha: str | None = None
|
||||
merged_by: GiteaUser | None = None
|
||||
base: PRBranchInfo
|
||||
head: PRBranchInfo
|
||||
merge_base: str | None = None
|
||||
due_date: datetime | None = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
closed_at: datetime | None = None
|
||||
allow_maintainer_edit: bool = False
|
||||
url: str
|
||||
|
||||
class PRReview(BaseModel):
|
||||
"""Pull request review"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
user: GiteaUser
|
||||
body: str | None = None
|
||||
commit_id: str
|
||||
state: str # "PENDING", "APPROVED", "REQUEST_CHANGES", "COMMENT"
|
||||
html_url: str
|
||||
pull_request_url: str
|
||||
submitted_at: datetime
|
||||
|
||||
class PRCommit(BaseModel):
|
||||
"""Pull request commit"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
sha: str
|
||||
commit: dict
|
||||
url: str
|
||||
html_url: str
|
||||
comments_url: str
|
||||
author: GiteaUser | None = None
|
||||
committer: GiteaUser | None = None
|
||||
parents: list[dict] = []
|
||||
|
||||
class PRFile(BaseModel):
|
||||
"""Pull request file change"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
filename: str
|
||||
status: str # "added", "removed", "modified", "renamed"
|
||||
additions: int
|
||||
deletions: int
|
||||
changes: int
|
||||
raw_url: str | None = None
|
||||
contents_url: str | None = None
|
||||
patch: str | None = None
|
||||
previous_filename: str | None = None
|
||||
|
||||
class CreatePullRequestRequest(BaseModel):
|
||||
"""Request to create a pull request"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
title: str = Field(..., min_length=1, max_length=255, description="PR title")
|
||||
head: str = Field(..., description="Source branch")
|
||||
base: str = Field(..., description="Target branch")
|
||||
body: str | None = Field(None, description="PR description")
|
||||
assignee: str | None = Field(None, description="Username of assignee")
|
||||
assignees: list[str] | None = Field(None, description="List of assignee usernames")
|
||||
labels: list[int] | None = Field(None, description="List of label IDs")
|
||||
milestone: int | None = Field(None, description="Milestone ID")
|
||||
due_date: datetime | None = Field(None, description="Due date")
|
||||
|
||||
class UpdatePullRequestRequest(BaseModel):
|
||||
"""Request to update a pull request"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
title: str | None = Field(None, min_length=1, max_length=255, description="PR title")
|
||||
body: str | None = Field(None, description="PR description")
|
||||
assignee: str | None = Field(None, description="Username of assignee")
|
||||
assignees: list[str] | None = Field(None, description="List of assignee usernames")
|
||||
labels: list[int] | None = Field(None, description="List of label IDs")
|
||||
milestone: int | None = Field(None, description="Milestone ID")
|
||||
state: str | None = Field(None, description="State (open/closed)")
|
||||
due_date: datetime | None = Field(None, description="Due date")
|
||||
unset_due_date: bool | None = Field(None, description="Unset due date")
|
||||
allow_maintainer_edit: bool | None = Field(None, description="Allow maintainer edit")
|
||||
|
||||
@classmethod
|
||||
@field_validator("state")
|
||||
def validate_state(cls, v):
|
||||
if v and v not in ["open", "closed"]:
|
||||
raise ValueError("State must be 'open' or 'closed'")
|
||||
return v
|
||||
|
||||
class MergePullRequestRequest(BaseModel):
|
||||
"""Request to merge a pull request"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
Do: str = Field(
|
||||
..., description="Merge method (merge/rebase/rebase-merge/squash/manually-merged)"
|
||||
)
|
||||
MergeTitleField: str | None = Field(None, description="Merge commit title")
|
||||
MergeMessageField: str | None = Field(None, description="Merge commit message")
|
||||
delete_branch_after_merge: bool | None = Field(False, description="Delete branch after merge")
|
||||
force_merge: bool | None = Field(False, description="Force merge even if not mergeable")
|
||||
head_commit_id: str | None = Field(None, description="Expected HEAD commit SHA")
|
||||
merge_when_checks_succeed: bool | None = Field(False, description="Auto-merge when checks pass")
|
||||
|
||||
@classmethod
|
||||
@field_validator("Do")
|
||||
def validate_merge_method(cls, v):
|
||||
allowed = ["merge", "rebase", "rebase-merge", "squash", "manually-merged"]
|
||||
if v not in allowed:
|
||||
raise ValueError(f"Merge method must be one of: {', '.join(allowed)}")
|
||||
return v
|
||||
|
||||
class CreateReviewRequest(BaseModel):
|
||||
"""Request to create a review"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
body: str | None = Field(None, description="Review comment")
|
||||
event: str = Field(..., description="Review event (APPROVED/REQUEST_CHANGES/COMMENT)")
|
||||
comments: list[dict] | None = Field(None, description="Inline review comments")
|
||||
|
||||
@classmethod
|
||||
@field_validator("event")
|
||||
def validate_event(cls, v):
|
||||
allowed = ["APPROVED", "REQUEST_CHANGES", "COMMENT"]
|
||||
if v not in allowed:
|
||||
raise ValueError(f"Review event must be one of: {', '.join(allowed)}")
|
||||
return v
|
||||
|
||||
class RequestReviewersRequest(BaseModel):
|
||||
"""Request reviewers for a pull request"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
reviewers: list[str] = Field(..., min_items=1, description="List of reviewer usernames")
|
||||
team_reviewers: list[str] | None = Field(None, description="List of team slugs")
|
||||
|
||||
class PRListFilters(BaseModel):
|
||||
"""Filters for listing pull requests"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
state: str | None = Field("open", description="Filter by state (open/closed/all)")
|
||||
sort: str | None = Field(
|
||||
"created", description="Sort by (created/updated/comments/recentupdate)"
|
||||
)
|
||||
labels: str | None = Field(None, description="Comma-separated label IDs")
|
||||
milestone: str | None = Field(None, description="Milestone name")
|
||||
|
||||
@classmethod
|
||||
@field_validator("state")
|
||||
def validate_state(cls, v):
|
||||
if v and v not in ["open", "closed", "all"]:
|
||||
raise ValueError("State must be 'open', 'closed', or 'all'")
|
||||
return v
|
||||
|
||||
@classmethod
|
||||
@field_validator("sort")
|
||||
def validate_sort(cls, v):
|
||||
allowed = ["created", "updated", "comments", "recentupdate"]
|
||||
if v and v not in allowed:
|
||||
raise ValueError(f"Sort must be one of: {', '.join(allowed)}")
|
||||
return v
|
||||
196
plugins/gitea/schemas/repository.py
Normal file
196
plugins/gitea/schemas/repository.py
Normal file
@@ -0,0 +1,196 @@
|
||||
"""
|
||||
Repository Pydantic Schemas
|
||||
|
||||
Validation schemas for Gitea repository operations.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
|
||||
from .common import GiteaPermissions, GiteaUser
|
||||
|
||||
class Repository(BaseModel):
|
||||
"""Gitea repository model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
owner: GiteaUser
|
||||
name: str
|
||||
full_name: str
|
||||
description: str | None = None
|
||||
empty: bool = False
|
||||
private: bool = False
|
||||
fork: bool = False
|
||||
template: bool = False
|
||||
parent: Optional["Repository"] = None
|
||||
mirror: bool = False
|
||||
size: int = 0
|
||||
language: str | None = None
|
||||
languages_url: str | None = None
|
||||
html_url: str
|
||||
ssh_url: str
|
||||
clone_url: str
|
||||
original_url: str | None = None
|
||||
website: str | None = None
|
||||
stars_count: int = 0
|
||||
forks_count: int = 0
|
||||
watchers_count: int = 0
|
||||
open_issues_count: int = 0
|
||||
open_pr_counter: int = 0
|
||||
release_counter: int = 0
|
||||
default_branch: str = "main"
|
||||
archived: bool = False
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
permissions: GiteaPermissions | None = None
|
||||
has_issues: bool = True
|
||||
internal_tracker: dict | None = None
|
||||
has_wiki: bool = False
|
||||
has_pull_requests: bool = True
|
||||
has_projects: bool = False
|
||||
ignore_whitespace_conflicts: bool = False
|
||||
allow_merge_commits: bool = True
|
||||
allow_rebase: bool = True
|
||||
allow_rebase_explicit: bool = True
|
||||
allow_squash_merge: bool = True
|
||||
default_merge_style: str = "merge"
|
||||
avatar_url: str | None = None
|
||||
|
||||
class Branch(BaseModel):
|
||||
"""Git branch model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
name: str
|
||||
commit: dict
|
||||
protected: bool = False
|
||||
required_approvals: int | None = None
|
||||
enable_status_check: bool = False
|
||||
status_check_contexts: list[str] | None = None
|
||||
user_can_push: bool = False
|
||||
user_can_merge: bool = False
|
||||
|
||||
class Tag(BaseModel):
|
||||
"""Git tag model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
name: str
|
||||
message: str | None = None
|
||||
id: str
|
||||
commit: dict
|
||||
zipball_url: str | None = None
|
||||
tarball_url: str | None = None
|
||||
|
||||
class FileContent(BaseModel):
|
||||
"""File content model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
name: str
|
||||
path: str
|
||||
sha: str
|
||||
size: int
|
||||
url: str
|
||||
html_url: str
|
||||
git_url: str
|
||||
download_url: str | None = None
|
||||
type: str # "file" or "dir"
|
||||
content: str | None = None # Base64 encoded
|
||||
encoding: str | None = None
|
||||
target: str | None = None # For symlinks
|
||||
submodule_git_url: str | None = None
|
||||
|
||||
class CreateRepositoryRequest(BaseModel):
|
||||
"""Request to create a repository"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
name: str = Field(..., min_length=1, max_length=100, description="Repository name")
|
||||
description: str | None = Field(None, max_length=500, description="Repository description")
|
||||
private: bool = Field(default=False, description="Make repository private")
|
||||
auto_init: bool = Field(default=False, description="Initialize with README")
|
||||
gitignores: str | None = Field(None, description="Gitignore template")
|
||||
license: str | None = Field(None, description="License template")
|
||||
readme: str | None = Field(None, description="Readme template")
|
||||
default_branch: str | None = Field(None, description="Default branch name")
|
||||
trust_model: str | None = Field(
|
||||
None, description="Trust model (default, collaborator, committer, collaboratorcommitter)"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@field_validator("name")
|
||||
def validate_name(cls, v):
|
||||
"""Validate repository name"""
|
||||
if not v.replace("-", "").replace("_", "").replace(".", "").isalnum():
|
||||
raise ValueError(
|
||||
"Repository name can only contain alphanumeric characters, hyphens, underscores, and dots"
|
||||
)
|
||||
return v
|
||||
|
||||
class UpdateRepositoryRequest(BaseModel):
|
||||
"""Request to update a repository"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
name: str | None = Field(None, min_length=1, max_length=100, description="New repository name")
|
||||
description: str | None = Field(None, max_length=500, description="Repository description")
|
||||
website: str | None = Field(None, description="Repository website")
|
||||
private: bool | None = Field(None, description="Make repository private")
|
||||
archived: bool | None = Field(None, description="Archive repository")
|
||||
has_issues: bool | None = Field(None, description="Enable issues")
|
||||
has_wiki: bool | None = Field(None, description="Enable wiki")
|
||||
default_branch: str | None = Field(None, description="Default branch")
|
||||
allow_merge_commits: bool | None = Field(None, description="Allow merge commits")
|
||||
allow_rebase: bool | None = Field(None, description="Allow rebase")
|
||||
allow_squash_merge: bool | None = Field(None, description="Allow squash merge")
|
||||
|
||||
class CreateBranchRequest(BaseModel):
|
||||
"""Request to create a branch"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
new_branch_name: str = Field(..., min_length=1, description="New branch name")
|
||||
old_branch_name: str | None = Field(None, description="Source branch (default: default branch)")
|
||||
old_ref_name: str | None = Field(None, description="Source commit SHA or ref")
|
||||
|
||||
class CreateTagRequest(BaseModel):
|
||||
"""Request to create a tag"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
tag_name: str = Field(..., min_length=1, description="Tag name")
|
||||
message: str | None = Field(None, description="Tag message")
|
||||
target: str | None = Field(None, description="Target commit SHA (default: latest)")
|
||||
|
||||
class CreateFileRequest(BaseModel):
|
||||
"""Request to create a file"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
content: str = Field(..., description="File content (will be Base64 encoded)")
|
||||
message: str = Field(..., min_length=1, description="Commit message")
|
||||
branch: str | None = Field(None, description="Branch name (default: default branch)")
|
||||
author_name: str | None = Field(None, description="Author name")
|
||||
author_email: str | None = Field(None, description="Author email")
|
||||
committer_name: str | None = Field(None, description="Committer name")
|
||||
committer_email: str | None = Field(None, description="Committer email")
|
||||
new_branch: str | None = Field(None, description="Create new branch for this commit")
|
||||
|
||||
class UpdateFileRequest(BaseModel):
|
||||
"""Request to update a file"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
content: str = Field(..., description="New file content (will be Base64 encoded)")
|
||||
message: str = Field(..., min_length=1, description="Commit message")
|
||||
sha: str = Field(..., description="SHA of the file being replaced")
|
||||
branch: str | None = Field(None, description="Branch name (default: default branch)")
|
||||
author_name: str | None = Field(None, description="Author name")
|
||||
author_email: str | None = Field(None, description="Author email")
|
||||
committer_name: str | None = Field(None, description="Committer name")
|
||||
committer_email: str | None = Field(None, description="Committer email")
|
||||
new_branch: str | None = Field(None, description="Create new branch for this commit")
|
||||
98
plugins/gitea/schemas/user.py
Normal file
98
plugins/gitea/schemas/user.py
Normal file
@@ -0,0 +1,98 @@
|
||||
"""
|
||||
User & Organization Pydantic Schemas
|
||||
|
||||
Validation schemas for Gitea user and organization operations.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
class User(BaseModel):
|
||||
"""Gitea user model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
login: str
|
||||
full_name: str | None = None
|
||||
email: str | None = None
|
||||
avatar_url: str
|
||||
language: str | None = None
|
||||
is_admin: bool = False
|
||||
last_login: datetime | None = None
|
||||
created: datetime
|
||||
restricted: bool = False
|
||||
active: bool = True
|
||||
prohibit_login: bool = False
|
||||
location: str | None = None
|
||||
website: str | None = None
|
||||
description: str | None = None
|
||||
visibility: str | None = None
|
||||
followers_count: int = 0
|
||||
following_count: int = 0
|
||||
starred_repos_count: int = 0
|
||||
username: str | None = None # Alias for login
|
||||
|
||||
class Organization(BaseModel):
|
||||
"""Gitea organization model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
name: str # org username
|
||||
full_name: str | None = None
|
||||
avatar_url: str
|
||||
description: str | None = None
|
||||
website: str | None = None
|
||||
location: str | None = None
|
||||
visibility: str # "public", "limited", "private"
|
||||
repo_admin_change_team_access: bool = False
|
||||
username: str | None = None # Alias for name
|
||||
|
||||
class Team(BaseModel):
|
||||
"""Organization team model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
name: str
|
||||
description: str | None = None
|
||||
organization: Organization | None = None
|
||||
permission: str # "none", "read", "write", "admin", "owner"
|
||||
can_create_org_repo: bool = False
|
||||
includes_all_repositories: bool = False
|
||||
units: list[str] | None = None
|
||||
units_map: dict | None = None
|
||||
|
||||
class TeamMember(BaseModel):
|
||||
"""Team member model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
user: User
|
||||
role: str | None = None # Role in team
|
||||
|
||||
class Email(BaseModel):
|
||||
"""User email model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
email: str
|
||||
verified: bool
|
||||
primary: bool
|
||||
|
||||
class SearchUsersRequest(BaseModel):
|
||||
"""Request to search users"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
q: str | None = Field(None, description="Search query")
|
||||
uid: int | None = Field(None, description="User ID")
|
||||
|
||||
class SearchOrgsRequest(BaseModel):
|
||||
"""Request to search organizations"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
q: str | None = Field(None, description="Search query")
|
||||
163
plugins/gitea/schemas/webhook.py
Normal file
163
plugins/gitea/schemas/webhook.py
Normal file
@@ -0,0 +1,163 @@
|
||||
"""
|
||||
Webhook Pydantic Schemas
|
||||
|
||||
Validation schemas for Gitea webhook operations.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
|
||||
class Webhook(BaseModel):
|
||||
"""Gitea webhook model"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
id: int
|
||||
type: str # "gitea", "gogs", "slack", "discord", etc.
|
||||
config: dict[str, Any]
|
||||
events: list[str]
|
||||
active: bool
|
||||
updated_at: datetime
|
||||
created_at: datetime
|
||||
|
||||
class WebhookConfig(BaseModel):
|
||||
"""Webhook configuration"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
url: str
|
||||
content_type: str = "json" # "json" or "form"
|
||||
secret: str | None = None
|
||||
http_method: str | None = "POST"
|
||||
branch_filter: str | None = None
|
||||
|
||||
class CreateWebhookRequest(BaseModel):
|
||||
"""Request to create a webhook"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
type: str = Field(
|
||||
default="gitea",
|
||||
description="Webhook type (gitea/gogs/slack/discord/dingtalk/telegram/msteams/feishu/wechatwork/packagist)",
|
||||
)
|
||||
config: dict[str, Any] = Field(..., description="Webhook configuration")
|
||||
events: list[str] = Field(..., min_items=1, description="List of events to trigger webhook")
|
||||
active: bool = Field(default=True, description="Activate webhook immediately")
|
||||
branch_filter: str | None = Field(None, description="Branch filter pattern")
|
||||
|
||||
@classmethod
|
||||
@field_validator("type")
|
||||
def validate_type(cls, v):
|
||||
allowed = [
|
||||
"gitea",
|
||||
"gogs",
|
||||
"slack",
|
||||
"discord",
|
||||
"dingtalk",
|
||||
"telegram",
|
||||
"msteams",
|
||||
"feishu",
|
||||
"wechatwork",
|
||||
"packagist",
|
||||
]
|
||||
if v not in allowed:
|
||||
raise ValueError(f"Webhook type must be one of: {', '.join(allowed)}")
|
||||
return v
|
||||
|
||||
@classmethod
|
||||
@field_validator("events")
|
||||
def validate_events(cls, v):
|
||||
allowed_events = [
|
||||
"create",
|
||||
"delete",
|
||||
"fork",
|
||||
"push",
|
||||
"issues",
|
||||
"issue_assign",
|
||||
"issue_label",
|
||||
"issue_milestone",
|
||||
"issue_comment",
|
||||
"pull_request",
|
||||
"pull_request_assign",
|
||||
"pull_request_label",
|
||||
"pull_request_milestone",
|
||||
"pull_request_comment",
|
||||
"pull_request_review_approved",
|
||||
"pull_request_review_rejected",
|
||||
"pull_request_review_comment",
|
||||
"pull_request_sync",
|
||||
"wiki",
|
||||
"repository",
|
||||
"release",
|
||||
]
|
||||
for event in v:
|
||||
if event not in allowed_events:
|
||||
raise ValueError(
|
||||
f"Invalid event: {event}. Must be one of: {', '.join(allowed_events)}"
|
||||
)
|
||||
return v
|
||||
|
||||
@classmethod
|
||||
@field_validator("config")
|
||||
def validate_config(cls, v):
|
||||
"""Validate webhook config has required fields"""
|
||||
if "url" not in v:
|
||||
raise ValueError("Webhook config must contain 'url'")
|
||||
if "content_type" not in v:
|
||||
v["content_type"] = "json"
|
||||
return v
|
||||
|
||||
class UpdateWebhookRequest(BaseModel):
|
||||
"""Request to update a webhook"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
config: dict[str, Any] | None = Field(None, description="Webhook configuration")
|
||||
events: list[str] | None = Field(None, description="List of events to trigger webhook")
|
||||
active: bool | None = Field(None, description="Activate/deactivate webhook")
|
||||
branch_filter: str | None = Field(None, description="Branch filter pattern")
|
||||
|
||||
@classmethod
|
||||
@field_validator("events")
|
||||
def validate_events(cls, v):
|
||||
if v is None:
|
||||
return v
|
||||
allowed_events = [
|
||||
"create",
|
||||
"delete",
|
||||
"fork",
|
||||
"push",
|
||||
"issues",
|
||||
"issue_assign",
|
||||
"issue_label",
|
||||
"issue_milestone",
|
||||
"issue_comment",
|
||||
"pull_request",
|
||||
"pull_request_assign",
|
||||
"pull_request_label",
|
||||
"pull_request_milestone",
|
||||
"pull_request_comment",
|
||||
"pull_request_review_approved",
|
||||
"pull_request_review_rejected",
|
||||
"pull_request_review_comment",
|
||||
"pull_request_sync",
|
||||
"wiki",
|
||||
"repository",
|
||||
"release",
|
||||
]
|
||||
for event in v:
|
||||
if event not in allowed_events:
|
||||
raise ValueError(f"Invalid event: {event}")
|
||||
return v
|
||||
|
||||
class WebhookTestResult(BaseModel):
|
||||
"""Webhook test result"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
success: bool
|
||||
message: str | None = None
|
||||
response_code: int | None = None
|
||||
response_body: str | None = None
|
||||
Reference in New Issue
Block a user