2017-01-20 09:58:46 +03:00
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repo
import (
"fmt"
2020-01-05 02:20:08 +03:00
"net/http"
2017-01-20 09:58:46 +03:00
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
2020-08-18 07:23:45 +03:00
"code.gitea.io/gitea/modules/storage"
2019-07-07 05:25:05 +03:00
"code.gitea.io/gitea/modules/upload"
2017-01-20 09:58:46 +03:00
)
2020-10-05 08:49:33 +03:00
// UploadIssueAttachment response for Issue/PR attachments
func UploadIssueAttachment ( ctx * context . Context ) {
uploadAttachment ( ctx , setting . Attachment . AllowedTypes )
2017-01-20 09:58:46 +03:00
}
2020-10-05 08:49:33 +03:00
// UploadReleaseAttachment response for uploading release attachments
func UploadReleaseAttachment ( ctx * context . Context ) {
uploadAttachment ( ctx , setting . Repository . Release . AllowedTypes )
}
// UploadAttachment response for uploading attachments
func uploadAttachment ( ctx * context . Context , allowedTypes string ) {
2020-08-18 07:23:45 +03:00
if ! setting . Attachment . Enabled {
2017-01-20 09:58:46 +03:00
ctx . Error ( 404 , "attachment is not enabled" )
return
}
file , header , err := ctx . Req . FormFile ( "file" )
if err != nil {
ctx . Error ( 500 , fmt . Sprintf ( "FormFile: %v" , err ) )
return
}
defer file . Close ( )
buf := make ( [ ] byte , 1024 )
n , _ := file . Read ( buf )
if n > 0 {
buf = buf [ : n ]
}
2020-10-05 08:49:33 +03:00
err = upload . Verify ( buf , header . Filename , allowedTypes )
2019-07-07 05:25:05 +03:00
if err != nil {
ctx . Error ( 400 , err . Error ( ) )
2017-01-20 09:58:46 +03:00
return
}
2019-04-02 22:25:05 +03:00
attach , err := models . NewAttachment ( & models . Attachment {
UploaderID : ctx . User . ID ,
Name : header . Filename ,
} , buf , file )
2017-01-20 09:58:46 +03:00
if err != nil {
ctx . Error ( 500 , fmt . Sprintf ( "NewAttachment: %v" , err ) )
return
}
log . Trace ( "New attachment uploaded: %s" , attach . UUID )
ctx . JSON ( 200 , map [ string ] string {
"uuid" : attach . UUID ,
} )
}
2019-10-15 15:19:32 +03:00
// DeleteAttachment response for deleting issue's attachment
func DeleteAttachment ( ctx * context . Context ) {
file := ctx . Query ( "file" )
attach , err := models . GetAttachmentByUUID ( file )
if err != nil {
ctx . Error ( 400 , err . Error ( ) )
return
}
2020-02-28 02:10:27 +03:00
if ! ctx . IsSigned || ( ctx . User . ID != attach . UploaderID ) {
ctx . Error ( 403 )
return
}
2019-10-15 15:19:32 +03:00
err = models . DeleteAttachment ( attach , true )
if err != nil {
ctx . Error ( 500 , fmt . Sprintf ( "DeleteAttachment: %v" , err ) )
return
}
ctx . JSON ( 200 , map [ string ] string {
"uuid" : attach . UUID ,
} )
}
2020-01-05 02:20:08 +03:00
// GetAttachment serve attachements
func GetAttachment ( ctx * context . Context ) {
attach , err := models . GetAttachmentByUUID ( ctx . Params ( ":uuid" ) )
if err != nil {
if models . IsErrAttachmentNotExist ( err ) {
ctx . Error ( 404 )
} else {
ctx . ServerError ( "GetAttachmentByUUID" , err )
}
return
}
repository , unitType , err := attach . LinkedRepository ( )
if err != nil {
ctx . ServerError ( "LinkedRepository" , err )
return
}
if repository == nil { //If not linked
if ! ( ctx . IsSigned && attach . UploaderID == ctx . User . ID ) { //We block if not the uploader
ctx . Error ( http . StatusNotFound )
return
}
} else { //If we have the repository we check access
perm , err := models . GetUserRepoPermission ( repository , ctx . User )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "GetUserRepoPermission" , err . Error ( ) )
return
}
if ! perm . CanRead ( unitType ) {
ctx . Error ( http . StatusNotFound )
return
}
}
2020-08-18 07:23:45 +03:00
if setting . Attachment . ServeDirect {
//If we have a signed url (S3, object storage), redirect to this directly.
u , err := storage . Attachments . URL ( attach . RelativePath ( ) , attach . Name )
if u != nil && err == nil {
if err := attach . IncreaseDownloadCount ( ) ; err != nil {
ctx . ServerError ( "Update" , err )
return
}
ctx . Redirect ( u . String ( ) )
return
}
}
2020-01-05 02:20:08 +03:00
//If we have matched and access to release or issue
2020-08-18 07:23:45 +03:00
fr , err := storage . Attachments . Open ( attach . RelativePath ( ) )
2020-01-05 02:20:08 +03:00
if err != nil {
ctx . ServerError ( "Open" , err )
return
}
defer fr . Close ( )
if err := attach . IncreaseDownloadCount ( ) ; err != nil {
ctx . ServerError ( "Update" , err )
return
}
2021-02-05 23:10:40 +03:00
if err = ServeData ( ctx , attach . Name , attach . Size , fr ) ; err != nil {
2020-01-05 02:20:08 +03:00
ctx . ServerError ( "ServeData" , err )
return
}
}