diff --git a/server/im_http.go b/server/im_http.go index af1ebe5..b4f71b2 100644 --- a/server/im_http.go +++ b/server/im_http.go @@ -9483,7 +9483,8 @@ func cleanStringList(values []string, limit int) []string { func isAllowedPublicUploadPurpose(purpose string) bool { switch strings.TrimSpace(purpose) { - case types.PublicUploadPurposeEnterpriseLicense, types.PublicUploadPurposeTenantFeedback: + case types.PublicUploadPurposeEnterpriseLicense, types.PublicUploadPurposeTenantFeedback, + types.PublicUploadPurposeGroupAvatar: return true default: return false @@ -9502,6 +9503,10 @@ func isAllowedPublicUploadMime(purpose, mimeType string) bool { return strings.HasPrefix(mimeType, "image/jpeg") || strings.HasPrefix(mimeType, "image/png") || strings.HasPrefix(mimeType, "image/webp") + case types.PublicUploadPurposeGroupAvatar: + return strings.HasPrefix(mimeType, "image/jpeg") || + strings.HasPrefix(mimeType, "image/png") || + strings.HasPrefix(mimeType, "image/webp") default: return false } diff --git a/server/im_http_test.go b/server/im_http_test.go index aaf687a..34b6a5d 100644 --- a/server/im_http_test.go +++ b/server/im_http_test.go @@ -1719,6 +1719,55 @@ func TestServeIMPublicUploads(t *testing.T) { } } +func TestServeIMPublicUploadsAllowsGroupAvatar(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + oldStore := store.Store + oldTenantEntry := store.TenantEntry + entry := &testTenantEntryStore{} + handler := &testPublicMediaHandler{} + mockStore := mock_store.NewMockPersistentStorageInterface(ctrl) + mockStore.EXPECT().GetMediaHandler().Return(handler).AnyTimes() + store.Store = mockStore + store.TenantEntry = entry + defer func() { + store.Store = oldStore + store.TenantEntry = oldTenantEntry + }() + + var body bytes.Buffer + writer := multipart.NewWriter(&body) + if err := writer.WriteField("purpose", types.PublicUploadPurposeGroupAvatar); err != nil { + t.Fatal(err) + } + part, err := writer.CreateFormFile("file", "avatar.png") + if err != nil { + t.Fatal(err) + } + if _, err := part.Write([]byte("\x89PNG\r\n\x1a\n" + strings.Repeat("\x00", 64))); err != nil { + t.Fatal(err) + } + if err := writer.Close(); err != nil { + t.Fatal(err) + } + req := httptest.NewRequest(http.MethodPost, "/v1/im/public/uploads", &body) + req.Header.Set("Content-Type", writer.FormDataContentType()) + rec := httptest.NewRecorder() + + serveIMPublicUploads(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("status: got %d, body=%s", rec.Code, rec.Body.String()) + } + if entry.upload == nil || entry.upload.Purpose != types.PublicUploadPurposeGroupAvatar { + t.Fatalf("unexpected upload: %#v", entry.upload) + } + data := decodeIMHTTPResponse(t, rec).Data.(map[string]any) + if !strings.HasPrefix(data["file_id"].(string), "file_") || data["purpose"] != types.PublicUploadPurposeGroupAvatar { + t.Fatalf("unexpected upload response: %#v", data) + } +} + func TestServeIMVerificationCodesCreatesChallenge(t *testing.T) { oldTenants := store.Tenants oldVerifications := store.Verifications diff --git a/server/store/types/tenant_entry.go b/server/store/types/tenant_entry.go index 455b2bf..687c213 100644 --- a/server/store/types/tenant_entry.go +++ b/server/store/types/tenant_entry.go @@ -5,6 +5,7 @@ import "time" const ( PublicUploadPurposeEnterpriseLicense = "enterprise_license" PublicUploadPurposeTenantFeedback = "tenant_entry_feedback" + PublicUploadPurposeGroupAvatar = "group_avatar" TenantApplicationStatusReceived = "received" TenantEntryFeedbackReceived = "received"