@@ -214,6 +214,7 @@ require (
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.15.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.1.0 // indirect
|
||||
github.com/leonelquinteros/gotext v1.5.2 // indirect
|
||||
github.com/libregraph/oidc-go v1.0.0 // indirect
|
||||
github.com/longsleep/go-metrics v1.0.0 // indirect
|
||||
github.com/longsleep/rndm v1.2.0 // indirect
|
||||
@@ -293,5 +294,3 @@ require (
|
||||
)
|
||||
|
||||
replace github.com/cs3org/go-cs3apis => github.com/c0rby/go-cs3apis v0.0.0-20230110100311-5b424f1baa35
|
||||
|
||||
replace github.com/cs3org/reva/v2 => github.com/kobergj/reva/v2 v2.0.0-20230306133911-885670aab8df
|
||||
|
||||
@@ -886,6 +886,8 @@ github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c
|
||||
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leonelquinteros/gotext v1.5.2 h1:T2y6ebHli+rMBCjcJlHTXyUrgXqsKBhl/ormgvt7lPo=
|
||||
github.com/leonelquinteros/gotext v1.5.2/go.mod h1:AT4NpQrOmyj1L/+hLja6aR0lk81yYYL4ePnj2kp7d6M=
|
||||
github.com/libregraph/idm v0.4.1-0.20230221143410-3503963047a5 h1:brLMXSjWoWhGXs8LpK+Lx+FQCtGLUa51Mq/ggHv9AV0=
|
||||
github.com/libregraph/idm v0.4.1-0.20230221143410-3503963047a5/go.mod h1:Tnm4pyVJTEbHm3GUNmceWT1DHzdrYqrJmZyt/xh7L+A=
|
||||
github.com/libregraph/lico v0.59.4 h1:aQNwWAtC3hyQeZpP+5U1M7PIrPtvHanRWRfMp33wbUQ=
|
||||
|
||||
@@ -12,12 +12,16 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
ehmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/eventhistory/v0"
|
||||
)
|
||||
|
||||
var (
|
||||
_resourceTypeSpace = "storagespace"
|
||||
_resourceTypeShare = "share"
|
||||
|
||||
// TODO: from config
|
||||
_pathToLocales = "/home/jkoberg/ocis/services/userlog/pkg/service/locales"
|
||||
)
|
||||
|
||||
// OC10Notification is the oc10 style representation of an event
|
||||
@@ -37,7 +41,7 @@ type OC10Notification struct {
|
||||
}
|
||||
|
||||
// ConvertEvent converts an eventhistory event to an OC10Notification
|
||||
func (ul *UserlogService) ConvertEvent(event *ehmsg.Event) (OC10Notification, error) {
|
||||
func (ul *UserlogService) ConvertEvent(event *ehmsg.Event, locale string) (OC10Notification, error) {
|
||||
etype, ok := ul.registeredEvents[event.Type]
|
||||
if !ok {
|
||||
// this should not happen
|
||||
@@ -55,33 +59,33 @@ func (ul *UserlogService) ConvertEvent(event *ehmsg.Event) (OC10Notification, er
|
||||
return OC10Notification{}, errors.New("unknown event type")
|
||||
// space related
|
||||
case events.SpaceDisabled:
|
||||
return ul.spaceMessage(event.Id, SpaceDisabled, ev.Executant, ev.ID.GetOpaqueId(), ev.Timestamp)
|
||||
return ul.spaceMessage(event.Id, SpaceDisabled, ev.Executant, ev.ID.GetOpaqueId(), ev.Timestamp, locale)
|
||||
case events.SpaceDeleted:
|
||||
return ul.spaceDeletedMessage(event.Id, ev.Executant, ev.ID.GetOpaqueId(), ev.SpaceName, ev.Timestamp)
|
||||
return ul.spaceDeletedMessage(event.Id, ev.Executant, ev.ID.GetOpaqueId(), ev.SpaceName, ev.Timestamp, locale)
|
||||
case events.SpaceShared:
|
||||
return ul.spaceMessage(event.Id, SpaceShared, ev.Executant, ev.ID.GetOpaqueId(), ev.Timestamp)
|
||||
return ul.spaceMessage(event.Id, SpaceShared, ev.Executant, ev.ID.GetOpaqueId(), ev.Timestamp, locale)
|
||||
case events.SpaceUnshared:
|
||||
return ul.spaceMessage(event.Id, SpaceUnshared, ev.Executant, ev.ID.GetOpaqueId(), ev.Timestamp)
|
||||
return ul.spaceMessage(event.Id, SpaceUnshared, ev.Executant, ev.ID.GetOpaqueId(), ev.Timestamp, locale)
|
||||
case events.SpaceMembershipExpired:
|
||||
return ul.spaceMessage(event.Id, SpaceMembershipExpired, ev.SpaceOwner, ev.SpaceID.GetOpaqueId(), ev.ExpiredAt)
|
||||
return ul.spaceMessage(event.Id, SpaceMembershipExpired, ev.SpaceOwner, ev.SpaceID.GetOpaqueId(), ev.ExpiredAt, locale)
|
||||
|
||||
// share related
|
||||
case events.ShareCreated:
|
||||
return ul.shareMessage(event.Id, ShareCreated, ev.Executant, ev.ItemID, ev.ShareID, utils.TSToTime(ev.CTime))
|
||||
return ul.shareMessage(event.Id, ShareCreated, ev.Executant, ev.ItemID, ev.ShareID, utils.TSToTime(ev.CTime), locale)
|
||||
case events.ShareExpired:
|
||||
return ul.shareMessage(event.Id, ShareExpired, ev.ShareOwner, ev.ItemID, ev.ShareID, ev.ExpiredAt)
|
||||
return ul.shareMessage(event.Id, ShareExpired, ev.ShareOwner, ev.ItemID, ev.ShareID, ev.ExpiredAt, locale)
|
||||
case events.ShareRemoved:
|
||||
return ul.shareMessage(event.Id, ShareRemoved, ev.Executant, ev.ItemID, ev.ShareID, ev.Timestamp)
|
||||
return ul.shareMessage(event.Id, ShareRemoved, ev.Executant, ev.ItemID, ev.ShareID, ev.Timestamp, locale)
|
||||
}
|
||||
}
|
||||
|
||||
func (ul *UserlogService) spaceDeletedMessage(eventid string, executant *user.UserId, spaceid string, spacename string, ts time.Time) (OC10Notification, error) {
|
||||
func (ul *UserlogService) spaceDeletedMessage(eventid string, executant *user.UserId, spaceid string, spacename string, ts time.Time, locale string) (OC10Notification, error) {
|
||||
_, user, err := utils.Impersonate(executant, ul.gwClient, ul.cfg.MachineAuthAPIKey)
|
||||
if err != nil {
|
||||
return OC10Notification{}, err
|
||||
}
|
||||
|
||||
subj, subjraw, msg, msgraw, err := ul.composeMessage(SpaceDeleted, map[string]string{
|
||||
subj, subjraw, msg, msgraw, err := ul.composeMessage(SpaceDeleted, locale, map[string]interface{}{
|
||||
"username": user.GetDisplayName(),
|
||||
"spacename": spacename,
|
||||
})
|
||||
@@ -110,7 +114,7 @@ func (ul *UserlogService) spaceDeletedMessage(eventid string, executant *user.Us
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ul *UserlogService) spaceMessage(eventid string, eventname string, executant *user.UserId, spaceid string, ts time.Time) (OC10Notification, error) {
|
||||
func (ul *UserlogService) spaceMessage(eventid string, nt NotificationTemplate, executant *user.UserId, spaceid string, ts time.Time, locale string) (OC10Notification, error) {
|
||||
ctx, user, err := utils.Impersonate(executant, ul.gwClient, ul.cfg.MachineAuthAPIKey)
|
||||
if err != nil {
|
||||
return OC10Notification{}, err
|
||||
@@ -121,7 +125,7 @@ func (ul *UserlogService) spaceMessage(eventid string, eventname string, executa
|
||||
return OC10Notification{}, err
|
||||
}
|
||||
|
||||
subj, subjraw, msg, msgraw, err := ul.composeMessage(eventname, map[string]string{
|
||||
subj, subjraw, msg, msgraw, err := ul.composeMessage(nt, locale, map[string]interface{}{
|
||||
"username": user.GetDisplayName(),
|
||||
"spacename": space.GetName(),
|
||||
})
|
||||
@@ -144,7 +148,7 @@ func (ul *UserlogService) spaceMessage(eventid string, eventname string, executa
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ul *UserlogService) shareMessage(eventid string, eventname string, executant *user.UserId, resourceid *storageprovider.ResourceId, shareid *collaboration.ShareId, ts time.Time) (OC10Notification, error) {
|
||||
func (ul *UserlogService) shareMessage(eventid string, nt NotificationTemplate, executant *user.UserId, resourceid *storageprovider.ResourceId, shareid *collaboration.ShareId, ts time.Time, locale string) (OC10Notification, error) {
|
||||
ctx, user, err := utils.Impersonate(executant, ul.gwClient, ul.cfg.MachineAuthAPIKey)
|
||||
if err != nil {
|
||||
return OC10Notification{}, err
|
||||
@@ -155,7 +159,7 @@ func (ul *UserlogService) shareMessage(eventid string, eventname string, executa
|
||||
return OC10Notification{}, err
|
||||
}
|
||||
|
||||
subj, subjraw, msg, msgraw, err := ul.composeMessage(eventname, map[string]string{
|
||||
subj, subjraw, msg, msgraw, err := ul.composeMessage(nt, locale, map[string]interface{}{
|
||||
"username": user.GetDisplayName(),
|
||||
"resourcename": info.GetName(),
|
||||
})
|
||||
@@ -178,23 +182,23 @@ func (ul *UserlogService) shareMessage(eventid string, eventname string, executa
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ul *UserlogService) composeMessage(eventname string, vars map[string]string) (string, string, string, string, error) {
|
||||
tpl, ok := _templates[eventname]
|
||||
if !ok {
|
||||
return "", "", "", "", errors.New("unknown template name")
|
||||
func (ul *UserlogService) composeMessage(nt NotificationTemplate, locale string, vars map[string]interface{}) (string, string, string, string, error) {
|
||||
subj, msg, err := ul.parseTemplate(nt, locale)
|
||||
if err != nil {
|
||||
return "", "", "", "", err
|
||||
}
|
||||
|
||||
subject := ul.executeTemplate(tpl.Subject, vars)
|
||||
subject := ul.executeTemplate(subj, vars)
|
||||
|
||||
subjectraw := ul.executeTemplate(tpl.Subject, map[string]string{
|
||||
subjectraw := ul.executeTemplate(subj, map[string]interface{}{
|
||||
"username": "{user}",
|
||||
"spacename": "{space}",
|
||||
"resourcename": "{resource}",
|
||||
})
|
||||
|
||||
message := ul.executeTemplate(tpl.Message, vars)
|
||||
message := ul.executeTemplate(msg, vars)
|
||||
|
||||
messageraw := ul.executeTemplate(tpl.Message, map[string]string{
|
||||
messageraw := ul.executeTemplate(msg, map[string]interface{}{
|
||||
"username": "{user}",
|
||||
"spacename": "{space}",
|
||||
"resourcename": "{resource}",
|
||||
@@ -238,7 +242,22 @@ func (ul *UserlogService) getDetails(user *user.User, space *storageprovider.Sto
|
||||
return details
|
||||
}
|
||||
|
||||
func (ul *UserlogService) executeTemplate(tpl *template.Template, vars map[string]string) string {
|
||||
func (ul *UserlogService) parseTemplate(nt NotificationTemplate, locale string) (*template.Template, *template.Template, error) {
|
||||
// Create Locale with library path and language code and load domain '.../default.po'
|
||||
l := gotext.NewLocale(_pathToLocales, locale)
|
||||
l.AddDomain("default")
|
||||
|
||||
subject, err := template.New("").Parse(l.Get(nt.Subject))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
message, err := template.New("").Parse(l.Get(nt.Message))
|
||||
return subject, message, err
|
||||
|
||||
}
|
||||
|
||||
func (ul *UserlogService) executeTemplate(tpl *template.Template, vars map[string]interface{}) 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")
|
||||
|
||||
@@ -28,9 +28,11 @@ func (ul *UserlogService) HandleGetEvents(w http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
|
||||
locale := r.Header.Get("Prefered-Language")
|
||||
|
||||
resp := GetEventResponseOC10{}
|
||||
for _, e := range evs {
|
||||
noti, err := ul.ConvertEvent(e)
|
||||
noti, err := ul.ConvertEvent(e, locale)
|
||||
if err != nil {
|
||||
ul.log.Error().Err(err).Str("eventid", e.Id).Str("eventtype", e.Type).Msg("failed to convert event")
|
||||
continue
|
||||
|
||||
@@ -1,65 +1,50 @@
|
||||
package service
|
||||
|
||||
import "text/template"
|
||||
|
||||
// the available templates
|
||||
var (
|
||||
SpaceShared = "space-shared"
|
||||
SpaceSharedSubject = "Space shared"
|
||||
SpaceSharedMessage = "{{ .username }} added you to Space {{ .spacename }}"
|
||||
SpaceShared = NotificationTemplate{
|
||||
Subject: "Space shared",
|
||||
Message: "{{ .username }} added you to Space {{ .spacename }}",
|
||||
}
|
||||
|
||||
SpaceUnshared = "space-unshared"
|
||||
SpaceUnsharedSubject = "Removed from Space"
|
||||
SpaceUnsharedMessage = "{{ .username }} removed you from Space {{ .spacename }}"
|
||||
SpaceUnshared = NotificationTemplate{
|
||||
Subject: "Removed from Space",
|
||||
Message: "{{ .username }} removed you from Space {{ .spacename }}",
|
||||
}
|
||||
|
||||
SpaceDisabled = "space-disabled"
|
||||
SpaceDisabledSubject = "Space disabled"
|
||||
SpaceDisabledMessage = "{{ .username }} disabled Space {{ .spacename }}"
|
||||
SpaceDisabled = NotificationTemplate{
|
||||
Subject: "Space disabled",
|
||||
Message: "{{ .username }} disabled Space {{ .spacename }}",
|
||||
}
|
||||
|
||||
SpaceDeleted = "space-deleted"
|
||||
SpaceDeletedSubject = "Space deleted"
|
||||
SpaceDeletedMessage = "{{ .username }} deleted Space {{ .spacename }}"
|
||||
SpaceDeleted = NotificationTemplate{
|
||||
Subject: "Space deleted",
|
||||
Message: "{{ .username }} deleted Space {{ .spacename }}",
|
||||
}
|
||||
|
||||
SpaceMembershipExpired = "space-membership-expired"
|
||||
SpaceMembershipExpiredSubject = "Membership expired"
|
||||
SpaceMembershipExpiredMessage = "Access to Space {{ .spacename }} lost"
|
||||
SpaceMembershipExpired = NotificationTemplate{
|
||||
Subject: "Membership expired",
|
||||
Message: "Access to Space {{ .spacename }} lost",
|
||||
}
|
||||
|
||||
ShareCreated = "item-shared"
|
||||
ShareCreatedSubject = "Resource shared"
|
||||
ShareCreatedMessage = "{{ .username }} shared {{ .resourcename }} with you"
|
||||
ShareCreated = NotificationTemplate{
|
||||
Subject: "Resource shared",
|
||||
Message: "{{ .username }} shared {{ .resourcename }} with you",
|
||||
}
|
||||
|
||||
ShareRemoved = "item-unshared"
|
||||
ShareRemovedSubject = "Resource unshared"
|
||||
ShareRemovedMessage = "{{ .username }} unshared {{ .resourcename }} with you"
|
||||
ShareRemoved = NotificationTemplate{
|
||||
Subject: "Resource unshared",
|
||||
Message: "{{ .username }} unshared {{ .resourcename }} with you",
|
||||
}
|
||||
|
||||
ShareExpired = "share-expired"
|
||||
ShareExpiredSubject = "Share expired"
|
||||
ShareExpiredMessage = "Access to {{ .resourcename }} expired"
|
||||
)
|
||||
|
||||
// rendered templates
|
||||
var (
|
||||
_templates = map[string]NotificationTemplate{
|
||||
SpaceShared: notiTmpl(SpaceSharedSubject, SpaceSharedMessage),
|
||||
SpaceUnshared: notiTmpl(SpaceUnsharedSubject, SpaceUnsharedMessage),
|
||||
SpaceDisabled: notiTmpl(SpaceDisabledSubject, SpaceDisabledMessage),
|
||||
SpaceDeleted: notiTmpl(SpaceDeletedSubject, SpaceDeletedMessage),
|
||||
SpaceMembershipExpired: notiTmpl(SpaceMembershipExpiredSubject, SpaceMembershipExpiredMessage),
|
||||
ShareCreated: notiTmpl(ShareCreatedSubject, ShareCreatedMessage),
|
||||
ShareRemoved: notiTmpl(ShareRemovedSubject, ShareRemovedMessage),
|
||||
ShareExpired: notiTmpl(ShareExpiredSubject, ShareExpiredMessage),
|
||||
ShareExpired = NotificationTemplate{
|
||||
Subject: "Share expired",
|
||||
Message: "Access to {{ .resourcename }} expired",
|
||||
}
|
||||
)
|
||||
|
||||
// NotificationTemplate is the data structure for the notifications
|
||||
type NotificationTemplate struct {
|
||||
Subject *template.Template
|
||||
Message *template.Template
|
||||
}
|
||||
|
||||
func notiTmpl(subjectname string, messagename string) NotificationTemplate {
|
||||
return NotificationTemplate{
|
||||
Subject: template.Must(template.New("").Parse(subjectname)),
|
||||
Message: template.Must(template.New("").Parse(messagename)),
|
||||
}
|
||||
Subject string
|
||||
Message string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user