Initial commit: SQL audit platform v0.1.0

FastAPI backend with auth, user, instance, ticket, query, dashboard APIs.
React + TypeScript frontend with mock data UI (10 pages).
SQLite + async SQLAlchemy, JWT auth, role-based access control.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
loganandClaude Opus 4.7 committed 2026-05-22 11:11:57 +08:00
commit 439155c92e
290 files changed
+61950

No files matched your search

View File
Whitespace-only changes.
+24
View File
@@ -0,0 +1,24 @@
from typing import Optional
from pydantic import BaseModel
class LoginRequest(BaseModel):
username: str
password: str
class TokenResponse(BaseModel):
access_token: str
token_type: str = "bearer"
user: "UserBrief"
class UserBrief(BaseModel):
id: int
username: str
display_name: str
role: str
email: Optional[str] = None
class Config:
from_attributes = True
+13
View File
@@ -0,0 +1,13 @@
from pydantic import BaseModel
from typing import Optional
class DashboardStats(BaseModel):
ticket_total: int = 0
ticket_pending: int = 0
ticket_month: int = 0
ticket_executing: int = 0
instance_total: int = 0
instance_online: int = 0
user_total: int = 0
queries_today: int = 0
+50
View File
@@ -0,0 +1,50 @@
from datetime import datetime
from pydantic import BaseModel, Field
from typing import Optional, Literal
class InstanceCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
db_type: Literal["mysql", "postgres", "redis", "mongo"]
host: str = Field(..., min_length=1)
port: int = Field(..., ge=1, le=65535)
username: str = Field(..., min_length=1)
password: str = Field(..., min_length=1)
database: Optional[str] = None
env: Literal["production", "staging", "development"] = "development"
description: Optional[str] = None
class InstanceUpdate(BaseModel):
name: Optional[str] = None
host: Optional[str] = None
port: Optional[int] = Field(default=None, ge=1, le=65535)
username: Optional[str] = None
password: Optional[str] = None
database: Optional[str] = None
env: Optional[Literal["production", "staging", "development"]] = None
description: Optional[str] = None
class InstanceResponse(BaseModel):
id: int
name: str
db_type: str
host: str
port: int
username: str
database: Optional[str] = None
env: str
description: Optional[str] = None
status: str
version: Optional[str] = None
created_at: datetime
class Config:
from_attributes = True
class ConnectionTestResult(BaseModel):
success: bool
message: str
version: Optional[str] = None
+16
View File
@@ -0,0 +1,16 @@
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field
class QueryRequest(BaseModel):
instance_id: int
database: Optional[str] = None
sql: str = Field(..., min_length=1)
class QueryResult(BaseModel):
columns: List[str]
rows: List[Dict[str, Any]]
total: int
elapsed_ms: int
truncated: bool = False
+52
View File
@@ -0,0 +1,52 @@
from datetime import datetime
from pydantic import BaseModel, Field
from typing import Optional, Literal
class TicketCreate(BaseModel):
title: str = Field(..., min_length=5, max_length=200)
db_type: Literal["mysql", "postgres", "redis", "mongo"]
instance_id: int
target_database: str = Field(..., min_length=1)
sql_content: str = Field(..., min_length=1)
rollback_sql: Optional[str] = None
reason: str = Field(..., min_length=5)
priority: Literal["high", "medium", "low"] = "medium"
class TicketReview(BaseModel):
action: Literal["approve", "reject"]
comment: str = Field(default="", max_length=500)
class TicketResponse(BaseModel):
id: int
title: str
db_type: str
instance_id: int
target_database: str
sql_content: str
rollback_sql: Optional[str] = None
status: str
priority: str
applicant_id: int
applicant_name: Optional[str] = None
approver_id: Optional[int] = None
approver_name: Optional[str] = None
reason: Optional[str] = None
audit_result: Optional[str] = None
execute_result: Optional[str] = None
create_time: datetime
review_time: Optional[datetime] = None
execute_time: Optional[datetime] = None
class Config:
from_attributes = True
class TicketListParams(BaseModel):
page: int = 1
page_size: int = 10
status: Optional[str] = None
db_type: Optional[str] = None
keyword: Optional[str] = None
+40
View File
@@ -0,0 +1,40 @@
from datetime import datetime
from pydantic import BaseModel, Field
from typing import Optional
class UserCreate(BaseModel):
username: str = Field(..., min_length=2, max_length=50)
display_name: str = Field(..., min_length=1, max_length=100)
password: str = Field(..., min_length=6)
email: Optional[str] = None
phone: Optional[str] = None
role: str = Field(default="developer", pattern="^(admin|dba|developer|guest)$")
class UserUpdate(BaseModel):
display_name: Optional[str] = None
email: Optional[str] = None
phone: Optional[str] = None
role: Optional[str] = Field(default=None, pattern="^(admin|dba|developer|guest)$")
is_active: Optional[bool] = None
class UserResponse(BaseModel):
id: int
username: str
display_name: str
email: Optional[str] = None
phone: Optional[str] = None
role: str
is_active: bool
last_login: Optional[datetime] = None
created_at: datetime
class Config:
from_attributes = True
class PasswordChange(BaseModel):
old_password: str
new_password: str = Field(..., min_length=6)