summaryrefslogtreecommitdiffstats
path: root/api/user.go
diff options
context:
space:
mode:
Diffstat (limited to 'api/user.go')
-rw-r--r--api/user.go815
1 files changed, 178 insertions, 637 deletions
diff --git a/api/user.go b/api/user.go
index 7587b83ad..37c9948ed 100644
--- a/api/user.go
+++ b/api/user.go
@@ -8,10 +8,6 @@ import (
b64 "encoding/base64"
"fmt"
"html/template"
- "image"
- _ "image/gif"
- _ "image/jpeg"
- "image/png"
"io"
"net/http"
"net/url"
@@ -20,7 +16,6 @@ import (
"time"
l4g "github.com/alecthomas/log4go"
- "github.com/disintegration/imaging"
"github.com/gorilla/mux"
"github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
@@ -140,7 +135,9 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
}
if shouldSendWelcomeEmail {
- sendWelcomeEmail(c, ruser.Id, ruser.Email, c.GetSiteURL(), ruser.EmailVerified)
+ if err := app.SendWelcomeEmail(ruser.Id, ruser.Email, ruser.EmailVerified, ruser.Locale, c.GetSiteURL()); err != nil {
+ l4g.Error(err.Error())
+ }
}
w.Write([]byte(ruser.ToJson()))
@@ -190,55 +187,6 @@ func IsVerifyHashRequired(user *model.User, team *model.Team, hash string) bool
return shouldVerifyHash
}
-func sendWelcomeEmail(c *Context, userId string, email string, siteURL string, verified bool) {
- rawUrl, _ := url.Parse(siteURL)
-
- subject := c.T("api.templates.welcome_subject", map[string]interface{}{"ServerURL": rawUrl.Host})
-
- bodyPage := utils.NewHTMLTemplate("welcome_body", c.Locale)
- bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["Title"] = c.T("api.templates.welcome_body.title", map[string]interface{}{"ServerURL": rawUrl.Host})
- bodyPage.Props["Info"] = c.T("api.templates.welcome_body.info")
- bodyPage.Props["Button"] = c.T("api.templates.welcome_body.button")
- bodyPage.Props["Info2"] = c.T("api.templates.welcome_body.info2")
- bodyPage.Props["Info3"] = c.T("api.templates.welcome_body.info3")
- bodyPage.Props["SiteURL"] = siteURL
-
- if *utils.Cfg.NativeAppSettings.AppDownloadLink != "" {
- bodyPage.Props["AppDownloadInfo"] = c.T("api.templates.welcome_body.app_download_info")
- bodyPage.Props["AppDownloadLink"] = *utils.Cfg.NativeAppSettings.AppDownloadLink
- }
-
- if !verified {
- link := fmt.Sprintf("%s/do_verify_email?uid=%s&hid=%s&email=%s", siteURL, userId, model.HashPassword(userId+utils.Cfg.EmailSettings.InviteSalt), url.QueryEscape(email))
- bodyPage.Props["VerifyUrl"] = link
- }
-
- if err := utils.SendMail(email, subject, bodyPage.Render()); err != nil {
- l4g.Error(utils.T("api.user.send_welcome_email_and_forget.failed.error"), err)
- }
-}
-
-func SendVerifyEmail(c *Context, userId, userEmail, siteURL string) {
- link := fmt.Sprintf("%s/do_verify_email?uid=%s&hid=%s&email=%s", siteURL, userId, model.HashPassword(userId+utils.Cfg.EmailSettings.InviteSalt), url.QueryEscape(userEmail))
-
- url, _ := url.Parse(siteURL)
-
- subject := c.T("api.templates.verify_subject",
- map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]})
-
- bodyPage := utils.NewHTMLTemplate("verify_body", c.Locale)
- bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["Title"] = c.T("api.templates.verify_body.title", map[string]interface{}{"ServerURL": url.Host})
- bodyPage.Props["Info"] = c.T("api.templates.verify_body.info")
- bodyPage.Props["VerifyUrl"] = link
- bodyPage.Props["Button"] = c.T("api.templates.verify_body.button")
-
- if err := utils.SendMail(userEmail, subject, bodyPage.Render()); err != nil {
- l4g.Error(utils.T("api.user.send_verify_email_and_forget.failed.error"), err)
- }
-}
-
func login(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
@@ -362,21 +310,10 @@ func doLogin(c *Context, w http.ResponseWriter, r *http.Request, user *model.Use
maxAge = *utils.Cfg.ServiceSettings.SessionLengthMobileInDays * 60 * 60 * 24
// A special case where we logout of all other sessions with the same Id
- if result := <-app.Srv.Store.Session().GetSessions(user.Id); result.Err != nil {
- c.Err = result.Err
+ if err := app.RevokeSessionsForDeviceId(user.Id, deviceId, ""); err != nil {
+ c.Err = err
c.Err.StatusCode = http.StatusInternalServerError
return
- } else {
- sessions := result.Data.([]*model.Session)
- for _, session := range sessions {
- if session.DeviceId == deviceId {
- l4g.Debug(utils.T("api.user.login.revoking.app_error"), session.Id, user.Id)
- if err := app.RevokeSessionById(session.Id); err != nil {
- c.LogError(err)
- c.Err = nil
- }
- }
- }
}
} else {
session.SetExpireInDays(*utils.Cfg.ServiceSettings.SessionLengthWebInDays)
@@ -399,10 +336,6 @@ func doLogin(c *Context, w http.ResponseWriter, r *http.Request, user *model.Use
bname = "unknown"
}
- if strings.Contains(r.UserAgent(), "Mattermost") {
- bname = "Desktop App"
- }
-
if bversion == "" {
bversion = "0.0"
}
@@ -411,13 +344,11 @@ func doLogin(c *Context, w http.ResponseWriter, r *http.Request, user *model.Use
session.AddProp(model.SESSION_PROP_OS, os)
session.AddProp(model.SESSION_PROP_BROWSER, fmt.Sprintf("%v/%v", bname, bversion))
- if result := <-app.Srv.Store.Session().Save(session); result.Err != nil {
- c.Err = result.Err
+ var err *model.AppError
+ if session, err = app.CreateSession(session); err != nil {
+ c.Err = err
c.Err.StatusCode = http.StatusInternalServerError
return
- } else {
- session = result.Data.(*model.Session)
- app.AddSessionToCache(session)
}
w.Header().Set(model.HEADER_TOKEN, session.Token)
@@ -476,7 +407,7 @@ func attachDeviceId(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- app.RemoveAllSessionsForUserId(c.Session.UserId)
+ app.ClearSessionCacheForUser(c.Session.UserId)
c.Session.SetExpireInDays(*utils.Cfg.ServiceSettings.SessionLengthMobileInDays)
maxAge := *utils.Cfg.ServiceSettings.SessionLengthMobileInDays * 60 * 60 * 24
@@ -507,58 +438,6 @@ func attachDeviceId(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(props)))
}
-// IF YOU UPDATE THIS PLEASE UPDATE BELOW
-func RevokeAllSession(c *Context, userId string) {
- if result := <-app.Srv.Store.Session().GetSessions(userId); result.Err != nil {
- c.Err = result.Err
- return
- } else {
- sessions := result.Data.([]*model.Session)
-
- for _, session := range sessions {
- c.LogAuditWithUserId(userId, "session_id="+session.Id)
- if session.IsOAuth {
- app.RevokeAccessToken(session.Token)
- } else {
- if result := <-app.Srv.Store.Session().Remove(session.Id); result.Err != nil {
- c.Err = result.Err
- return
- }
- }
-
- app.RevokeWebrtcToken(session.Id)
- }
- }
-
- app.RemoveAllSessionsForUserId(userId)
-}
-
-// UGH...
-// If you update this please update above
-func RevokeAllSessionsNoContext(userId string) *model.AppError {
- if result := <-app.Srv.Store.Session().GetSessions(userId); result.Err != nil {
- return result.Err
- } else {
- sessions := result.Data.([]*model.Session)
-
- for _, session := range sessions {
- if session.IsOAuth {
- app.RevokeAccessToken(session.Token)
- } else {
- if result := <-app.Srv.Store.Session().Remove(session.Id); result.Err != nil {
- return result.Err
- }
- }
-
- app.RevokeWebrtcToken(session.Id)
- }
- }
-
- app.RemoveAllSessionsForUserId(userId)
-
- return nil
-}
-
func getSessions(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
@@ -568,11 +447,10 @@ func getSessions(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-app.Srv.Store.Session().GetSessions(id); result.Err != nil {
- c.Err = result.Err
+ if sessions, err := app.GetSessions(id); err != nil {
+ c.Err = err
return
} else {
- sessions := result.Data.([]*model.Session)
for _, session := range sessions {
session.Sanitize()
}
@@ -990,64 +868,11 @@ func uploadProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
imageData := imageArray[0]
- file, err := imageData.Open()
- defer file.Close()
- if err != nil {
- c.Err = model.NewLocAppError("uploadProfileImage", "api.user.upload_profile_user.open.app_error", nil, err.Error())
- return
- }
-
- // Decode image config first to check dimensions before loading the whole thing into memory later on
- config, _, err := image.DecodeConfig(file)
- if err != nil {
- c.Err = model.NewLocAppError("uploadProfileFile", "api.user.upload_profile_user.decode_config.app_error", nil, err.Error())
- return
- } else if config.Width*config.Height > MaxImageSize {
- c.Err = model.NewLocAppError("uploadProfileFile", "api.user.upload_profile_user.too_large.app_error", nil, err.Error())
- return
- }
-
- file.Seek(0, 0)
-
- // Decode image into Image object
- img, _, err := image.Decode(file)
- if err != nil {
- c.Err = model.NewLocAppError("uploadProfileImage", "api.user.upload_profile_user.decode.app_error", nil, err.Error())
- return
- }
-
- // Scale profile image
- img = imaging.Resize(img, utils.Cfg.FileSettings.ProfileWidth, utils.Cfg.FileSettings.ProfileHeight, imaging.Lanczos)
-
- buf := new(bytes.Buffer)
- err = png.Encode(buf, img)
- if err != nil {
- c.Err = model.NewLocAppError("uploadProfileImage", "api.user.upload_profile_user.encode.app_error", nil, err.Error())
- return
- }
-
- path := "users/" + c.Session.UserId + "/profile.png"
-
- if err := app.WriteFile(buf.Bytes(), path); err != nil {
- c.Err = model.NewLocAppError("uploadProfileImage", "api.user.upload_profile_user.upload_profile.app_error", nil, "")
+ if err := app.SetProfileImage(c.Session.UserId, imageData); err != nil {
+ c.Err = err
return
}
- app.Srv.Store.User().UpdateLastPictureUpdate(c.Session.UserId)
-
- if result := <-app.Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
- l4g.Error(utils.T("api.user.get_me.getting.error"), c.Session.UserId)
- } else {
- user := result.Data.(*model.User)
- user = sanitizeProfile(c, user)
- omitUsers := make(map[string]bool, 1)
- omitUsers[user.Id] = true
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_UPDATED, "", "", "", omitUsers)
- message.Add("user", user)
-
- go app.Publish(message)
- }
-
c.LogAudit("")
// write something as the response since jQuery expects a json response
@@ -1071,29 +896,13 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-app.Srv.Store.User().Update(user, false); result.Err != nil {
- c.Err = result.Err
+ if ruser, err := app.UpdateUser(user, c.GetSiteURL()); err != nil {
+ c.Err = err
return
} else {
c.LogAudit("")
- rusers := result.Data.([2]*model.User)
-
- if rusers[0].Email != rusers[1].Email {
- go sendEmailChangeEmail(c, rusers[1].Email, rusers[0].Email, c.GetSiteURL())
-
- if utils.Cfg.EmailSettings.RequireEmailVerification {
- go SendEmailChangeVerifyEmail(c, rusers[0].Id, rusers[0].Email, c.GetSiteURL())
- }
- }
-
- if rusers[0].Username != rusers[1].Username {
- go sendEmailChangeUsername(c, rusers[1].Username, rusers[0].Username, rusers[0].Email, c.GetSiteURL())
- }
-
- app.InvalidateCacheForUser(user.Id)
-
- updatedUser := rusers[0]
+ updatedUser := ruser
updatedUser = sanitizeProfile(c, updatedUser)
omitUsers := make(map[string]bool, 1)
@@ -1102,10 +911,10 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) {
message.Add("user", updatedUser)
go app.Publish(message)
- rusers[0].Password = ""
- rusers[0].AuthData = new(string)
- *rusers[0].AuthData = ""
- w.Write([]byte(rusers[0].ToJson()))
+ ruser.Password = ""
+ ruser.AuthData = new(string)
+ *ruser.AuthData = ""
+ w.Write([]byte(ruser.ToJson()))
}
}
@@ -1138,21 +947,20 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- var result store.StoreResult
+ var user *model.User
+ var err *model.AppError
- if result = <-app.Srv.Store.User().Get(userId); result.Err != nil {
- c.Err = result.Err
+ if user, err = app.GetUser(userId); err != nil {
+ c.Err = err
return
}
- if result.Data == nil {
+ if user == nil {
c.Err = model.NewLocAppError("updatePassword", "api.user.update_password.valid_account.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
- user := result.Data.(*model.User)
-
if user.AuthData != nil && *user.AuthData != "" {
c.LogAudit("failed - tried to update user password who was logged in through oauth")
c.Err = model.NewLocAppError("updatePassword", "api.user.update_password.oauth.app_error", nil, "auth_service="+user.AuthService)
@@ -1170,16 +978,14 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if uresult := <-app.Srv.Store.User().UpdatePassword(c.Session.UserId, model.HashPassword(newPassword)); uresult.Err != nil {
- c.Err = model.NewLocAppError("updatePassword", "api.user.update_password.failed.app_error", nil, uresult.Err.Error())
+ if err := app.UpdatePasswordSendEmail(user, model.HashPassword(newPassword), c.T("api.user.update_password.menu"), c.GetSiteURL()); err != nil {
+ c.Err = err
return
} else {
c.LogAudit("completed")
- go sendPasswordChangeEmail(c, user.Email, c.GetSiteURL(), c.T("api.user.update_password.menu"))
-
data := make(map[string]string)
- data["user_id"] = uresult.Data.(string)
+ data["user_id"] = c.Session.UserId
w.Write([]byte(model.MapToJson(data)))
}
}
@@ -1204,18 +1010,10 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- var user *model.User
- if result := <-app.Srv.Store.User().Get(userId); result.Err != nil {
- c.Err = result.Err
+ if _, err := app.UpdateUserRoles(userId, newRoles); err != nil {
return
} else {
- user = result.Data.(*model.User)
- }
-
- if _, err := UpdateUserRoles(user, newRoles); err != nil {
- return
- } else {
- c.LogAuditWithUserId(user.Id, "roles="+newRoles)
+ c.LogAuditWithUserId(userId, "roles="+newRoles)
}
rdata := map[string]string{}
@@ -1223,34 +1021,11 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(rdata)))
}
-func UpdateUserRoles(user *model.User, newRoles string) (*model.User, *model.AppError) {
-
- user.Roles = newRoles
- uchan := app.Srv.Store.User().Update(user, true)
- schan := app.Srv.Store.Session().UpdateRoles(user.Id, newRoles)
-
- var ruser *model.User
- if result := <-uchan; result.Err != nil {
- return nil, result.Err
- } else {
- ruser = result.Data.([2]*model.User)[0]
- }
-
- if result := <-schan; result.Err != nil {
- // soft error since the user roles were still updated
- l4g.Error(result.Err)
- }
-
- app.RemoveAllSessionsForUserId(user.Id)
-
- return ruser, nil
-}
-
func updateActive(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
- user_id := props["user_id"]
- if len(user_id) != 26 {
+ userId := props["user_id"]
+ if len(userId) != 26 {
c.SetInvalidParam("updateActive", "user_id")
return
}
@@ -1258,142 +1033,35 @@ func updateActive(c *Context, w http.ResponseWriter, r *http.Request) {
active := props["active"] == "true"
var user *model.User
- if result := <-app.Srv.Store.User().Get(user_id); result.Err != nil {
- c.Err = result.Err
+ var err *model.AppError
+ if user, err = app.GetUser(userId); err != nil {
+ c.Err = err
return
- } else {
- user = result.Data.(*model.User)
}
// true when you're trying to de-activate yourself
- isSelfDeactive := !active && user_id == c.Session.UserId
+ isSelfDeactive := !active && userId == c.Session.UserId
if !isSelfDeactive && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
- c.Err = model.NewLocAppError("updateActive", "api.user.update_active.permissions.app_error", nil, "userId="+user_id)
+ c.Err = model.NewLocAppError("updateActive", "api.user.update_active.permissions.app_error", nil, "userId="+userId)
c.Err.StatusCode = http.StatusForbidden
return
}
if user.IsLDAPUser() {
- c.Err = model.NewLocAppError("updateActive", "api.user.update_active.no_deactivate_ldap.app_error", nil, "userId="+user_id)
+ c.Err = model.NewLocAppError("updateActive", "api.user.update_active.no_deactivate_ldap.app_error", nil, "userId="+userId)
c.Err.StatusCode = http.StatusBadRequest
return
}
- if ruser, err := UpdateActive(user, active); err != nil {
+ if ruser, err := app.UpdateActive(user, active); err != nil {
c.Err = err
} else {
- if !active {
- app.SetStatusOffline(ruser.Id, false)
- }
-
c.LogAuditWithUserId(ruser.Id, fmt.Sprintf("active=%v", active))
w.Write([]byte(ruser.ToJson()))
}
}
-func UpdateActive(user *model.User, active bool) (*model.User, *model.AppError) {
- if active {
- user.DeleteAt = 0
- } else {
- user.DeleteAt = model.GetMillis()
- }
-
- if result := <-app.Srv.Store.User().Update(user, true); result.Err != nil {
- return nil, result.Err
- } else {
- if user.DeleteAt > 0 {
- RevokeAllSessionsNoContext(user.Id)
- }
-
- if extra := <-app.Srv.Store.Channel().ExtraUpdateByUser(user.Id, model.GetMillis()); extra.Err != nil {
- return nil, extra.Err
- }
-
- ruser := result.Data.([2]*model.User)[0]
- options := utils.Cfg.GetSanitizeOptions()
- options["passwordupdate"] = false
- ruser.Sanitize(options)
- return ruser, nil
- }
-}
-
-func PermanentDeleteUser(user *model.User) *model.AppError {
- l4g.Warn(utils.T("api.user.permanent_delete_user.attempting.warn"), user.Email, user.Id)
- if user.IsInRole(model.ROLE_SYSTEM_ADMIN.Id) {
- l4g.Warn(utils.T("api.user.permanent_delete_user.system_admin.warn"), user.Email)
- }
-
- if _, err := UpdateActive(user, false); err != nil {
- return err
- }
-
- if result := <-app.Srv.Store.Session().PermanentDeleteSessionsByUser(user.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.OAuth().PermanentDeleteAuthDataByUser(user.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.Webhook().PermanentDeleteIncomingByUser(user.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.Webhook().PermanentDeleteOutgoingByUser(user.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.Command().PermanentDeleteByUser(user.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.Preference().PermanentDeleteByUser(user.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.Channel().PermanentDeleteMembersByUser(user.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.Post().PermanentDeleteByUser(user.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.User().PermanentDelete(user.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.Audit().PermanentDeleteByUser(user.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.Team().RemoveAllMembersByUser(user.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.PasswordRecovery().Delete(user.Id); result.Err != nil {
- return result.Err
- }
-
- l4g.Warn(utils.T("api.user.permanent_delete_user.deleted.warn"), user.Email, user.Id)
-
- return nil
-}
-
-func PermanentDeleteAllUsers() *model.AppError {
- if result := <-app.Srv.Store.User().GetAll(); result.Err != nil {
- return result.Err
- } else {
- users := result.Data.([]*model.User)
- for _, user := range users {
- PermanentDeleteUser(user)
- }
- }
-
- return nil
-}
-
func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
@@ -1404,11 +1072,10 @@ func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) {
}
var user *model.User
- if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
+ var err *model.AppError
+ if user, err = app.GetUserByEmail(email); err != nil {
w.Write([]byte(model.MapToJson(props)))
return
- } else {
- user = result.Data.(*model.User)
}
if user.AuthData != nil && len(*user.AuthData) != 0 {
@@ -1416,11 +1083,9 @@ func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- recovery := &model.PasswordRecovery{}
- recovery.UserId = user.Id
-
- if result := <-app.Srv.Store.PasswordRecovery().SaveOrUpdate(recovery); result.Err != nil {
- c.Err = result.Err
+ var recovery *model.PasswordRecovery
+ if recovery, err = app.CreatePasswordRecovery(user.Id); err != nil {
+ c.Err = err
return
}
@@ -1464,13 +1129,11 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) {
userId := ""
- if result := <-app.Srv.Store.PasswordRecovery().GetByCode(code); result.Err != nil {
+ if recovery, err := app.GetPasswordRecovery(code); err != nil {
c.LogAuditWithUserId(userId, "fail - bad code")
- c.Err = model.NewLocAppError("resetPassword", "api.user.reset_password.invalid_link.app_error", nil, result.Err.Error())
+ c.Err = err
return
} else {
- recovery := result.Data.(*model.PasswordRecovery)
-
if model.GetMillis()-recovery.CreateAt < model.PASSWORD_RECOVER_EXPIRY_TIME {
userId = recovery.UserId
} else {
@@ -1479,11 +1142,9 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- go func() {
- if result := <-app.Srv.Store.PasswordRecovery().Delete(userId); result.Err != nil {
- l4g.Error("%v", result.Err)
- }
- }()
+ if err := app.DeletePasswordRecoveryForUser(userId); err != nil {
+ l4g.Error(err.Error())
+ }
}
if err := ResetPassword(c, userId, newPassword); err != nil {
@@ -1500,10 +1161,9 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) {
func ResetPassword(c *Context, userId, newPassword string) *model.AppError {
var user *model.User
- if result := <-app.Srv.Store.User().Get(userId); result.Err != nil {
- return result.Err
- } else {
- user = result.Data.(*model.User)
+ var err *model.AppError
+ if user, err = app.GetUser(userId); err != nil {
+ return err
}
if user.AuthData != nil && len(*user.AuthData) != 0 && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
@@ -1511,116 +1171,23 @@ func ResetPassword(c *Context, userId, newPassword string) *model.AppError {
}
- if result := <-app.Srv.Store.User().UpdatePassword(userId, model.HashPassword(newPassword)); result.Err != nil {
- return result.Err
+ if err := app.UpdatePasswordSendEmail(user, model.HashPassword(newPassword), c.T("api.user.reset_password.method"), c.GetSiteURL()); err != nil {
+ return err
}
- go sendPasswordChangeEmail(c, user.Email, c.GetSiteURL(), c.T("api.user.reset_password.method"))
-
return nil
}
-func sendPasswordChangeEmail(c *Context, email, siteURL, method string) {
- subject := c.T("api.templates.password_change_subject",
- map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName, "SiteName": utils.Cfg.TeamSettings.SiteName})
-
- bodyPage := utils.NewHTMLTemplate("password_change_body", c.Locale)
- bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["Title"] = c.T("api.templates.password_change_body.title")
- bodyPage.Html["Info"] = template.HTML(c.T("api.templates.password_change_body.info",
- map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName, "TeamURL": siteURL, "Method": method}))
-
- if err := utils.SendMail(email, subject, bodyPage.Render()); err != nil {
- l4g.Error(utils.T("api.user.send_password_change_email_and_forget.error"), err)
- }
-}
-
-func sendMfaChangeEmail(c *Context, email string, siteURL string, activated bool) {
- subject := c.T("api.templates.mfa_change_subject",
- map[string]interface{}{"SiteName": utils.Cfg.TeamSettings.SiteName})
-
- bodyPage := utils.NewHTMLTemplate("mfa_change_body", c.Locale)
- bodyPage.Props["SiteURL"] = siteURL
-
- bodyText := ""
- if activated {
- bodyText = "api.templates.mfa_activated_body.info"
- bodyPage.Props["Title"] = c.T("api.templates.mfa_activated_body.title")
- } else {
- bodyText = "api.templates.mfa_deactivated_body.info"
- bodyPage.Props["Title"] = c.T("api.templates.mfa_deactivated_body.title")
- }
-
- bodyPage.Html["Info"] = template.HTML(c.T(bodyText,
- map[string]interface{}{"SiteURL": siteURL}))
-
- if err := utils.SendMail(email, subject, bodyPage.Render()); err != nil {
- l4g.Error(utils.T("api.user.send_mfa_change_email.error"), err)
- }
-}
-
-func sendEmailChangeEmail(c *Context, oldEmail, newEmail, siteURL string) {
- subject := fmt.Sprintf("[%v] %v", utils.Cfg.TeamSettings.SiteName, c.T("api.templates.email_change_subject",
- map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName}))
-
- bodyPage := utils.NewHTMLTemplate("email_change_body", c.Locale)
- bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["Title"] = c.T("api.templates.email_change_body.title")
- bodyPage.Html["Info"] = template.HTML(c.T("api.templates.email_change_body.info",
- map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName, "NewEmail": newEmail}))
-
- if err := utils.SendMail(oldEmail, subject, bodyPage.Render()); err != nil {
- l4g.Error(utils.T("api.user.send_email_change_email_and_forget.error"), err)
- }
-}
-
-func SendEmailChangeVerifyEmail(c *Context, userId, newUserEmail, siteURL string) {
- link := fmt.Sprintf("%s/do_verify_email?uid=%s&hid=%s&email=%s", siteURL, userId, model.HashPassword(userId+utils.Cfg.EmailSettings.InviteSalt), url.QueryEscape(newUserEmail))
-
- subject := fmt.Sprintf("[%v] %v", utils.Cfg.TeamSettings.SiteName, c.T("api.templates.email_change_verify_subject",
- map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName}))
-
- bodyPage := utils.NewHTMLTemplate("email_change_verify_body", c.Locale)
- bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["Title"] = c.T("api.templates.email_change_verify_body.title")
- bodyPage.Props["Info"] = c.T("api.templates.email_change_verify_body.info",
- map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName})
- bodyPage.Props["VerifyUrl"] = link
- bodyPage.Props["VerifyButton"] = c.T("api.templates.email_change_verify_body.button")
-
- if err := utils.SendMail(newUserEmail, subject, bodyPage.Render()); err != nil {
- l4g.Error(utils.T("api.user.send_email_change_verify_email_and_forget.error"), err)
- }
-}
-
-func sendEmailChangeUsername(c *Context, oldUsername, newUsername, email, siteURL string) {
- subject := fmt.Sprintf("[%v] %v", utils.Cfg.TeamSettings.SiteName, c.T("api.templates.username_change_subject",
- map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName}))
-
- bodyPage := utils.NewHTMLTemplate("email_change_body", c.Locale)
- bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["Title"] = c.T("api.templates.username_change_body.title")
- bodyPage.Html["Info"] = template.HTML(c.T("api.templates.username_change_body.info",
- map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName, "NewUsername": newUsername}))
-
- if err := utils.SendMail(email, subject, bodyPage.Render()); err != nil {
- l4g.Error(utils.T("api.user.send_email_change_username_and_forget.error"), err)
- }
-
-}
-
func updateUserNotify(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
- user_id := props["user_id"]
- if len(user_id) != 26 {
+ userId := props["user_id"]
+ if len(userId) != 26 {
c.SetInvalidParam("updateUserNotify", "user_id")
return
}
- uchan := app.Srv.Store.User().Get(user_id)
-
- if !HasPermissionToUser(c, user_id) {
+ if !HasPermissionToUser(c, userId) {
return
}
@@ -1651,28 +1218,26 @@ func updateUserNotify(c *Context, w http.ResponseWriter, r *http.Request) {
}
var user *model.User
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
+ var err *model.AppError
+ if user, err = app.GetUser(userId); err != nil {
+ c.Err = err
return
- } else {
- user = result.Data.(*model.User)
}
user.NotifyProps = props
- if result := <-app.Srv.Store.User().Update(user, false); result.Err != nil {
- c.Err = result.Err
+ var ruser *model.User
+ if ruser, err = app.UpdateUser(user, c.GetSiteURL()); err != nil {
+ c.Err = err
return
- } else {
- c.LogAuditWithUserId(user.Id, "")
- app.InvalidateCacheForUser(user.Id)
-
- ruser := result.Data.([2]*model.User)[0]
- options := utils.Cfg.GetSanitizeOptions()
- options["passwordupdate"] = false
- ruser.Sanitize(options)
- w.Write([]byte(ruser.ToJson()))
}
+
+ c.LogAuditWithUserId(user.Id, "")
+
+ options := utils.Cfg.GetSanitizeOptions()
+ options["passwordupdate"] = false
+ ruser.Sanitize(options)
+ w.Write([]byte(ruser.ToJson()))
}
func emailToOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -1701,12 +1266,11 @@ func emailToOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAudit("attempt")
var user *model.User
- if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
+ var err *model.AppError
+ if user, err = app.GetUserByEmail(email); err != nil {
c.LogAudit("fail - couldn't get user")
- c.Err = result.Err
+ c.Err = err
return
- } else {
- user = result.Data.(*model.User)
}
if err := checkPasswordAndAllCriteria(user, password, mfaToken); err != nil {
@@ -1754,12 +1318,11 @@ func oauthToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAudit("attempt")
var user *model.User
- if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
+ var err *model.AppError
+ if user, err = app.GetUserByEmail(email); err != nil {
c.LogAudit("fail - couldn't get user")
- c.Err = result.Err
+ c.Err = err
return
- } else {
- user = result.Data.(*model.User)
}
if user.Id != c.Session.UserId {
@@ -1769,15 +1332,24 @@ func oauthToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-app.Srv.Store.User().UpdatePassword(c.Session.UserId, model.HashPassword(password)); result.Err != nil {
+ if err := app.UpdatePassword(user, model.HashPassword(password)); err != nil {
c.LogAudit("fail - database issue")
- c.Err = result.Err
+ c.Err = err
return
}
- go sendSignInChangeEmail(c, user.Email, c.GetSiteURL(), c.T("api.templates.signin_change_email.body.method_email"))
+ go func() {
+ if err := app.SendSignInChangeEmail(user.Email, c.T("api.templates.signin_change_email.body.method_email"), user.Locale, c.GetSiteURL()); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
+
+ if err := app.RevokeAllSessions(c.Session.UserId); err != nil {
+ c.Err = err
+ return
+ }
+ c.LogAuditWithUserId(c.Session.UserId, "Revoked all sessions for user")
- RevokeAllSession(c, c.Session.UserId)
c.RemoveSessionCookie(w, r)
if c.Err != nil {
return
@@ -1822,12 +1394,11 @@ func emailToLdap(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAudit("attempt")
var user *model.User
- if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
+ var err *model.AppError
+ if user, err = app.GetUserByEmail(email); err != nil {
c.LogAudit("fail - couldn't get user")
- c.Err = result.Err
+ c.Err = err
return
- } else {
- user = result.Data.(*model.User)
}
if err := checkPasswordAndAllCriteria(user, emailPassword, token); err != nil {
@@ -1836,7 +1407,12 @@ func emailToLdap(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- RevokeAllSession(c, user.Id)
+ if err := app.RevokeAllSessions(user.Id); err != nil {
+ c.Err = err
+ return
+ }
+ c.LogAuditWithUserId(user.Id, "Revoked all sessions for user")
+
c.RemoveSessionCookie(w, r)
if c.Err != nil {
return
@@ -1855,7 +1431,11 @@ func emailToLdap(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- go sendSignInChangeEmail(c, user.Email, c.GetSiteURL(), "AD/LDAP")
+ go func() {
+ if err := app.SendSignInChangeEmail(user.Email, "AD/LDAP", user.Locale, c.GetSiteURL()); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
m := map[string]string{}
m["follow_link"] = "/login?extra=signin_change"
@@ -1890,12 +1470,11 @@ func ldapToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAudit("attempt")
var user *model.User
- if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
+ var err *model.AppError
+ if user, err = app.GetUserByEmail(email); err != nil {
c.LogAudit("fail - couldn't get user")
- c.Err = result.Err
+ c.Err = err
return
- } else {
- user = result.Data.(*model.User)
}
if user.AuthService != model.USER_AUTH_SERVICE_LDAP {
@@ -1922,19 +1501,28 @@ func ldapToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-app.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(emailPassword)); result.Err != nil {
+ if err := app.UpdatePassword(user, model.HashPassword(emailPassword)); err != nil {
c.LogAudit("fail - database issue")
- c.Err = result.Err
+ c.Err = err
+ return
+ }
+
+ if err := app.RevokeAllSessions(user.Id); err != nil {
+ c.Err = err
return
}
+ c.LogAuditWithUserId(user.Id, "Revoked all sessions for user")
- RevokeAllSession(c, user.Id)
c.RemoveSessionCookie(w, r)
if c.Err != nil {
return
}
- go sendSignInChangeEmail(c, user.Email, c.GetSiteURL(), c.T("api.templates.signin_change_email.body.method_email"))
+ go func() {
+ if err := app.SendSignInChangeEmail(user.Email, c.T("api.templates.signin_change_email.body.method_email"), user.Locale, c.GetSiteURL()); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
m := map[string]string{}
m["follow_link"] = "/login?extra=signin_change"
@@ -1943,21 +1531,6 @@ func ldapToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(m)))
}
-func sendSignInChangeEmail(c *Context, email, siteURL, method string) {
- subject := c.T("api.templates.singin_change_email.subject",
- map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]})
-
- bodyPage := utils.NewHTMLTemplate("signin_change_body", c.Locale)
- bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["Title"] = c.T("api.templates.signin_change_email.body.title")
- bodyPage.Html["Info"] = template.HTML(c.T("api.templates.singin_change_email.body.info",
- map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"], "Method": method}))
-
- if err := utils.SendMail(email, subject, bodyPage.Render()); err != nil {
- l4g.Error(utils.T("api.user.send_sign_in_change_email_and_forget.error"), err)
- }
-}
-
func verifyEmail(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
@@ -1974,7 +1547,7 @@ func verifyEmail(c *Context, w http.ResponseWriter, r *http.Request) {
}
if model.ComparePassword(hashedId, userId+utils.Cfg.EmailSettings.InviteSalt) {
- if c.Err = (<-app.Srv.Store.User().VerifyEmail(userId)).Err; c.Err != nil {
+ if c.Err = app.VerifyUserEmail(userId); c.Err != nil {
return
} else {
c.LogAudit("Email Verified")
@@ -2000,22 +1573,19 @@ func resendVerification(c *Context, w http.ResponseWriter, r *http.Request) {
return
} else {
if _, err := app.GetStatus(user.Id); err != nil {
- go SendVerifyEmail(c, user.Id, user.Email, c.GetSiteURL())
+ go app.SendVerifyEmail(user.Id, user.Email, user.Locale, c.GetSiteURL())
} else {
- go SendEmailChangeVerifyEmail(c, user.Id, user.Email, c.GetSiteURL())
+ go app.SendEmailChangeVerifyEmail(user.Id, user.Email, user.Locale, c.GetSiteURL())
}
}
}
func generateMfaSecret(c *Context, w http.ResponseWriter, r *http.Request) {
- uchan := app.Srv.Store.User().Get(c.Session.UserId)
-
var user *model.User
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
+ var err *model.AppError
+ if user, err = app.GetUser(c.Session.UserId); err != nil {
+ c.Err = err
return
- } else {
- user = result.Data.(*model.User)
}
mfaInterface := einterfaces.GetMfaInterface()
@@ -2077,13 +1647,15 @@ func updateMfa(c *Context, w http.ResponseWriter, r *http.Request) {
go func() {
var user *model.User
- if result := <-app.Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
- l4g.Warn(result.Err)
- } else {
- user = result.Data.(*model.User)
+ var err *model.AppError
+ if user, err = app.GetUser(c.Session.UserId); err != nil {
+ l4g.Warn(err.Error())
+ return
}
- sendMfaChangeEmail(c, user.Email, c.GetSiteURL(), activate)
+ if err := app.SendMfaChangeEmail(user.Email, activate, user.Locale, c.GetSiteURL()); err != nil {
+ l4g.Error(err.Error())
+ }
}()
rdata := map[string]string{}
@@ -2107,20 +1679,11 @@ func checkMfa(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- // we don't need to worry about contacting the ldap server to get this user because
- // only users already in the system could have MFA enabled
- uchan := app.Srv.Store.User().GetForLogin(
- loginId,
- *utils.Cfg.EmailSettings.EnableSignInWithUsername,
- *utils.Cfg.EmailSettings.EnableSignInWithEmail,
- *utils.Cfg.LdapSettings.Enable,
- )
-
rdata := map[string]string{}
- if result := <-uchan; result.Err != nil {
+ if user, err := app.GetUserForLogin(loginId, false); err != nil {
rdata["mfa_required"] = "false"
} else {
- rdata["mfa_required"] = strconv.FormatBool(result.Data.(*model.User).MfaActive)
+ rdata["mfa_required"] = strconv.FormatBool(user.MfaActive)
}
w.Write([]byte(model.MapToJson(rdata)))
}
@@ -2214,8 +1777,16 @@ func completeSaml(c *Context, w http.ResponseWriter, r *http.Request) {
}
break
case model.OAUTH_ACTION_EMAIL_TO_SSO:
- RevokeAllSession(c, user.Id)
- go sendSignInChangeEmail(c, user.Email, c.GetSiteURL(), strings.Title(model.USER_AUTH_SERVICE_SAML)+" SSO")
+ if err := app.RevokeAllSessions(user.Id); err != nil {
+ c.Err = err
+ return
+ }
+ c.LogAuditWithUserId(user.Id, "Revoked all sessions for user")
+ go func() {
+ if err := app.SendSignInChangeEmail(user.Email, strings.Title(model.USER_AUTH_SERVICE_SAML)+" SSO", user.Locale, c.GetSiteURL()); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
break
}
doLogin(c, w, r, user, "")
@@ -2307,27 +1878,26 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = nil
}
- var uchan store.StoreChannel
+ var profiles []*model.User
+ var err *model.AppError
if props.InChannelId != "" {
- uchan = app.Srv.Store.User().SearchInChannel(props.InChannelId, props.Term, searchOptions)
+ profiles, err = app.SearchUsersInChannel(props.InChannelId, props.Term, searchOptions)
} else if props.NotInChannelId != "" {
- uchan = app.Srv.Store.User().SearchNotInChannel(props.TeamId, props.NotInChannelId, props.Term, searchOptions)
+ profiles, err = app.SearchUsersNotInChannel(props.TeamId, props.NotInChannelId, props.Term, searchOptions)
} else {
- uchan = app.Srv.Store.User().Search(props.TeamId, props.Term, searchOptions)
+ profiles, err = app.SearchUsersInTeam(props.TeamId, props.Term, searchOptions)
}
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
+ if err != nil {
+ c.Err = err
return
- } else {
- profiles := result.Data.([]*model.User)
-
- for _, p := range profiles {
- sanitizeProfile(c, p)
- }
+ }
- w.Write([]byte(model.UserListToJson(profiles)))
+ for _, p := range profiles {
+ sanitizeProfile(c, p)
}
+
+ w.Write([]byte(model.UserListToJson(profiles)))
}
func getProfilesByIds(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -2338,12 +1908,10 @@ func getProfilesByIds(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-app.Srv.Store.User().GetProfileByIds(userIds, true); result.Err != nil {
- c.Err = result.Err
+ if profiles, err := app.GetUsersByIds(userIds); err != nil {
+ c.Err = err
return
} else {
- profiles := result.Data.(map[string]*model.User)
-
for _, p := range profiles {
sanitizeProfile(c, p)
}
@@ -2379,35 +1947,18 @@ func autocompleteUsersInChannel(c *Context, w http.ResponseWriter, r *http.Reque
searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true
}
- uchan := app.Srv.Store.User().SearchInChannel(channelId, term, searchOptions)
- nuchan := app.Srv.Store.User().SearchNotInChannel(teamId, channelId, term, searchOptions)
-
- autocomplete := &model.UserAutocompleteInChannel{}
-
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
+ autocomplete, err := app.AutocompleteUsersInChannel(teamId, channelId, term, searchOptions)
+ if err != nil {
+ c.Err = err
return
- } else {
- profiles := result.Data.([]*model.User)
-
- for _, p := range profiles {
- sanitizeProfile(c, p)
- }
-
- autocomplete.InChannel = profiles
}
- if result := <-nuchan; result.Err != nil {
- c.Err = result.Err
- return
- } else {
- profiles := result.Data.([]*model.User)
-
- for _, p := range profiles {
- sanitizeProfile(c, p)
- }
+ for _, p := range autocomplete.InChannel {
+ sanitizeProfile(c, p)
+ }
- autocomplete.OutOfChannel = profiles
+ for _, p := range autocomplete.OutOfChannel {
+ sanitizeProfile(c, p)
}
w.Write([]byte(autocomplete.ToJson()))
@@ -2435,21 +1986,14 @@ func autocompleteUsersInTeam(c *Context, w http.ResponseWriter, r *http.Request)
searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true
}
- uchan := app.Srv.Store.User().Search(teamId, term, searchOptions)
-
- autocomplete := &model.UserAutocompleteInTeam{}
-
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
+ autocomplete, err := app.AutocompleteUsersInTeam(teamId, term, searchOptions)
+ if err != nil {
+ c.Err = err
return
- } else {
- profiles := result.Data.([]*model.User)
-
- for _, p := range profiles {
- sanitizeProfile(c, p)
- }
+ }
- autocomplete.InTeam = profiles
+ for _, p := range autocomplete.InTeam {
+ sanitizeProfile(c, p)
}
w.Write([]byte(autocomplete.ToJson()))
@@ -2468,19 +2012,16 @@ func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) {
searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true
}
- uchan := app.Srv.Store.User().Search("", term, searchOptions)
-
var profiles []*model.User
+ var err *model.AppError
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
+ if profiles, err = app.SearchUsersInTeam("", term, searchOptions); err != nil {
+ c.Err = err
return
- } else {
- profiles = result.Data.([]*model.User)
+ }
- for _, p := range profiles {
- sanitizeProfile(c, p)
- }
+ for _, p := range profiles {
+ sanitizeProfile(c, p)
}
w.Write([]byte(model.UserListToJson(profiles)))