mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-01 09:52:23 -06:00
get SpaceDisabled event working
Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
@@ -25,36 +25,17 @@ import (
|
||||
|
||||
// all events we care about
|
||||
var _registeredEvents = []events.Unmarshaller{
|
||||
// file related
|
||||
events.UploadReady{},
|
||||
events.ContainerCreated{},
|
||||
events.FileTouched{},
|
||||
events.FileDownloaded{},
|
||||
events.FileVersionRestored{},
|
||||
events.ItemMoved{},
|
||||
events.ItemTrashed{},
|
||||
events.ItemPurged{},
|
||||
events.ItemRestored{},
|
||||
|
||||
// space related
|
||||
events.SpaceCreated{},
|
||||
events.SpaceRenamed{},
|
||||
events.SpaceEnabled{},
|
||||
events.SpaceDisabled{},
|
||||
events.SpaceDeleted{},
|
||||
events.SpaceShared{},
|
||||
events.SpaceUnshared{},
|
||||
events.SpaceUpdated{},
|
||||
events.SpaceMembershipExpired{},
|
||||
|
||||
// share related
|
||||
events.ShareCreated{},
|
||||
// events.ShareRemoved{}, // TODO: ShareRemoved doesn't hold sharee information
|
||||
events.ShareUpdated{},
|
||||
events.ShareRemoved{},
|
||||
events.ShareExpired{},
|
||||
events.LinkCreated{},
|
||||
// events.LinkRemoved{}, // TODO: LinkRemoved doesn't hold sharee information
|
||||
events.LinkUpdated{},
|
||||
}
|
||||
|
||||
// Server is the entrypoint for the server command.
|
||||
|
||||
144
services/userlog/pkg/service/conversion.go
Normal file
144
services/userlog/pkg/service/conversion.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
)
|
||||
|
||||
var (
|
||||
_resourceTypeSpace = "storagespace"
|
||||
)
|
||||
|
||||
// OC10Notification is the oc10 style representation of an event
|
||||
// some fields are left out for simplicity
|
||||
type OC10Notification struct {
|
||||
EventID string `json:"notification_id"`
|
||||
Service string `json:"app"`
|
||||
UserName string `json:"user"`
|
||||
Timestamp string `json:"datetime"`
|
||||
ResourceID string `json:"object_id"`
|
||||
ResourceType string `json:"object_type"`
|
||||
Subject string `json:"subject"`
|
||||
Message string `json:"message"`
|
||||
MessageRaw string `json:"messageRich"`
|
||||
MessageDetails map[string]interface{} `json:"messageRichParameters"`
|
||||
}
|
||||
|
||||
// SpaceDisabled converts a SpaceDisabled event to an OC10Notification
|
||||
func (ul *UserlogService) SpaceDisabled(ctx context.Context, eventid string, ev events.SpaceDisabled) (OC10Notification, error) {
|
||||
user, err := ul.getUser(ctx, ev.Executant)
|
||||
if err != nil {
|
||||
return OC10Notification{}, err
|
||||
}
|
||||
|
||||
space, err := ul.getSpace(ul.impersonate(user.GetId()), ev.ID.GetOpaqueId())
|
||||
if err != nil {
|
||||
return OC10Notification{}, err
|
||||
}
|
||||
|
||||
subj, msg, msgraw, err := ul.composeMessage("space-disabled", map[string]string{
|
||||
"username": user.GetUsername(),
|
||||
"spacename": space.GetName(),
|
||||
})
|
||||
if err != nil {
|
||||
return OC10Notification{}, err
|
||||
}
|
||||
|
||||
return OC10Notification{
|
||||
EventID: eventid,
|
||||
Service: ul.cfg.Service.Name,
|
||||
Timestamp: time.Now().Format(time.RFC3339Nano),
|
||||
Subject: subj,
|
||||
ResourceID: ev.ID.GetOpaqueId(),
|
||||
ResourceType: _resourceTypeSpace,
|
||||
Message: msg,
|
||||
MessageRaw: msgraw,
|
||||
MessageDetails: ul.getMessageDetails(user, space, nil),
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func (ul *UserlogService) composeMessage(eventname string, vars map[string]string) (string, string, string, error) {
|
||||
subjtpl, err := ul.parseTemplate(eventname + "-subj")
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
subject := ul.executeTemplate(subjtpl, vars)
|
||||
|
||||
msgtpl, err := ul.parseTemplate(eventname + "-msg")
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
message := ul.executeTemplate(msgtpl, vars)
|
||||
|
||||
messageraw := ul.executeTemplate(msgtpl, map[string]string{
|
||||
"username": "{user}",
|
||||
"spacename": "{space}",
|
||||
"resource": "{resource}",
|
||||
})
|
||||
|
||||
return subject, message, messageraw, nil
|
||||
|
||||
}
|
||||
|
||||
func (ul *UserlogService) getMessageDetails(user *user.User, space *storageprovider.StorageSpace, item *storageprovider.ResourceInfo) map[string]interface{} {
|
||||
details := make(map[string]interface{})
|
||||
|
||||
if user != nil {
|
||||
details["user"] = map[string]string{
|
||||
"id": user.GetId().GetOpaqueId(),
|
||||
"name": user.GetUsername(),
|
||||
}
|
||||
}
|
||||
|
||||
if space != nil {
|
||||
details["space"] = map[string]string{
|
||||
"id": space.GetId().GetOpaqueId(),
|
||||
"name": space.GetName(),
|
||||
}
|
||||
}
|
||||
|
||||
if item != nil {
|
||||
details["resource"] = map[string]string{
|
||||
"id": storagespace.FormatResourceID(*item.GetId()),
|
||||
"name": item.GetName(),
|
||||
}
|
||||
}
|
||||
|
||||
return details
|
||||
}
|
||||
|
||||
func (ul *UserlogService) parseTemplate(templateName string) (*template.Template, error) {
|
||||
var (
|
||||
tpl *template.Template
|
||||
err error
|
||||
)
|
||||
switch ul.templatePath {
|
||||
case "":
|
||||
tpl, err = template.ParseFS(templatesFS, filepath.Join("templates/", templateName+".tmpl"))
|
||||
default:
|
||||
tpl, err = template.ParseFiles(filepath.Join(ul.templatePath, templateName+".tmpl"))
|
||||
}
|
||||
|
||||
return tpl, err
|
||||
}
|
||||
|
||||
func (ul *UserlogService) executeTemplate(tpl *template.Template, vars map[string]string) string {
|
||||
var writer bytes.Buffer
|
||||
if err := tpl.Execute(&writer, vars); err != nil {
|
||||
ul.log.Error().Err(err).Str("templateName", tpl.Name()).Msg("cannot execute template")
|
||||
return ""
|
||||
}
|
||||
|
||||
return writer.String()
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -14,6 +15,11 @@ import (
|
||||
ehmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/eventhistory/v0"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed templates
|
||||
templatesFS embed.FS
|
||||
)
|
||||
|
||||
// ServeHTTP fulfills Handler interface
|
||||
func (ul *UserlogService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ul.m.ServeHTTP(w, r)
|
||||
@@ -97,119 +103,39 @@ func (ul *UserlogService) convertEvent(ctx context.Context, event *ehmsg.Event)
|
||||
|
||||
// TODO: strange bug with getting space -> fix postponed to make master panic-free
|
||||
var space storageprovider.StorageSpace
|
||||
switch ev := einterface.(type) {
|
||||
// file related
|
||||
case events.UploadReady:
|
||||
noti.UserID = ev.ExecutingUser.GetId().GetOpaqueId()
|
||||
noti.Subject = "File uploaded"
|
||||
noti.Message = fmt.Sprintf("File '%s' was uploaded to space '%s' by user '%s'", ev.Filename, space.GetName(), ev.ExecutingUser.GetUsername())
|
||||
case events.ContainerCreated:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Folder created"
|
||||
noti.Message = fmt.Sprintf("Folder '%s' was created", ev.Ref.GetPath())
|
||||
case events.FileTouched:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "File touched"
|
||||
noti.Message = fmt.Sprintf("File '%s' was touched", ev.Ref.GetPath())
|
||||
case events.FileDownloaded:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "File downloaded"
|
||||
noti.Message = fmt.Sprintf("File '%s' was downloaded", ev.Ref.GetPath())
|
||||
case events.FileVersionRestored:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "File version restored"
|
||||
noti.Message = fmt.Sprintf("An older version of file '%s' was restored", ev.Ref.GetPath())
|
||||
case events.ItemMoved:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "File moved"
|
||||
noti.Message = fmt.Sprintf("File '%s' was moved from '%s'", ev.Ref.GetPath(), ev.OldReference.GetPath())
|
||||
case events.ItemTrashed:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "File trashed"
|
||||
noti.Message = fmt.Sprintf("File '%s' was trashed", ev.Ref.GetPath())
|
||||
case events.ItemPurged:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "File purged"
|
||||
noti.Message = fmt.Sprintf("File '%s' was purged", ev.Ref.GetPath())
|
||||
case events.ItemRestored:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "File restored"
|
||||
noti.Message = fmt.Sprintf("File '%s' was restored", ev.Ref.GetPath())
|
||||
|
||||
switch ev := einterface.(type) {
|
||||
// space related
|
||||
case events.SpaceCreated:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Space created"
|
||||
noti.Message = fmt.Sprintf("Space '%s' was created", ev.Name)
|
||||
case events.SpaceRenamed:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Space renamed"
|
||||
noti.Message = fmt.Sprintf("Space '%s' was renamed", ev.Name)
|
||||
case events.SpaceEnabled:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Space enabled"
|
||||
noti.Message = fmt.Sprintf("Space '%s' was renamed", space.Name)
|
||||
case events.SpaceDisabled:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Space disabled"
|
||||
noti.Message = fmt.Sprintf("Space '%s' was disabled", space.Name)
|
||||
return ul.SpaceDisabled(ctx, event.Id, ev)
|
||||
case events.SpaceDeleted:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Space deleted"
|
||||
noti.Message = fmt.Sprintf("Space '%s' was deleted", space.Name)
|
||||
case events.SpaceShared:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Space shared"
|
||||
noti.Message = fmt.Sprintf("Space '%s' was shared", space.Name)
|
||||
case events.SpaceUnshared:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Space unshared"
|
||||
noti.Message = fmt.Sprintf("Space '%s' was unshared", space.Name)
|
||||
case events.SpaceUpdated:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Space updated"
|
||||
noti.Message = fmt.Sprintf("Space '%s' was updated", space.Name)
|
||||
case events.SpaceMembershipExpired:
|
||||
noti.UserID = ""
|
||||
noti.Subject = "Space membership expired"
|
||||
noti.Message = fmt.Sprintf("A spacemembership for space '%s' has expired", space.Name)
|
||||
|
||||
// share related
|
||||
case events.ShareCreated:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Share received"
|
||||
noti.Message = fmt.Sprintf("A file was shared in space %s", space.Name)
|
||||
case events.ShareUpdated:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Share updated"
|
||||
noti.Message = fmt.Sprintf("A share was updated in space %s", space.Name)
|
||||
case events.ShareExpired:
|
||||
noti.Subject = "Share expired"
|
||||
noti.Message = fmt.Sprintf("A share has expired in space %s", space.Name)
|
||||
case events.LinkCreated:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Share received"
|
||||
noti.Message = fmt.Sprintf("A link was created in space %s", space.Name)
|
||||
case events.LinkUpdated:
|
||||
noti.UserID = ev.Executant.GetOpaqueId()
|
||||
noti.Subject = "Share received"
|
||||
noti.Message = fmt.Sprintf("A link was updated in space %s", space.Name)
|
||||
case events.ShareRemoved:
|
||||
noti.Subject = "Share removed"
|
||||
noti.Message = "share was removed"
|
||||
}
|
||||
|
||||
return noti, nil
|
||||
}
|
||||
|
||||
// OC10Notification is the oc10 style representation of an event
|
||||
// some fields are left out for simplicity
|
||||
type OC10Notification struct {
|
||||
EventID string `json:"notification_id"`
|
||||
Service string `json:"app"`
|
||||
Timestamp string `json:"datetime"`
|
||||
UserID string `json:"user"`
|
||||
Subject string `json:"subject"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// GetEventResponseOC10 is the response from GET events endpoint in oc10 style
|
||||
type GetEventResponseOC10 struct {
|
||||
OCS struct {
|
||||
|
||||
@@ -23,6 +23,7 @@ type Options struct {
|
||||
HistoryClient ehsvc.EventHistoryService
|
||||
GatewayClient gateway.GatewayAPIClient
|
||||
RegisteredEvents []events.Unmarshaller
|
||||
TemplatePath string
|
||||
}
|
||||
|
||||
// Logger configures a logger for the userlog service
|
||||
@@ -80,3 +81,10 @@ func RegisteredEvents(e []events.Unmarshaller) Option {
|
||||
o.RegisteredEvents = e
|
||||
}
|
||||
}
|
||||
|
||||
// TemplatePath registers the events the service should listen to
|
||||
func TemplatePath(tmpl string) Option {
|
||||
return func(o *Options) {
|
||||
o.TemplatePath = tmpl
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ type UserlogService struct {
|
||||
historyClient ehsvc.EventHistoryService
|
||||
gwClient gateway.GatewayAPIClient
|
||||
registeredEvents map[string]events.Unmarshaller
|
||||
templatePath string // for custom notification templates
|
||||
}
|
||||
|
||||
// NewUserlogService returns an EventHistory service
|
||||
@@ -59,6 +60,7 @@ func NewUserlogService(opts ...Option) (*UserlogService, error) {
|
||||
historyClient: o.HistoryClient,
|
||||
gwClient: o.GatewayClient,
|
||||
registeredEvents: make(map[string]events.Unmarshaller),
|
||||
templatePath: o.TemplatePath,
|
||||
}
|
||||
|
||||
for _, e := range o.RegisteredEvents {
|
||||
@@ -85,62 +87,30 @@ func (ul *UserlogService) MemorizeEvents() {
|
||||
users []string
|
||||
err error
|
||||
)
|
||||
|
||||
fmt.Println("RECEIVED", event)
|
||||
switch e := event.Event.(type) {
|
||||
default:
|
||||
err = errors.New("unhandled event")
|
||||
|
||||
// file related
|
||||
case events.UploadReady:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.FileRef.GetResourceId().GetSpaceId(), viewer)
|
||||
case events.ContainerCreated:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), viewer)
|
||||
case events.FileTouched:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), viewer)
|
||||
case events.FileDownloaded:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.Ref.GetResourceId().GetSpaceId(), viewer) // no space owner in event
|
||||
case events.FileVersionRestored:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), editor)
|
||||
case events.ItemMoved:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), viewer)
|
||||
case events.ItemTrashed:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), viewer)
|
||||
case events.ItemPurged:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.Ref.GetResourceId().GetSpaceId(), editor) // no space owner in event
|
||||
case events.ItemRestored:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), viewer)
|
||||
|
||||
// space related // TODO: how to find spaceadmins?
|
||||
case events.SpaceCreated:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), viewer)
|
||||
case events.SpaceRenamed:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), viewer)
|
||||
case events.SpaceEnabled:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), viewer)
|
||||
case events.SpaceDisabled:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), viewer)
|
||||
case events.SpaceDeleted:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
|
||||
case events.SpaceShared:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
|
||||
case events.SpaceUnshared:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
|
||||
case events.SpaceUpdated:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
|
||||
case events.SpaceMembershipExpired:
|
||||
users, err = ul.resolveShare(ul.impersonate(e.SpaceOwner), e.GranteeUserID, e.GranteeGroupID, e.SpaceID.GetOpaqueId())
|
||||
|
||||
// share related
|
||||
case events.ShareCreated:
|
||||
users, err = ul.resolveShare(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID, e.ItemID.GetSpaceId())
|
||||
case events.ShareUpdated:
|
||||
users, err = ul.resolveShare(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID, e.ItemID.GetSpaceId())
|
||||
case events.ShareRemoved:
|
||||
err = errors.New("no grantee in share removed event")
|
||||
case events.ShareExpired:
|
||||
users, err = ul.resolveShare(ul.impersonate(e.ShareOwner), e.GranteeUserID, e.GranteeGroupID, e.ItemID.GetSpaceId())
|
||||
case events.LinkCreated:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ItemID.GetOpaqueId(), editor)
|
||||
case events.LinkUpdated:
|
||||
users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ItemID.GetOpaqueId(), editor)
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -423,6 +393,21 @@ func (ul *UserlogService) resolveShare(ctx context.Context, userid *user.UserId,
|
||||
return append(users, usr...), nil
|
||||
}
|
||||
|
||||
func (ul *UserlogService) getUser(ctx context.Context, userid *user.UserId) (*user.User, error) {
|
||||
getUserResponse, err := ul.gwClient.GetUser(context.Background(), &user.GetUserRequest{
|
||||
UserId: userid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if getUserResponse.Status.Code != rpc.Code_CODE_OK {
|
||||
return nil, fmt.Errorf("error getting user: %s", getUserResponse.Status.Message)
|
||||
}
|
||||
|
||||
return getUserResponse.GetUser(), nil
|
||||
}
|
||||
|
||||
func listStorageSpaceRequest(spaceID string) *storageprovider.ListStorageSpacesRequest {
|
||||
return &storageprovider.ListStorageSpacesRequest{
|
||||
Filters: []*storageprovider.ListStorageSpacesRequest_Filter{
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{{ .username }} disabled Space {{ .spacename }}
|
||||
@@ -0,0 +1 @@
|
||||
Space Disabled
|
||||
Reference in New Issue
Block a user