mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-11-08 21:43:00 -05:00
feat(policies): pass request lengths to the proxy policies
The proxy policies middleware now passes the Content-Length of the request body and the TUS Upload-Length header to the policies engine as input.request.content_length and input.request.upload_length. This allows rejecting uploads that are too big before any data is transferred, instead of only in postprocessing after the upload has completed. We add them to the request instead of setting resource.size, because the resource describes the target of the request (the middleware may even stat it) and in postprocessing resource.size is the actual file size. This can only be an early check. The TUS concatenation extension allows merging several smaller uploads into one file, so the file size still has to be checked in postprocessing. protojson encodes uint64 values as strings with camelCase keys, so NewEnvironmentFromPB copies the lengths explicitly. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
1 parent
331855fe99
commit
bd4325b75b
9 files changed
+195
-28
No files matched your search
@@ -223,6 +223,10 @@ type Request struct {
|
||||
|
||||
Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"`
|
||||
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
||||
// Content-Length of the request body, 0 if unknown
|
||||
ContentLength uint64 `protobuf:"varint,3,opt,name=content_length,json=contentLength,proto3" json:"content_length,omitempty"`
|
||||
// TUS Upload-Length header, the declared total size of an upload, 0 if absent
|
||||
UploadLength uint64 `protobuf:"varint,4,opt,name=upload_length,json=uploadLength,proto3" json:"upload_length,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Request) Reset() {
|
||||
@@ -271,6 +275,20 @@ func (x *Request) GetPath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Request) GetContentLength() uint64 {
|
||||
if x != nil {
|
||||
return x.ContentLength
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Request) GetUploadLength() uint64 {
|
||||
if x != nil {
|
||||
return x.UploadLength
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Environment struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -487,35 +505,40 @@ var file_opencloud_messages_policies_v0_policies_proto_rawDesc = []byte{
|
||||
0x75, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x70, 0x61,
|
||||
0x71, 0x75, 0x65, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69,
|
||||
0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64,
|
||||
0x22, 0x35, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d,
|
||||
0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74,
|
||||
0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x8d, 0x02, 0x0a, 0x0b, 0x45, 0x6e, 0x76, 0x69,
|
||||
0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f,
|
||||
0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x6f, 0x6c, 0x69,
|
||||
0x63, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, 0x73,
|
||||
0x74, 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73,
|
||||
0x2e, 0x76, 0x30, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x41,
|
||||
0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x30,
|
||||
0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x44, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
|
||||
0x22, 0x81, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65,
|
||||
0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
|
||||
0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12,
|
||||
0x23, 0x0a, 0x0d, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x65,
|
||||
0x6e, 0x67, 0x74, 0x68, 0x22, 0x8d, 0x02, 0x0a, 0x0b, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
|
||||
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65,
|
||||
0x73, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72,
|
||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2a, 0x25, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x67, 0x65,
|
||||
0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x50, 0x50, 0x10, 0x00, 0x12, 0x0e,
|
||||
0x0a, 0x0a, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x10, 0x01, 0x42, 0x4f,
|
||||
0x5a, 0x4d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65,
|
||||
0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c,
|
||||
0x6f, 0x75, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x65, 0x6e,
|
||||
0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x73, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2f, 0x76, 0x30, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x73, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67,
|
||||
0x65, 0x12, 0x38, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x24, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x30,
|
||||
0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x07, 0x72,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f,
|
||||
0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||
0x73, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44,
|
||||
0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x28, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73,
|
||||
0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x76,
|
||||
0x30, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x2a, 0x25, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x0c, 0x0a,
|
||||
0x08, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x50, 0x50, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x53,
|
||||
0x54, 0x41, 0x47, 0x45, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x10, 0x01, 0x42, 0x4f, 0x5a, 0x4d, 0x67,
|
||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c,
|
||||
0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
|
||||
0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2f, 0x76, 0x30, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -134,6 +134,16 @@
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"contentLength": {
|
||||
"type": "string",
|
||||
"format": "uint64",
|
||||
"title": "Content-Length of the request body, 0 if unknown"
|
||||
},
|
||||
"uploadLength": {
|
||||
"type": "string",
|
||||
"format": "uint64",
|
||||
"title": "TUS Upload-Length header, the declared total size of an upload, 0 if absent"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -32,6 +32,10 @@ message Resource {
|
||||
message Request {
|
||||
string method = 1;
|
||||
string path = 2;
|
||||
// Content-Length of the request body, 0 if unknown
|
||||
uint64 content_length = 3;
|
||||
// TUS Upload-Length header, the declared total size of an upload, 0 if absent
|
||||
uint64 upload_length = 4;
|
||||
}
|
||||
|
||||
enum Stage {
|
||||
|
||||
@@ -185,6 +185,31 @@ To identify available keys for OPA, you need to look at [`engine.go`](https://gi
|
||||
|
||||
Note that which keys are available depends on the module it is used in.
|
||||
|
||||
### Request Lengths
|
||||
|
||||
In the proxy module, `input.request.content_length` contains the `Content-Length` of the request body and `input.request.upload_length` the total size of an upload as declared by the TUS `Upload-Length` header. Both are `0` if unknown. They allow rejecting uploads that are too big before any data is transferred:
|
||||
|
||||
```rego
|
||||
package proxy
|
||||
|
||||
import future.keywords.if
|
||||
|
||||
default granted := true
|
||||
|
||||
# TUS creation declares the total size of the upload
|
||||
granted = false if {
|
||||
input.request.upload_length > 10737418240
|
||||
}
|
||||
|
||||
# a plain PUT carries the whole file, a PATCH a chunk
|
||||
granted = false if {
|
||||
input.request.method == ["PUT", "PATCH"][_]
|
||||
input.request.content_length > 10737418240
|
||||
}
|
||||
```
|
||||
|
||||
This is only an early check. The TUS concatenation extension can merge several smaller uploads into one file, so the actual file size has to be checked in postprocessing using `input.resource.size`.
|
||||
|
||||
## Rego Extensions
|
||||
|
||||
Besides the standard rego built-in functions, the following functions are added on top:
|
||||
|
||||
@@ -40,6 +40,10 @@ type Resource struct {
|
||||
type Request struct {
|
||||
Method string `json:"method"`
|
||||
Path string `json:"path"`
|
||||
// ContentLength is the length of the request body, 0 if unknown.
|
||||
ContentLength uint64 `json:"content_length"`
|
||||
// UploadLength is the total size of an upload as declared by the TUS Upload-Length header, 0 if absent.
|
||||
UploadLength uint64 `json:"upload_length"`
|
||||
}
|
||||
|
||||
// Environment contains every data that is needed to decide if the request should pass or not
|
||||
@@ -63,6 +67,10 @@ func NewEnvironmentFromPB(pEnv *v0.Environment) (Environment, error) {
|
||||
return env, err
|
||||
}
|
||||
|
||||
// protojson encodes uint64 as strings with camelCase keys, so copy the lengths explicitly
|
||||
env.Request.ContentLength = pEnv.GetRequest().GetContentLength()
|
||||
env.Request.UploadLength = pEnv.GetRequest().GetUploadLength()
|
||||
|
||||
switch pEnv.Stage {
|
||||
case v0.Stage_STAGE_HTTP:
|
||||
env.Stage = StageHTTP
|
||||
|
||||
@@ -22,4 +22,23 @@ var _ = Describe("Engine", func() {
|
||||
Entry("http stage", pMessage.Stage_STAGE_HTTP, engine.StageHTTP),
|
||||
Entry("pp stage", pMessage.Stage_STAGE_PP, engine.StagePP),
|
||||
)
|
||||
|
||||
It("NewEnvironmentFromPB keeps the request lengths", func() {
|
||||
pEnv := &pMessage.Environment{
|
||||
Stage: pMessage.Stage_STAGE_HTTP,
|
||||
Request: &pMessage.Request{
|
||||
Method: "POST",
|
||||
Path: "/remote.php/dav/spaces/some-space-id",
|
||||
ContentLength: 1024,
|
||||
UploadLength: 20000000000,
|
||||
},
|
||||
}
|
||||
|
||||
env, err := engine.NewEnvironmentFromPB(pEnv)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(env.Request.Method).To(Equal("POST"))
|
||||
Expect(env.Request.ContentLength).To(Equal(uint64(1024)))
|
||||
Expect(env.Request.UploadLength).To(Equal(uint64(20000000000)))
|
||||
})
|
||||
})
|
||||
@@ -150,5 +150,28 @@ var _ = Describe("engine", func() {
|
||||
Expect(granted).To(Equal(tc.want), "for %s", tc.name)
|
||||
}
|
||||
})
|
||||
|
||||
It("compares the request lengths as numbers", func() {
|
||||
e, _ := newEngine("package size\n\nimport future.keywords.if\n\ndefault granted := true\n\ngranted = false if {\n input.request.upload_length > 10737418240\n}\n\ngranted = false if {\n input.request.method == [\"PUT\", \"PATCH\"][_]\n input.request.content_length > 10737418240\n}\n")
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
request engine.Request
|
||||
want bool
|
||||
}{
|
||||
{"no lengths", engine.Request{Method: "POST"}, true},
|
||||
{"tus creation below limit", engine.Request{Method: "POST", UploadLength: 10737418240}, true},
|
||||
{"tus creation above limit", engine.Request{Method: "POST", UploadLength: 20000000000}, false},
|
||||
{"put above limit", engine.Request{Method: "PUT", ContentLength: 20000000000}, false},
|
||||
{"patch above limit", engine.Request{Method: "PATCH", ContentLength: 20000000000}, false},
|
||||
{"patch below limit", engine.Request{Method: "PATCH", ContentLength: 104857600}, true},
|
||||
} {
|
||||
granted, err := e.Evaluate(context.Background(), "data.size.granted", engine.Environment{
|
||||
Request: tc.request,
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(granted).To(Equal(tc.want), "for %s", tc.name)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -72,6 +73,14 @@ func Policies(qs string, opts ...Option) func(next http.Handler) http.Handler {
|
||||
},
|
||||
}
|
||||
|
||||
// the declared lengths allow policies to reject uploads before the data is transferred
|
||||
if r.ContentLength > 0 {
|
||||
req.Environment.Request.ContentLength = uint64(r.ContentLength)
|
||||
}
|
||||
if uploadLength, err := strconv.ParseUint(r.Header.Get(net.HeaderUploadLength), 10, 64); err == nil {
|
||||
req.Environment.Request.UploadLength = uploadLength
|
||||
}
|
||||
|
||||
resource := &pMessage.Resource{}
|
||||
|
||||
// tus
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
@@ -109,6 +110,51 @@ func TestPolicies_EvaluationEnvironment_Request(t *testing.T) {
|
||||
policiesMiddleware.ServeHTTP(responseRecorder, httptest.NewRequest(http.MethodDelete, "/whatever", nil))
|
||||
}
|
||||
|
||||
func TestPolicies_EvaluationEnvironment_RequestLengths(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
method string
|
||||
body string
|
||||
uploadLength string
|
||||
expectedContentLength uint64
|
||||
expectedUploadLength uint64
|
||||
}{
|
||||
{name: "tus creation", method: http.MethodPost, uploadLength: "20000000000", expectedUploadLength: 20000000000},
|
||||
{name: "put", method: http.MethodPut, body: "some content", expectedContentLength: 12},
|
||||
{name: "patch", method: http.MethodPatch, body: "a chunk", expectedContentLength: 7},
|
||||
{name: "invalid upload length", method: http.MethodPost, uploadLength: "-1"},
|
||||
{name: "no lengths", method: http.MethodGet},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var g = NewWithT(t)
|
||||
|
||||
policiesMiddleware, policiesProviderService, _ := prepare("any")
|
||||
policiesProviderService.On("Evaluate", mock.Anything, mock.Anything, mock.Anything).Return(
|
||||
func(_ context.Context, in *policiesPG.EvaluateRequest, _ ...client.CallOption) (*policiesPG.EvaluateResponse, error) {
|
||||
g.Expect(in.Environment.Request.ContentLength).To(Equal(tt.expectedContentLength))
|
||||
g.Expect(in.Environment.Request.UploadLength).To(Equal(tt.expectedUploadLength))
|
||||
|
||||
return &policiesPG.EvaluateResponse{Result: false}, nil
|
||||
},
|
||||
).Once()
|
||||
|
||||
var body io.Reader
|
||||
if tt.body != "" {
|
||||
body = strings.NewReader(tt.body)
|
||||
}
|
||||
request := httptest.NewRequest(tt.method, "/remote.php/dav/spaces/some-space-id/file.txt", body)
|
||||
if tt.uploadLength != "" {
|
||||
request.Header.Set(net.HeaderUploadLength, tt.uploadLength)
|
||||
}
|
||||
|
||||
policiesMiddleware.ServeHTTP(httptest.NewRecorder(), request)
|
||||
policiesProviderService.AssertExpectations(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPolicies_EvaluationEnvironment_Resource(t *testing.T) {
|
||||
var g = NewWithT(t)
|
||||
|
||||
|
||||
Reference in new issue
Block a user