diff --git a/pkg/models/events.go b/pkg/models/events.go index 40dc1bcb75..222c244120 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -216,7 +216,7 @@ func (n *NamespaceSharedWithTeamEvent) Name() string { type TeamMemberAddedEvent struct { Team *Team Member *user.User - Doer web.Auth + Doer *user.User } // Name defines the name for TeamMemberAddedEvent diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index c685b70e85..81171cf50c 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -43,6 +43,7 @@ func RegisterListeners() { events.RegisterListener((&TaskDeletedEvent{}).Name(), &SendTaskDeletedNotification{}) events.RegisterListener((&ListCreatedEvent{}).Name(), &SendListCreatedNotification{}) events.RegisterListener((&TaskAssigneeCreatedEvent{}).Name(), &SubscribeAssigneeToTask{}) + events.RegisterListener((&TeamMemberAddedEvent{}).Name(), &SendTeamMemberAddedNotification{}) } ////// @@ -377,3 +378,27 @@ func (s *DecreaseTeamCounter) Name() string { func (s *DecreaseTeamCounter) Handle(payload message.Payload) (err error) { return keyvalue.DecrBy(metrics.TeamCountKey, 1) } + +// SendTeamMemberAddedNotification represents a listener +type SendTeamMemberAddedNotification struct { +} + +// Name defines the name for the SendTeamMemberAddedNotification listener +func (s *SendTeamMemberAddedNotification) Name() string { + return "send.team.member.added.notification" +} + +// Handle is executed when the event SendTeamMemberAddedNotification listens on is fired +func (s *SendTeamMemberAddedNotification) Handle(payload message.Payload) (err error) { + event := &TeamMemberAddedEvent{} + err = json.Unmarshal(payload, event) + if err != nil { + return err + } + + return notifications.Notify(event.Member, &TeamMemberAddedNotification{ + Member: event.Member, + Doer: event.Doer, + Team: event.Team, + }) +} diff --git a/pkg/models/notifications.go b/pkg/models/notifications.go index a84db9b0c8..be96c98d05 100644 --- a/pkg/models/notifications.go +++ b/pkg/models/notifications.go @@ -59,7 +59,7 @@ type TaskCommentNotification struct { func (n *TaskCommentNotification) ToMail() *notifications.Mail { mail := notifications.NewMail(). - From(n.Doer.GetName() + " via Vikunja <" + config.MailerFromEmail.GetString() + ">"). + From(n.Doer.GetNameAndFromEmail()). Subject("Re: " + n.Task.Title) lines := bufio.NewScanner(strings.NewReader(n.Comment.Comment)) @@ -132,3 +132,25 @@ func (n *ListCreatedNotification) ToMail() *notifications.Mail { func (n *ListCreatedNotification) ToDB() interface{} { return nil } + +// TeamMemberAddedNotification represents a TeamMemberAddedNotification notification +type TeamMemberAddedNotification struct { + Member *user.User + Doer *user.User + Team *Team +} + +// ToMail returns the mail notification for TeamMemberAddedNotification +func (n *TeamMemberAddedNotification) ToMail() *notifications.Mail { + return notifications.NewMail(). + Subject(n.Doer.GetName()+" added you to the "+n.Team.Name+" team in Vikunja"). + From(n.Doer.GetNameAndFromEmail()). + Greeting("Hi "+n.Member.GetName()+","). + Line(n.Doer.GetName()+" has just added you to the "+n.Team.Name+" team in Vikunja."). + Action("View Team", config.ServiceFrontendurl.GetString()+"teams/"+strconv.FormatInt(n.Team.ID, 10)+"/edit") +} + +// ToDB returns the TeamMemberAddedNotification notification in a format which can be saved in the db +func (n *TeamMemberAddedNotification) ToDB() interface{} { + return nil +} diff --git a/pkg/models/team_members.go b/pkg/models/team_members.go index d6d64094fb..b7806f6987 100644 --- a/pkg/models/team_members.go +++ b/pkg/models/team_members.go @@ -46,11 +46,11 @@ func (tm *TeamMember) Create(s *xorm.Session, a web.Auth) (err error) { } // Check if the user exists - user, err := user2.GetUserByUsername(s, tm.Username) + member, err := user2.GetUserByUsername(s, tm.Username) if err != nil { return } - tm.UserID = user.ID + tm.UserID = member.ID // Check if that user is already part of the team exists, err := s. @@ -69,10 +69,11 @@ func (tm *TeamMember) Create(s *xorm.Session, a web.Auth) (err error) { return err } + doer, _ := user2.GetFromAuth(a) return events.Dispatch(&TeamMemberAddedEvent{ Team: team, - Member: user, - Doer: a, + Member: member, + Doer: doer, }) } diff --git a/pkg/user/user.go b/pkg/user/user.go index 021b5ced2c..5a1364c760 100644 --- a/pkg/user/user.go +++ b/pkg/user/user.go @@ -22,6 +22,8 @@ import ( "reflect" "time" + "code.vikunja.io/api/pkg/config" + "code.vikunja.io/api/pkg/db" "xorm.io/xorm" @@ -116,6 +118,11 @@ func (u *User) GetName() string { return u.Username } +// GetNameAndFromEmail returns the name and email address for a user. Useful to use in notifications. +func (u *User) GetNameAndFromEmail() string { + return u.GetName() + " via Vikunja <" + config.MailerFromEmail.GetString() + ">" +} + // GetFromAuth returns a user object from a web.Auth object and returns an error if the underlying type // is not a user object func GetFromAuth(a web.Auth) (*User, error) {