@@ -3,12 +3,15 @@ package routes
3
3
import (
4
4
"errors"
5
5
"fmt"
6
+ "mime/multipart"
6
7
"net/http"
8
+ "path/filepath"
9
+ "strings"
10
+ "time"
7
11
8
12
"github.com/mikestefanello/pagoda/ent"
9
13
"github.com/mikestefanello/pagoda/pkg/context"
10
14
"github.com/mikestefanello/pagoda/pkg/controller"
11
- "github.com/mikestefanello/pagoda/pkg/repo"
12
15
"github.com/mikestefanello/pagoda/pkg/repos/profilerepo"
13
16
storagerepo "github.com/mikestefanello/pagoda/pkg/repos/storage"
14
17
"github.com/mikestefanello/pagoda/templates/layouts"
@@ -73,13 +76,13 @@ func (p *currProfilePhoto) Post(ctx echo.Context) error {
73
76
}
74
77
75
78
// Validate and process the image
76
- err = repo . ValidateAndProcessImage (file )
79
+ err = ValidateAndProcessImage (file )
77
80
ctx .Logger ().Error (err )
78
81
if err != nil {
79
82
// Handle specific errors returned by ValidateAndProcessImage
80
- if errors .Is (err , repo . ErrInvalidMimeType ) || errors .Is (err , repo . ErrInvalidFileExtension ) {
83
+ if errors .Is (err , ErrInvalidMimeType ) || errors .Is (err , ErrInvalidFileExtension ) {
81
84
return echo .NewHTTPError (http .StatusBadRequest , "Invalid file type" )
82
- } else if errors .Is (err , repo . ErrImageProcessing ) {
85
+ } else if errors .Is (err , ErrImageProcessing ) {
83
86
return echo .NewHTTPError (http .StatusInternalServerError , "Error processing image" )
84
87
} else {
85
88
return echo .NewHTTPError (http .StatusInternalServerError , err .Error ())
@@ -110,3 +113,57 @@ func (p *currProfilePhoto) Post(ctx echo.Context) error {
110
113
111
114
return p .ctr .RenderJSON (ctx , nil )
112
115
}
116
+
117
+ var (
118
+ ErrInvalidMimeType = errors .New ("invalid MIME type" )
119
+ ErrInvalidFileExtension = errors .New ("invalid file extension" )
120
+ ErrImageProcessing = errors .New ("error processing image" )
121
+ )
122
+
123
+ func ValidateAndProcessImage (fileHeader * multipart.FileHeader ) error {
124
+ // TODO: need to do many other checks for file upload security: https://portswigger.net/web-security/file-upload
125
+
126
+ // Define allowed MIME types
127
+ allowedMimeTypes := map [string ]bool {
128
+ "image/jpeg" : true ,
129
+ "image/webp" : true ,
130
+ "image/png" : true ,
131
+ "image/gif" : true ,
132
+ }
133
+
134
+ // Define allowed file extensions
135
+ allowedExtensions := map [string ]bool {
136
+ ".jpg" : true ,
137
+ ".jpeg" : true ,
138
+ ".webp" : true ,
139
+ ".png" : true ,
140
+ ".gif" : true ,
141
+ }
142
+
143
+ // Check MIME type
144
+ contentType := fileHeader .Header .Get ("Content-Type" )
145
+ if ! allowedMimeTypes [contentType ] {
146
+ return ErrInvalidMimeType
147
+ }
148
+
149
+ // Check file extension
150
+ extension := strings .ToLower (filepath .Ext (fileHeader .Filename ))
151
+ if ! allowedExtensions [extension ] {
152
+ return ErrInvalidFileExtension
153
+ }
154
+
155
+ // Open the file
156
+ file , err := fileHeader .Open ()
157
+ if err != nil {
158
+ return err
159
+ }
160
+ defer file .Close ()
161
+
162
+ // TODO: verify that the file actually contains an image
163
+ return nil
164
+ }
165
+
166
+ // daysAgo returns a time.Time object for x days ago.
167
+ func daysAgo (x int ) time.Time {
168
+ return time .Now ().UTC ().AddDate (0 , 0 , - x )
169
+ }
0 commit comments