Bump reva
This commit is contained in:
Generated
Vendored
+3
-2
@@ -33,10 +33,11 @@ type Config struct {
|
||||
ProductVersion string `mapstructure:"product_version"`
|
||||
AllowPropfindDepthInfinitiy bool `mapstructure:"allow_depth_infinity"`
|
||||
|
||||
TransferSharedSecret string `mapstructure:"transfer_shared_secret"`
|
||||
|
||||
NameValidation NameValidation `mapstructure:"validation"`
|
||||
|
||||
// SharedSecret used to sign the 'oc:download' URLs
|
||||
URLSigningSharedSecret string `mapstructure:"url_signing_shared_secret"`
|
||||
|
||||
MachineAuthAPIKey string `mapstructure:"machine_auth_apikey"`
|
||||
}
|
||||
|
||||
|
||||
Generated
Vendored
+13
@@ -20,6 +20,7 @@ package ocdav
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path"
|
||||
@@ -41,6 +42,7 @@ import (
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rhttp"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rhttp/global"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rhttp/router"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/signedurl"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storage/favorite"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storage/favorite/registry"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storage/utils/templates"
|
||||
@@ -69,6 +71,7 @@ type svc struct {
|
||||
LockSystem LockSystem
|
||||
userIdentifierCache *ttlcache.Cache
|
||||
nameValidators []Validator
|
||||
urlSigner signedurl.Signer
|
||||
}
|
||||
|
||||
func (s *svc) Config() *config.Config {
|
||||
@@ -116,6 +119,15 @@ func NewWith(conf *config.Config, fm favorite.Manager, ls LockSystem, _ *zerolog
|
||||
// be safe - init the conf again
|
||||
conf.Init()
|
||||
|
||||
var signer signedurl.Signer
|
||||
if conf.URLSigningSharedSecret != "" {
|
||||
var err error
|
||||
signer, err = signedurl.NewJWTSignedURL(signedurl.WithSecret(conf.URLSigningSharedSecret))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize URL signer: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
s := &svc{
|
||||
c: conf,
|
||||
webDavHandler: new(WebDavHandler),
|
||||
@@ -129,6 +141,7 @@ func NewWith(conf *config.Config, fm favorite.Manager, ls LockSystem, _ *zerolog
|
||||
LockSystem: ls,
|
||||
userIdentifierCache: ttlcache.NewCache(),
|
||||
nameValidators: ValidatorsFromConfig(conf),
|
||||
urlSigner: signer,
|
||||
}
|
||||
_ = s.userIdentifierCache.SetTTL(60 * time.Second)
|
||||
|
||||
|
||||
Generated
Vendored
+50
-20
@@ -52,6 +52,7 @@ import (
|
||||
rstatus "github.com/opencloud-eu/reva/v2/pkg/rgrpc/status"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rhttp/router"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/signedurl"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storagespace"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/utils"
|
||||
"github.com/rs/zerolog"
|
||||
@@ -214,14 +215,16 @@ type Handler struct {
|
||||
PublicURL string
|
||||
selector pool.Selectable[gateway.GatewayAPIClient]
|
||||
c *config.Config
|
||||
urlSigner signedurl.Signer
|
||||
}
|
||||
|
||||
// NewHandler returns a new PropfindHandler instance
|
||||
func NewHandler(publicURL string, selector pool.Selectable[gateway.GatewayAPIClient], c *config.Config) *Handler {
|
||||
func NewHandler(publicURL string, selector pool.Selectable[gateway.GatewayAPIClient], signer signedurl.Signer, c *config.Config) *Handler {
|
||||
return &Handler{
|
||||
PublicURL: publicURL,
|
||||
selector: selector,
|
||||
c: c,
|
||||
urlSigner: signer,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,7 +497,7 @@ func (p *Handler) propfindResponse(ctx context.Context, w http.ResponseWriter, r
|
||||
prefer := net.ParsePrefer(r.Header.Get(net.HeaderPrefer))
|
||||
returnMinimal := prefer[net.HeaderPreferReturn] == "minimal"
|
||||
|
||||
propRes, err := MultistatusResponse(ctx, &pf, resourceInfos, p.PublicURL, namespace, linkshares, returnMinimal)
|
||||
propRes, err := MultistatusResponse(ctx, &pf, resourceInfos, p.PublicURL, namespace, linkshares, returnMinimal, p.urlSigner)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error formatting propfind")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
@@ -985,7 +988,7 @@ func ReadPropfind(r io.Reader) (pf XML, status int, err error) {
|
||||
}
|
||||
|
||||
// MultistatusResponse converts a list of resource infos into a multistatus response string
|
||||
func MultistatusResponse(ctx context.Context, pf *XML, mds []*provider.ResourceInfo, publicURL, ns string, linkshares map[string]struct{}, returnMinimal bool) ([]byte, error) {
|
||||
func MultistatusResponse(ctx context.Context, pf *XML, mds []*provider.ResourceInfo, publicURL, ns string, linkshares map[string]struct{}, returnMinimal bool, downloadURLSigner signedurl.Signer) ([]byte, error) {
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
type work struct {
|
||||
@@ -1020,7 +1023,7 @@ func MultistatusResponse(ctx context.Context, pf *XML, mds []*provider.ResourceI
|
||||
for i := 0; i < numWorkers; i++ {
|
||||
g.Go(func() error {
|
||||
for work := range workChan {
|
||||
res, err := mdToPropResponse(ctx, pf, work.info, publicURL, ns, linkshares, returnMinimal)
|
||||
res, err := mdToPropResponse(ctx, pf, work.info, publicURL, ns, linkshares, returnMinimal, downloadURLSigner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1061,7 +1064,7 @@ func MultistatusResponse(ctx context.Context, pf *XML, mds []*provider.ResourceI
|
||||
// mdToPropResponse converts the CS3 metadata into a webdav PropResponse
|
||||
// ns is the CS3 namespace that needs to be removed from the CS3 path before
|
||||
// prefixing it with the baseURI
|
||||
func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, publicURL, ns string, linkshares map[string]struct{}, returnMinimal bool) (*ResponseXML, error) {
|
||||
func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, publicURL, ns string, linkshares map[string]struct{}, returnMinimal bool, urlSigner signedurl.Signer) (*ResponseXML, error) {
|
||||
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "md_to_prop_response")
|
||||
span.SetAttributes(attribute.KeyValue{Key: "publicURL", Value: attribute.StringValue(publicURL)})
|
||||
span.SetAttributes(attribute.KeyValue{Key: "ns", Value: attribute.StringValue(ns)})
|
||||
@@ -1516,23 +1519,14 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
|
||||
appendToNotFound(prop.NotFound("oc:owner-display-name"))
|
||||
}
|
||||
case "downloadURL": // desktop
|
||||
if isPublic && md.Type == provider.ResourceType_RESOURCE_TYPE_FILE {
|
||||
var path string
|
||||
if !ls.PasswordProtected {
|
||||
path = p
|
||||
if md.Type == provider.ResourceType_RESOURCE_TYPE_FILE {
|
||||
url := downloadURL(ctx, sublog, isPublic, p, ls, publicURL, baseURI, urlSigner)
|
||||
if url != "" {
|
||||
appendToOK(prop.Escaped("oc:downloadURL", url))
|
||||
} else {
|
||||
expiration := time.Unix(int64(ls.Signature.SignatureExpiration.Seconds), int64(ls.Signature.SignatureExpiration.Nanos))
|
||||
var sb strings.Builder
|
||||
|
||||
sb.WriteString(p)
|
||||
sb.WriteString("?signature=")
|
||||
sb.WriteString(ls.Signature.Signature)
|
||||
sb.WriteString("&expiration=")
|
||||
sb.WriteString(url.QueryEscape(expiration.Format(time.RFC3339)))
|
||||
|
||||
path = sb.String()
|
||||
appendToNotFound(prop.NotFound("oc:" + pf.Prop[i].Local))
|
||||
}
|
||||
appendToOK(prop.Escaped("oc:downloadURL", publicURL+baseURI+path))
|
||||
|
||||
} else {
|
||||
appendToNotFound(prop.NotFound("oc:" + pf.Prop[i].Local))
|
||||
}
|
||||
@@ -1738,6 +1732,42 @@ func hasPreview(md *provider.ResourceInfo, appendToOK func(p ...prop.PropertyXML
|
||||
}
|
||||
}
|
||||
|
||||
func downloadURL(ctx context.Context, log zerolog.Logger, isPublic bool, path string, ls *link.PublicShare, publicURL string, baseURI string, urlSigner signedurl.Signer) string {
|
||||
switch {
|
||||
case isPublic:
|
||||
var queryString string
|
||||
if !ls.PasswordProtected {
|
||||
queryString = path
|
||||
} else {
|
||||
expiration := time.Unix(int64(ls.Signature.SignatureExpiration.Seconds), int64(ls.Signature.SignatureExpiration.Nanos))
|
||||
var sb strings.Builder
|
||||
|
||||
sb.WriteString(path)
|
||||
sb.WriteString("?signature=")
|
||||
sb.WriteString(ls.Signature.Signature)
|
||||
sb.WriteString("&expiration=")
|
||||
sb.WriteString(url.QueryEscape(expiration.Format(time.RFC3339)))
|
||||
|
||||
queryString = sb.String()
|
||||
}
|
||||
return publicURL + baseURI + queryString
|
||||
case urlSigner != nil:
|
||||
u, ok := ctxpkg.ContextGetUser(ctx)
|
||||
if !ok {
|
||||
log.Error().Msg("could not get user from context for download URL signing")
|
||||
return ""
|
||||
}
|
||||
signedURL, err := urlSigner.Sign(publicURL+baseURI+path, u.Id.OpaqueId, 30*time.Minute)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to sign download URL")
|
||||
return ""
|
||||
} else {
|
||||
return signedURL
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func activeLocks(log *zerolog.Logger, lock *provider.Lock) string {
|
||||
if lock == nil || lock.Type == provider.LockType_LOCK_TYPE_INVALID {
|
||||
return ""
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -147,7 +147,7 @@ func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns s
|
||||
prefer := net.ParsePrefer(r.Header.Get("prefer"))
|
||||
returnMinimal := prefer[net.HeaderPreferReturn] == "minimal"
|
||||
|
||||
propRes, err := propfind.MultistatusResponse(ctx, &pf, infos, s.c.PublicURL, ns, nil, returnMinimal)
|
||||
propRes, err := propfind.MultistatusResponse(ctx, &pf, infos, s.c.PublicURL, ns, nil, returnMinimal, nil)
|
||||
if err != nil {
|
||||
sublog.Error().Err(err).Msg("error formatting propfind")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -117,7 +117,7 @@ func (s *svc) doFilterFiles(w http.ResponseWriter, r *http.Request, ff *reportFi
|
||||
prefer := net.ParsePrefer(r.Header.Get("prefer"))
|
||||
returnMinimal := prefer[net.HeaderPreferReturn] == "minimal"
|
||||
|
||||
responsesXML, err := propfind.MultistatusResponse(ctx, &propfind.XML{Prop: ff.Prop}, infos, s.c.PublicURL, namespace, nil, returnMinimal)
|
||||
responsesXML, err := propfind.MultistatusResponse(ctx, &propfind.XML{Prop: ff.Prop}, infos, s.c.PublicURL, namespace, nil, returnMinimal, nil)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error formatting propfind")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -82,7 +82,7 @@ func (h *SpacesHandler) Handler(s *svc, trashbinHandler *TrashbinHandler) http.H
|
||||
var err error
|
||||
switch r.Method {
|
||||
case MethodPropfind:
|
||||
p := propfind.NewHandler(config.PublicURL, s.gatewaySelector, config)
|
||||
p := propfind.NewHandler(config.PublicURL, s.gatewaySelector, s.urlSigner, config)
|
||||
p.HandleSpacesPropfind(w, r, spaceID)
|
||||
case MethodProppatch:
|
||||
status, err = s.handleSpacesProppatch(w, r, spaceID)
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -200,7 +200,7 @@ func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request,
|
||||
prefer := net.ParsePrefer(r.Header.Get("prefer"))
|
||||
returnMinimal := prefer[net.HeaderPreferReturn] == "minimal"
|
||||
|
||||
propRes, err := propfind.MultistatusResponse(ctx, &pf, infos, s.c.PublicURL, "", nil, returnMinimal)
|
||||
propRes, err := propfind.MultistatusResponse(ctx, &pf, infos, s.c.PublicURL, "", nil, returnMinimal, nil)
|
||||
if err != nil {
|
||||
sublog.Error().Err(err).Msg("error formatting propfind")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -72,7 +72,7 @@ func (h *WebDavHandler) Handler(s *svc) http.Handler {
|
||||
var status int // status 0 means the handler already sent the response
|
||||
switch r.Method {
|
||||
case MethodPropfind:
|
||||
p := propfind.NewHandler(config.PublicURL, s.gatewaySelector, config)
|
||||
p := propfind.NewHandler(config.PublicURL, s.gatewaySelector, s.urlSigner, config)
|
||||
p.HandlePathPropfind(w, r, ns)
|
||||
case MethodLock:
|
||||
status, err = s.handleLock(w, r, ns)
|
||||
|
||||
+12
-14
@@ -40,14 +40,13 @@ func (_m *Stream) EXPECT() *Stream_Expecter {
|
||||
|
||||
// Consume provides a mock function with given fields: _a0, _a1
|
||||
func (_m *Stream) Consume(_a0 string, _a1 ...events.ConsumeOption) (<-chan events.Event, error) {
|
||||
_va := make([]interface{}, len(_a1))
|
||||
for _i := range _a1 {
|
||||
_va[_i] = _a1[_i]
|
||||
var tmpRet mock.Arguments
|
||||
if len(_a1) > 0 {
|
||||
tmpRet = _m.Called(_a0, _a1)
|
||||
} else {
|
||||
tmpRet = _m.Called(_a0)
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, _a0)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Consume")
|
||||
@@ -113,14 +112,13 @@ func (_c *Stream_Consume_Call) RunAndReturn(run func(string, ...events.ConsumeOp
|
||||
|
||||
// Publish provides a mock function with given fields: _a0, _a1, _a2
|
||||
func (_m *Stream) Publish(_a0 string, _a1 interface{}, _a2 ...events.PublishOption) error {
|
||||
_va := make([]interface{}, len(_a2))
|
||||
for _i := range _a2 {
|
||||
_va[_i] = _a2[_i]
|
||||
var tmpRet mock.Arguments
|
||||
if len(_a2) > 0 {
|
||||
tmpRet = _m.Called(_a0, _a1, _a2)
|
||||
} else {
|
||||
tmpRet = _m.Called(_a0, _a1)
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, _a0, _a1)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Publish")
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package raw
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
// newCertPoolFromPEM reads certificates from io.Reader and returns a x509.CertPool
|
||||
// containing those certificates.
|
||||
func newCertPoolFromPEM(crts ...io.Reader) (*x509.CertPool, error) {
|
||||
certPool := x509.NewCertPool()
|
||||
|
||||
var buf bytes.Buffer
|
||||
for _, c := range crts {
|
||||
if _, err := io.Copy(&buf, c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !certPool.AppendCertsFromPEM(buf.Bytes()) {
|
||||
return nil, errors.New("failed to append cert from PEM")
|
||||
}
|
||||
buf.Reset()
|
||||
}
|
||||
|
||||
return certPool, nil
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
// Copyright 2018-2022 CERN
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// In applying this license, CERN does not waive the privileges and immunities
|
||||
// granted to it by virtue of its status as an Intergovernmental Organization
|
||||
// or submit itself to any jurisdiction.
|
||||
|
||||
// Code generated by mockery v2.53.2. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
events "github.com/opencloud-eu/reva/v2/pkg/events"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
raw "github.com/opencloud-eu/reva/v2/pkg/events/raw"
|
||||
)
|
||||
|
||||
// Stream is an autogenerated mock type for the Stream type
|
||||
type Stream struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type Stream_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *Stream) EXPECT() *Stream_Expecter {
|
||||
return &Stream_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Consume provides a mock function with given fields: group, evs
|
||||
func (_m *Stream) Consume(group string, evs ...events.Unmarshaller) (<-chan raw.Event, error) {
|
||||
var tmpRet mock.Arguments
|
||||
if len(evs) > 0 {
|
||||
tmpRet = _m.Called(group, evs)
|
||||
} else {
|
||||
tmpRet = _m.Called(group)
|
||||
}
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Consume")
|
||||
}
|
||||
|
||||
var r0 <-chan raw.Event
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string, ...events.Unmarshaller) (<-chan raw.Event, error)); ok {
|
||||
return rf(group, evs...)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, ...events.Unmarshaller) <-chan raw.Event); ok {
|
||||
r0 = rf(group, evs...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(<-chan raw.Event)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string, ...events.Unmarshaller) error); ok {
|
||||
r1 = rf(group, evs...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Stream_Consume_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Consume'
|
||||
type Stream_Consume_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Consume is a helper method to define mock.On call
|
||||
// - group string
|
||||
// - evs ...events.Unmarshaller
|
||||
func (_e *Stream_Expecter) Consume(group interface{}, evs ...interface{}) *Stream_Consume_Call {
|
||||
return &Stream_Consume_Call{Call: _e.mock.On("Consume",
|
||||
append([]interface{}{group}, evs...)...)}
|
||||
}
|
||||
|
||||
func (_c *Stream_Consume_Call) Run(run func(group string, evs ...events.Unmarshaller)) *Stream_Consume_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]events.Unmarshaller, len(args)-1)
|
||||
for i, a := range args[1:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(events.Unmarshaller)
|
||||
}
|
||||
}
|
||||
run(args[0].(string), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Stream_Consume_Call) Return(_a0 <-chan raw.Event, _a1 error) *Stream_Consume_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Stream_Consume_Call) RunAndReturn(run func(string, ...events.Unmarshaller) (<-chan raw.Event, error)) *Stream_Consume_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewStream creates a new instance of Stream. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewStream(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *Stream {
|
||||
mock := &Stream{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
package raw
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/events"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Config is the configuration needed for a NATS event stream
|
||||
type Config struct {
|
||||
Endpoint string `mapstructure:"address"` // Endpoint of the nats server
|
||||
Cluster string `mapstructure:"clusterID"` // CluserID of the nats cluster
|
||||
TLSInsecure bool `mapstructure:"tls-insecure"` // Whether to verify TLS certificates
|
||||
TLSRootCACertificate string `mapstructure:"tls-root-ca-cert"` // The root CA certificate used to validate the TLS certificate
|
||||
EnableTLS bool `mapstructure:"enable-tls"` // Enable TLS
|
||||
AuthUsername string `mapstructure:"username"` // Username for authentication
|
||||
AuthPassword string `mapstructure:"password"` // Password for authentication
|
||||
MaxAckPending int `mapstructure:"max-ack-pending"` // Maximum number of unacknowledged messages
|
||||
AckWait time.Duration `mapstructure:"ack-wait"` // Time to wait for an ack
|
||||
}
|
||||
|
||||
type RawEvent struct {
|
||||
Timestamp time.Time
|
||||
Metadata map[string]string
|
||||
ID string
|
||||
Topic string
|
||||
Payload []byte
|
||||
|
||||
msg jetstream.Msg
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
events.Event
|
||||
|
||||
msg jetstream.Msg
|
||||
}
|
||||
|
||||
func (re *Event) Ack() error {
|
||||
if re.msg == nil {
|
||||
return errors.New("cannot ack event without message")
|
||||
}
|
||||
return re.msg.Ack()
|
||||
}
|
||||
|
||||
func (re *Event) InProgress() error {
|
||||
if re.msg == nil {
|
||||
return errors.New("cannot mark event as in progress without message")
|
||||
}
|
||||
return re.msg.InProgress()
|
||||
}
|
||||
|
||||
type Stream interface {
|
||||
Consume(group string, evs ...events.Unmarshaller) (<-chan Event, error)
|
||||
}
|
||||
|
||||
type RawStream struct {
|
||||
Js jetstream.Stream
|
||||
|
||||
c Config
|
||||
}
|
||||
|
||||
func FromConfig(ctx context.Context, name string, cfg Config) (Stream, error) {
|
||||
var s Stream
|
||||
b := backoff.NewExponentialBackOff()
|
||||
|
||||
connect := func() error {
|
||||
var tlsConf *tls.Config
|
||||
if cfg.EnableTLS {
|
||||
var rootCAPool *x509.CertPool
|
||||
if cfg.TLSRootCACertificate != "" {
|
||||
rootCrtFile, err := os.Open(cfg.TLSRootCACertificate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rootCAPool, err = newCertPoolFromPEM(rootCrtFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.TLSInsecure = false
|
||||
}
|
||||
|
||||
tlsConf = &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: cfg.TLSInsecure,
|
||||
RootCAs: rootCAPool,
|
||||
}
|
||||
}
|
||||
|
||||
nopts := nats.GetDefaultOptions()
|
||||
nopts.Name = name
|
||||
if tlsConf != nil {
|
||||
nopts.Secure = true
|
||||
nopts.TLSConfig = tlsConf
|
||||
}
|
||||
|
||||
if len(cfg.Endpoint) > 0 {
|
||||
nopts.Servers = []string{cfg.Endpoint}
|
||||
}
|
||||
|
||||
if cfg.AuthUsername != "" && cfg.AuthPassword != "" {
|
||||
nopts.User = cfg.AuthUsername
|
||||
nopts.Password = cfg.AuthPassword
|
||||
}
|
||||
|
||||
conn, err := nopts.Connect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsConn, err := jetstream.New(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
js, err := jsConn.Stream(ctx, events.MainQueueName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s = &RawStream{
|
||||
Js: js,
|
||||
c: cfg,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
err := backoff.Retry(connect, b)
|
||||
if err != nil {
|
||||
return s, errors.Wrap(err, "could not connect to nats jetstream")
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *RawStream) Consume(group string, evs ...events.Unmarshaller) (<-chan Event, error) {
|
||||
c, err := s.consumeRaw(group)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
registeredEvents := map[string]events.Unmarshaller{}
|
||||
for _, e := range evs {
|
||||
typ := reflect.TypeOf(e)
|
||||
registeredEvents[typ.String()] = e
|
||||
}
|
||||
|
||||
outchan := make(chan Event)
|
||||
go func() {
|
||||
for {
|
||||
e := <-c
|
||||
eventType := e.Metadata[events.MetadatakeyEventType]
|
||||
ev, ok := registeredEvents[eventType]
|
||||
if !ok {
|
||||
_ = e.msg.Ack() // Discard. We are not interested in this event type
|
||||
continue
|
||||
}
|
||||
|
||||
event, err := ev.Unmarshal(e.Payload)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
outchan <- Event{
|
||||
Event: events.Event{
|
||||
Type: eventType,
|
||||
ID: e.Metadata[events.MetadatakeyEventID],
|
||||
TraceParent: e.Metadata[events.MetadatakeyTraceParent],
|
||||
InitiatorID: e.Metadata[events.MetadatakeyInitiatorID],
|
||||
Event: event,
|
||||
},
|
||||
msg: e.msg,
|
||||
}
|
||||
}
|
||||
}()
|
||||
return outchan, nil
|
||||
}
|
||||
|
||||
func (s *RawStream) consumeRaw(group string) (<-chan RawEvent, error) {
|
||||
consumer, err := s.Js.CreateOrUpdateConsumer(context.Background(), jetstream.ConsumerConfig{
|
||||
Durable: group,
|
||||
DeliverPolicy: jetstream.DeliverNewPolicy,
|
||||
AckPolicy: jetstream.AckExplicitPolicy, // Require manual acknowledgment
|
||||
MaxAckPending: s.c.MaxAckPending, // Maximum number of unacknowledged messages
|
||||
AckWait: s.c.AckWait, // Time to wait for an ack
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
channel := make(chan RawEvent)
|
||||
callback := func(msg jetstream.Msg) {
|
||||
var rawEvent RawEvent
|
||||
if err := json.Unmarshal(msg.Data(), &rawEvent); err != nil {
|
||||
fmt.Printf("error unmarshalling event: %v\n", err)
|
||||
return
|
||||
}
|
||||
rawEvent.msg = msg
|
||||
channel <- rawEvent
|
||||
}
|
||||
_, err = consumer.Consume(callback)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return channel, nil
|
||||
}
|
||||
+7
@@ -401,3 +401,10 @@ func RegisterInterval(interval time.Duration) Option {
|
||||
o.RegisterInterval = interval
|
||||
}
|
||||
}
|
||||
|
||||
// URLSigningSharedSecret provides a function to set the URLSigningSharedSecret config option.
|
||||
func URLSigningSharedSecret(secret string) Option {
|
||||
return func(o *Options) {
|
||||
o.config.URLSigningSharedSecret = secret
|
||||
}
|
||||
}
|
||||
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
package signedurl
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
// JWTSignedURL implements the Signer and Verifier interfaces using JWT for signing URLs.
|
||||
type JWTSignedURL struct {
|
||||
JWTOptions
|
||||
}
|
||||
|
||||
type claims struct {
|
||||
TargetURL string `json:"target_url"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
// JWTOption defines a single option function.
|
||||
type JWTOption func(o *JWTOptions)
|
||||
|
||||
// JWTOptions defines the available options for this package.
|
||||
type JWTOptions struct {
|
||||
secret string // Secret key used for signing and verifying JWTs
|
||||
queryParam string // Name of the query parameter for the signature
|
||||
}
|
||||
|
||||
func NewJWTSignedURL(opts ...JWTOption) (*JWTSignedURL, error) {
|
||||
opt := JWTOptions{}
|
||||
for _, o := range opts {
|
||||
o(&opt)
|
||||
}
|
||||
|
||||
if opt.secret == "" {
|
||||
return nil, ErrInvalidKey
|
||||
}
|
||||
|
||||
if opt.queryParam == "" {
|
||||
opt.queryParam = "oc-jwt-sig"
|
||||
}
|
||||
|
||||
return &JWTSignedURL{opt}, nil
|
||||
}
|
||||
|
||||
func WithSecret(secret string) JWTOption {
|
||||
return func(o *JWTOptions) {
|
||||
o.secret = secret
|
||||
}
|
||||
}
|
||||
|
||||
func WithQueryParam(queryParam string) JWTOption {
|
||||
return func(o *JWTOptions) {
|
||||
o.queryParam = queryParam
|
||||
}
|
||||
}
|
||||
|
||||
// Sign signs a URL using JWT with a specified time-to-live (ttl).
|
||||
func (j *JWTSignedURL) Sign(unsignedURL, subject string, ttl time.Duration) (string, error) {
|
||||
// Re-encode the Query parameters to ensure they are "normalized" (Values.Encode() does return them alphabetically ordered).
|
||||
u, err := url.Parse(unsignedURL)
|
||||
if err != nil {
|
||||
return "", NewSignedURLError(err, "failed to parse url")
|
||||
}
|
||||
query := u.Query()
|
||||
u.RawQuery = query.Encode()
|
||||
c := claims{
|
||||
TargetURL: u.String(),
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(ttl)),
|
||||
Issuer: "reva",
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
Subject: subject,
|
||||
},
|
||||
}
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
|
||||
signedToken, err := token.SignedString([]byte(j.secret))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("signing failed: %w", err)
|
||||
}
|
||||
query.Set(j.queryParam, signedToken)
|
||||
u.RawQuery = query.Encode()
|
||||
return u.String(), nil
|
||||
}
|
||||
|
||||
// Verify verifies a signed URL using a JWT. Returns the subject of the JWT if verification is successful.
|
||||
func (j *JWTSignedURL) Verify(signedURL string) (string, error) {
|
||||
u, err := url.Parse(signedURL)
|
||||
if err != nil {
|
||||
return "", NewSignatureVerificationError(fmt.Errorf("could not parse URL: %w", err))
|
||||
}
|
||||
query := u.Query()
|
||||
tokenString := query.Get(j.queryParam)
|
||||
if tokenString == "" {
|
||||
return "", NewSignatureVerificationError(errors.New("no signature in url"))
|
||||
}
|
||||
token, err := jwt.ParseWithClaims(tokenString, &claims{}, func(token *jwt.Token) (any, error) { return []byte(j.secret), nil })
|
||||
if err != nil {
|
||||
return "", NewSignatureVerificationError(err)
|
||||
}
|
||||
c, ok := token.Claims.(*claims)
|
||||
if !ok {
|
||||
return "", NewSignatureVerificationError(errors.New("invalid JWT claims"))
|
||||
}
|
||||
|
||||
query.Del(j.queryParam)
|
||||
u.RawQuery = query.Encode()
|
||||
|
||||
if c.TargetURL != u.String() {
|
||||
return "", NewSignatureVerificationError(errors.New("url mismatch"))
|
||||
}
|
||||
|
||||
return c.Subject, nil
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// Package signedurl provides interfaces and implementations for signing and verifying URLs.
|
||||
package signedurl
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Signer interface {
|
||||
// Sign signs a URL
|
||||
Sign(url, principal string, ttl time.Duration) (string, error)
|
||||
}
|
||||
|
||||
type Verifier interface {
|
||||
// Verify verifies a signed URL
|
||||
Verify(signedURL string) (string, error)
|
||||
}
|
||||
|
||||
type SignedURLError struct {
|
||||
innerErr error
|
||||
message string
|
||||
}
|
||||
|
||||
// NewSignedURLError creates a new SignedURLError with the provided inner error and message.
|
||||
func NewSignedURLError(innerErr error, message string) SignedURLError {
|
||||
return SignedURLError{
|
||||
innerErr: innerErr,
|
||||
message: message,
|
||||
}
|
||||
}
|
||||
|
||||
var ErrInvalidKey = NewSignedURLError(nil, "invalid key provided")
|
||||
|
||||
type SignatureVerificationError struct {
|
||||
SignedURLError
|
||||
}
|
||||
|
||||
func NewSignatureVerificationError(innerErr error) SignatureVerificationError {
|
||||
return SignatureVerificationError{
|
||||
SignedURLError: SignedURLError{
|
||||
innerErr: innerErr,
|
||||
message: "signature verification failed",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (e SignatureVerificationError) Is(tgt error) bool {
|
||||
// Check if the target error is of type SignatureVerificationError
|
||||
if _, ok := tgt.(SignatureVerificationError); ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Error implements the error interface for errorConst.
|
||||
func (e SignedURLError) Error() string {
|
||||
if e.innerErr != nil {
|
||||
return e.message + ": " + e.innerErr.Error()
|
||||
}
|
||||
return e.message
|
||||
}
|
||||
|
||||
func (e SignedURLError) Unwrap() error {
|
||||
return e.innerErr
|
||||
}
|
||||
Generated
Vendored
+3
-1
@@ -98,11 +98,13 @@ func (w *CephFSWatcher) Watch(topic string) {
|
||||
switch {
|
||||
case mask&CEPH_MDS_NOTIFY_DELETE > 0:
|
||||
err = w.tree.Scan(path, ActionDelete, isDir)
|
||||
case mask&CEPH_MDS_NOTIFY_CREATE > 0 || mask&CEPH_MDS_NOTIFY_MOVED_TO > 0:
|
||||
case mask&CEPH_MDS_NOTIFY_MOVED_TO > 0:
|
||||
if ev.SrcMask > 0 {
|
||||
// This is a move, clean up the old path
|
||||
err = w.tree.Scan(filepath.Join(w.tree.options.WatchRoot, ev.SrcPath), ActionMoveFrom, isDir)
|
||||
}
|
||||
err = w.tree.Scan(path, ActionMove, isDir)
|
||||
case mask&CEPH_MDS_NOTIFY_CREATE > 0:
|
||||
err = w.tree.Scan(path, ActionCreate, isDir)
|
||||
case mask&CEPH_MDS_NOTIFY_CLOSE_WRITE > 0:
|
||||
err = w.tree.Scan(path, ActionUpdate, isDir)
|
||||
|
||||
Generated
Vendored
+3
-1
@@ -92,7 +92,9 @@ func (iw *InotifyWatcher) Watch(path string) {
|
||||
err = iw.tree.Scan(event.Filename, ActionDelete, event.IsDir)
|
||||
case inotifywaitgo.MOVED_FROM:
|
||||
err = iw.tree.Scan(event.Filename, ActionMoveFrom, event.IsDir)
|
||||
case inotifywaitgo.CREATE, inotifywaitgo.MOVED_TO:
|
||||
case inotifywaitgo.MOVED_TO:
|
||||
err = iw.tree.Scan(event.Filename, ActionMove, event.IsDir)
|
||||
case inotifywaitgo.CREATE:
|
||||
err = iw.tree.Scan(event.Filename, ActionCreate, event.IsDir)
|
||||
case inotifywaitgo.CLOSE_WRITE:
|
||||
err = iw.tree.Scan(event.Filename, ActionUpdate, event.IsDir)
|
||||
|
||||
+6
-6
@@ -1117,22 +1117,22 @@ func (n *Node) ReadUserPermissions(ctx context.Context, u *userpb.User) (ap *pro
|
||||
continue
|
||||
}
|
||||
|
||||
if isGrantExpired(g) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case err == nil:
|
||||
if isGrantExpired(g) {
|
||||
continue
|
||||
}
|
||||
|
||||
// If all permissions are set to false we have a deny grant
|
||||
if grants.PermissionsEqual(g.Permissions, &provider.ResourcePermissions{}) {
|
||||
return NoPermissions(), true, nil
|
||||
}
|
||||
AddPermissions(ap, g.GetPermissions())
|
||||
case metadata.IsAttrUnset(err):
|
||||
appctx.GetLogger(ctx).Error().Str("spaceid", n.SpaceID).Str("nodeid", n.ID).Str("grant", grantees[i]).Interface("grantees", grantees).Msg("grant vanished from node after listing")
|
||||
appctx.GetLogger(ctx).Error().Err(err).Str("spaceid", n.SpaceID).Str("nodeid", n.ID).Str("path", n.InternalPath()).Str("grant", grantees[i]).Interface("grantees", grantees).Msg("grant vanished from node after listing")
|
||||
// continue with next segment
|
||||
default:
|
||||
appctx.GetLogger(ctx).Error().Err(err).Str("spaceid", n.SpaceID).Str("nodeid", n.ID).Str("grant", grantees[i]).Msg("error reading permissions")
|
||||
appctx.GetLogger(ctx).Error().Err(err).Str("spaceid", n.SpaceID).Str("nodeid", n.ID).Str("path", n.InternalPath()).Str("grant", grantees[i]).Msg("error reading permissions")
|
||||
// continue with next segment
|
||||
}
|
||||
}
|
||||
|
||||
Generated
Vendored
+48
-56
@@ -45,14 +45,13 @@ func (_m *CollaborationAPIClient) EXPECT() *CollaborationAPIClient_Expecter {
|
||||
|
||||
// CreateShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) CreateShare(ctx context.Context, in *collaborationv1beta1.CreateShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.CreateShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
var tmpRet mock.Arguments
|
||||
if len(opts) > 0 {
|
||||
tmpRet = _m.Called(ctx, in, opts)
|
||||
} else {
|
||||
tmpRet = _m.Called(ctx, in)
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreateShare")
|
||||
@@ -119,14 +118,13 @@ func (_c *CollaborationAPIClient_CreateShare_Call) RunAndReturn(run func(context
|
||||
|
||||
// GetReceivedShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) GetReceivedShare(ctx context.Context, in *collaborationv1beta1.GetReceivedShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.GetReceivedShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
var tmpRet mock.Arguments
|
||||
if len(opts) > 0 {
|
||||
tmpRet = _m.Called(ctx, in, opts)
|
||||
} else {
|
||||
tmpRet = _m.Called(ctx, in)
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetReceivedShare")
|
||||
@@ -193,14 +191,13 @@ func (_c *CollaborationAPIClient_GetReceivedShare_Call) RunAndReturn(run func(co
|
||||
|
||||
// GetShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) GetShare(ctx context.Context, in *collaborationv1beta1.GetShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.GetShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
var tmpRet mock.Arguments
|
||||
if len(opts) > 0 {
|
||||
tmpRet = _m.Called(ctx, in, opts)
|
||||
} else {
|
||||
tmpRet = _m.Called(ctx, in)
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetShare")
|
||||
@@ -267,14 +264,13 @@ func (_c *CollaborationAPIClient_GetShare_Call) RunAndReturn(run func(context.Co
|
||||
|
||||
// ListReceivedShares provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) ListReceivedShares(ctx context.Context, in *collaborationv1beta1.ListReceivedSharesRequest, opts ...grpc.CallOption) (*collaborationv1beta1.ListReceivedSharesResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
var tmpRet mock.Arguments
|
||||
if len(opts) > 0 {
|
||||
tmpRet = _m.Called(ctx, in, opts)
|
||||
} else {
|
||||
tmpRet = _m.Called(ctx, in)
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListReceivedShares")
|
||||
@@ -341,14 +337,13 @@ func (_c *CollaborationAPIClient_ListReceivedShares_Call) RunAndReturn(run func(
|
||||
|
||||
// ListShares provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) ListShares(ctx context.Context, in *collaborationv1beta1.ListSharesRequest, opts ...grpc.CallOption) (*collaborationv1beta1.ListSharesResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
var tmpRet mock.Arguments
|
||||
if len(opts) > 0 {
|
||||
tmpRet = _m.Called(ctx, in, opts)
|
||||
} else {
|
||||
tmpRet = _m.Called(ctx, in)
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListShares")
|
||||
@@ -415,14 +410,13 @@ func (_c *CollaborationAPIClient_ListShares_Call) RunAndReturn(run func(context.
|
||||
|
||||
// RemoveShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) RemoveShare(ctx context.Context, in *collaborationv1beta1.RemoveShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.RemoveShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
var tmpRet mock.Arguments
|
||||
if len(opts) > 0 {
|
||||
tmpRet = _m.Called(ctx, in, opts)
|
||||
} else {
|
||||
tmpRet = _m.Called(ctx, in)
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveShare")
|
||||
@@ -489,14 +483,13 @@ func (_c *CollaborationAPIClient_RemoveShare_Call) RunAndReturn(run func(context
|
||||
|
||||
// UpdateReceivedShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) UpdateReceivedShare(ctx context.Context, in *collaborationv1beta1.UpdateReceivedShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.UpdateReceivedShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
var tmpRet mock.Arguments
|
||||
if len(opts) > 0 {
|
||||
tmpRet = _m.Called(ctx, in, opts)
|
||||
} else {
|
||||
tmpRet = _m.Called(ctx, in)
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateReceivedShare")
|
||||
@@ -563,14 +556,13 @@ func (_c *CollaborationAPIClient_UpdateReceivedShare_Call) RunAndReturn(run func
|
||||
|
||||
// UpdateShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) UpdateShare(ctx context.Context, in *collaborationv1beta1.UpdateShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.UpdateShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
var tmpRet mock.Arguments
|
||||
if len(opts) > 0 {
|
||||
tmpRet = _m.Called(ctx, in, opts)
|
||||
} else {
|
||||
tmpRet = _m.Called(ctx, in)
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateShare")
|
||||
|
||||
+600
-700
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user