Fix upload
This commit is contained in:
parent
39e11fcb2b
commit
7634498c1c
|
@ -19,6 +19,7 @@ package background
|
|||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/web"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
// Image represents an image which can be used as a list background
|
||||
|
@ -33,7 +34,7 @@ type Image struct {
|
|||
// Provider represents something that is able to get a list of images and set one of them as background
|
||||
type Provider interface {
|
||||
// Search is used to either return a pre-defined list of Image or let the user search for an image
|
||||
Search(search string, page int64) (result []*Image, err error)
|
||||
Search(s *xorm.Session, search string, page int64) (result []*Image, err error)
|
||||
// Set sets an image which was most likely previously obtained by Search as list background
|
||||
Set(image *Image, list *models.List, auth web.Auth) (err error)
|
||||
Set(s *xorm.Session, image *Image, list *models.List, auth web.Auth) (err error)
|
||||
}
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"xorm.io/xorm"
|
||||
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
|
@ -59,8 +61,17 @@ func (bp *BackgroundProvider) SearchBackgrounds(c echo.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
result, err := p.Search(search, page)
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
result, err := p.Search(s, search, page)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "An error occurred: "+err.Error())
|
||||
}
|
||||
|
||||
if err := s.Commit(); err != nil {
|
||||
_ = s.Rollback()
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "An error occurred: "+err.Error())
|
||||
}
|
||||
|
||||
|
@ -68,7 +79,7 @@ func (bp *BackgroundProvider) SearchBackgrounds(c echo.Context) error {
|
|||
}
|
||||
|
||||
// This function does all kinds of preparations for setting and uploading a background
|
||||
func (bp *BackgroundProvider) setBackgroundPreparations(c echo.Context) (list *models.List, auth web.Auth, err error) {
|
||||
func (bp *BackgroundProvider) setBackgroundPreparations(s *xorm.Session, c echo.Context) (list *models.List, auth web.Auth, err error) {
|
||||
auth, err = auth2.GetAuthFromClaims(c)
|
||||
if err != nil {
|
||||
return nil, nil, echo.NewHTTPError(http.StatusBadRequest, "Invalid auth token: "+err.Error())
|
||||
|
@ -96,8 +107,12 @@ func (bp *BackgroundProvider) setBackgroundPreparations(c echo.Context) (list *m
|
|||
|
||||
// SetBackground sets an Image as list background
|
||||
func (bp *BackgroundProvider) SetBackground(c echo.Context) error {
|
||||
list, auth, err := bp.setBackgroundPreparations(c)
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
list, auth, err := bp.setBackgroundPreparations(s, c)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
|
@ -106,11 +121,13 @@ func (bp *BackgroundProvider) SetBackground(c echo.Context) error {
|
|||
image := &background.Image{}
|
||||
err = c.Bind(image)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "No or invalid model provided: "+err.Error())
|
||||
}
|
||||
|
||||
err = p.Set(image, list, auth)
|
||||
err = p.Set(s, image, list, auth)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
return c.JSON(http.StatusOK, list)
|
||||
|
@ -118,8 +135,12 @@ func (bp *BackgroundProvider) SetBackground(c echo.Context) error {
|
|||
|
||||
// UploadBackground uploads a background and passes the id of the uploaded file as an Image to the Set function of the BackgroundProvider.
|
||||
func (bp *BackgroundProvider) UploadBackground(c echo.Context) error {
|
||||
list, auth, err := bp.setBackgroundPreparations(c)
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
list, auth, err := bp.setBackgroundPreparations(s, c)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
|
@ -128,10 +149,12 @@ func (bp *BackgroundProvider) UploadBackground(c echo.Context) error {
|
|||
// Get + upload the image
|
||||
file, err := c.FormFile("background")
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return err
|
||||
}
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return err
|
||||
}
|
||||
defer src.Close()
|
||||
|
@ -139,9 +162,11 @@ func (bp *BackgroundProvider) UploadBackground(c echo.Context) error {
|
|||
// Validate we're dealing with an image
|
||||
mime, err := mimetype.DetectReader(src)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
if !strings.HasPrefix(mime.String(), "image") {
|
||||
_ = s.Rollback()
|
||||
return c.JSON(http.StatusBadRequest, models.Message{Message: "Uploaded file is no image."})
|
||||
}
|
||||
_, _ = src.Seek(0, io.SeekStart)
|
||||
|
@ -149,6 +174,7 @@ func (bp *BackgroundProvider) UploadBackground(c echo.Context) error {
|
|||
// Save the file
|
||||
f, err := files.CreateWithMime(src, file.Filename, uint64(file.Size), auth, mime.String())
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
if files.IsErrFileIsTooLarge(err) {
|
||||
return echo.ErrBadRequest
|
||||
}
|
||||
|
@ -158,10 +184,17 @@ func (bp *BackgroundProvider) UploadBackground(c echo.Context) error {
|
|||
|
||||
image := &background.Image{ID: strconv.FormatInt(f.ID, 10)}
|
||||
|
||||
err = p.Set(image, list, auth)
|
||||
err = p.Set(s, image, list, auth)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
if err := s.Commit(); err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, list)
|
||||
}
|
||||
|
||||
|
@ -190,17 +223,23 @@ func GetListBackground(c echo.Context) error {
|
|||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid list ID: "+err.Error())
|
||||
}
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
// Check if a background for this list exists + Rights
|
||||
list := &models.List{ID: listID}
|
||||
can, _, err := list.CanRead(nil, auth)
|
||||
can, _, err := list.CanRead(s, auth)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
if !can {
|
||||
_ = s.Rollback()
|
||||
log.Infof("Tried to get list background of list %d while not having the rights for it (User: %v)", listID, auth)
|
||||
return echo.NewHTTPError(http.StatusForbidden)
|
||||
}
|
||||
if list.BackgroundFileID == 0 {
|
||||
_ = s.Rollback()
|
||||
return echo.NotFoundHandler(c)
|
||||
}
|
||||
|
||||
|
@ -209,13 +248,19 @@ func GetListBackground(c echo.Context) error {
|
|||
ID: list.BackgroundFileID,
|
||||
}
|
||||
if err := bgFile.LoadFileByID(); err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
// Unsplash requires pingbacks as per their api usage guidelines.
|
||||
// To do this in a privacy-preserving manner, we do the ping from inside of Vikunja to not expose any user details.
|
||||
// FIXME: This should use an event once we have events
|
||||
unsplash.Pingback(bgFile)
|
||||
unsplash.Pingback(s, bgFile)
|
||||
|
||||
if err := s.Commit(); err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
// Serve the file
|
||||
return c.Stream(http.StatusOK, "image/jpg", bgFile.File)
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"xorm.io/xorm"
|
||||
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
|
@ -150,7 +151,7 @@ func getUnsplashPhotoInfoByID(photoID string) (photo *Photo, err error) {
|
|||
// @Success 200 {array} background.Image "An array with photos"
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /backgrounds/unsplash/search [get]
|
||||
func (p *Provider) Search(search string, page int64) (result []*background.Image, err error) {
|
||||
func (p *Provider) Search(s *xorm.Session, search string, page int64) (result []*background.Image, err error) {
|
||||
|
||||
// If we don't have a search query, return results from the unsplash featured collection
|
||||
if search == "" {
|
||||
|
@ -243,7 +244,7 @@ func (p *Provider) Search(search string, page int64) (result []*background.Image
|
|||
// @Failure 403 {object} web.HTTPError "The user does not have access to the list"
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /lists/{id}/backgrounds/unsplash [post]
|
||||
func (p *Provider) Set(image *background.Image, list *models.List, auth web.Auth) (err error) {
|
||||
func (p *Provider) Set(s *xorm.Session, image *background.Image, list *models.List, auth web.Auth) (err error) {
|
||||
|
||||
// Find the photo
|
||||
photo, err := getUnsplashPhotoInfoByID(image.ID)
|
||||
|
@ -315,13 +316,13 @@ func (p *Provider) Set(image *background.Image, list *models.List, auth web.Auth
|
|||
list.BackgroundInformation = unsplashPhoto
|
||||
|
||||
// Set it as the list background
|
||||
return models.SetListBackground(list.ID, file)
|
||||
return models.SetListBackground(s, list.ID, file)
|
||||
}
|
||||
|
||||
// Pingback pings the unsplash api if an unsplash photo has been accessed.
|
||||
func Pingback(f *files.File) {
|
||||
func Pingback(s *xorm.Session, f *files.File) {
|
||||
// Check if the file is actually downloaded from unsplash
|
||||
unsplashPhoto, err := models.GetUnsplashPhotoByFileID(f.ID)
|
||||
unsplashPhoto, err := models.GetUnsplashPhotoByFileID(s, f.ID)
|
||||
if err != nil {
|
||||
if files.IsErrFileIsNotUnsplashFile(err) {
|
||||
return
|
||||
|
|
|
@ -18,6 +18,7 @@ package upload
|
|||
|
||||
import (
|
||||
"strconv"
|
||||
"xorm.io/xorm"
|
||||
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
|
@ -30,7 +31,7 @@ type Provider struct {
|
|||
}
|
||||
|
||||
// Search is only used to implement the interface
|
||||
func (p *Provider) Search(search string, page int64) (result []*background.Image, err error) {
|
||||
func (p *Provider) Search(s *xorm.Session, search string, page int64) (result []*background.Image, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -50,7 +51,7 @@ func (p *Provider) Search(search string, page int64) (result []*background.Image
|
|||
// @Failure 404 {object} models.Message "The list does not exist."
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /lists/{id}/backgrounds/upload [put]
|
||||
func (p *Provider) Set(image *background.Image, list *models.List, auth web.Auth) (err error) {
|
||||
func (p *Provider) Set(s *xorm.Session, image *background.Image, list *models.List, auth web.Auth) (err error) {
|
||||
// Remove the old background if one exists
|
||||
if list.BackgroundFileID != 0 {
|
||||
file := files.File{ID: list.BackgroundFileID}
|
||||
|
@ -67,5 +68,5 @@ func (p *Provider) Set(image *background.Image, list *models.List, auth web.Auth
|
|||
|
||||
list.BackgroundInformation = &models.ListBackgroundType{Type: models.ListBackgroundUpload}
|
||||
|
||||
return models.SetListBackground(list.ID, file)
|
||||
return models.SetListBackground(s, list.ID, file)
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package caldav
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -90,9 +91,16 @@ func (vcls *VikunjaCaldavListStorage) GetResources(rpath string, withChildren bo
|
|||
return []data.Resource{r}, nil
|
||||
}
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
// Otherwise get all lists
|
||||
thelists, _, _, err := vcls.list.ReadAll(vcls.user, "", -1, 50)
|
||||
thelists, _, _, err := vcls.list.ReadAll(s, vcls.user, "", -1, 50)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
if err := s.Commit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lists := thelists.([]*models.List)
|
||||
|
@ -125,10 +133,17 @@ func (vcls *VikunjaCaldavListStorage) GetResourcesByList(rpaths []string) ([]dat
|
|||
uids = append(uids, string(uid[:endlen]))
|
||||
}
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
// GetTasksByUIDs...
|
||||
// Parse these into ressources...
|
||||
tasks, err := models.GetTasksByUIDs(s, uids)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
if err := s.Commit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -187,15 +202,22 @@ func (vcls *VikunjaCaldavListStorage) GetResource(rpath string) (*data.Resource,
|
|||
|
||||
// If the task is not nil, we need to get the task and not the list
|
||||
if vcls.task != nil {
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
// save and override the updated unix date to not break any later etag checks
|
||||
updated := vcls.task.Updated
|
||||
task, err := models.GetTaskSimple(s, &models.Task{ID: vcls.task.ID, UID: vcls.task.UID})
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
if models.IsErrTaskDoesNotExist(err) {
|
||||
return nil, false, errs.ResourceNotFoundError
|
||||
}
|
||||
return nil, false, err
|
||||
}
|
||||
if err := s.Commit(); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
vcls.task = &task
|
||||
if updated.Unix() > 0 {
|
||||
|
@ -230,6 +252,9 @@ func (vcls *VikunjaCaldavListStorage) GetShallowResource(rpath string) (*data.Re
|
|||
// CreateResource creates a new resource
|
||||
func (vcls *VikunjaCaldavListStorage) CreateResource(rpath, content string) (*data.Resource, error) {
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
vTask, err := parseTaskFromVTODO(content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -249,6 +274,11 @@ func (vcls *VikunjaCaldavListStorage) CreateResource(rpath, content string) (*da
|
|||
// Create the task
|
||||
err = vTask.Create(s, vcls.user)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.Commit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -272,18 +302,28 @@ func (vcls *VikunjaCaldavListStorage) UpdateResource(rpath, content string) (*da
|
|||
// At this point, we already have the right task in vcls.task, so we can use that ID directly
|
||||
vTask.ID = vcls.task.ID
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
// Check the rights
|
||||
canUpdate, err := vTask.CanUpdate(s, vcls.user)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
if !canUpdate {
|
||||
_ = s.Rollback()
|
||||
return nil, errs.ForbiddenError
|
||||
}
|
||||
|
||||
// Update the task
|
||||
err = vTask.Update(s)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.Commit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -299,9 +339,13 @@ func (vcls *VikunjaCaldavListStorage) UpdateResource(rpath, content string) (*da
|
|||
// DeleteResource deletes a resource
|
||||
func (vcls *VikunjaCaldavListStorage) DeleteResource(rpath string) error {
|
||||
if vcls.task != nil {
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
// Check the rights
|
||||
canDelete, err := vcls.task.CanDelete(s, vcls.user)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return err
|
||||
}
|
||||
if !canDelete {
|
||||
|
@ -309,7 +353,13 @@ func (vcls *VikunjaCaldavListStorage) DeleteResource(rpath string) error {
|
|||
}
|
||||
|
||||
// Delete it
|
||||
return vcls.task.Delete(s)
|
||||
err = vcls.task.Delete(s)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
return s.Commit()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -385,16 +435,22 @@ func (vlra *VikunjaListResourceAdapter) GetModTime() time.Time {
|
|||
}
|
||||
|
||||
func (vcls *VikunjaCaldavListStorage) getListRessource(isCollection bool) (rr VikunjaListResourceAdapter, err error) {
|
||||
can, _, err := vcls.list.CanRead(nil, vcls.user)
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
can, _, err := vcls.list.CanRead(s, vcls.user)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return
|
||||
}
|
||||
if !can {
|
||||
_ = s.Rollback()
|
||||
log.Errorf("User %v tried to access a caldav resource (List %v) which they are not allowed to access", vcls.user.Username, vcls.list.ID)
|
||||
return rr, models.ErrUserDoesNotHaveAccessToList{ListID: vcls.list.ID}
|
||||
}
|
||||
err = vcls.list.ReadOne()
|
||||
err = vcls.list.ReadOne(s)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -405,6 +461,7 @@ func (vcls *VikunjaCaldavListStorage) getListRessource(isCollection bool) (rr Vi
|
|||
}
|
||||
iface, _, _, err := tk.ReadAll(s, vcls.user, "", 1, 1000)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return rr, err
|
||||
}
|
||||
tasks, ok := iface.([]*models.Task)
|
||||
|
@ -416,6 +473,10 @@ func (vcls *VikunjaCaldavListStorage) getListRessource(isCollection bool) (rr Vi
|
|||
vcls.list.Tasks = tasks
|
||||
}
|
||||
|
||||
if err := s.Commit(); err != nil {
|
||||
return rr, err
|
||||
}
|
||||
|
||||
rr = VikunjaListResourceAdapter{
|
||||
list: vcls.list,
|
||||
listTasks: listTasks,
|
||||
|
|
Loading…
Reference in New Issue