feat: add support for video formats to upload (#960)

eb/code-1016-2
Akhilesh Pandey 2024-01-12 15:43:53 +00:00 committed by Harness
parent 76e3c06b6b
commit 74def977f2
4 changed files with 37 additions and 21 deletions

View File

@ -17,8 +17,9 @@ package upload
import (
"bufio"
"context"
"errors"
"fmt"
"net/http"
"io"
"strings"
apiauth "github.com/harness/gitness/app/api/auth"
@ -29,15 +30,21 @@ import (
"github.com/harness/gitness/blob"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/gabriel-vasile/mimetype"
)
const (
imageContentType = "image"
MaxFileSize = 5 << 20 // 5 MB file limit set in Handler
MaxFileSize = 10 << 20 // 10 MB file limit set in Handler
fileBucketPathFmt = "uploads/%d/%s"
peekBytes = 512
)
var supportedFileTypes = map[string]struct{}{
"image": {},
"video": {},
}
type Controller struct {
authorizer authz.Authorizer
repoStore store.RepoStore
@ -76,23 +83,24 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context,
return repo, nil
}
func (c *Controller) ensureTypeImgAndGetExtn(file *bufio.Reader) (string, error) {
func (c *Controller) getFileExtension(file *bufio.Reader) (string, error) {
buf, err := file.Peek(peekBytes)
if err != nil {
if err != nil && !errors.Is(err, io.EOF) {
return "", fmt.Errorf("failed to read file: %w", err)
}
detectedContentType := http.DetectContentType(buf)
if !strings.HasPrefix(detectedContentType, imageContentType) {
return "", usererror.BadRequestf("only image files are supported, uploaded file is of type %s", detectedContentType)
// Example: mType.String() = image/png
// Splitting on "/" and taking the first element of the slice
// will give us the file type.
mType := mimetype.Detect(buf)
if _, ok := supportedFileTypes[strings.Split(mType.String(), "/")[0]]; !ok {
return "",
usererror.BadRequestf(
"only image and video files are supported, uploaded file is of type %s",
mType.String())
}
contentTypeSlice := strings.Split(detectedContentType, "/")
if len(contentTypeSlice) < 2 {
return "", fmt.Errorf("failed to parse content type %s", detectedContentType)
}
extn := contentTypeSlice[1]
return extn, nil
return mType.Extension(), nil
}
func getFileBucketPath(repoID int64, fileName string) string {

View File

@ -33,7 +33,7 @@ type Result struct {
}
const (
fileNameFmt = "%s.%s"
fileNameFmt = "%s%s"
)
func (c *Controller) Upload(ctx context.Context,
@ -51,8 +51,8 @@ func (c *Controller) Upload(ctx context.Context,
return nil, usererror.BadRequest("no file provided")
}
bufReader := bufio.NewReader(file)
// Check if the file is an image
extn, err := c.ensureTypeImgAndGetExtn(bufReader)
// Check if the file is an image or video
extn, err := c.getFileExtension(bufReader)
if err != nil {
return nil, fmt.Errorf("failed to determine file type: %w", err)
}

9
go.mod
View File

@ -52,11 +52,11 @@ require (
github.com/swaggest/swgui v1.4.2
github.com/unrolled/secure v1.0.8
go.uber.org/multierr v1.8.0
golang.org/x/crypto v0.13.0
golang.org/x/crypto v0.14.0
golang.org/x/exp v0.0.0-20230108222341-4b8118a2686a
golang.org/x/oauth2 v0.10.0
golang.org/x/sync v0.3.0
golang.org/x/term v0.12.0
golang.org/x/term v0.13.0
golang.org/x/text v0.13.0
google.golang.org/api v0.132.0
gopkg.in/alecthomas/kingpin.v2 v2.2.6
@ -129,6 +129,7 @@ require (
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/fullstorydev/grpcurl v1.8.1 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/goccy/go-json v0.9.7 // indirect
@ -282,8 +283,8 @@ require (
github.com/yuin/goldmark v1.4.13 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect

7
go.sum
View File

@ -490,6 +490,8 @@ github.com/fullstorydev/grpcurl v1.8.1 h1:Pp648wlTTg3OKySeqxM5pzh8XF6vLqrm8wRq66
github.com/fullstorydev/grpcurl v1.8.1/go.mod h1:3BWhvHZwNO7iLXaQlojdg5NA6SxUDePli4ecpK1N7gw=
github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
@ -1558,6 +1560,7 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -1674,6 +1677,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1827,6 +1832,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -1836,6 +1842,7 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=