mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-02-05 11:38:50 -06:00
enhancement: Evaluate policy resource information on single file shares (#6888)
* enhancement: Evaluate policy resource information on single file shares * enhancement: switch to resource name evaluation for example rego put rule
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
Enhancement: Evaluate policy resource information on single file shares
|
||||
|
||||
The policy environment for single file shares now also includes information about the resource.
|
||||
As a result, it is now possible to set up and check rules for them.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/6888
|
||||
@@ -6,14 +6,28 @@ import data.utils
|
||||
default granted := true
|
||||
|
||||
granted = false if {
|
||||
print("PRINT MESSAGE EXAMPLE")
|
||||
input.request.method == "PUT"
|
||||
not startswith(input.request.path, "/ocs")
|
||||
not utils.is_extension_allowed(input.request.path)
|
||||
pathPrefixes := [
|
||||
"/dav",
|
||||
"/remote.php/webdav",
|
||||
"/remote.php/dav",
|
||||
"/webdav",
|
||||
]
|
||||
restricted := pathPrefixes[_]
|
||||
startswith(input.request.path, restricted)
|
||||
not utils.is_extension_allowed(input.resource.name)
|
||||
}
|
||||
|
||||
granted = false if {
|
||||
input.request.method == "POST"
|
||||
startswith(input.request.path, "/remote.php")
|
||||
pathPrefixes := [
|
||||
"/data",
|
||||
"/dav",
|
||||
"/remote.php/webdav",
|
||||
"/remote.php/dav",
|
||||
"/webdav",
|
||||
]
|
||||
restricted := pathPrefixes[_]
|
||||
startswith(input.request.path, restricted)
|
||||
not utils.is_extension_allowed(input.resource.name)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ docs-generate: config-docs-generate
|
||||
include ../../.make/generate.mk
|
||||
|
||||
.PHONY: ci-go-generate
|
||||
ci-go-generate: # CI runs ci-node-generate automatically before this target
|
||||
ci-go-generate: $(MOCKERY) # CI runs ci-node-generate automatically before this target
|
||||
$(MOCKERY) --dir ../../protogen/gen/ocis/services/policies/v0 --case underscore --name PoliciesProviderService
|
||||
|
||||
.PHONY: ci-node-generate
|
||||
ci-node-generate:
|
||||
|
||||
66
services/proxy/mocks/policies_provider_service.go
Normal file
66
services/proxy/mocks/policies_provider_service.go
Normal file
@@ -0,0 +1,66 @@
|
||||
// Code generated by mockery v2.22.1. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
client "go-micro.dev/v4/client"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
v0 "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/policies/v0"
|
||||
)
|
||||
|
||||
// PoliciesProviderService is an autogenerated mock type for the PoliciesProviderService type
|
||||
type PoliciesProviderService struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Evaluate provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *PoliciesProviderService) Evaluate(ctx context.Context, in *v0.EvaluateRequest, opts ...client.CallOption) (*v0.EvaluateResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *v0.EvaluateResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *v0.EvaluateRequest, ...client.CallOption) (*v0.EvaluateResponse, error)); ok {
|
||||
return rf(ctx, in, opts...)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *v0.EvaluateRequest, ...client.CallOption) *v0.EvaluateResponse); ok {
|
||||
r0 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0.EvaluateResponse)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *v0.EvaluateRequest, ...client.CallOption) error); ok {
|
||||
r1 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewPoliciesProviderService interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewPoliciesProviderService creates a new instance of PoliciesProviderService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewPoliciesProviderService(t mockConstructorTestingTNewPoliciesProviderService) *PoliciesProviderService {
|
||||
mock := &PoliciesProviderService{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
@@ -8,14 +8,19 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/cs3org/reva/v2/pkg/store"
|
||||
"github.com/cs3org/reva/v2/pkg/token/manager/jwt"
|
||||
"github.com/go-chi/chi/v5"
|
||||
chimiddleware "github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/go-chi/render"
|
||||
"github.com/justinas/alice"
|
||||
"github.com/oklog/run"
|
||||
"github.com/urfave/cli/v2"
|
||||
microstore "go-micro.dev/v4/store"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/cs3org/reva/v2/pkg/store"
|
||||
"github.com/cs3org/reva/v2/pkg/token/manager/jwt"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
pkgmiddleware "github.com/owncloud/ocis/v2/ocis-pkg/middleware"
|
||||
@@ -24,6 +29,7 @@ import (
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/tracing"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/version"
|
||||
policiessvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/policies/v0"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
storesvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/store/v0"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/autoprovision"
|
||||
@@ -38,10 +44,6 @@ import (
|
||||
proxyHTTP "github.com/owncloud/ocis/v2/services/proxy/pkg/server/http"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/user/backend"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/userroles"
|
||||
"github.com/urfave/cli/v2"
|
||||
microstore "go-micro.dev/v4/store"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Server is the entrypoint for the server command.
|
||||
@@ -273,6 +275,7 @@ func (h *StaticRouteHandler) backchannelLogout(w http.ResponseWriter, r *http.Re
|
||||
|
||||
func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config, userInfoCache microstore.Store, traceProvider trace.TracerProvider) alice.Chain {
|
||||
rolesClient := settingssvc.NewRoleService("com.owncloud.api.settings", cfg.GrpcClient)
|
||||
policiesProviderClient := policiessvc.NewPoliciesProviderService("com.owncloud.api.policies", cfg.GrpcClient)
|
||||
gatewaySelector, err := pool.GatewaySelector(cfg.Reva.Address, append(cfg.Reva.GetRevaOptions(), pool.WithRegistry(registry.GetRegistry()))...)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("Failed to get gateway selector")
|
||||
@@ -411,7 +414,12 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config,
|
||||
middleware.Logger(logger),
|
||||
middleware.PolicySelectorConfig(*cfg.PolicySelector),
|
||||
),
|
||||
middleware.Policies(logger, cfg.PoliciesMiddleware.Query, cfg.GrpcClient),
|
||||
middleware.Policies(
|
||||
cfg.PoliciesMiddleware.Query,
|
||||
middleware.Logger(logger),
|
||||
middleware.WithRevaGatewaySelector(gatewaySelector),
|
||||
middleware.PoliciesProviderService(policiesProviderClient),
|
||||
),
|
||||
// finally, trigger home creation when a user logs in
|
||||
middleware.CreateHome(
|
||||
middleware.Logger(logger),
|
||||
|
||||
@@ -5,16 +5,19 @@ import (
|
||||
"time"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
"go-micro.dev/v4/store"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/oidc"
|
||||
policiessvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/policies/v0"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
storesvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/store/v0"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/config"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/user/backend"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/userroles"
|
||||
store "go-micro.dev/v4/store"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Option defines a single option function.
|
||||
@@ -36,6 +39,8 @@ type Options struct {
|
||||
UserRoleAssigner userroles.UserRoleAssigner
|
||||
// SettingsRoleService for the roles API in settings
|
||||
SettingsRoleService settingssvc.RoleService
|
||||
// PoliciesProviderService for policy evaluation
|
||||
PoliciesProviderService policiessvc.PoliciesProviderService
|
||||
// OIDCProviderFunc to lazily initialize an oidc provider, must be set for the oidc_auth middleware
|
||||
OIDCClient oidc.OIDCClient
|
||||
// OIDCIss is the oidcAuth-issuer
|
||||
@@ -118,7 +123,14 @@ func SettingsRoleService(rc settingssvc.RoleService) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// OIDCClient provides a function to set the the oidc client option.
|
||||
// PoliciesProviderService provides a function to set the policies provider option.
|
||||
func PoliciesProviderService(pps policiessvc.PoliciesProviderService) Option {
|
||||
return func(o *Options) {
|
||||
o.PoliciesProviderService = pps
|
||||
}
|
||||
}
|
||||
|
||||
// OIDCClient provides a function to set the oidc client option.
|
||||
func OIDCClient(val oidc.OIDCClient) Option {
|
||||
return func(o *Options) {
|
||||
o.OIDCClient = val
|
||||
@@ -139,7 +151,7 @@ func CredentialsByUserAgent(v map[string]string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithRevaGatewaySelector provides a function to set the the reva gateway service selector option.
|
||||
// WithRevaGatewaySelector provides a function to set the reva gateway service selector option.
|
||||
func WithRevaGatewaySelector(val pool.Selectable[gateway.GatewayAPIClient]) Option {
|
||||
return func(o *Options) {
|
||||
o.RevaGatewaySelector = val
|
||||
|
||||
@@ -3,17 +3,23 @@ package middleware
|
||||
import (
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
revactx "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/go-chi/render"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
tusd "github.com/tus/tusd/pkg/handler"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
revactx "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
|
||||
pMessage "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/policies/v0"
|
||||
pService "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/policies/v0"
|
||||
"github.com/owncloud/ocis/v2/services/webdav/pkg/net"
|
||||
tusd "github.com/tus/tusd/pkg/handler"
|
||||
"go-micro.dev/v4/client"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -34,8 +40,11 @@ type (
|
||||
const DeniedMessage = "Operation denied due to security policies"
|
||||
|
||||
// Policies verifies if a request is granted or not.
|
||||
func Policies(logger log.Logger, qs string, grpcClient client.Client) func(next http.Handler) http.Handler {
|
||||
pClient := pService.NewPoliciesProviderService("com.owncloud.api.policies", grpcClient)
|
||||
func Policies(qs string, opts ...Option) func(next http.Handler) http.Handler {
|
||||
options := newOptions(opts...)
|
||||
logger := options.Logger
|
||||
gatewaySelector := options.RevaGatewaySelector
|
||||
policiesProviderClient := options.PoliciesProviderService
|
||||
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -55,11 +64,53 @@ func Policies(logger log.Logger, qs string, grpcClient client.Client) func(next
|
||||
},
|
||||
}
|
||||
|
||||
resource := &pMessage.Resource{}
|
||||
|
||||
// tus
|
||||
meta := tusd.ParseMetadataHeader(r.Header.Get(net.HeaderUploadMetadata))
|
||||
req.Environment.Resource = &pMessage.Resource{
|
||||
Name: meta["filename"],
|
||||
resource.Name = meta["filename"]
|
||||
|
||||
// name is part of the request path
|
||||
if resource.Name == "" && filepath.Ext(r.URL.Path) != "" {
|
||||
resource.Name = filepath.Base(r.URL.Path)
|
||||
}
|
||||
|
||||
// no resource info in path, stat the resource and try to obtain the file information.
|
||||
// this should only be used as last bastion, every request goes through the proxy and doing stats is expensive!
|
||||
// needed for:
|
||||
// - if a single resource is shared -> the url only contains the resourceID (spaceRef)
|
||||
if resource.Name == "" && filepath.Ext(r.URL.Path) == "" && r.Method == http.MethodPut && strings.HasPrefix(r.URL.Path, "/remote.php/dav/spaces") {
|
||||
client, err := gatewaySelector.Next()
|
||||
if err != nil {
|
||||
logger.Err(err).Msg("error selecting next gateway client")
|
||||
RenderError(w, r, req, http.StatusForbidden, DeniedMessage)
|
||||
return
|
||||
}
|
||||
|
||||
resourceID, err := storagespace.ParseID(strings.TrimPrefix(r.URL.Path, "/remote.php/dav/spaces/"))
|
||||
if err != nil {
|
||||
logger.Debug().Err(err).Msg("error parsing the resourceId")
|
||||
RenderError(w, r, req, http.StatusForbidden, DeniedMessage)
|
||||
return
|
||||
}
|
||||
|
||||
if resourceID.StorageId == "" && resourceID.SpaceId == utils.ShareStorageSpaceID {
|
||||
resourceID.StorageId = utils.ShareStorageProviderID
|
||||
}
|
||||
|
||||
token := r.Header.Get(revactx.TokenHeader)
|
||||
ctx := metadata.AppendToOutgoingContext(r.Context(), revactx.TokenHeader, token)
|
||||
sRes, err := client.Stat(ctx, &provider.StatRequest{
|
||||
Ref: &provider.Reference{
|
||||
ResourceId: &resourceID,
|
||||
},
|
||||
})
|
||||
|
||||
resource.Name = sRes.GetInfo().GetName()
|
||||
}
|
||||
|
||||
req.Environment.Resource = resource
|
||||
|
||||
if user, ok := revactx.ContextGetUser(r.Context()); ok {
|
||||
req.Environment.User = &pMessage.User{
|
||||
Id: &pMessage.User_ID{
|
||||
@@ -72,7 +123,7 @@ func Policies(logger log.Logger, qs string, grpcClient client.Client) func(next
|
||||
}
|
||||
}
|
||||
|
||||
rsp, err := pClient.Evaluate(r.Context(), req)
|
||||
rsp, err := policiesProviderClient.Evaluate(r.Context(), req)
|
||||
if err != nil {
|
||||
logger.Err(err).Msg("error evaluating request")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
173
services/proxy/pkg/middleware/policies_test.go
Normal file
173
services/proxy/pkg/middleware/policies_test.go
Normal file
@@ -0,0 +1,173 @@
|
||||
package middleware_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"go-micro.dev/v4/client"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/mocks"
|
||||
"github.com/owncloud/ocis/v2/services/webdav/pkg/net"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
||||
pMessage "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/policies/v0"
|
||||
policiesPG "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/policies/v0"
|
||||
"github.com/owncloud/ocis/v2/services/proxy/pkg/middleware"
|
||||
)
|
||||
|
||||
func TestPolicies_NoQuery_PassThrough(t *testing.T) {
|
||||
var g = NewWithT(t)
|
||||
|
||||
policiesMiddleware, _, _ := prepare("")
|
||||
|
||||
responseRecorder := httptest.NewRecorder()
|
||||
policiesMiddleware.ServeHTTP(responseRecorder, httptest.NewRequest(http.MethodGet, "/policies", nil))
|
||||
|
||||
g.Expect(responseRecorder.Code).To(Equal(http.StatusOK))
|
||||
}
|
||||
|
||||
func TestPolicies_ErrorsOnEvaluationError(t *testing.T) {
|
||||
var g = NewWithT(t)
|
||||
|
||||
policiesMiddleware, policiesProviderService, _ := prepare("any")
|
||||
policiesProviderService.On("Evaluate", mock.Anything, mock.Anything).Return(
|
||||
nil,
|
||||
errors.New("any"),
|
||||
)
|
||||
|
||||
responseRecorder := httptest.NewRecorder()
|
||||
policiesMiddleware.ServeHTTP(responseRecorder, httptest.NewRequest(http.MethodGet, "/policies", nil))
|
||||
|
||||
g.Expect(responseRecorder.Code).To(Equal(http.StatusInternalServerError))
|
||||
}
|
||||
|
||||
func TestPolicies_ErrorsOnDeny(t *testing.T) {
|
||||
var g = NewWithT(t)
|
||||
|
||||
policiesMiddleware, policiesProviderService, _ := prepare("any")
|
||||
policiesProviderService.On("Evaluate", mock.Anything, mock.Anything).Return(
|
||||
&policiesPG.EvaluateResponse{},
|
||||
nil,
|
||||
)
|
||||
|
||||
responseRecorder := httptest.NewRecorder()
|
||||
policiesMiddleware.ServeHTTP(responseRecorder, httptest.NewRequest(http.MethodGet, "/policies", nil))
|
||||
|
||||
result := responseRecorder.Result()
|
||||
defer func() {
|
||||
g.Expect(result.Body.Close()).ToNot(HaveOccurred())
|
||||
}()
|
||||
|
||||
data, err := io.ReadAll(result.Body)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(data).To(ContainSubstring(middleware.DeniedMessage))
|
||||
g.Expect(responseRecorder.Code).To(Equal(http.StatusForbidden))
|
||||
}
|
||||
|
||||
func TestPolicies_EvaluationEnvironment_HTTPStage(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.Stage).To(Equal(pMessage.Stage_STAGE_HTTP))
|
||||
|
||||
return &policiesPG.EvaluateResponse{Result: false}, nil
|
||||
},
|
||||
)
|
||||
|
||||
responseRecorder := httptest.NewRecorder()
|
||||
policiesMiddleware.ServeHTTP(responseRecorder, httptest.NewRequest(http.MethodGet, "/policies", nil))
|
||||
}
|
||||
|
||||
func TestPolicies_EvaluationEnvironment_Request(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.Method).To(Equal(http.MethodDelete))
|
||||
g.Expect(in.Environment.Request.Path).To(Equal("/whatever"))
|
||||
|
||||
return &policiesPG.EvaluateResponse{Result: false}, nil
|
||||
},
|
||||
)
|
||||
|
||||
responseRecorder := httptest.NewRecorder()
|
||||
policiesMiddleware.ServeHTTP(responseRecorder, httptest.NewRequest(http.MethodDelete, "/whatever", nil))
|
||||
}
|
||||
|
||||
func TestPolicies_EvaluationEnvironment_Resource(t *testing.T) {
|
||||
var g = NewWithT(t)
|
||||
|
||||
policiesMiddleware, policiesProviderService, _ := prepare("any")
|
||||
|
||||
// tus metadata
|
||||
{
|
||||
responseRecorder := httptest.NewRecorder()
|
||||
request := httptest.NewRequest(http.MethodPost, "/remote.php/dav/spaces", nil)
|
||||
request.Header.Set(net.HeaderUploadMetadata, fmt.Sprintf("filename %v", base64.StdEncoding.EncodeToString([]byte("tus-file-name.png"))))
|
||||
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.Resource.Name).To(Equal("tus-file-name.png"))
|
||||
|
||||
return &policiesPG.EvaluateResponse{Result: false}, nil
|
||||
},
|
||||
).Once()
|
||||
policiesMiddleware.ServeHTTP(responseRecorder, request)
|
||||
}
|
||||
|
||||
// url path
|
||||
{
|
||||
responseRecorder := httptest.NewRecorder()
|
||||
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.Resource.Name).To(Equal("simple-file-name.png"))
|
||||
|
||||
return &policiesPG.EvaluateResponse{Result: false}, nil
|
||||
},
|
||||
).Once()
|
||||
policiesMiddleware.ServeHTTP(responseRecorder, httptest.NewRequest(http.MethodPut, "/remote.php/dav/spaces/simple-file-name.png", nil))
|
||||
}
|
||||
}
|
||||
|
||||
func prepare(q string) (http.Handler, *mocks.PoliciesProviderService, *cs3mocks.GatewayAPIClient) {
|
||||
|
||||
// mocked gatewaySelector
|
||||
gatewayClient := &cs3mocks.GatewayAPIClient{}
|
||||
gatewaySelector := pool.GetSelector[gateway.GatewayAPIClient](
|
||||
"GatewaySelector",
|
||||
"com.owncloud.api.gateway",
|
||||
func(cc *grpc.ClientConn) gateway.GatewayAPIClient {
|
||||
return gatewayClient
|
||||
},
|
||||
)
|
||||
defer pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
|
||||
|
||||
// mocked policiesProviderService
|
||||
policiesProviderService := &mocks.PoliciesProviderService{}
|
||||
|
||||
// spin up middleware
|
||||
policiesMiddleware := middleware.Policies(
|
||||
q,
|
||||
middleware.WithRevaGatewaySelector(gatewaySelector),
|
||||
middleware.PoliciesProviderService(policiesProviderService),
|
||||
)(mockHandler{})
|
||||
|
||||
return policiesMiddleware, policiesProviderService, gatewayClient
|
||||
}
|
||||
|
||||
type mockHandler struct{}
|
||||
|
||||
func (m mockHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {}
|
||||
Reference in New Issue
Block a user