Started adding attachment download
continuous-integration/drone/pr Build is passing
Details
continuous-integration/drone/pr Build is passing
Details
This commit is contained in:
parent
07b54d385b
commit
6455120b49
|
@ -43,6 +43,7 @@ This document describes the different errors Vikunja can return.
|
|||
| 4008 | 409 | The user tried to create a task relation which already exists. |
|
||||
| 4009 | 404 | The task relation does not exist. |
|
||||
| 4010 | 400 | Cannot relate a task with itself. |
|
||||
| 4011 | 404 | The task attachment does not exist. |
|
||||
| 5001 | 404 | The namspace does not exist. |
|
||||
| 5003 | 403 | The user does not have access to the specified namespace. |
|
||||
| 5006 | 400 | The namespace name cannot be empty. |
|
||||
|
|
|
@ -731,6 +731,35 @@ func (err ErrRelationTasksCannotBeTheSame) HTTPError() web.HTTPError {
|
|||
}
|
||||
}
|
||||
|
||||
// ErrTaskAttachmentDoesNotExist represents an error where the user tries to relate a task with itself
|
||||
type ErrTaskAttachmentDoesNotExist struct {
|
||||
TaskID int64
|
||||
AttachmentID int64
|
||||
FileID int64
|
||||
}
|
||||
|
||||
// IsErrTaskAttachmentDoesNotExist checks if an error is ErrTaskAttachmentDoesNotExist.
|
||||
func IsErrTaskAttachmentDoesNotExist(err error) bool {
|
||||
_, ok := err.(ErrTaskAttachmentDoesNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrTaskAttachmentDoesNotExist) Error() string {
|
||||
return fmt.Sprintf("Task Attachment does not exist [TaskID: %d, AttachmentID: %d, FileID: %d]", err.TaskID, err.AttachmentID, err.FileID)
|
||||
}
|
||||
|
||||
// ErrCodeTaskAttachmentDoesNotExist holds the unique world-error code of this error
|
||||
const ErrCodeTaskAttachmentDoesNotExist = 4011
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrTaskAttachmentDoesNotExist) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{
|
||||
HTTPCode: http.StatusNotFound,
|
||||
Code: ErrCodeTaskAttachmentDoesNotExist,
|
||||
Message: "This task attachment does not exist.",
|
||||
}
|
||||
}
|
||||
|
||||
// =================
|
||||
// Namespace errors
|
||||
// =================
|
||||
|
|
|
@ -19,19 +19,18 @@ package models
|
|||
import (
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/web"
|
||||
"mime/multipart"
|
||||
)
|
||||
|
||||
// TaskAttachment is the definition of a task attachment
|
||||
type TaskAttachment struct {
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"`
|
||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"attachment"`
|
||||
TaskID int64 `xorm:"int(11) not null" json:"task_id" param:"task"`
|
||||
FileID int64 `xorm:"int(11) not null" json:"-"`
|
||||
|
||||
CreatedByID int64 `xorm:"int(11) not null" json:"-"`
|
||||
CreatedBy *User `xorm:"-" json:"created_by"`
|
||||
|
||||
File *multipart.FileHeader `xorm:"-" json:"-"`
|
||||
File *files.File `xorm:"-" json:"-"`
|
||||
|
||||
Created int64 `xorm:"created"`
|
||||
|
||||
|
@ -43,7 +42,7 @@ type TaskAttachment struct {
|
|||
func (ta *TaskAttachment) Create(a web.Auth) error {
|
||||
|
||||
// Store the file
|
||||
file, err := files.Create(ta.File)
|
||||
file, err := files.Create(ta.File.File)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -62,9 +61,27 @@ func (ta *TaskAttachment) Create(a web.Auth) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ReadOne returns a new task attachment
|
||||
func (ta *TaskAttachment) ReadOne() error {
|
||||
panic("implement me")
|
||||
// ReadOne returns a task attachment
|
||||
func (ta *TaskAttachment) ReadOne() (err error) {
|
||||
exists, err := x.Where("id = ?", ta.ID).Get(ta)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !exists {
|
||||
return ErrTaskAttachmentDoesNotExist{
|
||||
TaskID: ta.TaskID,
|
||||
AttachmentID: ta.ID,
|
||||
}
|
||||
}
|
||||
|
||||
// Get the file
|
||||
ta.File.ID = ta.FileID
|
||||
err = ta.File.GetFileByID()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ReadAll returns a list with all attachments
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/labstack/echo/v4"
|
||||
|
@ -50,12 +51,12 @@ func UploadTaskAttachment(c echo.Context) error {
|
|||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
files := form.File["files"]
|
||||
for _, file := range files {
|
||||
fileHeaders := form.File["fileHeaders"]
|
||||
for _, file := range fileHeaders {
|
||||
// We create a new attachment object here to have a clean start
|
||||
ta := models.TaskAttachment{
|
||||
TaskID: taskAttachment.TaskID,
|
||||
File: file,
|
||||
File: &files.File{File: file},
|
||||
}
|
||||
err = ta.Create(user)
|
||||
if err != nil {
|
||||
|
@ -65,3 +66,35 @@ func UploadTaskAttachment(c echo.Context) error {
|
|||
|
||||
return c.NoContent(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// GetTaskAttachment returns a task attachment to download for the user
|
||||
func GetTaskAttachment(c echo.Context) error {
|
||||
|
||||
var taskAttachment models.TaskAttachment
|
||||
if err := c.Bind(&taskAttachment); err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "No task ID provided")
|
||||
}
|
||||
|
||||
// Rights check
|
||||
user, err := models.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
can, err := taskAttachment.CanRead(user)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
if !can {
|
||||
return echo.ErrForbidden
|
||||
}
|
||||
|
||||
// Get the attachment incl file
|
||||
err = taskAttachment.ReadOne()
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
// Send the file to the client
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -267,6 +267,7 @@ func registerAPIRoutes(a *echo.Group) {
|
|||
a.DELETE("/tasks/:task/relations", taskRelationHandler.DeleteWeb)
|
||||
|
||||
a.PUT("/tasks/:task/attachments", apiv1.UploadTaskAttachment)
|
||||
a.GET("/tasks/:task/attachments/:attachment", apiv1.GetTaskAttachment)
|
||||
|
||||
labelHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
|
|
Loading…
Reference in New Issue