feat(handler): update GetFile and ListFiles handlers for new FileResponse fields
- GetFile uses new GetFileResponse instead of manual FileResponse construction - ListFiles handler parses optional user_id query parameter - Wire FolderStore into FileService in app.go, testenv, and file_test Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -185,7 +185,7 @@ func setupFileTestRouter(t *testing.T) (*gin.Engine, *gorm.DB, *inMemoryStorage)
|
|||||||
uploadSvc := service.NewUploadService(memStore, blobStore, fileStore, uploadStore, cfg, db, zap.NewNop())
|
uploadSvc := service.NewUploadService(memStore, blobStore, fileStore, uploadStore, cfg, db, zap.NewNop())
|
||||||
_ = service.NewDownloadService(memStore, blobStore, fileStore, "files", zap.NewNop())
|
_ = service.NewDownloadService(memStore, blobStore, fileStore, "files", zap.NewNop())
|
||||||
folderSvc := service.NewFolderService(folderStore, fileStore, zap.NewNop())
|
folderSvc := service.NewFolderService(folderStore, fileStore, zap.NewNop())
|
||||||
fileSvc := service.NewFileService(memStore, blobStore, fileStore, "files", db, zap.NewNop())
|
fileSvc := service.NewFileService(memStore, blobStore, fileStore, folderStore, "files", db, zap.NewNop())
|
||||||
|
|
||||||
uploadH := handler.NewUploadHandler(uploadSvc, zap.NewNop())
|
uploadH := handler.NewUploadHandler(uploadSvc, zap.NewNop())
|
||||||
fileH := handler.NewFileHandler(fileSvc, zap.NewNop())
|
fileH := handler.NewFileHandler(fileSvc, zap.NewNop())
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ func initHTTPServer(cfg *config.Config, db *gorm.DB, slurmClient *slurm.Client,
|
|||||||
|
|
||||||
uploadSvc := service.NewUploadService(minioClient, blobStore, fileStore, uploadStore, cfg.Minio, db, logger)
|
uploadSvc := service.NewUploadService(minioClient, blobStore, fileStore, uploadStore, cfg.Minio, db, logger)
|
||||||
folderSvc := service.NewFolderService(folderStore, fileStore, logger)
|
folderSvc := service.NewFolderService(folderStore, fileStore, logger)
|
||||||
fileSvc := service.NewFileService(minioClient, blobStore, fileStore, cfg.Minio.Bucket, db, logger)
|
fileSvc := service.NewFileService(minioClient, blobStore, fileStore, folderStore, cfg.Minio.Bucket, db, logger)
|
||||||
|
|
||||||
uploadH = handler.NewUploadHandler(uploadSvc, logger)
|
uploadH = handler.NewUploadHandler(uploadSvc, logger)
|
||||||
fileH = handler.NewFileHandler(fileSvc, logger)
|
fileH = handler.NewFileHandler(fileSvc, logger)
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type fileServiceProvider interface {
|
type fileServiceProvider interface {
|
||||||
ListFiles(ctx context.Context, folderID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error)
|
ListFiles(ctx context.Context, folderID *int64, userID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error)
|
||||||
|
GetFileResponse(ctx context.Context, fileID int64) (*model.FileResponse, error)
|
||||||
GetFileMetadata(ctx context.Context, fileID int64) (*model.File, *model.FileBlob, error)
|
GetFileMetadata(ctx context.Context, fileID int64) (*model.File, *model.FileBlob, error)
|
||||||
DownloadFile(ctx context.Context, fileID int64, rangeHeader string) (io.ReadCloser, *model.File, *model.FileBlob, int64, int64, error)
|
DownloadFile(ctx context.Context, fileID int64, rangeHeader string) (io.ReadCloser, *model.File, *model.FileBlob, int64, int64, error)
|
||||||
DeleteFile(ctx context.Context, fileID int64) error
|
DeleteFile(ctx context.Context, fileID int64) error
|
||||||
@@ -50,9 +51,20 @@ func (h *FileHandler) ListFiles(c *gin.Context) {
|
|||||||
folderID = &id
|
folderID = &id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var userID *int64
|
||||||
|
if v := c.Query("user_id"); v != "" {
|
||||||
|
id, err := strconv.ParseInt(v, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
h.logger.Warn("invalid user_id", zap.String("user_id", v))
|
||||||
|
server.BadRequest(c, "invalid user_id")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userID = &id
|
||||||
|
}
|
||||||
|
|
||||||
search := c.Query("search")
|
search := c.Query("search")
|
||||||
|
|
||||||
files, total, err := h.svc.ListFiles(c.Request.Context(), folderID, page, pageSize, search)
|
files, total, err := h.svc.ListFiles(c.Request.Context(), folderID, userID, page, pageSize, search)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("failed to list files", zap.Error(err))
|
h.logger.Error("failed to list files", zap.Error(err))
|
||||||
server.InternalError(c, err.Error())
|
server.InternalError(c, err.Error())
|
||||||
@@ -75,23 +87,13 @@ func (h *FileHandler) GetFile(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file, blob, err := h.svc.GetFileMetadata(c.Request.Context(), id)
|
resp, err := h.svc.GetFileResponse(c.Request.Context(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("failed to get file", zap.Int64("id", id), zap.Error(err))
|
h.logger.Error("failed to get file", zap.Int64("id", id), zap.Error(err))
|
||||||
server.InternalError(c, err.Error())
|
server.InternalError(c, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := model.FileResponse{
|
|
||||||
ID: file.ID,
|
|
||||||
Name: file.Name,
|
|
||||||
FolderID: file.FolderID,
|
|
||||||
Size: blob.FileSize,
|
|
||||||
MimeType: blob.MimeType,
|
|
||||||
SHA256: file.BlobSHA256,
|
|
||||||
CreatedAt: file.CreatedAt,
|
|
||||||
UpdatedAt: file.UpdatedAt,
|
|
||||||
}
|
|
||||||
server.OK(c, resp)
|
server.OK(c, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,14 +18,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type mockFileService struct {
|
type mockFileService struct {
|
||||||
listFilesFn func(ctx context.Context, folderID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error)
|
listFilesFn func(ctx context.Context, folderID *int64, userID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error)
|
||||||
|
getFileResponseFn func(ctx context.Context, fileID int64) (*model.FileResponse, error)
|
||||||
getFileMetadataFn func(ctx context.Context, fileID int64) (*model.File, *model.FileBlob, error)
|
getFileMetadataFn func(ctx context.Context, fileID int64) (*model.File, *model.FileBlob, error)
|
||||||
downloadFileFn func(ctx context.Context, fileID int64, rangeHeader string) (io.ReadCloser, *model.File, *model.FileBlob, int64, int64, error)
|
downloadFileFn func(ctx context.Context, fileID int64, rangeHeader string) (io.ReadCloser, *model.File, *model.FileBlob, int64, int64, error)
|
||||||
deleteFileFn func(ctx context.Context, fileID int64) error
|
deleteFileFn func(ctx context.Context, fileID int64) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockFileService) ListFiles(ctx context.Context, folderID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error) {
|
func (m *mockFileService) ListFiles(ctx context.Context, folderID *int64, userID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error) {
|
||||||
return m.listFilesFn(ctx, folderID, page, pageSize, search)
|
return m.listFilesFn(ctx, folderID, userID, page, pageSize, search)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockFileService) GetFileResponse(ctx context.Context, fileID int64) (*model.FileResponse, error) {
|
||||||
|
return m.getFileResponseFn(ctx, fileID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockFileService) GetFileMetadata(ctx context.Context, fileID int64) (*model.File, *model.FileBlob, error) {
|
func (m *mockFileService) GetFileMetadata(ctx context.Context, fileID int64) (*model.File, *model.FileBlob, error) {
|
||||||
@@ -67,7 +72,7 @@ func newFileHandlerSetup() *fileHandlerSetup {
|
|||||||
|
|
||||||
func TestListFiles_Empty(t *testing.T) {
|
func TestListFiles_Empty(t *testing.T) {
|
||||||
s := newFileHandlerSetup()
|
s := newFileHandlerSetup()
|
||||||
s.mock.listFilesFn = func(ctx context.Context, folderID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error) {
|
s.mock.listFilesFn = func(ctx context.Context, folderID *int64, userID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error) {
|
||||||
return []model.FileResponse{}, 0, nil
|
return []model.FileResponse{}, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +102,7 @@ func TestListFiles_Empty(t *testing.T) {
|
|||||||
func TestListFiles_WithFiles(t *testing.T) {
|
func TestListFiles_WithFiles(t *testing.T) {
|
||||||
s := newFileHandlerSetup()
|
s := newFileHandlerSetup()
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
s.mock.listFilesFn = func(ctx context.Context, folderID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error) {
|
s.mock.listFilesFn = func(ctx context.Context, folderID *int64, userID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error) {
|
||||||
return []model.FileResponse{
|
return []model.FileResponse{
|
||||||
{ID: 1, Name: "a.txt", Size: 100, MimeType: "text/plain", SHA256: "abc123", CreatedAt: now, UpdatedAt: now},
|
{ID: 1, Name: "a.txt", Size: 100, MimeType: "text/plain", SHA256: "abc123", CreatedAt: now, UpdatedAt: now},
|
||||||
{ID: 2, Name: "b.pdf", Size: 200, MimeType: "application/pdf", SHA256: "def456", CreatedAt: now, UpdatedAt: now},
|
{ID: 2, Name: "b.pdf", Size: 200, MimeType: "application/pdf", SHA256: "def456", CreatedAt: now, UpdatedAt: now},
|
||||||
@@ -133,7 +138,7 @@ func TestListFiles_WithFiles(t *testing.T) {
|
|||||||
func TestListFiles_WithFolderID(t *testing.T) {
|
func TestListFiles_WithFolderID(t *testing.T) {
|
||||||
s := newFileHandlerSetup()
|
s := newFileHandlerSetup()
|
||||||
var capturedFolderID *int64
|
var capturedFolderID *int64
|
||||||
s.mock.listFilesFn = func(ctx context.Context, folderID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error) {
|
s.mock.listFilesFn = func(ctx context.Context, folderID *int64, userID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error) {
|
||||||
capturedFolderID = folderID
|
capturedFolderID = folderID
|
||||||
return []model.FileResponse{}, 0, nil
|
return []model.FileResponse{}, 0, nil
|
||||||
}
|
}
|
||||||
@@ -152,7 +157,7 @@ func TestListFiles_WithFolderID(t *testing.T) {
|
|||||||
|
|
||||||
func TestListFiles_ServiceError(t *testing.T) {
|
func TestListFiles_ServiceError(t *testing.T) {
|
||||||
s := newFileHandlerSetup()
|
s := newFileHandlerSetup()
|
||||||
s.mock.listFilesFn = func(ctx context.Context, folderID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error) {
|
s.mock.listFilesFn = func(ctx context.Context, folderID *int64, userID *int64, page, pageSize int, search string) ([]model.FileResponse, int64, error) {
|
||||||
return nil, 0, fmt.Errorf("db error")
|
return nil, 0, fmt.Errorf("db error")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,11 +175,10 @@ func TestListFiles_ServiceError(t *testing.T) {
|
|||||||
func TestGetFile_Found(t *testing.T) {
|
func TestGetFile_Found(t *testing.T) {
|
||||||
s := newFileHandlerSetup()
|
s := newFileHandlerSetup()
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
s.mock.getFileMetadataFn = func(ctx context.Context, fileID int64) (*model.File, *model.FileBlob, error) {
|
rootPath := "/"
|
||||||
return &model.File{
|
s.mock.getFileResponseFn = func(ctx context.Context, fileID int64) (*model.FileResponse, error) {
|
||||||
ID: 1, Name: "test.txt", BlobSHA256: "abc123", CreatedAt: now, UpdatedAt: now,
|
return &model.FileResponse{
|
||||||
}, &model.FileBlob{
|
ID: 1, Name: "test.txt", SHA256: "abc123", FolderPath: &rootPath, CreatedAt: now, UpdatedAt: now,
|
||||||
ID: 1, SHA256: "abc123", FileSize: 1024, MimeType: "text/plain", CreatedAt: now,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,8 +199,8 @@ func TestGetFile_Found(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetFile_NotFound(t *testing.T) {
|
func TestGetFile_NotFound(t *testing.T) {
|
||||||
s := newFileHandlerSetup()
|
s := newFileHandlerSetup()
|
||||||
s.mock.getFileMetadataFn = func(ctx context.Context, fileID int64) (*model.File, *model.FileBlob, error) {
|
s.mock.getFileResponseFn = func(ctx context.Context, fileID int64) (*model.FileResponse, error) {
|
||||||
return nil, nil, fmt.Errorf("file not found: 999")
|
return nil, fmt.Errorf("file not found: 999")
|
||||||
}
|
}
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ func NewTestEnv(t interface {
|
|||||||
taskSvc := service.NewTaskService(taskStore, appStore, fileStore, blobStore, stagingSvc, jobSvc, workDir, logger)
|
taskSvc := service.NewTaskService(taskStore, appStore, fileStore, blobStore, stagingSvc, jobSvc, workDir, logger)
|
||||||
appSvc := service.NewApplicationService(appStore, jobSvc, workDir, logger, taskSvc)
|
appSvc := service.NewApplicationService(appStore, jobSvc, workDir, logger, taskSvc)
|
||||||
uploadSvc := service.NewUploadService(mockMinIO, blobStore, fileStore, uploadStore, minioCfg, db, logger)
|
uploadSvc := service.NewUploadService(mockMinIO, blobStore, fileStore, uploadStore, minioCfg, db, logger)
|
||||||
fileSvc := service.NewFileService(mockMinIO, blobStore, fileStore, minioCfg.Bucket, db, logger)
|
fileSvc := service.NewFileService(mockMinIO, blobStore, fileStore, folderStore, minioCfg.Bucket, db, logger)
|
||||||
|
|
||||||
// 9. All 7 Handler instances
|
// 9. All 7 Handler instances
|
||||||
jobH := handler.NewJobHandler(jobSvc, logger)
|
jobH := handler.NewJobHandler(jobSvc, logger)
|
||||||
|
|||||||
Reference in New Issue
Block a user