Started adding attachment download
continuous-integration/drone/pr Build is passing Details

This commit is contained in:
kolaente 2019-10-10 13:00:27 +02:00
parent 07b54d385b
commit 6455120b49
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
5 changed files with 91 additions and 10 deletions

View File

@ -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. |

View File

@ -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
// =================

View File

@ -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

View File

@ -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
}

View File

@ -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 {