mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-05-08 04:20:59 -05:00
add email templating
Signed-off-by: Christian Richter <crichter@owncloud.com> Co-authored-by: Jörn Dreyer <jfd@butonic.de>
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
"github.com/cs3org/reva/v2/pkg/events/server"
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/go-micro/plugins/v4/events/natsjs"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
|
||||
"github.com/owncloud/ocis/v2/services/notifications/pkg/channels"
|
||||
@@ -47,7 +48,12 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
svc := service.NewEventsNotifier(evts, channel, logger)
|
||||
gwclient, err := pool.GetGatewayServiceClient(cfg.Notifications.RevaGateway)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Str("addr", cfg.Notifications.RevaGateway).Msg("could not get reva client")
|
||||
}
|
||||
|
||||
svc := service.NewEventsNotifier(evts, channel, logger, gwclient, cfg.Commons.MachineAuthAPIKey)
|
||||
return svc.Run()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package email
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"html/template"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const templatePath string = "../../email/templates"
|
||||
|
||||
// RenderEmailTemplate renders the email template for a new share
|
||||
func RenderEmailTemplate(templateName string, templateVariables map[string]string) (string, error) {
|
||||
content, err := os.ReadFile(filepath.Join(templatePath, templateName))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tpl := template.Must(template.New("").Parse(string(content)))
|
||||
writer := bytes.NewBufferString("")
|
||||
err = tpl.Execute(writer, templateVariables)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return writer.String(), nil
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{{ShareSharer}} has shared {{ShareFolder}} with you.
|
||||
@@ -1,33 +1,47 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/services/notifications/pkg/channels"
|
||||
"github.com/owncloud/ocis/v2/services/notifications/pkg/email"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/protobuf/types/known/fieldmaskpb"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
Run() error
|
||||
}
|
||||
|
||||
func NewEventsNotifier(events <-chan interface{}, channel channels.Channel, logger log.Logger) Service {
|
||||
func NewEventsNotifier(events <-chan interface{}, channel channels.Channel, logger log.Logger, gwClient gateway.GatewayAPIClient, machineAuthAPIKey string) Service {
|
||||
return eventsNotifier{
|
||||
logger: logger,
|
||||
channel: channel,
|
||||
events: events,
|
||||
signals: make(chan os.Signal, 1),
|
||||
logger: logger,
|
||||
channel: channel,
|
||||
events: events,
|
||||
signals: make(chan os.Signal, 1),
|
||||
gwClient: gwClient,
|
||||
machineAuthAPIKey: machineAuthAPIKey,
|
||||
}
|
||||
}
|
||||
|
||||
type eventsNotifier struct {
|
||||
logger log.Logger
|
||||
channel channels.Channel
|
||||
events <-chan interface{}
|
||||
signals chan os.Signal
|
||||
logger log.Logger
|
||||
channel channels.Channel
|
||||
events <-chan interface{}
|
||||
signals chan os.Signal
|
||||
gwClient gateway.GatewayAPIClient
|
||||
machineAuthAPIKey string
|
||||
}
|
||||
|
||||
func (s eventsNotifier) Run() error {
|
||||
@@ -39,20 +53,10 @@ func (s eventsNotifier) Run() error {
|
||||
case evt := <-s.events:
|
||||
go func() {
|
||||
switch e := evt.(type) {
|
||||
case events.SpaceCreated:
|
||||
s.handleSpaceCreated(e)
|
||||
case events.ShareCreated:
|
||||
msg := "You got a share!"
|
||||
var err error
|
||||
if e.GranteeUserID != nil {
|
||||
err = s.channel.SendMessage([]string{e.GranteeUserID.OpaqueId}, msg)
|
||||
} else if e.GranteeGroupID != nil {
|
||||
err = s.channel.SendMessageToGroup(e.GranteeGroupID, msg)
|
||||
}
|
||||
if err != nil {
|
||||
s.logger.Error().
|
||||
Err(err).
|
||||
Str("event", "ShareCreated").
|
||||
Msg("failed to send a message")
|
||||
}
|
||||
s.handleShareCreated(e)
|
||||
}
|
||||
}()
|
||||
case <-s.signals:
|
||||
@@ -62,3 +66,103 @@ func (s eventsNotifier) Run() error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s eventsNotifier) handleSpaceCreated(e events.SpaceCreated) {
|
||||
// TODO: implement me
|
||||
}
|
||||
|
||||
func (s eventsNotifier) handleShareCreated(e events.ShareCreated) {
|
||||
userResponse, err := s.gwClient.GetUser(context.Background(), &userv1beta1.GetUserRequest{
|
||||
UserId: e.Sharer,
|
||||
})
|
||||
if err != nil || userResponse.Status.Code != rpcv1beta1.Code_CODE_OK {
|
||||
s.logger.Error().
|
||||
Err(err).
|
||||
Str("event", "ShareCreated").
|
||||
Msg("Could not get user response from gatway client")
|
||||
return
|
||||
}
|
||||
|
||||
// Get auth context
|
||||
ownerCtx := ctxpkg.ContextSetUser(context.Background(), userResponse.User)
|
||||
authRes, err := s.gwClient.Authenticate(ownerCtx, &gateway.AuthenticateRequest{
|
||||
Type: "machine",
|
||||
ClientId: "userid:" + e.Sharer.OpaqueId,
|
||||
ClientSecret: s.machineAuthAPIKey,
|
||||
})
|
||||
if err != nil || authRes.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
|
||||
s.logger.Error().
|
||||
Err(err).
|
||||
Str("event", "ShareCreated").
|
||||
Msg("Could not impersonate sharer")
|
||||
return
|
||||
}
|
||||
|
||||
if authRes.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
|
||||
s.logger.Error().
|
||||
Err(err).
|
||||
Str("event", "ShareCreated").
|
||||
Msg("could not get authenticated context for user")
|
||||
return
|
||||
}
|
||||
ownerCtx = metadata.AppendToOutgoingContext(ownerCtx, ctxpkg.TokenHeader, authRes.Token)
|
||||
|
||||
resourceID, err := storagespace.ParseID(e.ItemID.OpaqueId)
|
||||
if err != nil {
|
||||
s.logger.Error().
|
||||
Err(err).
|
||||
Str("event", "ShareCreated").
|
||||
Str("itemid", e.ItemID.OpaqueId).
|
||||
Msg("could not parse resourceid from ItemID ")
|
||||
return
|
||||
}
|
||||
// TODO: maybe cache this stat to reduce storage iops
|
||||
md, err := s.gwClient.Stat(ownerCtx, &providerv1beta1.StatRequest{
|
||||
Ref: &providerv1beta1.Reference{
|
||||
ResourceId: &resourceID,
|
||||
},
|
||||
FieldMask: &fieldmaskpb.FieldMask{Paths: []string{"name"}},
|
||||
})
|
||||
|
||||
if err != nil || md.Status.Code != rpcv1beta1.Code_CODE_OK {
|
||||
s.logger.Error().
|
||||
Err(err).
|
||||
Str("event", "ShareCreated").
|
||||
Str("itemid", e.ItemID.OpaqueId).
|
||||
Msg("could not stat resource")
|
||||
return
|
||||
}
|
||||
|
||||
if md.Status.Code != rpcv1beta1.Code_CODE_OK {
|
||||
s.logger.Error().
|
||||
Err(err).
|
||||
Str("event", "ShareCreated").
|
||||
Str("itemid", e.ItemID.OpaqueId).
|
||||
Str("rpc status", md.Status.Code.String()).
|
||||
Msg("could not stat resource")
|
||||
return
|
||||
}
|
||||
|
||||
msg, err := email.RenderEmailTemplate("shareCreated.email.tmpl", map[string]string{
|
||||
"ShareSharer": userResponse.User.DisplayName,
|
||||
"ShareFolder": md.Info.Name,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error().
|
||||
Err(err).
|
||||
Str("event", "ShareCreated").
|
||||
Msg("Could not render E-Mail template for shares")
|
||||
}
|
||||
if e.GranteeUserID != nil {
|
||||
err = s.channel.SendMessage([]string{e.GranteeUserID.OpaqueId}, msg)
|
||||
} else if e.GranteeGroupID != nil {
|
||||
err = s.channel.SendMessageToGroup(e.GranteeGroupID, msg)
|
||||
}
|
||||
if err != nil {
|
||||
s.logger.Error().
|
||||
Err(err).
|
||||
Str("event", "ShareCreated").
|
||||
Msg("failed to send a message")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user