feat(files): MinIO fallback for stale S3 downloads (#152) #21

Merged
eSlider merged 2 commits from feat/oo-minio-fallback#152 into main 2026-09-14 22:31:33 +01:00
Owner

Что

Задача A из edelweiss/office-assistant#152: fallback-загрузка файлов, которые
портал отдаёт через свой устаревший AWS S3 consumer (403 InvalidAccessKeyId,
ключ minio).

  • storage_fallback.go (новый): детект stale-S3 (isStaleS3Redirect), ключ
    объекта (minioObjectKey / minioObjectKeyFromURL), скачивание из MinIO с
    подписью AWS SigV4 (github.com/aws/aws-sdk-go-v2/aws/signer/v4).
  • files.go: DownloadFile делегирует в общий downloadFileEntry с fallback.
  • files_webdav.go: DownloadDavFile теперь использует тот же путь (без дубля).
  • .env.example: имена MINIO_ENDPOINT / MINIO_BUCKET / MINIO_ACCESS_KEY /
    MINIO_SECRET_KEY (значения не в git).

Реальный ключ объекта (важно)

В задаче предполагалось 00/00/01/files/folder_{folderId}/file_{fileId}, где
folderId из GetFile. На проде это не так:

  • GetFile для 3785/3859/3666 даёт folderId 655/656/704, но объекты лежат под
    storage root folder_4000;
  • у ключа есть суффикс /v1/content.pdf;
  • S3-redirect дублирует bucket: /office/office/00/00/01/....
    Поэтому ключ берётся из S3-redirect URL (авторитетно), а minioObjectKey
    оставлен только как fallback. Проверено на MinIO: ключ
    00/00/01/files/folder_4000/file_3785/v1/content.pdf → 200.

TDD / доказательство

Unit (go test -race ./... — зелёный):

  • TestMinioObjectKey, TestMinioObjectKeyFromURL (path-style, double-bucket, traversal)
  • TestIsStaleS3Redirect (7 кейсов: XML InvalidAccessKeyId, AWSAccessKeyId=minio, обычный PDF и т.д.)
  • TestDownloadFileMinioFallback — offline httptest: портал → 403 stale → подписанный GET в fake MinIO
  • TestDownloadFileMinioFallbackWithoutCreds — внятная ошибка без ключей

Integration (-tags=integration, skip без creds):

  • TestIntegrationMinioFallback на live: 3785 = 13 126 082 B, 3859 = 10 738 272 B, 3666 = 12 821 432 B — PASS.

Тег

v0.20.0 (MINOR), коммит 8ac777c, на Gitea и GitHub; Go proxy резолвит.

Замечание: база — v0.19.0 (c576bfe), поэтому в PR также коммиты PR #20
(Dav/UpdateFile), который ещё не влит.

Refs: edelweiss/office-assistant#152

## Что Задача A из edelweiss/office-assistant#152: fallback-загрузка файлов, которые портал отдаёт через свой устаревший AWS S3 consumer (403 InvalidAccessKeyId, ключ `minio`). - `storage_fallback.go` (новый): детект stale-S3 (`isStaleS3Redirect`), ключ объекта (`minioObjectKey` / `minioObjectKeyFromURL`), скачивание из MinIO с подписью AWS SigV4 (`github.com/aws/aws-sdk-go-v2/aws/signer/v4`). - `files.go`: `DownloadFile` делегирует в общий `downloadFileEntry` с fallback. - `files_webdav.go`: `DownloadDavFile` теперь использует тот же путь (без дубля). - `.env.example`: имена `MINIO_ENDPOINT` / `MINIO_BUCKET` / `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY` (значения не в git). ## Реальный ключ объекта (важно) В задаче предполагалось `00/00/01/files/folder_{folderId}/file_{fileId}`, где `folderId` из GetFile. На проде это не так: - GetFile для 3785/3859/3666 даёт folderId 655/656/704, но объекты лежат под **storage root folder_4000**; - у ключа есть суффикс `/v1/content.pdf`; - S3-redirect дублирует bucket: `/office/office/00/00/01/...`. Поэтому ключ берётся **из S3-redirect URL** (авторитетно), а `minioObjectKey` оставлен только как fallback. Проверено на MinIO: ключ `00/00/01/files/folder_4000/file_3785/v1/content.pdf` → 200. ## TDD / доказательство Unit (`go test -race ./...` — зелёный): - `TestMinioObjectKey`, `TestMinioObjectKeyFromURL` (path-style, double-bucket, traversal) - `TestIsStaleS3Redirect` (7 кейсов: XML InvalidAccessKeyId, `AWSAccessKeyId=minio`, обычный PDF и т.д.) - `TestDownloadFileMinioFallback` — offline httptest: портал → 403 stale → подписанный GET в fake MinIO - `TestDownloadFileMinioFallbackWithoutCreds` — внятная ошибка без ключей Integration (`-tags=integration`, skip без creds): - `TestIntegrationMinioFallback` на live: **3785 = 13 126 082 B, 3859 = 10 738 272 B, 3666 = 12 821 432 B** — PASS. ## Тег `v0.20.0` (MINOR), коммит `8ac777c`, на Gitea и GitHub; Go proxy резолвит. Замечание: база — `v0.19.0` (`c576bfe`), поэтому в PR также коммиты PR #20 (Dav/UpdateFile), который ещё не влит. Refs: edelweiss/office-assistant#152
eSlider added 2 commits 2026-09-14 16:42:08 +01:00
feat(files): Documents Dav ops + UpdateFile, fileops errors (#152)
Release Please / Release Please (push) Skipped
Tests / Secret scan (gitleaks) (push) Skipped
Tests / Test (Go 1.25) (push) Skipped
Tests / Test (Go stable) (push) Skipped
Release / GoReleaser (push) Skipped
Tests / Secret scan (gitleaks) (pull_request) Successful in 4s
Tests / Test (Go stable) (pull_request) Successful in 1m17s
Tests / Test (Go 1.25) (pull_request) Successful in 1m20s
c576bfe2ee
feat(files): MinIO fallback for stale S3 downloads (#152)
Release Please / Release Please (push) Skipped
Tests / Secret scan (gitleaks) (push) Skipped
Tests / Test (Go 1.25) (push) Skipped
Tests / Test (Go stable) (push) Skipped
Release / GoReleaser (push) Skipped
Tests / Secret scan (gitleaks) (pull_request) Successful in 4s
Tests / Test (Go stable) (pull_request) Successful in 1m15s
Tests / Test (Go 1.25) (pull_request) Successful in 1m22s
8ac777c031
eSlider merged commit 4310aa7002 into main 2026-09-14 22:31:33 +01:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: eSlider/go-onlyoffice#21