diff --git a/models/attachment.go b/models/attachment.go index aa5f4e8d1..621f34216 100644 --- a/models/attachment.go +++ b/models/attachment.go @@ -303,3 +303,13 @@ func (a *Attachment) LinkedDataSet() (*Dataset, error) { } return nil, nil } + +// InsertAttachment insert a record into attachment. +func InsertAttachment(attach *Attachment) (_ *Attachment, err error) { + + if _, err := x.Insert(attach); err != nil { + return nil, err + } + + return attach, nil +} diff --git a/modules/storage/local.go b/modules/storage/local.go index 310d1883c..4d2f28029 100644 --- a/modules/storage/local.go +++ b/modules/storage/local.go @@ -72,3 +72,7 @@ func (l *LocalStorage) PresignedGetURL(path string, fileName string) (string,err func (l *LocalStorage) PresignedPutURL(path string) (string,error) { return "",nil } + +func (l *LocalStorage) HasObject(path string) (bool,error) { + return false,nil +} diff --git a/modules/storage/minio.go b/modules/storage/minio.go index ddbb9328b..dfbe39558 100644 --- a/modules/storage/minio.go +++ b/modules/storage/minio.go @@ -101,3 +101,24 @@ func (m *MinioStorage) PresignedPutURL(path string) (string,error) { return preURL.String(),nil } + +//check if has the object +func (m *MinioStorage) HasObject(path string) (bool,error) { + hasObject := false + // Create a done channel to control 'ListObjects' go routine. + doneCh := make(chan struct{}) + + // Indicate to our routine to exit cleanly upon return. + defer close(doneCh) + + objectCh := m.client.ListObjects(m.bucket, m.buildMinioPath(path), false, doneCh) + for object := range objectCh { + if object.Err != nil { + return hasObject, object.Err + } + + hasObject = true + } + + return hasObject,nil +} diff --git a/modules/storage/storage.go b/modules/storage/storage.go index 811315cab..d06ec7208 100644 --- a/modules/storage/storage.go +++ b/modules/storage/storage.go @@ -23,6 +23,7 @@ type ObjectStorage interface { Delete(path string) error PresignedGetURL(path string, fileName string) (string, error) PresignedPutURL(path string) (string, error) + HasObject(path string) (bool, error) } // Copy copys a file from source ObjectStorage to dest ObjectStorage diff --git a/modules/upload/filetype.go b/modules/upload/filetype.go index 2ab326d11..ff88eb140 100644 --- a/modules/upload/filetype.go +++ b/modules/upload/filetype.go @@ -31,11 +31,15 @@ func (err ErrFileTypeForbidden) Error() string { func VerifyAllowedContentType(buf []byte, allowedTypes []string) error { fileType := http.DetectContentType(buf) + return VerifyFileType(fileType, allowedTypes) +} + +func VerifyFileType(fileType string, allowedTypes []string) error { for _, t := range allowedTypes { t := strings.Trim(t, " ") if t == "*/*" || t == fileType || - // Allow directives after type, like 'text/plain; charset=utf-8' + // Allow directives after type, like 'text/plain; charset=utf-8' strings.HasPrefix(fileType, t+";") { return nil } diff --git a/routers/repo/attachment.go b/routers/repo/attachment.go index 5ef85b820..1a1e9f186 100644 --- a/routers/repo/attachment.go +++ b/routers/repo/attachment.go @@ -203,6 +203,12 @@ func GetPresignedPutObjectURL(ctx *context.Context) { return } + err := upload.VerifyFileType(ctx.Params("file_type"), strings.Split(setting.Attachment.AllowedTypes, ",")) + if err != nil { + ctx.Error(400, err.Error()) + return + } + if setting.Attachment.StoreType == storage.MinioStorageType { uuid := gouuid.NewV4().String() url, err := storage.Attachments.PresignedPutURL(models.AttachmentRelativePath(uuid)) @@ -219,6 +225,35 @@ func GetPresignedPutObjectURL(ctx *context.Context) { ctx.Error(404, "storage type is not enabled") return } +} +// AddAttachment response for add attachment record +func AddAttachment(ctx *context.Context) { + uuid := ctx.Query("uuid") + has,err := storage.Attachments.HasObject(models.AttachmentRelativePath(uuid)) + if err != nil { + ctx.ServerError("HasObject", err) + return + } + if !has { + ctx.Error(404, "attachment has not been uploaded") + return + } + + _, err = models.InsertAttachment(&models.Attachment{ + UUID: uuid, + UploaderID: ctx.User.ID, + Name: ctx.Query("file_name"), + Size: ctx.QueryInt64("size"), + }) + + if err != nil { + ctx.Error(500, fmt.Sprintf("InsertAttachment: %v", err)) + return + } + + ctx.JSON(200, map[string]string{ + "result_code": "0", + }) } diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 9f0943deb..42e83242b 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -520,6 +520,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("", repo.UploadAttachment) m.Post("/delete", repo.DeleteAttachment) m.Get("/get_pre_url", repo.GetPresignedPutObjectURL) + m.Post("/add", repo.AddAttachment) }, reqSignIn) m.Group("/:username", func() {