diff --git a/internal/database/migrations/20240915121635_function.sql b/internal/database/migrations/20240915121635_function.sql new file mode 100644 index 0000000..0d18fee --- /dev/null +++ b/internal/database/migrations/20240915121635_function.sql @@ -0,0 +1,52 @@ +-- +goose Up +-- +goose StatementBegin +CREATE OR REPLACE FUNCTION teldrive.get_path_from_file_id(file_id uuid) + RETURNS text + LANGUAGE plpgsql +AS $function$ +DECLARE + full_path TEXT; + trimmed_path TEXT; +BEGIN + WITH RECURSIVE path_hierarchy AS ( + SELECT + f.id, + f.name, + f.parent_id, + f.name AS path_segment + FROM + teldrive.files f + WHERE + f.id = file_id + + UNION ALL + + SELECT + p.id, + p.name, + p.parent_id, + CASE + WHEN ph.parent_id IS NULL THEN ph.path_segment + ELSE p.name || '/' || ph.path_segment + END AS path_segment + FROM + teldrive.files p + JOIN + path_hierarchy ph ON ph.parent_id = p.id + ) + + SELECT path_segment INTO full_path + FROM path_hierarchy + WHERE parent_id IS NULL; + + SELECT + CASE + WHEN position('/' in full_path) > 0 THEN substring(full_path from position('/' in full_path) + 1) + ELSE full_path + END INTO trimmed_path; + + RETURN '/' || trimmed_path; +END; +$function$ +; +-- +goose StatementEnd \ No newline at end of file diff --git a/pkg/schemas/file.go b/pkg/schemas/file.go index 11e51ee..e136f65 100644 --- a/pkg/schemas/file.go +++ b/pkg/schemas/file.go @@ -117,16 +117,20 @@ type FileShareIn struct { } type FileShareOut struct { - ID string `json:"id"` + ID string `json:"id,omitempty"` ExpiresAt *time.Time `json:"expiresAt,omitempty"` Protected bool `json:"protected"` UserID int64 `json:"userId,omitempty"` + Type string `json:"type"` + Name string `json:"name"` } type FileShare struct { Password *string ExpiresAt *time.Time Type string - FileId string - UserId int64 + FileID string + UserID int64 + Path string + Name string } diff --git a/pkg/schemas/share.go b/pkg/schemas/share.go index b5e69f0..a553cee 100644 --- a/pkg/schemas/share.go +++ b/pkg/schemas/share.go @@ -5,9 +5,9 @@ type ShareAccess struct { } type ShareFileQuery struct { - ParentID string `form:"parentId"` - Sort string `form:"sort"` - Order string `form:"order"` - Limit int `form:"limit"` - Page int `form:"page"` + Path string `form:"path"` + Sort string `form:"sort"` + Order string `form:"order"` + Limit int `form:"limit"` + Page int `form:"page"` } diff --git a/pkg/services/share.go b/pkg/services/share.go index c980b22..1d82a14 100644 --- a/pkg/services/share.go +++ b/pkg/services/share.go @@ -36,9 +36,12 @@ func NewShareService(db *gorm.DB, fs *FileService, cache cache.Cacher) *ShareSer func (ss *ShareService) GetShareById(shareId string) (*schemas.FileShareOut, *types.AppError) { - var result []models.FileShare + var result []schemas.FileShare - if err := ss.db.Model(&models.FileShare{}).Where("id = ?", shareId).Find(&result).Error; err != nil { + if err := ss.db.Model(&models.FileShare{}).Where("file_shares.id = ?", shareId). + Select("file_shares.*", "f.type", "f.name"). + Joins("left join teldrive.files as f on f.id = file_shares.file_id"). + Scan(&result).Error; err != nil { return nil, &types.AppError{Error: err} } @@ -54,6 +57,8 @@ func (ss *ShareService) GetShareById(shareId string) (*schemas.FileShareOut, *ty ExpiresAt: result[0].ExpiresAt, Protected: result[0].Password != nil, UserID: result[0].UserID, + Type: result[0].Type, + Name: result[0].Name, } return res, nil @@ -82,7 +87,6 @@ func (ss *ShareService) ListShareFiles(shareId string, query *schemas.ShareFileQ var ( userId int64 fileType string - fileId string ) var result []schemas.FileShare @@ -91,7 +95,8 @@ func (ss *ShareService) ListShareFiles(shareId string, query *schemas.ShareFileQ if err := ss.cache.Get(key, &result); err != nil { if err := ss.db.Model(&models.FileShare{}).Where("file_shares.id = ?", shareId). - Select("file_shares.*", "f.type"). + Select("file_shares.*", "f.type", + "(select get_path_from_file_id as path from teldrive.get_path_from_file_id(f.id))"). Joins("left join teldrive.files as f on f.id = file_shares.file_id"). Scan(&result).Error; err != nil { return nil, &types.AppError{Error: err} @@ -118,34 +123,32 @@ func (ss *ShareService) ListShareFiles(shareId string, query *schemas.ShareFileQ } - userId = result[0].UserId + userId = result[0].UserID fileType = "folder" - fileId = query.ParentID - - if query.ParentID == "" { + if query.Path == "" { fileType = result[0].Type - fileId = result[0].FileId } if fileType == "folder" { return ss.fs.ListFiles(userId, &schemas.FileQuery{ - ParentID: fileId, - Limit: query.Limit, - Page: query.Page, - Order: query.Order, - Sort: query.Sort, - Op: "list"}) + Path: result[0].Path + query.Path, + Limit: query.Limit, + Page: query.Page, + Order: query.Order, + Sort: query.Sort, + Op: "list"}) } else { var file models.File - if err := ss.db.Where("id = ?", fileId).First(&file).Error; err != nil { + if err := ss.db.Where("id = ?", result[0].FileID).First(&file).Error; err != nil { if database.IsRecordNotFoundErr(err) { return nil, &types.AppError{Error: database.ErrNotFound, Code: http.StatusNotFound} } return nil, &types.AppError{Error: err} } - return &schemas.FileResponse{Files: []schemas.FileOut{*mapper.ToFileOut(file)}}, nil + return &schemas.FileResponse{Files: []schemas.FileOut{*mapper.ToFileOut(file)}, + Meta: schemas.Meta{TotalPages: 1, Count: 1, CurrentPage: 1}}, nil } }