feat(sora): add GDrive full-cycle test endpoint (upload/download/delete)

This commit is contained in:
erio
2026-03-06 22:33:37 +08:00
parent 3f1ca43514
commit 298f5c1baf
4 changed files with 82 additions and 2 deletions
+1 -1
View File
@@ -177,7 +177,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
soraGenerationService := service.NewSoraGenerationService(soraGenerationRepository, soraStorageRouter, soraQuotaService)
settingHandler := admin.NewSettingHandler(settingService, emailService, turnstileService, opsService, soraS3Storage)
soraGDriveOAuthService := service.NewSoraGDriveOAuthService(settingService)
gdriveOAuthHandler := admin.NewGDriveOAuthHandler(settingService, soraGDriveOAuthService)
gdriveOAuthHandler := admin.NewGDriveOAuthHandler(settingService, soraGDriveOAuthService, soraGDriveStorage)
opsHandler := admin.NewOpsHandler(opsService)
updateCache := repository.NewUpdateCache(redisClient)
gitHubReleaseClient := repository.ProvideGitHubReleaseClient(configConfig)
@@ -13,13 +13,15 @@ import (
type GDriveOAuthHandler struct {
settingService *service.SettingService
gdriveOAuth *service.SoraGDriveOAuthService
gdriveStorage *service.SoraGDriveStorage
}
// NewGDriveOAuthHandler 创建 GDrive OAuth Handler。
func NewGDriveOAuthHandler(settingService *service.SettingService, gdriveOAuth *service.SoraGDriveOAuthService) *GDriveOAuthHandler {
func NewGDriveOAuthHandler(settingService *service.SettingService, gdriveOAuth *service.SoraGDriveOAuthService, gdriveStorage *service.SoraGDriveStorage) *GDriveOAuthHandler {
return &GDriveOAuthHandler{
settingService: settingService,
gdriveOAuth: gdriveOAuth,
gdriveStorage: gdriveStorage,
}
}
@@ -127,3 +129,20 @@ func (h *GDriveOAuthHandler) OAuthCallback(c *gin.Context) {
"message": "OAuth 授权成功",
})
}
// TestGDriveStorage 测试 GDrive 存储的完整上传→下载→删除流程。
// POST /api/v1/admin/settings/sora-storage/gdrive-test
func (h *GDriveOAuthHandler) TestGDriveStorage(c *gin.Context) {
if h.gdriveStorage == nil {
response.Error(c, http.StatusInternalServerError, "GDrive storage not initialized")
return
}
result, err := h.gdriveStorage.TestFullCycle(c.Request.Context())
if err != nil {
response.Error(c, http.StatusBadRequest, "GDrive 测试失败: "+err.Error())
return
}
response.Success(c, result)
}
+1
View File
@@ -413,6 +413,7 @@ func registerSettingsRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
// Google Drive OAuth
adminSettings.POST("/sora-storage/gdrive-oauth/start", h.Admin.GDriveOAuth.StartOAuth)
adminSettings.POST("/sora-storage/gdrive-oauth/callback", h.Admin.GDriveOAuth.OAuthCallback)
adminSettings.POST("/sora-storage/gdrive-test", h.Admin.GDriveOAuth.TestGDriveStorage)
}
}
@@ -188,6 +188,66 @@ func (s *SoraGDriveStorage) TestConnection(ctx context.Context) error {
return nil
}
// TestFullCycle 执行完整的上传→获取链接→删除测试。
func (s *SoraGDriveStorage) TestFullCycle(ctx context.Context) (map[string]any, error) {
srv, cfg, err := s.getService(ctx)
if err != nil {
return nil, fmt.Errorf("init client: %w", err)
}
result := map[string]any{}
// 1. 测试 API 连接
about, err := srv.About.Get().Fields("storageQuota").Context(ctx).Do()
if err != nil {
return nil, fmt.Errorf("API connection failed: %w", err)
}
if about.StorageQuota != nil {
result["quota_limit_bytes"] = about.StorageQuota.Limit
result["quota_used_bytes"] = about.StorageQuota.Usage
}
// 2. 上传测试文件
testContent := "sub2api GDrive test file - " + time.Now().Format(time.RFC3339)
fileMeta := &drive.File{
Name: "sub2api_test_" + uuid.NewString()[:8] + ".txt",
MimeType: "text/plain",
}
if cfg.FolderID != "" {
fileMeta.Parents = []string{cfg.FolderID}
}
uploaded, err := srv.Files.Create(fileMeta).
Media(strings.NewReader(testContent)).
Fields("id,name,size,webViewLink").
Context(ctx).Do()
if err != nil {
return nil, fmt.Errorf("upload test file failed: %w", err)
}
result["uploaded_file_id"] = uploaded.Id
result["uploaded_file_name"] = uploaded.Name
result["uploaded_file_size"] = uploaded.Size
result["web_view_link"] = uploaded.WebViewLink
// 3. 获取访问链接
accessURL, err := s.GetAccessURL(ctx, uploaded.Id)
if err != nil {
// 即使获取链接失败,仍尝试清理
_ = srv.Files.Delete(uploaded.Id).Context(ctx).Do()
return nil, fmt.Errorf("get access URL failed: %w", err)
}
result["access_url"] = accessURL
// 4. 删除测试文件
if err := srv.Files.Delete(uploaded.Id).Context(ctx).Do(); err != nil {
result["delete_warning"] = fmt.Sprintf("delete failed (manual cleanup needed): %v", err)
} else {
result["deleted"] = true
}
result["status"] = "ok"
return result, nil
}
// IsHealthy 返回 Google Drive 健康状态(带短缓存)。
func (s *SoraGDriveStorage) IsHealthy(ctx context.Context) bool {
if s == nil {