From 9fecf96d3bf49e7c10cff58f656eabf829c83167 Mon Sep 17 00:00:00 2001 From: Corey Hulen Date: Thu, 28 Apr 2016 06:53:30 -0700 Subject: PLT-2687 sending email on upgrade and moving profile pic to new location (#2808) * Fixing CLI and adding unit tests * Adding the upgrade_db_30 to the help text * Adding the upgrade_db_30 to the help text * Adding the upgrade_db_30 to the help text * Fixing CLI tests * PLT-2687 sending email on upgrade and moving profile pic to new location * Fixing img move * Fixing moving of profile image * making upgrade email localizable * Fixing email template --- api/file.go | 7 ++++- api/post.go | 2 +- i18n/en.json | 8 ++++++ mattermost.go | 63 ++++++++++++++++++++++++++++++++++++++---- templates/email_footer.html | 3 -- templates/upgrade_30_body.html | 37 +++++++++++++++++++++++++ utils/html.go | 13 +++++++-- 7 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 templates/upgrade_30_body.html diff --git a/api/file.go b/api/file.go index c51a4a046..82fcefc7b 100644 --- a/api/file.go +++ b/api/file.go @@ -553,7 +553,7 @@ func WriteFile(f []byte, path string) *model.AppError { return nil } -func moveFile(oldPath, newPath string) *model.AppError { +func MoveFile(oldPath, newPath string) *model.AppError { if utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { fileData := make(chan []byte) getFileAndForget(oldPath, fileData) @@ -578,6 +578,11 @@ func moveFile(oldPath, newPath string) *model.AppError { return err } } else if utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_LOCAL { + + if err := os.MkdirAll(filepath.Dir(utils.Cfg.FileSettings.Directory+newPath), 0774); err != nil { + return model.NewLocAppError("moveFile", "api.file.move_file.rename.app_error", nil, err.Error()) + } + if err := os.Rename(utils.Cfg.FileSettings.Directory+oldPath, utils.Cfg.FileSettings.Directory+newPath); err != nil { return model.NewLocAppError("moveFile", "api.file.move_file.rename.app_error", nil, err.Error()) } diff --git a/api/post.go b/api/post.go index 7899145a6..c533ad656 100644 --- a/api/post.go +++ b/api/post.go @@ -1211,7 +1211,7 @@ func DeletePostFilesAndForget(teamId string, post *model.Post) { splitUrl := strings.Split(filename, "/") oldPath := prefix + splitUrl[len(splitUrl)-2] + "/" + splitUrl[len(splitUrl)-1] newPath := prefix + splitUrl[len(splitUrl)-2] + "/deleted_" + splitUrl[len(splitUrl)-1] - moveFile(oldPath, newPath) + MoveFile(oldPath, newPath) } }() diff --git a/i18n/en.json b/i18n/en.json index 990db5277..4b67d8c78 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1311,6 +1311,14 @@ "id": "api.templates.signup_team_subject", "translation": "{{ .SiteName }} Team Setup" }, + { + "id": "api.templates.upgrade_30_subject.info", + "translation": "[MATTERMOST] Changes to your account for Mattermost 3.0 Upgrade" + }, + { + "id": "api.templates.upgrade_30_body.info", + "translation": "

YOUR DUPLICATE ACCOUNTS HAVE BEEN UPDATED

Your Mattermost server is being upgraded to Version 3.0, which lets you use a single account across multiple teams.

You are receiving this email because the upgrade process has detected your account had the same email or username as other accounts on the server.

The following updates have been made:

{{if .EmailChanged }}- The duplicate email of an account on the `/{{.TeamName}}` team was changed to `{{.Email}}`. If you use email and password to login, you can use this new email address for login.

{{end}}{{if .UsernameChanged }}- The duplicate username of an account on the team site `/{{.TeamName}}` has been changed to `{{.Username}}` to avoid confusion with other accounts.

{{end}} RECOMMENDED ACTION:

It is recommended that you login to your teams used by your duplicate accounts and add your primary account to the team and any public channels and private groups which you wish to continue using.

This gives your primary account access to all public channel and private group history. You can continue to access the direct message history of your duplicate accounts by logging in with their credentials.

FOR MORE INFORMATION:

For more information on the upgrade to Mattermost 3.0 please see: http://www.mattermost.org/upgrading-to-mattermost-3-0/

" + }, { "id": "api.templates.singin_change_email.body.info", "translation": "You updated your sign-in method for on {{ .SiteName }} to {{.Method}}.
If this change wasn't initiated by you, please contact your system administrator." diff --git a/mattermost.go b/mattermost.go index a11e79a9f..647899b58 100644 --- a/mattermost.go +++ b/mattermost.go @@ -6,6 +6,7 @@ package main import ( "flag" "fmt" + "html/template" "io/ioutil" "net/http" "net/url" @@ -297,6 +298,7 @@ func cmdUpdateDb30() { api.Srv = &api.Server{} api.Srv.Store = store.NewSqlStoreForUpgrade30() store := api.Srv.Store.(*store.SqlStore) + utils.InitHTML() l4g.Info("Attempting to run speical upgrade of the database schema to version 3.0 for user model changes") time.Sleep(time.Second) @@ -359,14 +361,14 @@ func cmdUpdateDb30() { uniqueEmails := make(map[string]bool) uniqueUsernames := make(map[string]bool) - primaryUsers := convertTeamTo30(team, uniqueEmails, uniqueUsernames) + primaryUsers := convertTeamTo30(team.Name, team, uniqueEmails, uniqueUsernames) l4g.Info("Upgraded %v users", len(primaryUsers)) for _, otherTeam := range teams { if otherTeam.Id != team.Id { l4g.Info("Upgrading team %v", otherTeam.Name) - users := convertTeamTo30(otherTeam, uniqueEmails, uniqueUsernames) + users := convertTeamTo30(team.Name, otherTeam, uniqueEmails, uniqueUsernames) l4g.Info("Upgraded %v users", len(users)) } @@ -436,7 +438,7 @@ type UserForUpgrade struct { TeamId string } -func convertTeamTo30(team *TeamForUpgrade, uniqueEmails map[string]bool, uniqueUsernames map[string]bool) []*UserForUpgrade { +func convertTeamTo30(primaryTeamName string, team *TeamForUpgrade, uniqueEmails map[string]bool, uniqueUsernames map[string]bool) []*UserForUpgrade { store := api.Srv.Store.(*store.SqlStore) var users []*UserForUpgrade if _, err := store.GetMaster().Select(&users, "SELECT Users.Id, Users.Username, Users.Email, Users.Roles, Users.TeamId FROM Users WHERE Users.TeamId = :TeamId", map[string]interface{}{"TeamId": team.Id}); err != nil { @@ -484,6 +486,15 @@ func convertTeamTo30(team *TeamForUpgrade, uniqueEmails map[string]bool, uniqueU } } + err := api.MoveFile( + "teams/"+team.Id+"/users/"+user.Id+"/profile.png", + "users/"+user.Id+"/profile.png", + ) + + if err != nil { + l4g.Warn("No profile image to move for %v", user.Email) + } + if uniqueEmails[user.Email] { shouldUpdateUser = true emailParts := strings.Split(user.Email, "@") @@ -492,11 +503,19 @@ func convertTeamTo30(team *TeamForUpgrade, uniqueEmails map[string]bool, uniqueU } else { user.Email = user.Email + "." + team.Name } + + if len(user.Email) > 127 { + user.Email = user.Email[:127] + } } if uniqueUsernames[user.Username] { shouldUpdateUser = true - user.Username = user.Username + "." + team.Name + user.Username = team.Name + "." + user.Username + + if len(user.Username) > 63 { + user.Username = user.Username[:63] + } } if shouldUpdateUser { @@ -521,6 +540,40 @@ func convertTeamTo30(team *TeamForUpgrade, uniqueEmails map[string]bool, uniqueU } l4g.Info("modified user_id=%v, changed email from=%v to=%v, changed username from=%v to %v changed roles from=%v to=%v", user.Id, previousEmail, user.Email, previousUsername, user.Username, previousRole, user.Roles) + + emailChanged := previousEmail != user.Email + usernameChanged := previousUsername != user.Username + + if emailChanged || usernameChanged { + bodyPage := utils.NewHTMLTemplate("upgrade_30_body", "") + + EmailChanged := "" + UsernameChanged := "" + + if emailChanged { + EmailChanged = "true" + } + + if usernameChanged { + UsernameChanged = "true" + } + + bodyPage.Html["Info"] = template.HTML(utils.T("api.templates.upgrade_30_body.info", + map[string]interface{}{ + "SiteName": utils.ClientCfg["SiteName"], + "TeamName": team.Name, + "Email": user.Email, + "Username": user.Username, + "EmailChanged": EmailChanged, + "UsernameChanged": UsernameChanged, + })) + + utils.SendMail( + previousEmail, + utils.T("api.templates.upgrade_30_subject.info"), + bodyPage.Render(), + ) + } } uniqueEmails[user.Email] = true @@ -984,7 +1037,7 @@ FLAGS: -team_name="name" The team name used in other commands - -role="system_admin" The role used in other commands + -role="system_admin" The role used in other commands valid values are "" - The empty role is basic user permissions diff --git a/templates/email_footer.html b/templates/email_footer.html index 6dc7fa483..a15a2e908 100644 --- a/templates/email_footer.html +++ b/templates/email_footer.html @@ -1,9 +1,6 @@ {{define "email_footer"}} -

- -

(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.
{{.Props.Footer}} diff --git a/templates/upgrade_30_body.html b/templates/upgrade_30_body.html new file mode 100644 index 000000000..38de49d3b --- /dev/null +++ b/templates/upgrade_30_body.html @@ -0,0 +1,37 @@ +{{define "upgrade_30_body"}} + + + + + +
+ + + + +
+ + + + + + {{template "email_footer" . }} + +
+ + + + + + {{template "email_info" . }} + +
+ {{ .Html.Info }} +
+
+
+
+ +{{end}} + + diff --git a/utils/html.go b/utils/html.go index e89cb12a0..7bb594e07 100644 --- a/utils/html.go +++ b/utils/html.go @@ -9,6 +9,7 @@ import ( "net/http" l4g "github.com/alecthomas/log4go" + "github.com/nicksnyder/go-i18n/i18n" "gopkg.in/fsnotify.v1" ) @@ -77,9 +78,15 @@ func NewHTMLTemplate(templateName string, locale string) *HTMLTemplate { } func (t *HTMLTemplate) addDefaultProps() { - T := GetUserTranslations(t.Locale) - t.Props["Footer"] = T("api.templates.email_footer") - t.Html["EmailInfo"] = template.HTML(T("api.templates.email_info", + var localT i18n.TranslateFunc + if len(t.Locale) > 0 { + localT = GetUserTranslations(t.Locale) + } else { + localT = T + } + + t.Props["Footer"] = localT("api.templates.email_footer") + t.Html["EmailInfo"] = template.HTML(localT("api.templates.email_info", map[string]interface{}{"SupportEmail": Cfg.SupportSettings.SupportEmail, "SiteName": Cfg.TeamSettings.SiteName})) } -- cgit v1.2.3-1-g7c22