Ctrl K
ComunidadGuías…

api/controller/cleanup_upload_inventory_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package controller

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"github.com/goodrain/rainbond/api/middleware"
	"github.com/goodrain/rainbond/db/model"
	"github.com/goodrain/rainbond/pkg/component/storage"
	"github.com/jinzhu/gorm"
)

// capability_id: rainbond.cleanup.upload-inventory-api
func TestUploadInventoryRestrictsEventsAndPreservesUnknownSizes(t *testing.T) {
	database, err := gorm.Open("sqlite3", filepath.Join(t.TempDir(), "uploads.db"))
	if err != nil {
		t.Fatal(err)
	}
	defer database.Close()
	if err := database.AutoMigrate(&model.UploadSession{}).Error; err != nil {
		t.Fatal(err)
	}
	for _, row := range []model.UploadSession{
		{ID: "known", EventID: "owned", Status: "uploading", FileName: "upload.zip", FileSize: 999999, StoragePath: "/private-path-never-return", FileMD5: "private-checksum-never-return", ExpiresAt: time.Now().Add(-time.Hour)},
		{ID: "unknown", EventID: "owned", Status: "completed", FileSize: 888888},
		{ID: "foreign", EventID: "other", Status: "uploading", FileName: "foreign-never-return"},
	} {
		if err := database.Create(&row).Error; err != nil {
			t.Fatal(err)
		}
	}
	measured := 0
	packages := 0
	h := &CleanupCoordinationHandler{uploadPackageReferences: func(*gorm.DB, []string) (map[string]bool, error) { return map[string]bool{"owned": true}, nil }, measureUploadEvent: func(ctx context.Context, eventID string) (storage.UploadChunkUsage, error) {
		packages++
		if eventID != "owned" {
			t.Fatal("measured foreign package event")
		}
		return storage.UploadChunkUsage{Bytes: 97, Objects: 3}, nil
	}, database: func() *gorm.DB { return database }, measureUploadChunks: func(ctx context.Context, id string) (storage.UploadChunkUsage, error) {
		measured++
		if id == "known" {
			return storage.UploadChunkUsage{Bytes: 17, Objects: 2}, nil
		}
		if id == "unknown" {
			return storage.UploadChunkUsage{}, errors.New("private-upstream-error")
		}
		t.Fatal("measured an unrequested event")
		return storage.UploadChunkUsage{}, nil
	}}
	t.Setenv("TOKEN", "isolated-upload-inventory-fixture")
	post := func(body string, auth bool) *httptest.ResponseRecorder {
		r := httptest.NewRequest(http.MethodPost, "/uploads/inventory", strings.NewReader(body))
		if auth {
			r.Header.Set("Authorization", "Token isolated-upload-inventory-fixture")
		}
		w := httptest.NewRecorder()
		middleware.CleanupIdentity(http.HandlerFunc(h.UploadInventory)).ServeHTTP(w, r)
		return w
	}
	if w := post(`{"event_ids":["owned"]}`, false); w.Code == 200 || measured != 0 {
		t.Fatal("unauthenticated inventory read")
	}
	for _, body := range []string{`{}`, `{"event_ids":[]}`, `{"event_ids":["../other"]}`, `{"event_ids":["owned","owned"]}`, `{"event_ids":["owned"],"path":"/tmp"}`} {
		if w := post(body, true); w.Code != 400 || measured != 0 {
			t.Fatal("invalid scope accepted", w.Code)
		}
	}
	w := post(`{"event_ids":["owned"]}`, true)
	if w.Code != 200 {
		t.Fatal("inventory failed", w.Code)
	}
	for _, private := range []string{"private-", "foreign-never-return", "999999", "888888"} {
		if strings.Contains(w.Body.String(), private) {
			t.Fatal("untrusted size or private metadata escaped")
		}
	}
	var reply struct {
		Bean struct {
			Packages []struct {
				Referenced         *bool  `json:"referenced"`
				ReferencesComplete bool   `json:"references_complete"`
				EventID            string `json:"event_id"`
				Bytes              *int64 `json:"bytes"`
			} `json:"packages"`
			Protocol int `json:"protocol"`
			Items    []struct {
				ID         string `json:"id"`
				Bytes      *int64 `json:"bytes"`
				SizeStatus string `json:"size_status"`
			} `json:"items"`
		} `json:"bean"`
	}
	if err := json.Unmarshal(w.Body.Bytes(), &reply); err != nil {
		t.Fatal(err)
	}
	if reply.Bean.Protocol != 1 || len(reply.Bean.Items) != 2 || measured != 2 {
		t.Fatal("incorrect scoped inventory")
	}
	if packages != 1 || len(reply.Bean.Packages) != 1 || reply.Bean.Packages[0].EventID != "owned" || reply.Bean.Packages[0].Bytes == nil || *reply.Bean.Packages[0].Bytes != 97 {
		t.Fatal("package was omitted or counted per session")
	}
	if reply.Bean.Packages[0].Referenced == nil || !*reply.Bean.Packages[0].Referenced || !reply.Bean.Packages[0].ReferencesComplete {
		t.Fatal("positive reference or complete bounded evidence missing")
	}
	known, unknown := reply.Bean.Items[0], reply.Bean.Items[1]
	if known.ID != "known" || known.Bytes == nil || *known.Bytes != 17 || known.SizeStatus != "measured" {
		t.Fatal("actual stored size not returned")
	}
	if unknown.ID != "unknown" || unknown.Bytes != nil || unknown.SizeStatus != "unavailable" {
		t.Fatal("unknown size reported as zero")
	}
}

// capability_id: rainbond.cleanup.upload-inventory-bounds
func TestUploadInventoryRejectsOversizedResultBeforeReadingStorage(t *testing.T) {
	database, err := gorm.Open("sqlite3", filepath.Join(t.TempDir(), "bounded.db"))
	if err != nil {
		t.Fatal(err)
	}
	defer database.Close()
	if err := database.AutoMigrate(&model.UploadSession{}).Error; err != nil {
		t.Fatal(err)
	}
	transaction := database.Begin()
	for i := 0; i < 501; i++ {
		if err := transaction.Create(&model.UploadSession{ID: fmt.Sprintf("owned-%d", i), EventID: "owned"}).Error; err != nil {
			t.Fatal(err)
		}
	}
	if err := transaction.Commit().Error; err != nil {
		t.Fatal(err)
	}
	calls := 0
	h := &CleanupCoordinationHandler{database: func() *gorm.DB { return database }, measureUploadChunks: func(context.Context, string) (storage.UploadChunkUsage, error) {
		calls++
		return storage.UploadChunkUsage{}, nil
	}}
	w := httptest.NewRecorder()
	h.UploadInventory(w, httptest.NewRequest(http.MethodPost, "/uploads/inventory", strings.NewReader(`{"event_ids":["owned"]}`)))
	if w.Code != 413 || calls != 0 {
		t.Fatal("truncated inventory accepted or unbounded storage reads", w.Code, calls)
	}
	w = httptest.NewRecorder()
	h.UploadInventory(w, httptest.NewRequest(http.MethodPost, "/uploads/inventory", strings.NewReader(`{"event_ids":["missing"]}`)))
	if w.Code != 200 || calls != 0 || !strings.Contains(w.Body.String(), `"items":[]`) {
		t.Fatal("empty explicit scope not represented")
	}
}