Initial QSfera import
This commit is contained in:
+203
@@ -0,0 +1,203 @@
|
||||
// Copyright 2018-2021 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.
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"reflect"
|
||||
|
||||
"github.com/google/uuid"
|
||||
ctxpkg "github.com/opencloud-eu/reva/v2/pkg/ctx"
|
||||
"go-micro.dev/v4/events"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
)
|
||||
|
||||
var (
|
||||
// MainQueueName is the name of the main queue
|
||||
// All events will go through here as they are forwarded to the consumer via the
|
||||
// group name
|
||||
// TODO: "fan-out" so not all events go through the same queue? requires investigation
|
||||
MainQueueName = "main-queue"
|
||||
|
||||
// MetadatakeyEventType is the key used for the eventtype in the metadata map of the event
|
||||
MetadatakeyEventType = "eventtype"
|
||||
|
||||
// MetadatakeyEventID is the key used for the eventID in the metadata map of the event
|
||||
MetadatakeyEventID = "eventid"
|
||||
|
||||
// MetadatakeyTraceParent is the key used for the traceparent in the metadata map of the event
|
||||
MetadatakeyTraceParent = "traceparent"
|
||||
|
||||
// MetadatakeyInitiatorID is the key used for the initiator id in the metadata map of the event
|
||||
MetadatakeyInitiatorID = "initiatorid"
|
||||
)
|
||||
|
||||
type (
|
||||
// Unmarshaller is the interface events need to fulfill
|
||||
Unmarshaller interface {
|
||||
Unmarshal([]byte) (interface{}, error)
|
||||
}
|
||||
|
||||
// Publisher is the interface publishers need to fulfill
|
||||
Publisher interface {
|
||||
Publish(string, interface{}, ...events.PublishOption) error
|
||||
}
|
||||
|
||||
// Consumer is the interface consumer need to fulfill
|
||||
Consumer interface {
|
||||
Consume(string, ...events.ConsumeOption) (<-chan events.Event, error)
|
||||
}
|
||||
|
||||
// Stream is the interface common to Publisher and Consumer
|
||||
Stream interface {
|
||||
Publish(string, interface{}, ...events.PublishOption) error
|
||||
Consume(string, ...events.ConsumeOption) (<-chan events.Event, error)
|
||||
}
|
||||
|
||||
// Event is the envelope for events
|
||||
Event struct {
|
||||
Type string
|
||||
ID string
|
||||
TraceParent string
|
||||
InitiatorID string
|
||||
Event interface{}
|
||||
}
|
||||
)
|
||||
|
||||
// Consume returns a channel that will get all events that match the given evs
|
||||
// group defines the service type: One group will get exactly one copy of a event that is emitted
|
||||
// NOTE: uses reflect on initialization
|
||||
func Consume(s Consumer, group string, evs ...Unmarshaller) (<-chan Event, error) {
|
||||
return ConsumeWithOptions(s, ConsumeOptions{Group: group}, evs...)
|
||||
}
|
||||
|
||||
// ConsumeWithOptions returns a channel that will get all events that match the given evs
|
||||
// opts defines the options for the consumer
|
||||
func ConsumeWithOptions(s Consumer, opts ConsumeOptions, evs ...Unmarshaller) (<-chan Event, error) {
|
||||
o := []events.ConsumeOption{
|
||||
events.WithGroup(opts.Group),
|
||||
}
|
||||
if !opts.AutoAck {
|
||||
o = append(o, events.WithAutoAck(false, opts.AckWait))
|
||||
}
|
||||
c, err := s.Consume(MainQueueName, o...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
registeredEvents := map[string]Unmarshaller{}
|
||||
for _, e := range evs {
|
||||
typ := reflect.TypeOf(e)
|
||||
registeredEvents[typ.String()] = e
|
||||
}
|
||||
|
||||
outchan := make(chan Event)
|
||||
go func() {
|
||||
for {
|
||||
e := <-c
|
||||
et := e.Metadata[MetadatakeyEventType]
|
||||
ev, ok := registeredEvents[et]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
event, err := ev.Unmarshal(e.Payload)
|
||||
if err != nil {
|
||||
log.Printf("can't unmarshal event %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
outchan <- Event{
|
||||
Type: et,
|
||||
ID: e.Metadata[MetadatakeyEventID],
|
||||
TraceParent: e.Metadata[MetadatakeyTraceParent],
|
||||
InitiatorID: e.Metadata[MetadatakeyInitiatorID],
|
||||
Event: event,
|
||||
}
|
||||
}
|
||||
}()
|
||||
return outchan, nil
|
||||
}
|
||||
|
||||
// ConsumeAll allows consuming all events. Note that unmarshalling must be done manually in this case, therefore Event.Event will always be of type []byte
|
||||
func ConsumeAll(s Consumer, group string) (<-chan Event, error) {
|
||||
return ConsumeAllWithOptions(s, ConsumeOptions{Group: group})
|
||||
}
|
||||
|
||||
// ConsumeAllWithOptions allows consuming all events. Note that unmarshalling must be done manually in this case, therefore Event.Event will always be of type []byte
|
||||
func ConsumeAllWithOptions(s Consumer, opts ConsumeOptions) (<-chan Event, error) {
|
||||
o := []events.ConsumeOption{
|
||||
events.WithGroup(opts.Group),
|
||||
}
|
||||
if !opts.AutoAck {
|
||||
o = append(o, events.WithAutoAck(false, opts.AckWait))
|
||||
}
|
||||
c, err := s.Consume(MainQueueName, o...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outchan := make(chan Event)
|
||||
go func() {
|
||||
for {
|
||||
e := <-c
|
||||
outchan <- Event{
|
||||
Type: e.Metadata[MetadatakeyEventType],
|
||||
ID: e.Metadata[MetadatakeyEventID],
|
||||
TraceParent: e.Metadata[MetadatakeyTraceParent],
|
||||
InitiatorID: e.Metadata[MetadatakeyInitiatorID],
|
||||
Event: e.Payload,
|
||||
}
|
||||
}
|
||||
}()
|
||||
return outchan, nil
|
||||
}
|
||||
|
||||
// Publish publishes the ev to the MainQueue from where it is distributed to all subscribers
|
||||
// NOTE: needs to use reflect on runtime
|
||||
func Publish(ctx context.Context, s Publisher, ev interface{}) error {
|
||||
evName := reflect.TypeOf(ev).String()
|
||||
traceParent := getTraceParentFromCtx(ctx)
|
||||
iid, _ := ctxpkg.ContextGetInitiator(ctx)
|
||||
return s.Publish(MainQueueName, ev, events.WithMetadata(map[string]string{
|
||||
MetadatakeyEventType: evName,
|
||||
MetadatakeyEventID: uuid.New().String(),
|
||||
MetadatakeyTraceParent: traceParent,
|
||||
MetadatakeyInitiatorID: iid,
|
||||
}))
|
||||
}
|
||||
|
||||
// GetTraceContext extracts the trace context from the event and injects it into the given
|
||||
// context.
|
||||
func (e *Event) GetTraceContext(ctx context.Context) context.Context {
|
||||
return propagation.TraceContext{}.Extract(ctx, propagation.MapCarrier{
|
||||
"traceparent": e.TraceParent,
|
||||
})
|
||||
}
|
||||
|
||||
// getTraceParentFromCtx will return a traceparent from the context if it exists.
|
||||
// it will be a string as specificied here: https://www.w3.org/TR/trace-context/
|
||||
// If no trace info in the context, the return will be an empty string
|
||||
func getTraceParentFromCtx(ctx context.Context) string {
|
||||
mc := propagation.MapCarrier{}
|
||||
tc := propagation.TraceContext{}
|
||||
tc.Inject(ctx, &mc)
|
||||
return mc["traceparent"]
|
||||
}
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
// 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.
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
)
|
||||
|
||||
// ContainerCreated is emitted when a directory has been created
|
||||
type ContainerCreated struct {
|
||||
SpaceOwner *user.UserId
|
||||
Executant *user.UserId
|
||||
Ref *provider.Reference
|
||||
ParentID *provider.ResourceId
|
||||
Owner *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (ContainerCreated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ContainerCreated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// FileUploaded is emitted when a file is uploaded
|
||||
type FileUploaded struct {
|
||||
SpaceOwner *user.UserId
|
||||
Executant *user.UserId
|
||||
Ref *provider.Reference
|
||||
Owner *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (FileUploaded) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := FileUploaded{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// FileTouched is emitted when a file is uploaded
|
||||
type FileTouched struct {
|
||||
SpaceOwner *user.UserId
|
||||
Executant *user.UserId
|
||||
Ref *provider.Reference
|
||||
ParentID *provider.ResourceId
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (FileTouched) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := FileTouched{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// FileDownloaded is emitted when a file is downloaded
|
||||
type FileDownloaded struct {
|
||||
Executant *user.UserId
|
||||
Ref *provider.Reference
|
||||
Owner *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (FileDownloaded) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := FileDownloaded{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// FileLocked is emitted when a file is locked
|
||||
type FileLocked struct {
|
||||
Executant *user.UserId
|
||||
Ref *provider.Reference
|
||||
Owner *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (FileLocked) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := FileLocked{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// FileUnlocked is emitted when a file is unlocked
|
||||
type FileUnlocked struct {
|
||||
Executant *user.UserId
|
||||
Ref *provider.Reference
|
||||
Owner *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (FileUnlocked) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := FileUnlocked{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// ItemTrashed is emitted when a file or folder is trashed
|
||||
type ItemTrashed struct {
|
||||
SpaceOwner *user.UserId
|
||||
Executant *user.UserId
|
||||
ID *provider.ResourceId
|
||||
Ref *provider.Reference
|
||||
Owner *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (ItemTrashed) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ItemTrashed{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// ItemMoved is emitted when a file or folder is moved
|
||||
type ItemMoved struct {
|
||||
SpaceOwner *user.UserId
|
||||
Executant *user.UserId
|
||||
Ref *provider.Reference
|
||||
Owner *user.UserId
|
||||
OldReference *provider.Reference
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (ItemMoved) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ItemMoved{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// TrashbinPurged is emitted when the whole trashbin is purged
|
||||
type TrashbinPurged struct {
|
||||
Executant *user.UserId
|
||||
Ref *provider.Reference
|
||||
Owner *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (TrashbinPurged) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := TrashbinPurged{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// ItemPurged is emitted when a file or folder is removed from trashbin
|
||||
type ItemPurged struct {
|
||||
Executant *user.UserId
|
||||
ID *provider.ResourceId
|
||||
Ref *provider.Reference
|
||||
Owner *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (ItemPurged) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ItemPurged{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// ItemRestored is emitted when a file or folder is restored from trashbin
|
||||
type ItemRestored struct {
|
||||
SpaceOwner *user.UserId
|
||||
Executant *user.UserId
|
||||
ID *provider.ResourceId
|
||||
Ref *provider.Reference
|
||||
Owner *user.UserId
|
||||
OldReference *provider.Reference
|
||||
Key string
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (ItemRestored) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ItemRestored{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// FileVersionRestored is emitted when a file version is restored
|
||||
type FileVersionRestored struct {
|
||||
SpaceOwner *user.UserId
|
||||
Executant *user.UserId
|
||||
Ref *provider.Reference
|
||||
Owner *user.UserId
|
||||
Key string
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (FileVersionRestored) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := FileVersionRestored{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
// 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.
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
)
|
||||
|
||||
// GroupCreated is emitted when a group was created
|
||||
type GroupCreated struct {
|
||||
Executant *user.UserId
|
||||
GroupID string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (GroupCreated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := GroupCreated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// GroupDeleted is emitted when a group was deleted
|
||||
type GroupDeleted struct {
|
||||
Executant *user.UserId
|
||||
GroupID string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (GroupDeleted) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := GroupDeleted{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// GroupMemberAdded is emitted when a user was added to a group
|
||||
type GroupMemberAdded struct {
|
||||
Executant *user.UserId
|
||||
GroupID string
|
||||
UserID string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (GroupMemberAdded) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := GroupMemberAdded{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// GroupMemberRemoved is emitted when a user was removed from a group
|
||||
type GroupMemberRemoved struct {
|
||||
Executant *user.UserId
|
||||
GroupID string
|
||||
UserID string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (GroupMemberRemoved) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := GroupMemberRemoved{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// GroupFeature represents a group feature
|
||||
type GroupFeature struct {
|
||||
Name string
|
||||
Value string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// GroupFeatureChanged is emitted when a group feature was changed
|
||||
type GroupFeatureChanged struct {
|
||||
Executant *user.UserId
|
||||
GroupID string
|
||||
Features []GroupFeature
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill unmarshaller interface
|
||||
func (GroupFeatureChanged) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := GroupFeatureChanged{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// Copyright 2026 OpenCloud GmbH <mail@opencloud.eu>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
)
|
||||
|
||||
// LabelAdded is emitted when a user adds a label to a resource
|
||||
type LabelAdded struct {
|
||||
Ref *provider.Reference
|
||||
Label string
|
||||
Executant *user.UserId
|
||||
UserID *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (LabelAdded) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := LabelAdded{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// LabelRemoved is emitted when a user removes a label from a resource
|
||||
type LabelRemoved struct {
|
||||
Ref *provider.Reference
|
||||
Label string
|
||||
Executant *user.UserId
|
||||
UserID *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (LabelRemoved) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := LabelRemoved{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
// 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 (
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
events "go-micro.dev/v4/events"
|
||||
)
|
||||
|
||||
// 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: _a0, _a1
|
||||
func (_m *Stream) Consume(_a0 string, _a1 ...events.ConsumeOption) (<-chan events.Event, error) {
|
||||
var tmpRet mock.Arguments
|
||||
if len(_a1) > 0 {
|
||||
tmpRet = _m.Called(_a0, _a1)
|
||||
} else {
|
||||
tmpRet = _m.Called(_a0)
|
||||
}
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Consume")
|
||||
}
|
||||
|
||||
var r0 <-chan events.Event
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string, ...events.ConsumeOption) (<-chan events.Event, error)); ok {
|
||||
return rf(_a0, _a1...)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, ...events.ConsumeOption) <-chan events.Event); ok {
|
||||
r0 = rf(_a0, _a1...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(<-chan events.Event)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string, ...events.ConsumeOption) error); ok {
|
||||
r1 = rf(_a0, _a1...)
|
||||
} 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
|
||||
// - _a0 string
|
||||
// - _a1 ...events.ConsumeOption
|
||||
func (_e *Stream_Expecter) Consume(_a0 interface{}, _a1 ...interface{}) *Stream_Consume_Call {
|
||||
return &Stream_Consume_Call{Call: _e.mock.On("Consume",
|
||||
append([]interface{}{_a0}, _a1...)...)}
|
||||
}
|
||||
|
||||
func (_c *Stream_Consume_Call) Run(run func(_a0 string, _a1 ...events.ConsumeOption)) *Stream_Consume_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]events.ConsumeOption, len(args)-1)
|
||||
for i, a := range args[1:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(events.ConsumeOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(string), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Stream_Consume_Call) Return(_a0 <-chan events.Event, _a1 error) *Stream_Consume_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Stream_Consume_Call) RunAndReturn(run func(string, ...events.ConsumeOption) (<-chan events.Event, error)) *Stream_Consume_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Publish provides a mock function with given fields: _a0, _a1, _a2
|
||||
func (_m *Stream) Publish(_a0 string, _a1 interface{}, _a2 ...events.PublishOption) error {
|
||||
var tmpRet mock.Arguments
|
||||
if len(_a2) > 0 {
|
||||
tmpRet = _m.Called(_a0, _a1, _a2)
|
||||
} else {
|
||||
tmpRet = _m.Called(_a0, _a1)
|
||||
}
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Publish")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, interface{}, ...events.PublishOption) error); ok {
|
||||
r0 = rf(_a0, _a1, _a2...)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Stream_Publish_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Publish'
|
||||
type Stream_Publish_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Publish is a helper method to define mock.On call
|
||||
// - _a0 string
|
||||
// - _a1 interface{}
|
||||
// - _a2 ...events.PublishOption
|
||||
func (_e *Stream_Expecter) Publish(_a0 interface{}, _a1 interface{}, _a2 ...interface{}) *Stream_Publish_Call {
|
||||
return &Stream_Publish_Call{Call: _e.mock.On("Publish",
|
||||
append([]interface{}{_a0, _a1}, _a2...)...)}
|
||||
}
|
||||
|
||||
func (_c *Stream_Publish_Call) Run(run func(_a0 string, _a1 interface{}, _a2 ...events.PublishOption)) *Stream_Publish_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]events.PublishOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(events.PublishOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(string), args[1].(interface{}), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Stream_Publish_Call) Return(_a0 error) *Stream_Publish_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Stream_Publish_Call) RunAndReturn(run func(string, interface{}, ...events.PublishOption) error) *Stream_Publish_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
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// SendEmailsEvent instructs the notification service to send grouped emails
|
||||
type SendEmailsEvent struct {
|
||||
Interval string
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SendEmailsEvent) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := SendEmailsEvent{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// Copyright 2018-2024 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.
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
)
|
||||
|
||||
// OCMCoreShareCreated is emitted when an ocm share is received
|
||||
type OCMCoreShareCreated struct {
|
||||
ShareID string
|
||||
Executant *user.UserId
|
||||
Sharer *user.UserId
|
||||
GranteeUserID *user.UserId
|
||||
ItemID string
|
||||
ResourceName string
|
||||
Permissions *provider.ResourcePermissions
|
||||
CTime *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (OCMCoreShareCreated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := OCMCoreShareCreated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// ConsumeOptions contains all the options which can be provided when consuming events
|
||||
type ConsumeOptions struct {
|
||||
Group string
|
||||
AutoAck bool
|
||||
AckWait time.Duration
|
||||
}
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
// 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.
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
)
|
||||
|
||||
type (
|
||||
// Postprocessingstep are the available postprocessingsteps
|
||||
Postprocessingstep string
|
||||
|
||||
// PostprocessingOutcome defines the result of the postprocessing
|
||||
PostprocessingOutcome string
|
||||
)
|
||||
|
||||
var (
|
||||
// PPStepAntivirus is the step that scans for viruses
|
||||
PPStepAntivirus Postprocessingstep = "virusscan"
|
||||
// PPStepPolicies is the step the step that enforces policies
|
||||
PPStepPolicies Postprocessingstep = "policies"
|
||||
// PPStepDelay is the step that processing. Useful for testing or user annoyment
|
||||
PPStepDelay Postprocessingstep = "delay"
|
||||
// PPStepFinished is the step that signals that postprocessing is finished, but storage provider hasn't acknowledged it yet
|
||||
PPStepFinished Postprocessingstep = "finished"
|
||||
|
||||
// PPOutcomeDelete means that the file and the upload should be deleted
|
||||
PPOutcomeDelete PostprocessingOutcome = "delete"
|
||||
// PPOutcomeAbort means that the upload is cancelled but the bytes are being kept in the upload folder
|
||||
PPOutcomeAbort PostprocessingOutcome = "abort"
|
||||
// PPOutcomeContinue means that the upload is moved to its final destination (eventually being marked with pp results)
|
||||
PPOutcomeContinue PostprocessingOutcome = "continue"
|
||||
// PPOutcomeRetry means that there was a temporary issue and the postprocessing should be retried at a later point in time
|
||||
PPOutcomeRetry PostprocessingOutcome = "retry"
|
||||
)
|
||||
|
||||
// BytesReceived is emitted by the server when it received all bytes of an upload
|
||||
type BytesReceived struct {
|
||||
UploadID string
|
||||
SpaceOwner *user.UserId
|
||||
ExecutingUser *user.User
|
||||
ResourceID *provider.ResourceId
|
||||
Filename string
|
||||
Filesize uint64
|
||||
URL string
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (BytesReceived) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := BytesReceived{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// StartPostprocessingStep can be issued by the server to start a postprocessing step
|
||||
type StartPostprocessingStep struct {
|
||||
UploadID string
|
||||
URL string
|
||||
ExecutingUser *user.User
|
||||
Filename string
|
||||
Filesize uint64
|
||||
Token string // for file retrieval in after upload case
|
||||
ResourceID *provider.ResourceId // for file retrieval in after upload case
|
||||
RevaToken string // for file retrieval in after upload case
|
||||
|
||||
StepToStart Postprocessingstep
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (StartPostprocessingStep) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := StartPostprocessingStep{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// PostprocessingStepFinished can be issued by the server when a postprocessing step is finished
|
||||
type PostprocessingStepFinished struct {
|
||||
UploadID string
|
||||
ExecutingUser *user.User
|
||||
Filename string
|
||||
|
||||
FinishedStep Postprocessingstep // name of the step
|
||||
Result interface{} // result information see VirusscanResult for example
|
||||
Error error // possible error of the step
|
||||
Outcome PostprocessingOutcome // some services may cause postprocessing to stop
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (PostprocessingStepFinished) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := PostprocessingStepFinished{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch e.FinishedStep {
|
||||
case PPStepAntivirus:
|
||||
var res VirusscanResult
|
||||
b, _ := json.Marshal(e.Result)
|
||||
err = json.Unmarshal(b, &res)
|
||||
e.Result = res
|
||||
case PPStepPolicies:
|
||||
// nothing to do, but this makes the linter happy
|
||||
}
|
||||
return e, err
|
||||
}
|
||||
|
||||
// VirusscanResult is the Result of a PostprocessingStepFinished event from the antivirus
|
||||
type VirusscanResult struct {
|
||||
Infected bool
|
||||
Description string
|
||||
Scandate time.Time
|
||||
ResourceID *provider.ResourceId
|
||||
ErrorMsg string // empty when no error
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// PostprocessingFinished is emitted by *some* service which can decide that
|
||||
type PostprocessingFinished struct {
|
||||
UploadID string
|
||||
Filename string
|
||||
SpaceOwner *user.UserId
|
||||
ExecutingUser *user.User
|
||||
Result map[Postprocessingstep]interface{} // it is a map[step]Event
|
||||
Outcome PostprocessingOutcome
|
||||
Timestamp *types.Timestamp
|
||||
ImpersonatingUser *user.User
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (PostprocessingFinished) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := PostprocessingFinished{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// PostprocessingRetry is emitted by *some* service which can decide that
|
||||
type PostprocessingRetry struct {
|
||||
UploadID string
|
||||
Filename string
|
||||
ExecutingUser *user.User
|
||||
Failures int
|
||||
BackoffDuration time.Duration
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (PostprocessingRetry) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := PostprocessingRetry{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// UploadReady is emitted by the storage provider when postprocessing is finished
|
||||
type UploadReady struct {
|
||||
UploadID string
|
||||
Filename string
|
||||
SpaceOwner *user.UserId
|
||||
ExecutingUser *user.User
|
||||
ImpersonatingUser *user.User
|
||||
FileRef *provider.Reference
|
||||
ParentID *provider.ResourceId
|
||||
Timestamp *types.Timestamp
|
||||
Failed bool
|
||||
IsVersion bool
|
||||
// add reference here? We could use it to inform client pp is finished
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (UploadReady) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := UploadReady{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// ResumePostprocessing can be emitted to repair broken postprocessing
|
||||
type ResumePostprocessing struct {
|
||||
UploadID string
|
||||
Step Postprocessingstep
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (ResumePostprocessing) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ResumePostprocessing{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// RestartPostprocessing will be emitted by postprocessing service if it doesn't know about an upload
|
||||
type RestartPostprocessing struct {
|
||||
UploadID string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (RestartPostprocessing) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := RestartPostprocessing{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+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
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
// 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 (
|
||||
jetstream "github.com/nats-io/nats.go/jetstream"
|
||||
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
|
||||
}
|
||||
|
||||
// JetStream provides a mock function with no fields
|
||||
func (_m *Stream) JetStream() jetstream.Stream {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for JetStream")
|
||||
}
|
||||
|
||||
var r0 jetstream.Stream
|
||||
if rf, ok := ret.Get(0).(func() jetstream.Stream); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(jetstream.Stream)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Stream_JetStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'JetStream'
|
||||
type Stream_JetStream_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// JetStream is a helper method to define mock.On call
|
||||
func (_e *Stream_Expecter) JetStream() *Stream_JetStream_Call {
|
||||
return &Stream_JetStream_Call{Call: _e.mock.On("JetStream")}
|
||||
}
|
||||
|
||||
func (_c *Stream_JetStream_Call) Run(run func()) *Stream_JetStream_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Stream_JetStream_Call) Return(_a0 jetstream.Stream) *Stream_JetStream_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Stream_JetStream_Call) RunAndReturn(run func() jetstream.Stream) *Stream_JetStream_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
|
||||
}
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
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)
|
||||
JetStream() jetstream.Stream
|
||||
}
|
||||
|
||||
type RawStream struct {
|
||||
js jetstream.Stream
|
||||
|
||||
c Config
|
||||
}
|
||||
|
||||
func JetStream(ctx context.Context, name string, cfg Config) (jetstream.JetStream, error) {
|
||||
var js jetstream.JetStream
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
js, err = jetstream.New(conn)
|
||||
return err
|
||||
}
|
||||
|
||||
err := backoff.Retry(connect, backoff.NewExponentialBackOff())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not connect to nats jetstream")
|
||||
}
|
||||
return js, nil
|
||||
}
|
||||
|
||||
func FromConfig(ctx context.Context, name string, cfg Config) (Stream, error) {
|
||||
jsConn, err := JetStream(ctx, name, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
js, err := jsConn.Stream(ctx, events.MainQueueName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &RawStream{
|
||||
js: js,
|
||||
c: cfg,
|
||||
}, 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
|
||||
}
|
||||
|
||||
func (s *RawStream) JetStream() jetstream.Stream {
|
||||
return s.js
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
)
|
||||
|
||||
// ScienceMeshInviteTokenGenerated is emitted when a sciencemesh token is generated
|
||||
type ScienceMeshInviteTokenGenerated struct {
|
||||
Sharer *user.UserId
|
||||
RecipientMail string
|
||||
Token string
|
||||
Description string
|
||||
Expiration uint64
|
||||
InviteLink string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill unmarshaller interface
|
||||
func (ScienceMeshInviteTokenGenerated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ScienceMeshInviteTokenGenerated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
// Copyright 2018-2021 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.
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
|
||||
link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
)
|
||||
|
||||
// ShareCreated is emitted when a share is created
|
||||
type ShareCreated struct {
|
||||
ShareID *collaboration.ShareId
|
||||
Executant *user.UserId
|
||||
Sharer *user.UserId
|
||||
// split the protobuf Grantee oneof so we can use stdlib encoding/json
|
||||
GranteeUserID *user.UserId
|
||||
GranteeGroupID *group.GroupId
|
||||
Sharee *provider.Grantee
|
||||
ItemID *provider.ResourceId
|
||||
ResourceName string
|
||||
Permissions *collaboration.SharePermissions
|
||||
CTime *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (ShareCreated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ShareCreated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// ShareRemoved is emitted when a share is removed
|
||||
type ShareRemoved struct {
|
||||
Executant *user.UserId
|
||||
// split protobuf Spec
|
||||
ShareID *collaboration.ShareId
|
||||
ShareKey *collaboration.ShareKey
|
||||
// split the protobuf Grantee oneof so we can use stdlib encoding/json
|
||||
GranteeUserID *user.UserId
|
||||
GranteeGroupID *group.GroupId
|
||||
|
||||
ItemID *provider.ResourceId
|
||||
ResourceName string
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (ShareRemoved) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ShareRemoved{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// ShareUpdated is emitted when a share is updated
|
||||
type ShareUpdated struct {
|
||||
Executant *user.UserId
|
||||
ShareID *collaboration.ShareId
|
||||
ItemID *provider.ResourceId
|
||||
ResourceName string
|
||||
Permissions *collaboration.SharePermissions
|
||||
GranteeUserID *user.UserId
|
||||
GranteeGroupID *group.GroupId
|
||||
Sharer *user.UserId
|
||||
MTime *types.Timestamp
|
||||
|
||||
Updated string // Deprecated
|
||||
// indicates what was updated
|
||||
UpdateMask []string
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (ShareUpdated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ShareUpdated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// ShareExpired is emitted when a share expires
|
||||
type ShareExpired struct {
|
||||
ShareID *collaboration.ShareId
|
||||
ShareOwner *user.UserId
|
||||
ItemID *provider.ResourceId
|
||||
Path string
|
||||
ExpiredAt time.Time
|
||||
// split the protobuf Grantee oneof so we can use stdlib encoding/json
|
||||
GranteeUserID *user.UserId
|
||||
GranteeGroupID *group.GroupId
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (ShareExpired) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ShareExpired{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// ReceivedShareUpdated is emitted when a received share is accepted or declined
|
||||
type ReceivedShareUpdated struct {
|
||||
Executant *user.UserId
|
||||
ShareID *collaboration.ShareId
|
||||
ItemID *provider.ResourceId
|
||||
Path string
|
||||
Permissions *collaboration.SharePermissions
|
||||
GranteeUserID *user.UserId
|
||||
GranteeGroupID *group.GroupId
|
||||
Sharer *user.UserId
|
||||
MTime *types.Timestamp
|
||||
|
||||
State string
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (ReceivedShareUpdated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ReceivedShareUpdated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// LinkCreated is emitted when a public link is created
|
||||
type LinkCreated struct {
|
||||
Executant *user.UserId
|
||||
ShareID *link.PublicShareId
|
||||
Sharer *user.UserId
|
||||
ItemID *provider.ResourceId
|
||||
ResourceName string
|
||||
Permissions *link.PublicSharePermissions
|
||||
DisplayName string
|
||||
Expiration *types.Timestamp
|
||||
PasswordProtected bool
|
||||
CTime *types.Timestamp
|
||||
Token string
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (LinkCreated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := LinkCreated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// LinkUpdated is emitted when a public link is updated
|
||||
type LinkUpdated struct {
|
||||
Executant *user.UserId
|
||||
ShareID *link.PublicShareId
|
||||
Sharer *user.UserId
|
||||
ItemID *provider.ResourceId
|
||||
ResourceName string
|
||||
Permissions *link.PublicSharePermissions
|
||||
DisplayName string
|
||||
Expiration *types.Timestamp
|
||||
PasswordProtected bool
|
||||
MTime *types.Timestamp
|
||||
Token string
|
||||
|
||||
FieldUpdated string
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (LinkUpdated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := LinkUpdated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// LinkAccessed is emitted when a public link is accessed successfully (by token)
|
||||
type LinkAccessed struct {
|
||||
Executant *user.UserId
|
||||
ShareID *link.PublicShareId
|
||||
Sharer *user.UserId
|
||||
ItemID *provider.ResourceId
|
||||
Path string
|
||||
Permissions *link.PublicSharePermissions
|
||||
DisplayName string
|
||||
Expiration *types.Timestamp
|
||||
PasswordProtected bool
|
||||
CTime *types.Timestamp
|
||||
Token string
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (LinkAccessed) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := LinkAccessed{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// LinkAccessFailed is emitted when an access to a public link has resulted in an error (by token)
|
||||
type LinkAccessFailed struct {
|
||||
Executant *user.UserId
|
||||
ShareID *link.PublicShareId
|
||||
Token string
|
||||
Status rpc.Code
|
||||
Message string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (LinkAccessFailed) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := LinkAccessFailed{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// LinkRemoved is emitted when a share is removed
|
||||
type LinkRemoved struct {
|
||||
Executant *user.UserId
|
||||
// split protobuf Ref
|
||||
ShareID *link.PublicShareId
|
||||
ShareToken string
|
||||
Timestamp *types.Timestamp
|
||||
ItemID *provider.ResourceId
|
||||
ResourceName string
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (LinkRemoved) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := LinkRemoved{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
// 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.
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
)
|
||||
|
||||
// SpaceCreated is emitted when a space is created
|
||||
type SpaceCreated struct {
|
||||
Executant *user.UserId
|
||||
ID *provider.StorageSpaceId
|
||||
Owner *user.UserId
|
||||
Root *provider.ResourceId
|
||||
Name string
|
||||
Type string
|
||||
Quota *provider.Quota
|
||||
MTime *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SpaceCreated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := SpaceCreated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// SpaceRenamed is emitted when a space is renamed
|
||||
type SpaceRenamed struct {
|
||||
Executant *user.UserId
|
||||
ID *provider.StorageSpaceId
|
||||
Owner *user.UserId
|
||||
Name string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SpaceRenamed) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := SpaceRenamed{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// SpaceDisabled is emitted when a space is disabled
|
||||
type SpaceDisabled struct {
|
||||
Executant *user.UserId
|
||||
ID *provider.StorageSpaceId
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SpaceDisabled) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := SpaceDisabled{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// SpaceEnabled is emitted when a space is (re-)enabled
|
||||
type SpaceEnabled struct {
|
||||
Executant *user.UserId
|
||||
ID *provider.StorageSpaceId
|
||||
Owner *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SpaceEnabled) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := SpaceEnabled{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// SpaceDeleted is emitted when a space is deleted
|
||||
type SpaceDeleted struct {
|
||||
Executant *user.UserId
|
||||
ID *provider.StorageSpaceId
|
||||
SpaceName string
|
||||
FinalMembers map[string]provider.ResourcePermissions
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SpaceDeleted) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := SpaceDeleted{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// SpaceShared is emitted when a space is shared
|
||||
type SpaceShared struct {
|
||||
Executant *user.UserId
|
||||
GranteeUserID *user.UserId
|
||||
GranteeGroupID *group.GroupId
|
||||
Creator *user.UserId
|
||||
ID *provider.StorageSpaceId
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SpaceShared) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := SpaceShared{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// SpaceShareUpdated is emitted when a space share is updated
|
||||
type SpaceShareUpdated struct {
|
||||
Executant *user.UserId
|
||||
GranteeUserID *user.UserId
|
||||
GranteeGroupID *group.GroupId
|
||||
ID *provider.StorageSpaceId
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SpaceShareUpdated) Unmarshal(v []byte) (interface{}, error) {
|
||||
ev := SpaceShareUpdated{}
|
||||
err := json.Unmarshal(v, &ev)
|
||||
return ev, err
|
||||
}
|
||||
|
||||
// SpaceUnshared is emitted when a space is unshared
|
||||
type SpaceUnshared struct {
|
||||
Executant *user.UserId
|
||||
GranteeUserID *user.UserId
|
||||
GranteeGroupID *group.GroupId
|
||||
ID *provider.StorageSpaceId
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SpaceUnshared) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := SpaceUnshared{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// SpaceUpdated is emitted when a space is updated
|
||||
type SpaceUpdated struct {
|
||||
Executant *user.UserId
|
||||
ID *provider.StorageSpaceId
|
||||
Space *provider.StorageSpace
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SpaceUpdated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := SpaceUpdated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// SpaceMembershipExpired is emitted when a space membership expires
|
||||
type SpaceMembershipExpired struct {
|
||||
SpaceOwner *user.UserId
|
||||
SpaceID *provider.StorageSpaceId
|
||||
SpaceName string
|
||||
ExpiredAt time.Time
|
||||
// split the protobuf Grantee oneof so we can use stdlib encoding/json
|
||||
GranteeUserID *user.UserId
|
||||
GranteeGroupID *group.GroupId
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SpaceMembershipExpired) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := SpaceMembershipExpired{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// SendSSE instructs the sse service to send one or multiple notifications
|
||||
type SendSSE struct {
|
||||
UserIDs []string
|
||||
Type string
|
||||
Message []byte
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (SendSSE) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := SendSSE{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
package stream
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff"
|
||||
"github.com/go-micro/plugins/v4/events/natsjs"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/events"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/events/raw"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/logger"
|
||||
)
|
||||
|
||||
// NatsConfig is the configuration needed for a NATS event stream
|
||||
type NatsConfig 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
|
||||
|
||||
}
|
||||
|
||||
// NatsFromConfig returns a nats stream from the given config
|
||||
func NatsFromConfig(connName string, disableDurability bool, cfg NatsConfig) (events.Stream, 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 nil, err
|
||||
}
|
||||
|
||||
rootCAPool, err = newCertPoolFromPEM(rootCrtFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.TLSInsecure = false
|
||||
}
|
||||
|
||||
tlsConf = &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: cfg.TLSInsecure, //nolint:gosec
|
||||
RootCAs: rootCAPool,
|
||||
}
|
||||
}
|
||||
|
||||
opts := []natsjs.Option{
|
||||
natsjs.TLSConfig(tlsConf),
|
||||
natsjs.Address(cfg.Endpoint),
|
||||
natsjs.ClusterID(cfg.Cluster),
|
||||
natsjs.SynchronousPublish(true),
|
||||
natsjs.Name(connName),
|
||||
natsjs.Authenticate(cfg.AuthUsername, cfg.AuthPassword),
|
||||
}
|
||||
|
||||
if disableDurability {
|
||||
opts = append(opts, natsjs.DisableDurableStreams())
|
||||
}
|
||||
|
||||
s, err := Nats(opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// apply a MaxAge to the main queue to prevent it from filling up
|
||||
ctx := context.Background()
|
||||
jsConn, err := raw.JetStream(ctx, connName, raw.Config{
|
||||
Endpoint: cfg.Endpoint,
|
||||
Cluster: cfg.Cluster,
|
||||
TLSInsecure: cfg.TLSInsecure,
|
||||
TLSRootCACertificate: cfg.TLSRootCACertificate,
|
||||
EnableTLS: cfg.EnableTLS,
|
||||
AuthUsername: cfg.AuthUsername,
|
||||
AuthPassword: cfg.AuthPassword,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
streamCfg := jetstream.StreamConfig{
|
||||
Name: "main-queue",
|
||||
MaxAge: 7 * 24 * time.Hour,
|
||||
}
|
||||
_, err = jsConn.CreateStream(ctx, streamCfg)
|
||||
if err != nil {
|
||||
// If the stream already exists, update its configuration
|
||||
if err == jetstream.ErrStreamNameAlreadyInUse {
|
||||
_, _ = jsConn.UpdateStream(ctx, streamCfg)
|
||||
}
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// nats returns a nats streaming client
|
||||
// retries exponentially to connect to a nats server
|
||||
func Nats(opts ...natsjs.Option) (events.Stream, error) {
|
||||
b := backoff.NewExponentialBackOff()
|
||||
var stream events.Stream
|
||||
o := func() error {
|
||||
n := b.NextBackOff()
|
||||
s, err := natsjs.NewStream(opts...)
|
||||
if err != nil && n > time.Second {
|
||||
logger.New().Error().Err(err).Msgf("can't connect to nats (jetstream) server, retrying in %s", n)
|
||||
}
|
||||
stream = s
|
||||
return err
|
||||
}
|
||||
|
||||
err := backoff.Retry(o, b)
|
||||
return stream, err
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// Package stream provides streaming clients used by `Consume` and `Publish` methods
|
||||
package stream
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
|
||||
"go-micro.dev/v4/events"
|
||||
)
|
||||
|
||||
// Chan is a channel based streaming clients
|
||||
// Useful for tests or in memory applications
|
||||
type Chan [2]chan interface{}
|
||||
|
||||
// Publish implementation
|
||||
func (ch Chan) Publish(_ string, msg interface{}, _ ...events.PublishOption) error {
|
||||
go func() {
|
||||
ch[0] <- msg
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Consume implementation
|
||||
func (ch Chan) Consume(_ string, _ ...events.ConsumeOption) (<-chan events.Event, error) {
|
||||
evch := make(chan events.Event)
|
||||
go func() {
|
||||
for {
|
||||
e := <-ch[1]
|
||||
if e == nil {
|
||||
// channel closed
|
||||
return
|
||||
}
|
||||
b, _ := json.Marshal(e)
|
||||
evname := reflect.TypeOf(e).String()
|
||||
evch <- events.Event{
|
||||
Payload: b,
|
||||
Metadata: map[string]string{"eventtype": evname},
|
||||
}
|
||||
}
|
||||
}()
|
||||
return evch, nil
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// 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.
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
)
|
||||
|
||||
// TagsAdded is emitted when a Tag has been added
|
||||
type TagsAdded struct {
|
||||
SpaceOwner *user.UserId
|
||||
Tags string
|
||||
Ref *provider.Reference
|
||||
Executant *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (TagsAdded) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := TagsAdded{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// TagsRemoved is emitted when a Tag has been added
|
||||
type TagsRemoved struct {
|
||||
SpaceOwner *user.UserId
|
||||
Tags string
|
||||
Ref *provider.Reference
|
||||
Executant *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (TagsRemoved) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := TagsRemoved{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
// 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.
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
)
|
||||
|
||||
// UserCreated is emitted when a user was created
|
||||
type UserCreated struct {
|
||||
Executant *user.UserId
|
||||
UserID string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (UserCreated) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := UserCreated{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// UserDeleted is emitted when a user was deleted
|
||||
type UserDeleted struct {
|
||||
Executant *user.UserId
|
||||
UserID string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (UserDeleted) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := UserDeleted{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// UserSoftDeleted is emitted when a user was soft-deleted
|
||||
type UserSoftDeleted struct {
|
||||
Executant *user.UserId
|
||||
UserID string
|
||||
Timestamp *types.Timestamp
|
||||
RetentionTime time.Duration
|
||||
Reason string
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill unmarshaller interface
|
||||
func (UserSoftDeleted) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := UserSoftDeleted{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// UserFeature represents a user feature
|
||||
type UserFeature struct {
|
||||
Name string
|
||||
Value string
|
||||
OldValue *string
|
||||
}
|
||||
|
||||
// UserFeatureChanged is emitted when a user feature was changed
|
||||
type UserFeatureChanged struct {
|
||||
Executant *user.UserId
|
||||
UserID string
|
||||
Features []UserFeature
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (UserFeatureChanged) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := UserFeatureChanged{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// PersonalDataExtracted is emitted when a user data extraction is finished
|
||||
type PersonalDataExtracted struct {
|
||||
Executant *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
ErrorMsg string
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (PersonalDataExtracted) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := PersonalDataExtracted{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// BackchannelLogout is emitted when the callback from the identity provider is received
|
||||
type BackchannelLogout struct {
|
||||
Executant *user.UserId
|
||||
SessionId string
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (BackchannelLogout) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := BackchannelLogout{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
|
||||
// UserSignedIn is emitted when a user signs in
|
||||
type UserSignedIn struct {
|
||||
Executant *user.UserId
|
||||
Timestamp *types.Timestamp
|
||||
}
|
||||
|
||||
// Unmarshal to fulfill umarshaller interface
|
||||
func (UserSignedIn) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := UserSignedIn{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
Reference in New Issue
Block a user