Skip to content

Commit

Permalink
translate templates
Browse files Browse the repository at this point in the history
Signed-off-by: jkoberg <[email protected]>
  • Loading branch information
kobergj committed Mar 7, 2023
1 parent 28ee5a2 commit 694abde
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 73 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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/longsleep/go-metrics v1.0.0 // indirect
github.com/longsleep/rndm v1.2.0 // indirect
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,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.54.1-0.20220325072321-31efc3995d63 h1:oPqyRePmq+59YF1tAur7WXuM/z/epRd+HGGyPPx2Vv8=
Expand Down
67 changes: 43 additions & 24 deletions services/userlog/pkg/service/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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,
})
Expand Down Expand Up @@ -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
Expand All @@ -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(),
})
Expand All @@ -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
Expand All @@ -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(),
})
Expand All @@ -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}",
Expand Down Expand Up @@ -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")
Expand Down
4 changes: 3 additions & 1 deletion services/userlog/pkg/service/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
81 changes: 33 additions & 48 deletions services/userlog/pkg/service/templates.go
Original file line number Diff line number Diff line change
@@ -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 }}"

SpaceUnshared = "space-unshared"
SpaceUnsharedSubject = "Removed from Space"
SpaceUnsharedMessage = "{{ .username }} removed you from Space {{ .spacename }}"
SpaceShared = NotificationTemplate{
Subject: "Space shared",
Message: "{{ .username }} added you to Space {{ .spacename }}",
}

SpaceDisabled = "space-disabled"
SpaceDisabledSubject = "Space disabled"
SpaceDisabledMessage = "{{ .username }} disabled Space {{ .spacename }}"
SpaceUnshared = NotificationTemplate{
Subject: "Removed from Space",
Message: "{{ .username }} removed you from Space {{ .spacename }}",
}

SpaceDeleted = "space-deleted"
SpaceDeletedSubject = "Space deleted"
SpaceDeletedMessage = "{{ .username }} deleted Space {{ .spacename }}"
SpaceDisabled = NotificationTemplate{
Subject: "Space disabled",
Message: "{{ .username }} disabled Space {{ .spacename }}",
}

SpaceMembershipExpired = "space-membership-expired"
SpaceMembershipExpiredSubject = "Membership expired"
SpaceMembershipExpiredMessage = "Access to Space {{ .spacename }} lost"
SpaceDeleted = NotificationTemplate{
Subject: "Space deleted",
Message: "{{ .username }} deleted Space {{ .spacename }}",
}

ShareCreated = "item-shared"
ShareCreatedSubject = "Resource shared"
ShareCreatedMessage = "{{ .username }} shared {{ .resourcename }} with you"
SpaceMembershipExpired = NotificationTemplate{
Subject: "Membership expired",
Message: "Access to Space {{ .spacename }} lost",
}

ShareRemoved = "item-unshared"
ShareRemovedSubject = "Resource unshared"
ShareRemovedMessage = "{{ .username }} unshared {{ .resourcename }} with you"
ShareCreated = NotificationTemplate{
Subject: "Resource shared",
Message: "{{ .username }} shared {{ .resourcename }} with you",
}

ShareExpired = "share-expired"
ShareExpiredSubject = "Share expired"
ShareExpiredMessage = "Access to {{ .resourcename }} expired"
)
ShareRemoved = NotificationTemplate{
Subject: "Resource unshared",
Message: "{{ .username }} unshared {{ .resourcename }} with you",
}

// 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
}

0 comments on commit 694abde

Please sign in to comment.