@@ -13,6 +13,7 @@ import (
1313 amodels "github.com/abhinavxd/libredesk/internal/auth/models"
1414 "github.com/abhinavxd/libredesk/internal/envelope"
1515 "github.com/abhinavxd/libredesk/internal/image"
16+ mmodels "github.com/abhinavxd/libredesk/internal/media/models"
1617 "github.com/abhinavxd/libredesk/internal/stringutil"
1718 "github.com/google/uuid"
1819 "github.com/valyala/fasthttp"
@@ -148,20 +149,29 @@ func handleMediaUpload(r *fastglue.Request) error {
148149}
149150
150151// handleServeMedia serves uploaded media.
152+ // Supports both authenticated access (with permission checks) and signed URL access (no permission checks).
151153func handleServeMedia (r * fastglue.Request ) error {
152154 var (
153- app = r .Context .(* App )
154- auser = r .RequestCtx .UserValue ("user " ).(amodels. User )
155- uuid = r .RequestCtx .UserValue ("uuid" ).( string )
155+ app = r .Context .(* App )
156+ uuid = r .RequestCtx .UserValue ("uuid " ).(string )
157+ authMethod = r .RequestCtx .UserValue ("auth_method" )
156158 )
157159
160+ // If accessed via signed URL, skip permission checks and serve file directly.
161+ if authMethod == "signed_url" {
162+ return serveMediaFile (r , app , uuid , nil )
163+ }
164+
165+ // Session/API key authenticated - perform full permission check.
166+ auser := r .RequestCtx .UserValue ("user" ).(amodels.User )
167+
158168 user , err := app .user .GetAgent (auser .ID , "" )
159169 if err != nil {
160170 return sendErrorEnvelope (r , err )
161171 }
162172
163173 // Fetch media from DB.
164- media , err := app . media . Get ( 0 , strings . TrimPrefix ( uuid , image . ThumbPrefix ) )
174+ media , err := getMediaByUUID ( app , uuid )
165175 if err != nil {
166176 return sendErrorEnvelope (r , err )
167177 }
@@ -187,6 +197,22 @@ func handleServeMedia(r *fastglue.Request) error {
187197 if ! allowed {
188198 return r .SendErrorEnvelope (http .StatusUnauthorized , app .i18n .Ts ("globals.messages.denied" , "name" , "{globals.terms.permission}" ), nil , envelope .UnauthorizedError )
189199 }
200+
201+ return serveMediaFile (r , app , uuid , & media )
202+ }
203+
204+ // serveMediaFile serves the actual file content based on the storage provider.
205+ // If media is nil, it will be fetched from DB.
206+ func serveMediaFile (r * fastglue.Request , app * App , uuid string , media * mmodels.Media ) error {
207+ // Fetch media metadata from DB if not provided.
208+ if media == nil {
209+ m , err := getMediaByUUID (app , uuid )
210+ if err != nil {
211+ return sendErrorEnvelope (r , err )
212+ }
213+ media = & m
214+ }
215+
190216 consts := app .consts .Load ().(* constants )
191217 switch consts .UploadProvider {
192218 case "fs" :
@@ -213,3 +239,8 @@ func handleServeMedia(r *fastglue.Request) error {
213239func bytesToMegabytes (bytes int64 ) float64 {
214240 return float64 (bytes ) / 1024 / 1024
215241}
242+
243+ // getMediaByUUID fetches media metadata from DB, handling thumbnail prefix.
244+ func getMediaByUUID (app * App , uuid string ) (mmodels.Media , error ) {
245+ return app .media .Get (0 , strings .TrimPrefix (uuid , image .ThumbPrefix ))
246+ }
0 commit comments