From d94389f00c14dec8223242e925d946511b520cfb Mon Sep 17 00:00:00 2001
From: Pascal Bleser
Date: Tue, 18 Nov 2025 09:36:57 +0100
Subject: [PATCH] groupware: fix recently introduced error with UploadedBlob
with and without a sha512
---
pkg/jmap/jmap_api_blob.go | 21 ++++++++++---------
pkg/jmap/jmap_model.go | 6 ++++++
pkg/jmap/jmap_test.go | 5 -----
.../pkg/groupware/groupware_api_blob.go | 3 +--
4 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/pkg/jmap/jmap_api_blob.go b/pkg/jmap/jmap_api_blob.go
index b83129fba..bb0b0a675 100644
--- a/pkg/jmap/jmap_api_blob.go
+++ b/pkg/jmap/jmap_api_blob.go
@@ -38,10 +38,11 @@ func (j *Client) GetBlobMetadata(accountId string, session *Session, ctx context
})
}
-type UploadedBlob struct {
+type UploadedBlobWithHash struct {
BlobId string `json:"blobId"`
Size int `json:"size,omitzero"`
Type string `json:"type,omitempty"`
+ Sha512 string `json:"sha:512,omitempty"`
}
func (j *Client) UploadBlobStream(accountId string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, contentType string, body io.Reader) (UploadedBlob, Language, Error) {
@@ -63,7 +64,7 @@ func (j *Client) DownloadBlobStream(accountId string, blobId string, name string
return j.blob.DownloadBinary(ctx, logger, session, downloadUrl, session.DownloadEndpoint, acceptLanguage)
}
-func (j *Client) UploadBlob(accountId string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, data []byte, contentType string) (UploadedBlob, SessionState, State, Language, Error) {
+func (j *Client) UploadBlob(accountId string, session *Session, ctx context.Context, logger *log.Logger, acceptLanguage string, data []byte, contentType string) (UploadedBlobWithHash, SessionState, State, Language, Error) {
encoded := base64.StdEncoding.EncodeToString(data)
upload := BlobUploadCommand{
@@ -93,39 +94,39 @@ func (j *Client) UploadBlob(accountId string, session *Session, ctx context.Cont
invocation(CommandBlobGet, getHash, "1"),
)
if jerr != nil {
- return UploadedBlob{}, "", "", "", jerr
+ return UploadedBlobWithHash{}, "", "", "", jerr
}
- return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) (UploadedBlob, State, Error) {
+ return command(j.api, logger, ctx, session, j.onSessionOutdated, cmd, acceptLanguage, func(body *Response) (UploadedBlobWithHash, State, Error) {
var uploadResponse BlobUploadResponse
err := retrieveResponseMatchParameters(logger, body, CommandBlobUpload, "0", &uploadResponse)
if err != nil {
- return UploadedBlob{}, "", err
+ return UploadedBlobWithHash{}, "", err
}
var getResponse BlobGetResponse
err = retrieveResponseMatchParameters(logger, body, CommandBlobGet, "1", &getResponse)
if err != nil {
- return UploadedBlob{}, "", err
+ return UploadedBlobWithHash{}, "", err
}
if len(uploadResponse.Created) != 1 {
logger.Error().Msgf("%T.Created has %v entries instead of 1", uploadResponse, len(uploadResponse.Created))
- return UploadedBlob{}, "", simpleError(err, JmapErrorInvalidJmapResponsePayload)
+ return UploadedBlobWithHash{}, "", simpleError(err, JmapErrorInvalidJmapResponsePayload)
}
upload, ok := uploadResponse.Created["0"]
if !ok {
logger.Error().Msgf("%T.Created has no item '0'", uploadResponse)
- return UploadedBlob{}, "", simpleError(err, JmapErrorInvalidJmapResponsePayload)
+ return UploadedBlobWithHash{}, "", simpleError(err, JmapErrorInvalidJmapResponsePayload)
}
if len(getResponse.List) != 1 {
logger.Error().Msgf("%T.List has %v entries instead of 1", getResponse, len(getResponse.List))
- return UploadedBlob{}, "", simpleError(err, JmapErrorInvalidJmapResponsePayload)
+ return UploadedBlobWithHash{}, "", simpleError(err, JmapErrorInvalidJmapResponsePayload)
}
get := getResponse.List[0]
- return UploadedBlob{
+ return UploadedBlobWithHash{
BlobId: upload.Id,
Size: upload.Size,
Type: upload.Type,
diff --git a/pkg/jmap/jmap_model.go b/pkg/jmap/jmap_model.go
index b9dd5238a..7a653c54e 100644
--- a/pkg/jmap/jmap_model.go
+++ b/pkg/jmap/jmap_model.go
@@ -3638,6 +3638,12 @@ type BlobDownload struct {
CacheControl string
}
+type UploadedBlob struct {
+ BlobId string `json:"blobId"`
+ Size int `json:"size,omitzero"`
+ Type string `json:"type,omitempty"`
+}
+
// When doing a search on a String property, the client may wish to show the relevant
// section of the body that matches the search as a preview and to highlight any
// matching terms in both this and the subject of the Email.
diff --git a/pkg/jmap/jmap_test.go b/pkg/jmap/jmap_test.go
index 80fe89a61..697fea941 100644
--- a/pkg/jmap/jmap_test.go
+++ b/pkg/jmap/jmap_test.go
@@ -2,8 +2,6 @@ package jmap
import (
"context"
- "crypto/sha512"
- "encoding/base64"
"encoding/json"
"fmt"
"io"
@@ -123,13 +121,10 @@ func (t TestJmapBlobClient) UploadBinary(ctx context.Context, logger *log.Logger
if err != nil {
return UploadedBlob{}, "", SimpleError{code: 0, err: err}
}
- hasher := sha512.New()
- hasher.Write(bytes)
return UploadedBlob{
BlobId: uuid.NewString(),
Size: len(bytes),
Type: contentType,
- Sha512: base64.StdEncoding.EncodeToString(hasher.Sum(nil)),
}, "", nil
}
diff --git a/services/groupware/pkg/groupware/groupware_api_blob.go b/services/groupware/pkg/groupware/groupware_api_blob.go
index 1e38f57ec..07a139291 100644
--- a/services/groupware/pkg/groupware/groupware_api_blob.go
+++ b/services/groupware/pkg/groupware/groupware_api_blob.go
@@ -7,7 +7,6 @@ import (
"strconv"
"github.com/go-chi/chi/v5"
- "github.com/opencloud-eu/opencloud/pkg/jmap"
"github.com/opencloud-eu/opencloud/pkg/log"
)
@@ -64,7 +63,7 @@ func (g *Groupware) UploadBlob(w http.ResponseWriter, r *http.Request) {
return req.errorResponseFromJmap(jerr)
}
- return etagOnlyResponse(resp, jmap.State(resp.Sha512), lang)
+ return response(resp, req.session.State, lang)
})
}