mirror of
https://github.com/abhinavxd/libredesk.git
synced 2026-09-10 06:05:41 +00:00
fix: harden media + conversation queries against empty-uuid casts
This commit is contained in:
@@ -53,6 +53,9 @@ func handleCreateTemplate(r *fastglue.Request) error {
|
||||
if req.Name == "" {
|
||||
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.empty", "name", "`name`"), nil, envelope.InputError)
|
||||
}
|
||||
if req.Type == "" {
|
||||
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.empty", "name", "`type`"), nil, envelope.InputError)
|
||||
}
|
||||
template, err := app.tmpl.Create(req)
|
||||
if err != nil {
|
||||
return sendErrorEnvelope(r, err)
|
||||
@@ -77,6 +80,9 @@ func handleUpdateTemplate(r *fastglue.Request) error {
|
||||
if req.Name == "" {
|
||||
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.empty", "name", "`name`"), nil, envelope.InputError)
|
||||
}
|
||||
if req.Type == "" {
|
||||
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.empty", "name", "`type`"), nil, envelope.InputError)
|
||||
}
|
||||
updatedTemplate, err := app.tmpl.Update(id, req)
|
||||
if err != nil {
|
||||
return sendErrorEnvelope(r, err)
|
||||
|
||||
@@ -141,7 +141,7 @@ type mediaStore interface {
|
||||
SetContentID(id int, contentID string) error
|
||||
GetByModel(id int, model string) ([]mmodels.Media, error)
|
||||
GetByContentIDs(contentIDs []string, conversationUUID string) ([]mmodels.Media, error)
|
||||
ContentIDExists(contentID string) (bool, string, error)
|
||||
ContentIDExists(contentID, conversationUUID string) (bool, string, error)
|
||||
Upload(fileName, contentType string, content io.ReadSeeker) (string, string, error)
|
||||
UploadAndInsert(fileName, contentType, contentID string, modelType null.String, modelID null.Int, content io.ReadSeeker, fileSize int, disposition null.String, meta []byte) (mmodels.Media, error)
|
||||
}
|
||||
|
||||
@@ -1425,7 +1425,7 @@ func (m *Manager) findExistingMedia(rawContentID, conversationUUID string) (stri
|
||||
if !strings.HasPrefix(rawContentID, "ldsk-") {
|
||||
storedCID = conversationUUID + "_" + rawContentID
|
||||
}
|
||||
exists, mediaUUID, err := m.mediaStore.ContentIDExists(storedCID)
|
||||
exists, mediaUUID, err := m.mediaStore.ContentIDExists(storedCID, conversationUUID)
|
||||
if err != nil {
|
||||
m.lo.Error("error checking media existence by content ID", "content_id", storedCID, "error", err)
|
||||
}
|
||||
|
||||
@@ -204,10 +204,10 @@ LEFT JOIN LATERAL (
|
||||
ORDER BY se.created_at DESC
|
||||
LIMIT 1
|
||||
) nxt_resp_event ON true
|
||||
WHERE
|
||||
WHERE
|
||||
($1 > 0 AND c.id = $1)
|
||||
OR
|
||||
($2::uuid IS NOT NULL AND c.uuid = $2::uuid)
|
||||
OR
|
||||
(NULLIF($2, '')::uuid IS NOT NULL AND c.uuid = NULLIF($2, '')::uuid)
|
||||
OR
|
||||
($3::TEXT != '' AND c.reference_number = $3::TEXT)
|
||||
|
||||
@@ -799,7 +799,7 @@ ORDER BY cd.updated_at DESC;
|
||||
DELETE FROM conversation_drafts
|
||||
WHERE conversation_id IN (
|
||||
SELECT id FROM conversations
|
||||
WHERE ($1 > 0 AND id = $1) OR ($2::uuid IS NOT NULL AND uuid = $2::uuid)
|
||||
WHERE ($1 > 0 AND id = $1) OR (NULLIF($2, '')::uuid IS NOT NULL AND uuid = NULLIF($2, '')::uuid)
|
||||
) AND user_id = $3;
|
||||
|
||||
-- name: delete-stale-drafts
|
||||
|
||||
@@ -180,10 +180,13 @@ func (m *Manager) SetContentID(id int, contentID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContentIDExists checks if a content_id exists in the database and returns the UUID of the media file.
|
||||
func (m *Manager) ContentIDExists(contentID string) (bool, string, error) {
|
||||
// ContentIDExists reports whether a media row with the given content_id is linked to a message in the given conversation. Scoped this way so an orphan media row (e.g., from a partial failure) doesn't short-circuit a retry into skipping the upload.
|
||||
func (m *Manager) ContentIDExists(contentID, conversationUUID string) (bool, string, error) {
|
||||
if contentID == "" || conversationUUID == "" {
|
||||
return false, "", nil
|
||||
}
|
||||
var uuid string
|
||||
if err := m.queries.ContentIDExists.Get(&uuid, contentID); err != nil {
|
||||
if err := m.queries.ContentIDExists.Get(&uuid, contentID, conversationUUID); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return false, "", nil
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@ RETURNING id;
|
||||
-- name: get-media
|
||||
SELECT id, created_at, updated_at, "uuid", store, filename, content_type, content_id, model_id, model_type, disposition, "size", meta
|
||||
FROM media
|
||||
WHERE
|
||||
WHERE
|
||||
($1 > 0 AND id = $1)
|
||||
OR
|
||||
($2 != '' AND uuid = $2::uuid)
|
||||
($2 != '' AND uuid = NULLIF($2, '')::uuid)
|
||||
|
||||
-- name: get-media-by-uuid
|
||||
SELECT id, created_at, updated_at, "uuid", store, filename, content_type, content_id, model_id, model_type, disposition, "size", meta
|
||||
@@ -51,7 +51,12 @@ WHERE model_type = 'messages'
|
||||
AND created_at < NOW() - INTERVAL '7 days';
|
||||
|
||||
-- name: content-id-exists
|
||||
SELECT uuid FROM media WHERE content_id = $1;
|
||||
SELECT m.uuid
|
||||
FROM media m
|
||||
INNER JOIN conversation_messages cm ON cm.id = m.model_id
|
||||
WHERE m.model_type = 'messages'
|
||||
AND m.content_id = $1
|
||||
AND cm.conversation_id = (SELECT id FROM conversations WHERE uuid = $2::uuid LIMIT 1);
|
||||
|
||||
-- name: get-media-by-content-ids
|
||||
SELECT m.id, m.created_at, m.updated_at, m."uuid", m.store, m.filename, m.content_type, m.content_id, m.model_id, m.model_type, m.disposition, m."size", m.meta
|
||||
|
||||
Reference in New Issue
Block a user