Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions openapi/Swarm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ paths:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmActHistoryAddress"
name: swarm-act-history-address
required: false
- in: header
schema:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmRedundancyLevelParameter"
name: swarm-redundancy-level
required: false
requestBody:
required: true
content:
Expand Down Expand Up @@ -89,6 +94,11 @@ paths:
$ref: "SwarmCommon.yaml#/components/schemas/SwarmEncryptedReference"
required: true
description: Grantee list reference
- in: header
schema:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmRedundancyLevelParameter"
name: swarm-redundancy-level
required: false
responses:
"200":
description: OK
Expand Down Expand Up @@ -139,6 +149,11 @@ paths:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmDeferredUpload"
name: swarm-deferred-upload
required: false
- in: header
schema:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmRedundancyLevelParameter"
name: swarm-redundancy-level
required: false
requestBody:
required: true
content:
Expand Down Expand Up @@ -281,6 +296,12 @@ paths:
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmPostageStamp"
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmAct"
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmActHistoryAddress"
- in: header
schema:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmRedundancyLevelParameter"
name: swarm-redundancy-level
required: false
description: Redundancy level for ACT encryption only
requestBody:
description: Chunk binary data containing at least 8 bytes.
content:
Expand Down Expand Up @@ -659,6 +680,12 @@ paths:
summary: Pin a root hash by reference
tags:
- Pinning
parameters:
- in: header
schema:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmRedundancyLevelParameter"
name: swarm-redundancy-level
required: false
responses:
"200":
description: Pin already exists
Expand Down Expand Up @@ -867,6 +894,12 @@ paths:
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmPostageStamp"
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmAct"
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmActHistoryAddress"
- in: header
schema:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmRedundancyLevelParameter"
name: swarm-redundancy-level
required: false
description: Redundancy level for ACT encryption only
requestBody:
required: true
description: The SOC binary data, composed of the span (8 bytes) and up to 4KB of payload.
Expand Down Expand Up @@ -965,6 +998,12 @@ paths:
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmPostageBatchId"
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmAct"
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmActHistoryAddress"
- in: header
schema:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmRedundancyLevelParameter"
name: swarm-redundancy-level
required: false
description: Redundancy level for ACT encryption only
responses:
"201":
description: Created
Expand Down Expand Up @@ -1064,6 +1103,11 @@ paths:
$ref: "SwarmCommon.yaml#/components/schemas/SwarmReference"
required: true
description: "Root hash of content (can be of any type: collection, file, chunk)"
- in: header
schema:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmRedundancyLevelParameter"
name: swarm-redundancy-level
required: false
responses:
"200":
description: Returns if the content is retrievable
Expand Down Expand Up @@ -1093,6 +1137,11 @@ paths:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmPostageBatchId"
name: swarm-postage-batch-id
description: Postage batch to use for re-upload. If none is provided and the file was uploaded on the same node before, it will reuse the same batch. If not found, it will return error. If a new batch is provided, the chunks are stamped again with the new batch.
- in: header
schema:
$ref: "SwarmCommon.yaml#/components/parameters/SwarmRedundancyLevelParameter"
name: swarm-redundancy-level
required: false
responses:
"200":
description: OK
Expand Down
4 changes: 2 additions & 2 deletions pkg/accesscontrol/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ func TestController_UpdateHandler(t *testing.T) {
assertNoError(t, "Session key", err)
refCipher := encryption.New(keys[0], 0, 0, sha3.NewLegacyKeccak256)
ls := createLs()
gls := loadsave.New(mockStorer.ChunkStore(), mockStorer.Cache(), requestPipelineFactory(context.Background(), mockStorer.Cache(), true, redundancy.NONE), redundancy.DefaultLevel)
gls := loadsave.New(mockStorer.ChunkStore(), mockStorer.Cache(), requestPipelineFactory(context.Background(), mockStorer.Cache(), true, redundancy.NONE), redundancy.DefaultDownloadLevel)
c := accesscontrol.NewController(al)
href, err := getHistoryFixture(t, ctx, ls, al, &publisher.PublicKey)
assertNoError(t, "history fixture create", err)
Expand Down Expand Up @@ -310,7 +310,7 @@ func TestController_Get(t *testing.T) {
al1 := accesscontrol.NewLogic(diffieHellman1)
al2 := accesscontrol.NewLogic(diffieHellman2)
ls := createLs()
gls := loadsave.New(mockStorer.ChunkStore(), mockStorer.Cache(), requestPipelineFactory(context.Background(), mockStorer.Cache(), true, redundancy.NONE), redundancy.DefaultLevel)
gls := loadsave.New(mockStorer.ChunkStore(), mockStorer.Cache(), requestPipelineFactory(context.Background(), mockStorer.Cache(), true, redundancy.NONE), redundancy.DefaultDownloadLevel)
c1 := accesscontrol.NewController(al1)
c2 := accesscontrol.NewController(al2)

Expand Down
2 changes: 1 addition & 1 deletion pkg/accesscontrol/grantee_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func requestPipelineFactory(ctx context.Context, s storage.Putter, encrypt bool,
}

func createLs() file.LoadSaver {
return loadsave.New(mockStorer.ChunkStore(), mockStorer.Cache(), requestPipelineFactory(context.Background(), mockStorer.Cache(), false, redundancy.NONE), redundancy.DefaultLevel)
return loadsave.New(mockStorer.ChunkStore(), mockStorer.Cache(), requestPipelineFactory(context.Background(), mockStorer.Cache(), false, redundancy.NONE), redundancy.DefaultDownloadLevel)
}

func generateKeyListFixture() ([]*ecdsa.PublicKey, error) {
Expand Down
6 changes: 3 additions & 3 deletions pkg/accesscontrol/history_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestSingleNodeHistoryLookup(t *testing.T) {
t.Parallel()
storer := mockstorer.New()
ctx := context.Background()
ls := loadsave.New(storer.ChunkStore(), storer.Cache(), pipelineFactory(storer.Cache(), false), redundancy.DefaultLevel)
ls := loadsave.New(storer.ChunkStore(), storer.Cache(), pipelineFactory(storer.Cache(), false), redundancy.DefaultDownloadLevel)

h, err := accesscontrol.NewHistory(ls)
assertNoError(t, "create history", err)
Expand All @@ -62,7 +62,7 @@ func TestMultiNodeHistoryLookup(t *testing.T) {
t.Parallel()
storer := mockstorer.New()
ctx := context.Background()
ls := loadsave.New(storer.ChunkStore(), storer.Cache(), pipelineFactory(storer.Cache(), false), redundancy.DefaultLevel)
ls := loadsave.New(storer.ChunkStore(), storer.Cache(), pipelineFactory(storer.Cache(), false), redundancy.DefaultDownloadLevel)

h, err := accesscontrol.NewHistory(ls)
assertNoError(t, "create history", err)
Expand Down Expand Up @@ -134,7 +134,7 @@ func TestHistoryStore(t *testing.T) {
t.Parallel()
storer := mockstorer.New()
ctx := context.Background()
ls := loadsave.New(storer.ChunkStore(), storer.Cache(), pipelineFactory(storer.Cache(), false), redundancy.DefaultLevel)
ls := loadsave.New(storer.ChunkStore(), storer.Cache(), pipelineFactory(storer.Cache(), false), redundancy.DefaultDownloadLevel)

h1, err := accesscontrol.NewHistory(ls)
assertNoError(t, "create history", err)
Expand Down
2 changes: 1 addition & 1 deletion pkg/accesscontrol/kvs/kvs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func requestPipelineFactory(ctx context.Context, s storage.Putter, encrypt bool,
}

func createLs() file.LoadSaver {
return loadsave.New(mockStorer.ChunkStore(), mockStorer.Cache(), requestPipelineFactory(context.Background(), mockStorer.Cache(), false, redundancy.NONE), redundancy.DefaultLevel)
return loadsave.New(mockStorer.ChunkStore(), mockStorer.Cache(), requestPipelineFactory(context.Background(), mockStorer.Cache(), false, redundancy.NONE), redundancy.DefaultDownloadLevel)
}

func keyValuePair(t *testing.T) ([]byte, []byte) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/accesscontrol/mock/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func New(o ...Option) accesscontrol.Controller {
refMap: make(map[string]swarm.Address),
publisher: "",
encrypter: encryption.New(encryption.Key("b6ee086390c280eeb9824c331a4427596f0c8510d5564bc1b6168d0059a46e2b"), 0, 0, sha3.NewLegacyKeccak256),
ls: loadsave.New(storer.ChunkStore(), storer.Cache(), requestPipelineFactory(context.Background(), storer.Cache(), false, redundancy.NONE), redundancy.DefaultLevel),
ls: loadsave.New(storer.ChunkStore(), storer.Cache(), requestPipelineFactory(context.Background(), storer.Cache(), false, redundancy.NONE), redundancy.DefaultDownloadLevel),
}
for _, v := range o {
v.apply(m)
Expand Down
71 changes: 49 additions & 22 deletions pkg/api/accesscontrol.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,11 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler {
}

headers := struct {
Timestamp *int64 `map:"Swarm-Act-Timestamp"`
Publisher *ecdsa.PublicKey `map:"Swarm-Act-Publisher"`
HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address"`
Cache *bool `map:"Swarm-Cache"`
Timestamp *int64 `map:"Swarm-Act-Timestamp"`
Publisher *ecdsa.PublicKey `map:"Swarm-Act-Publisher"`
HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address"`
Cache *bool `map:"Swarm-Cache"`
RLevel *redundancy.Level `map:"Swarm-Redundancy-Level" validate:"omitempty,rLevel"`
}{}
if response := s.mapStructure(r.Header, &headers); response != nil {
response("invalid header params", logger, w)
Expand All @@ -125,8 +126,14 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler {
if headers.Cache != nil {
cache = *headers.Cache
}

rLevel := redundancy.DefaultDownloadLevel
if headers.RLevel != nil {
rLevel = *headers.RLevel
}

ctx := r.Context()
ls := loadsave.NewReadonly(s.storer.Download(cache), s.storer.Cache(), redundancy.DefaultLevel)
ls := loadsave.NewReadonly(s.storer.Download(cache), s.storer.Cache(), rLevel)
reference, err := s.accesscontrol.DownloadHandler(ctx, ls, paths.Address, headers.Publisher, *headers.HistoryAddress, timestamp)
if err != nil {
logger.Debug("access control download failed", "error", err)
Expand Down Expand Up @@ -157,9 +164,10 @@ func (s *Service) actEncryptionHandler(
putter storer.PutterSession,
reference swarm.Address,
historyRootHash swarm.Address,
rLevel redundancy.Level,
) (swarm.Address, swarm.Address, error) {
publisherPublicKey := &s.publicKey
ls := loadsave.New(s.storer.Download(true), s.storer.Cache(), requestPipelineFactory(ctx, putter, false, redundancy.NONE), redundancy.DefaultLevel)
ls := loadsave.New(s.storer.Download(true), s.storer.Cache(), requestPipelineFactory(ctx, putter, false, redundancy.NONE), rLevel)
storageReference, historyReference, encryptedReference, err := s.accesscontrol.UploadHandler(ctx, ls, reference, publisherPublicKey, historyRootHash)
if err != nil {
return swarm.ZeroAddress, swarm.ZeroAddress, err
Expand Down Expand Up @@ -193,7 +201,8 @@ func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request)
}

headers := struct {
Cache *bool `map:"Swarm-Cache"`
Cache *bool `map:"Swarm-Cache"`
RLevel *redundancy.Level `map:"Swarm-Redundancy-Level" validate:"omitempty,rLevel"`
}{}
if response := s.mapStructure(r.Header, &headers); response != nil {
response("invalid header params", logger, w)
Expand All @@ -203,8 +212,14 @@ func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request)
if headers.Cache != nil {
cache = *headers.Cache
}

rLevel := redundancy.DefaultDownloadLevel
if headers.RLevel != nil {
rLevel = *headers.RLevel
}

publisher := &s.publicKey
ls := loadsave.NewReadonly(s.storer.Download(cache), s.storer.Cache(), redundancy.DefaultLevel)
ls := loadsave.NewReadonly(s.storer.Download(cache), s.storer.Cache(), rLevel)
grantees, err := s.accesscontrol.Get(r.Context(), ls, publisher, paths.GranteesAddress)
if err != nil {
logger.Debug("could not get grantees", "error", err)
Expand Down Expand Up @@ -239,11 +254,12 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request)
}

headers := struct {
BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"`
SwarmTag uint64 `map:"Swarm-Tag"`
Pin bool `map:"Swarm-Pin"`
Deferred *bool `map:"Swarm-Deferred-Upload"`
HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address" validate:"required"`
BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"`
SwarmTag uint64 `map:"Swarm-Tag"`
Pin bool `map:"Swarm-Pin"`
Deferred *bool `map:"Swarm-Deferred-Upload"`
HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address" validate:"required"`
RLevel *redundancy.Level `map:"Swarm-Redundancy-Level" validate:"omitempty,rLevel"`
}{}
if response := s.mapStructure(r.Header, &headers); response != nil {
response("invalid header params", logger, w)
Expand All @@ -255,6 +271,11 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request)
historyAddress = *headers.HistoryAddress
}

rLevel := redundancy.DefaultUploadLevel
if headers.RLevel != nil {
rLevel = *headers.RLevel
}

var (
tag uint64
err error
Expand Down Expand Up @@ -342,8 +363,8 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request)

granteeref := paths.GranteesAddress
publisher := &s.publicKey
ls := loadsave.New(s.storer.Download(true), s.storer.Cache(), requestPipelineFactory(ctx, putter, false, redundancy.NONE), redundancy.DefaultLevel)
gls := loadsave.New(s.storer.Download(true), s.storer.Cache(), requestPipelineFactory(ctx, putter, granteeListEncrypt, redundancy.NONE), redundancy.DefaultLevel)
ls := loadsave.New(s.storer.Download(true), s.storer.Cache(), requestPipelineFactory(ctx, putter, false, redundancy.NONE), rLevel)
gls := loadsave.New(s.storer.Download(true), s.storer.Cache(), requestPipelineFactory(ctx, putter, granteeListEncrypt, redundancy.NONE), rLevel)
granteeref, encryptedglref, historyref, actref, err := s.accesscontrol.UpdateHandler(ctx, ls, gls, granteeref, historyAddress, publisher, grantees.Addlist, grantees.Revokelist)
if err != nil {
logger.Debug("failed to update grantee list", "error", err)
Expand Down Expand Up @@ -403,11 +424,12 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques
}

headers := struct {
BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"`
SwarmTag uint64 `map:"Swarm-Tag"`
Pin bool `map:"Swarm-Pin"`
Deferred *bool `map:"Swarm-Deferred-Upload"`
HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address"`
BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"`
SwarmTag uint64 `map:"Swarm-Tag"`
Pin bool `map:"Swarm-Pin"`
Deferred *bool `map:"Swarm-Deferred-Upload"`
HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address"`
RLevel *redundancy.Level `map:"Swarm-Redundancy-Level" validate:"omitempty,rLevel"`
}{}
if response := s.mapStructure(r.Header, &headers); response != nil {
response("invalid header params", logger, w)
Expand All @@ -419,6 +441,11 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques
historyAddress = *headers.HistoryAddress
}

rLevel := redundancy.DefaultUploadLevel
if headers.RLevel != nil {
rLevel = *headers.RLevel
}

var (
tag uint64
err error
Expand Down Expand Up @@ -494,8 +521,8 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques
}

publisher := &s.publicKey
ls := loadsave.New(s.storer.Download(true), s.storer.Cache(), requestPipelineFactory(ctx, putter, false, redundancy.NONE), redundancy.DefaultLevel)
gls := loadsave.New(s.storer.Download(true), s.storer.Cache(), requestPipelineFactory(ctx, putter, granteeListEncrypt, redundancy.NONE), redundancy.DefaultLevel)
ls := loadsave.New(s.storer.Download(true), s.storer.Cache(), requestPipelineFactory(ctx, putter, false, redundancy.NONE), rLevel)
gls := loadsave.New(s.storer.Download(true), s.storer.Cache(), requestPipelineFactory(ctx, putter, granteeListEncrypt, redundancy.NONE), rLevel)
granteeref, encryptedglref, historyref, actref, err := s.accesscontrol.UpdateHandler(ctx, ls, gls, swarm.ZeroAddress, historyAddress, publisher, list, nil)
if err != nil {
logger.Debug("failed to create grantee list", "error", err)
Expand Down
3 changes: 2 additions & 1 deletion pkg/api/accesscontrol_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import (
//nolint:ireturn
func prepareHistoryFixture(storer api.Storer) (accesscontrol.History, swarm.Address) {
ctx := context.Background()
ls := loadsave.New(storer.ChunkStore(), storer.Cache(), pipelineFactory(storer.Cache(), false, redundancy.NONE), redundancy.DefaultLevel)
ls := loadsave.New(storer.ChunkStore(), storer.Cache(), pipelineFactory(storer.Cache(), false, redundancy.NONE), redundancy.DefaultDownloadLevel)

h, _ := accesscontrol.NewHistory(ls)

Expand Down Expand Up @@ -170,6 +170,7 @@ func TestAccessLogicEachEndpointWithAct(t *testing.T) {
jsonhttptest.WithRequestHeader(api.SwarmPostageBatchIdHeader, batchOkStr),
jsonhttptest.WithRequestHeader(api.SwarmPinHeader, "true"),
jsonhttptest.WithRequestHeader(api.SwarmTagHeader, fmt.Sprintf("%d", tag.TagID)),
jsonhttptest.WithRequestHeader(api.SwarmRedundancyLevelHeader, "0"),
jsonhttptest.WithRequestBody(v.data),
jsonhttptest.WithExpectedJSONResponse(v.resp),
jsonhttptest.WithRequestHeader(api.ContentTypeHeader, v.contenttype),
Expand Down
Loading
Loading