summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/apitestlib.go10
-rw-r--r--api/channel.go772
-rw-r--r--api/command_invite_people.go20
-rw-r--r--api/context.go2
-rw-r--r--api/deprecated.go4
-rw-r--r--api/file.go4
-rw-r--r--api/oauth.go11
-rw-r--r--api/slackimport.go2
-rw-r--r--api/team.go508
-rw-r--r--api/team_test.go4
-rw-r--r--api/user.go815
-rw-r--r--api/user_test.go4
-rw-r--r--app/channel.go340
-rw-r--r--app/email.go236
-rw-r--r--app/notification.go1
-rw-r--r--app/oauth.go2
-rw-r--r--app/session.go54
-rw-r--r--app/session_test.go2
-rw-r--r--app/team.go352
-rw-r--r--app/user.go359
-rw-r--r--cmd/platform/channel.go3
-rw-r--r--cmd/platform/oldcommands.go17
-rw-r--r--cmd/platform/roles.go6
-rw-r--r--cmd/platform/team.go5
-rw-r--r--cmd/platform/user.go11
-rw-r--r--einterfaces/cluster.go2
-rw-r--r--i18n/en.json14
-rw-r--r--model/file.go4
-rw-r--r--store/sql_channel_store.go4
-rw-r--r--store/sql_channel_store_test.go10
-rw-r--r--store/sql_team_store.go4
-rw-r--r--store/sql_team_store_test.go2
-rw-r--r--utils/config.go2
-rw-r--r--web/web_test.go2
34 files changed, 1931 insertions, 1657 deletions
diff --git a/api/apitestlib.go b/api/apitestlib.go
index abd4767b7..09aed0e33 100644
--- a/api/apitestlib.go
+++ b/api/apitestlib.go
@@ -99,7 +99,7 @@ func (me *TestHelper) InitSystemAdmin() *TestHelper {
me.SystemAdminUser = me.CreateUser(me.SystemAdminClient)
LinkUserToTeam(me.SystemAdminUser, me.SystemAdminTeam)
me.SystemAdminClient.SetTeamId(me.SystemAdminTeam.Id)
- UpdateUserRoles(me.SystemAdminUser, model.ROLE_SYSTEM_USER.Id+" "+model.ROLE_SYSTEM_ADMIN.Id)
+ app.UpdateUserRoles(me.SystemAdminUser.Id, model.ROLE_SYSTEM_USER.Id+" "+model.ROLE_SYSTEM_ADMIN.Id)
me.SystemAdminUser.Password = "Password1"
me.LoginSystemAdmin()
me.SystemAdminChannel = me.CreateChannel(me.SystemAdminClient, me.SystemAdminTeam)
@@ -180,9 +180,9 @@ func MakeUserChannelAdmin(user *model.User, channel *model.Channel) {
utils.DisableDebugLogForTest()
if cmr := <-app.Srv.Store.Channel().GetMember(channel.Id, user.Id); cmr.Err == nil {
- cm := cmr.Data.(model.ChannelMember)
+ cm := cmr.Data.(*model.ChannelMember)
cm.Roles = "channel_admin channel_user"
- if sr := <-app.Srv.Store.Channel().UpdateMember(&cm); sr.Err != nil {
+ if sr := <-app.Srv.Store.Channel().UpdateMember(cm); sr.Err != nil {
utils.EnableDebugLogForTest()
panic(sr.Err)
}
@@ -198,9 +198,9 @@ func MakeUserChannelUser(user *model.User, channel *model.Channel) {
utils.DisableDebugLogForTest()
if cmr := <-app.Srv.Store.Channel().GetMember(channel.Id, user.Id); cmr.Err == nil {
- cm := cmr.Data.(model.ChannelMember)
+ cm := cmr.Data.(*model.ChannelMember)
cm.Roles = "channel_user"
- if sr := <-app.Srv.Store.Channel().UpdateMember(&cm); sr.Err != nil {
+ if sr := <-app.Srv.Store.Channel().UpdateMember(cm); sr.Err != nil {
utils.EnableDebugLogForTest()
panic(sr.Err)
}
diff --git a/api/channel.go b/api/channel.go
index b8b73bf38..4c0c56496 100644
--- a/api/channel.go
+++ b/api/channel.go
@@ -13,7 +13,6 @@ import (
"github.com/gorilla/mux"
"github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
- "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
)
@@ -83,12 +82,11 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
if channel.TeamId == c.TeamId {
// Get total number of channels on current team
- if result := <-app.Srv.Store.Channel().GetTeamChannels(channel.TeamId); result.Err != nil {
- c.Err = model.NewLocAppError("createChannel", "api.channel.get_channels.error", nil, result.Err.Message)
+ if count, err := app.GetNumberOfChannelsOnTeam(channel.TeamId); err != nil {
+ c.Err = model.NewLocAppError("createChannel", "api.channel.get_channels.error", nil, err.Error())
return
} else {
- data := result.Data.(*model.ChannelList)
- if int64(len(*data)+1) > *utils.Cfg.TeamSettings.MaxChannelsPerTeam {
+ if int64(count+1) > *utils.Cfg.TeamSettings.MaxChannelsPerTeam {
c.Err = model.NewLocAppError("createChannel", "api.channel.create_channel.max_channel_limit.app_error", map[string]interface{}{"MaxChannelsPerTeam": *utils.Cfg.TeamSettings.MaxChannelsPerTeam}, "")
return
}
@@ -148,68 +146,66 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- sc := app.Srv.Store.Channel().Get(channel.Id, true)
- cmc := app.Srv.Store.Channel().GetMember(channel.Id, c.Session.UserId)
+ var oldChannel *model.Channel
+ var err *model.AppError
+ if oldChannel, err = app.GetChannel(channel.Id); err != nil {
+ c.Err = err
+ return
+ }
- if cresult := <-sc; cresult.Err != nil {
- c.Err = cresult.Err
+ if _, err = app.GetChannelMember(channel.Id, c.Session.UserId); err != nil {
+ c.Err = err
return
- } else if cmcresult := <-cmc; cmcresult.Err != nil {
- c.Err = cmcresult.Err
+ }
+
+ if !CanManageChannel(c, channel) {
return
- } else {
- oldChannel := cresult.Data.(*model.Channel)
- // Don't need to do anything with channel member, just wanted to confirm it exists
+ }
- if !CanManageChannel(c, channel) {
- return
- }
+ if oldChannel.DeleteAt > 0 {
+ c.Err = model.NewLocAppError("updateChannel", "api.channel.update_channel.deleted.app_error", nil, "")
+ c.Err.StatusCode = http.StatusBadRequest
+ return
+ }
- if oldChannel.DeleteAt > 0 {
- c.Err = model.NewLocAppError("updateChannel", "api.channel.update_channel.deleted.app_error", nil, "")
+ if oldChannel.Name == model.DEFAULT_CHANNEL {
+ if (len(channel.Name) > 0 && channel.Name != oldChannel.Name) || (len(channel.Type) > 0 && channel.Type != oldChannel.Type) {
+ c.Err = model.NewLocAppError("updateChannel", "api.channel.update_channel.tried.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
+ }
- if oldChannel.Name == model.DEFAULT_CHANNEL {
- if (len(channel.Name) > 0 && channel.Name != oldChannel.Name) || (len(channel.Type) > 0 && channel.Type != oldChannel.Type) {
- c.Err = model.NewLocAppError("updateChannel", "api.channel.update_channel.tried.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "")
- c.Err.StatusCode = http.StatusBadRequest
- return
- }
- }
-
- oldChannel.Header = channel.Header
- oldChannel.Purpose = channel.Purpose
+ oldChannel.Header = channel.Header
+ oldChannel.Purpose = channel.Purpose
- oldChannelDisplayName := oldChannel.DisplayName
+ oldChannelDisplayName := oldChannel.DisplayName
- if len(channel.DisplayName) > 0 {
- oldChannel.DisplayName = channel.DisplayName
- }
+ if len(channel.DisplayName) > 0 {
+ oldChannel.DisplayName = channel.DisplayName
+ }
- if len(channel.Name) > 0 {
- oldChannel.Name = channel.Name
- }
+ if len(channel.Name) > 0 {
+ oldChannel.Name = channel.Name
+ }
- if len(channel.Type) > 0 {
- oldChannel.Type = channel.Type
- }
+ if len(channel.Type) > 0 {
+ oldChannel.Type = channel.Type
+ }
- app.InvalidateCacheForChannel(oldChannel.Id)
- if ucresult := <-app.Srv.Store.Channel().Update(oldChannel); ucresult.Err != nil {
- c.Err = ucresult.Err
- return
- } else {
- if oldChannelDisplayName != channel.DisplayName {
- if err := app.PostUpdateChannelDisplayNameMessage(c.Session.UserId, channel.Id, c.TeamId, oldChannelDisplayName, channel.DisplayName); err != nil {
- l4g.Error(err.Error())
- }
+ if _, err := app.UpdateChannel(oldChannel); err != nil {
+ c.Err = err
+ return
+ } else {
+ if oldChannelDisplayName != channel.DisplayName {
+ if err := app.PostUpdateChannelDisplayNameMessage(c.Session.UserId, channel.Id, c.TeamId, oldChannelDisplayName, channel.DisplayName); err != nil {
+ l4g.Error(err.Error())
}
- c.LogAudit("name=" + channel.Name)
- w.Write([]byte(oldChannel.ToJson()))
}
+ c.LogAudit("name=" + channel.Name)
+ w.Write([]byte(oldChannel.ToJson()))
}
+
}
func updateChannelHeader(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -227,37 +223,34 @@ func updateChannelHeader(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- sc := app.Srv.Store.Channel().Get(channelId, true)
- cmc := app.Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
-
- if cresult := <-sc; cresult.Err != nil {
- c.Err = cresult.Err
+ var channel *model.Channel
+ var err *model.AppError
+ if channel, err = app.GetChannel(channelId); err != nil {
+ c.Err = err
return
- } else if cmcresult := <-cmc; cmcresult.Err != nil {
- c.Err = cmcresult.Err
+ }
+
+ if _, err = app.GetChannelMember(channelId, c.Session.UserId); err != nil {
+ c.Err = err
return
- } else {
- channel := cresult.Data.(*model.Channel)
- // Don't need to do anything with channel member, just wanted to confirm it exists
+ }
- if !CanManageChannel(c, channel) {
- return
- }
+ if !CanManageChannel(c, channel) {
+ return
+ }
- oldChannelHeader := channel.Header
- channel.Header = channelHeader
+ oldChannelHeader := channel.Header
+ channel.Header = channelHeader
- app.InvalidateCacheForChannel(channel.Id)
- if ucresult := <-app.Srv.Store.Channel().Update(channel); ucresult.Err != nil {
- c.Err = ucresult.Err
- return
- } else {
- if err := app.PostUpdateChannelHeaderMessage(c.Session.UserId, channel.Id, c.TeamId, oldChannelHeader, channelHeader); err != nil {
- l4g.Error(err.Error())
- }
- c.LogAudit("name=" + channel.Name)
- w.Write([]byte(channel.ToJson()))
+ if _, err := app.UpdateChannel(channel); err != nil {
+ c.Err = err
+ return
+ } else {
+ if err := app.PostUpdateChannelHeaderMessage(c.Session.UserId, channel.Id, c.TeamId, oldChannelHeader, channelHeader); err != nil {
+ l4g.Error(err.Error())
}
+ c.LogAudit("name=" + channel.Name)
+ w.Write([]byte(channel.ToJson()))
}
}
@@ -276,37 +269,34 @@ func updateChannelPurpose(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- sc := app.Srv.Store.Channel().Get(channelId, true)
- cmc := app.Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
-
- if cresult := <-sc; cresult.Err != nil {
- c.Err = cresult.Err
+ var channel *model.Channel
+ var err *model.AppError
+ if channel, err = app.GetChannel(channelId); err != nil {
+ c.Err = err
return
- } else if cmcresult := <-cmc; cmcresult.Err != nil {
- c.Err = cmcresult.Err
+ }
+
+ if _, err = app.GetChannelMember(channelId, c.Session.UserId); err != nil {
+ c.Err = err
return
- } else {
- channel := cresult.Data.(*model.Channel)
- // Don't need to do anything with channel member, just wanted to confirm it exists
+ }
- if !CanManageChannel(c, channel) {
- return
- }
+ if !CanManageChannel(c, channel) {
+ return
+ }
- oldChannelPurpose := channel.Purpose
- channel.Purpose = channelPurpose
+ oldChannelPurpose := channel.Purpose
+ channel.Purpose = channelPurpose
- app.InvalidateCacheForChannel(channel.Id)
- if ucresult := <-app.Srv.Store.Channel().Update(channel); ucresult.Err != nil {
- c.Err = ucresult.Err
- return
- } else {
- if err := app.PostUpdateChannelPurposeMessage(c.Session.UserId, channel.Id, c.TeamId, oldChannelPurpose, channelPurpose); err != nil {
- l4g.Error(err.Error())
- }
- c.LogAudit("name=" + channel.Name)
- w.Write([]byte(channel.ToJson()))
+ if _, err := app.UpdateChannel(channel); err != nil {
+ c.Err = err
+ return
+ } else {
+ if err := app.PostUpdateChannelPurposeMessage(c.Session.UserId, channel.Id, c.TeamId, oldChannelPurpose, channelPurpose); err != nil {
+ l4g.Error(err.Error())
}
+ c.LogAudit("name=" + channel.Name)
+ w.Write([]byte(channel.ToJson()))
}
}
@@ -319,24 +309,23 @@ func getChannels(c *Context, w http.ResponseWriter, r *http.Request) {
// user is already in the team
// Get's all channels the user is a member of
- if result := <-app.Srv.Store.Channel().GetChannels(c.TeamId, c.Session.UserId); result.Err != nil {
- if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" {
+ if channels, err := app.GetChannelsForUser(c.TeamId, c.Session.UserId); err != nil {
+ if err.Id == "store.sql_channel.get_channels.not_found.app_error" {
// lets make sure the user is valid
- if result := <-app.Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
- c.Err = result.Err
+ if _, err := app.GetUser(c.Session.UserId); err != nil {
+ c.Err = err
c.RemoveSessionCookie(w, r)
l4g.Error(utils.T("api.channel.get_channels.error"), c.Session.UserId)
return
}
}
- c.Err = result.Err
+ c.Err = err
return
- } else if HandleEtag(result.Data.(*model.ChannelList).Etag(), "Get Channels", w, r) {
+ } else if HandleEtag(channels.Etag(), "Get Channels", w, r) {
return
} else {
- data := result.Data.(*model.ChannelList)
- w.Header().Set(model.HEADER_ETAG_SERVER, data.Etag())
- w.Write([]byte(data.ToJson()))
+ w.Header().Set(model.HEADER_ETAG_SERVER, channels.Etag())
+ w.Write([]byte(channels.ToJson()))
}
}
@@ -360,13 +349,12 @@ func getMoreChannelsPage(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-app.Srv.Store.Channel().GetMoreChannels(c.TeamId, c.Session.UserId, offset, limit); result.Err != nil {
- c.Err = result.Err
+ if channels, err := app.GetChannelsUserNotIn(c.TeamId, c.Session.UserId, offset, limit); err != nil {
+ c.Err = err
return
} else {
- data := result.Data.(*model.ChannelList)
- w.Header().Set(model.HEADER_ETAG_SERVER, data.Etag())
- w.Write([]byte(data.ToJson()))
+ w.Header().Set(model.HEADER_ETAG_SERVER, channels.Etag())
+ w.Write([]byte(channels.ToJson()))
}
}
@@ -374,15 +362,14 @@ func getChannelCounts(c *Context, w http.ResponseWriter, r *http.Request) {
// user is already in the team
- if result := <-app.Srv.Store.Channel().GetChannelCounts(c.TeamId, c.Session.UserId); result.Err != nil {
- c.Err = model.NewLocAppError("getChannelCounts", "api.channel.get_channel_counts.app_error", nil, result.Err.Message)
+ if counts, err := app.GetChannelCounts(c.TeamId, c.Session.UserId); err != nil {
+ c.Err = model.NewLocAppError("getChannelCounts", "api.channel.get_channel_counts.app_error", nil, err.Message)
return
- } else if HandleEtag(result.Data.(*model.ChannelCounts).Etag(), "Get Channel Counts", w, r) {
+ } else if HandleEtag(counts.Etag(), "Get Channel Counts", w, r) {
return
} else {
- data := result.Data.(*model.ChannelCounts)
- w.Header().Set(model.HEADER_ETAG_SERVER, data.Etag())
- w.Write([]byte(data.ToJson()))
+ w.Header().Set(model.HEADER_ETAG_SERVER, counts.Etag())
+ w.Write([]byte(counts.ToJson()))
}
}
@@ -427,55 +414,15 @@ func leave(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["channel_id"]
- sc := app.Srv.Store.Channel().Get(id, true)
- uc := app.Srv.Store.User().Get(c.Session.UserId)
- ccm := app.Srv.Store.Channel().GetMemberCount(id, false)
-
- if cresult := <-sc; cresult.Err != nil {
- c.Err = cresult.Err
- return
- } else if uresult := <-uc; uresult.Err != nil {
- c.Err = cresult.Err
- return
- } else if ccmresult := <-ccm; ccmresult.Err != nil {
- c.Err = ccmresult.Err
+ err := app.LeaveChannel(id, c.Session.UserId)
+ if err != nil {
+ c.Err = err
return
- } else {
- channel := cresult.Data.(*model.Channel)
- user := uresult.Data.(*model.User)
- membersCount := ccmresult.Data.(int64)
-
- if channel.Type == model.CHANNEL_DIRECT {
- c.Err = model.NewLocAppError("leave", "api.channel.leave.direct.app_error", nil, "")
- c.Err.StatusCode = http.StatusBadRequest
- return
- }
-
- if channel.Type == model.CHANNEL_PRIVATE && membersCount == 1 {
- c.Err = model.NewLocAppError("leave", "api.channel.leave.last_member.app_error", nil, "userId="+user.Id)
- c.Err.StatusCode = http.StatusBadRequest
- return
- }
-
- if channel.Name == model.DEFAULT_CHANNEL {
- c.Err = model.NewLocAppError("leave", "api.channel.leave.default.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "")
- c.Err.StatusCode = http.StatusBadRequest
- return
- }
-
- if cmresult := <-app.Srv.Store.Channel().RemoveMember(channel.Id, c.Session.UserId); cmresult.Err != nil {
- c.Err = cmresult.Err
- return
- }
-
- RemoveUserFromChannel(c.Session.UserId, c.Session.UserId, channel)
-
- go app.PostUserAddRemoveMessage(c.Session.UserId, channel.Id, channel.TeamId, fmt.Sprintf(utils.T("api.channel.leave.left"), user.Username), model.POST_JOIN_LEAVE)
-
- result := make(map[string]string)
- result["id"] = channel.Id
- w.Write([]byte(model.MapToJson(result)))
}
+
+ result := make(map[string]string)
+ result["id"] = id
+ w.Write([]byte(model.MapToJson(result)))
}
func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -483,181 +430,99 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["channel_id"]
- sc := app.Srv.Store.Channel().Get(id, true)
- scm := app.Srv.Store.Channel().GetMember(id, c.Session.UserId)
- cmc := app.Srv.Store.Channel().GetMemberCount(id, false)
- uc := app.Srv.Store.User().Get(c.Session.UserId)
- ihc := app.Srv.Store.Webhook().GetIncomingByChannel(id)
- ohc := app.Srv.Store.Webhook().GetOutgoingByChannel(id)
-
- if cresult := <-sc; cresult.Err != nil {
- c.Err = cresult.Err
- return
- } else if uresult := <-uc; uresult.Err != nil {
- c.Err = cresult.Err
- return
- } else if scmresult := <-scm; scmresult.Err != nil {
- c.Err = scmresult.Err
- return
- } else if cmcresult := <-cmc; cmcresult.Err != nil {
- c.Err = cmcresult.Err
- return
- } else if ihcresult := <-ihc; ihcresult.Err != nil {
- c.Err = ihcresult.Err
- return
- } else if ohcresult := <-ohc; ohcresult.Err != nil {
- c.Err = ohcresult.Err
+ var channel *model.Channel
+ var err *model.AppError
+ if channel, err = app.GetChannel(id); err != nil {
+ c.Err = err
return
- } else {
- channel := cresult.Data.(*model.Channel)
- memberCount := cmcresult.Data.(int64)
- user := uresult.Data.(*model.User)
- incomingHooks := ihcresult.Data.([]*model.IncomingWebhook)
- outgoingHooks := ohcresult.Data.([]*model.OutgoingWebhook)
- // Don't need to do anything with channel member, just wanted to confirm it exists
-
- // Allow delete if user is the only member left in channel
- if memberCount > 1 {
- if channel.Type == model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_DELETE_PUBLIC_CHANNEL) {
- return
- }
+ }
- if channel.Type == model.CHANNEL_PRIVATE && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_DELETE_PRIVATE_CHANNEL) {
- return
- }
- }
+ var memberCount int64
+ if memberCount, err = app.GetChannelMemberCount(id); err != nil {
+ c.Err = err
+ return
+ }
- if channel.DeleteAt > 0 {
- c.Err = model.NewLocAppError("deleteChannel", "api.channel.delete_channel.deleted.app_error", nil, "")
- c.Err.StatusCode = http.StatusBadRequest
+ // Allow delete if user is the only member left in channel
+ if memberCount > 1 {
+ if channel.Type == model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_DELETE_PUBLIC_CHANNEL) {
return
}
- if channel.Name == model.DEFAULT_CHANNEL {
- c.Err = model.NewLocAppError("deleteChannel", "api.channel.delete_channel.cannot.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "")
- c.Err.StatusCode = http.StatusBadRequest
+ if channel.Type == model.CHANNEL_PRIVATE && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_DELETE_PRIVATE_CHANNEL) {
return
}
+ }
- post := &model.Post{
- ChannelId: channel.Id,
- Message: fmt.Sprintf(c.T("api.channel.delete_channel.archived"), user.Username),
- Type: model.POST_CHANNEL_DELETED,
- UserId: c.Session.UserId,
- }
-
- if _, err := app.CreatePost(post, c.TeamId, false); err != nil {
- l4g.Error(utils.T("api.channel.delete_channel.failed_post.error"), err)
- }
-
- now := model.GetMillis()
- for _, hook := range incomingHooks {
- if result := <-app.Srv.Store.Webhook().DeleteIncoming(hook.Id, now); result.Err != nil {
- l4g.Error(utils.T("api.channel.delete_channel.incoming_webhook.error"), hook.Id)
- }
- }
-
- for _, hook := range outgoingHooks {
- if result := <-app.Srv.Store.Webhook().DeleteOutgoing(hook.Id, now); result.Err != nil {
- l4g.Error(utils.T("api.channel.delete_channel.outgoing_webhook.error"), hook.Id)
- }
- }
-
- if dresult := <-app.Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); dresult.Err != nil {
- c.Err = dresult.Err
- return
- }
- app.InvalidateCacheForChannel(channel.Id)
-
- c.LogAudit("name=" + channel.Name)
-
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_DELETED, c.TeamId, "", "", nil)
- message.Add("channel_id", channel.Id)
+ err = app.DeleteChannel(channel, c.Session.UserId)
+ if err != nil {
+ c.Err = err
+ return
+ }
- app.Publish(message)
+ c.LogAudit("name=" + channel.Name)
- result := make(map[string]string)
- result["id"] = channel.Id
- w.Write([]byte(model.MapToJson(result)))
- }
+ result := make(map[string]string)
+ result["id"] = channel.Id
+ w.Write([]byte(model.MapToJson(result)))
}
func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["channel_id"]
- cchan := app.Srv.Store.Channel().Get(id, true)
- cmchan := app.Srv.Store.Channel().GetMember(id, c.Session.UserId)
-
- if cresult := <-cchan; cresult.Err != nil {
- c.Err = cresult.Err
- return
- } else if cmresult := <-cmchan; cmresult.Err != nil {
- c.Err = cmresult.Err
+ var channel *model.Channel
+ var err *model.AppError
+ if channel, err = app.GetChannel(id); err != nil {
+ c.Err = err
return
- } else {
- data := &model.ChannelData{}
- data.Channel = cresult.Data.(*model.Channel)
- member := cmresult.Data.(model.ChannelMember)
- data.Member = &member
-
- if data.Channel.TeamId != c.TeamId && data.Channel.Type != model.CHANNEL_DIRECT {
- c.Err = model.NewLocAppError("getChannel", "api.channel.get_channel.wrong_team.app_error", map[string]interface{}{"ChannelId": id, "TeamId": c.TeamId}, "")
- return
- }
+ }
- if HandleEtag(data.Etag(), "Get Channel", w, r) {
- return
- } else {
- w.Header().Set(model.HEADER_ETAG_SERVER, data.Etag())
- w.Write([]byte(data.ToJson()))
- }
+ if channel.TeamId != c.TeamId && channel.Type != model.CHANNEL_DIRECT {
+ c.Err = model.NewLocAppError("getChannel", "api.channel.get_channel.wrong_team.app_error", map[string]interface{}{"ChannelId": id, "TeamId": c.TeamId}, "")
+ return
}
-}
-func SetActiveChannel(userId string, channelId string) *model.AppError {
- status, err := app.GetStatus(userId)
- if err != nil {
- status = &model.Status{userId, model.STATUS_ONLINE, false, model.GetMillis(), channelId}
- } else {
- status.ActiveChannel = channelId
- if !status.Manual {
- status.Status = model.STATUS_ONLINE
- }
- status.LastActivityAt = model.GetMillis()
+ var member *model.ChannelMember
+ if member, err = app.GetChannelMember(id, c.Session.UserId); err != nil {
+ c.Err = err
+ return
}
- app.AddStatusCache(status)
+ data := &model.ChannelData{}
+ data.Channel = channel
+ data.Member = member
- return nil
+ if HandleEtag(data.Etag(), "Get Channel", w, r) {
+ return
+ } else {
+ w.Header().Set(model.HEADER_ETAG_SERVER, data.Etag())
+ w.Write([]byte(data.ToJson()))
+ }
}
func getChannelByName(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
channelName := params["channel_name"]
- cchan := app.Srv.Store.Channel().GetByName(c.TeamId, channelName)
-
- if cresult := <-cchan; cresult.Err != nil {
- c.Err = cresult.Err
+ if channel, err := app.GetChannelByName(channelName, c.TeamId); err != nil {
+ c.Err = err
return
} else {
- data := cresult.Data.(*model.Channel)
-
- if !HasPermissionToChannelContext(c, data.Id, model.PERMISSION_READ_CHANNEL) {
+ if !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_READ_CHANNEL) {
return
}
- if data.TeamId != c.TeamId && data.Type != model.CHANNEL_DIRECT {
+ if channel.TeamId != c.TeamId && channel.Type != model.CHANNEL_DIRECT {
c.Err = model.NewLocAppError("getChannel", "api.channel.get_channel.wrong_team.app_error", map[string]interface{}{"ChannelName": channelName, "TeamId": c.TeamId}, "")
return
}
- if HandleEtag(data.Etag(), "Get Channel By Name", w, r) {
+ if HandleEtag(channel.Etag(), "Get Channel By Name", w, r) {
return
} else {
- w.Header().Set(model.HEADER_ETAG_SERVER, data.Etag())
- w.Write([]byte(data.ToJson()))
+ w.Header().Set(model.HEADER_ETAG_SERVER, channel.Etag())
+ w.Write([]byte(channel.ToJson()))
}
}
}
@@ -666,33 +531,29 @@ func getChannelStats(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["channel_id"]
- sc := app.Srv.Store.Channel().Get(id, true)
var channel *model.Channel
- if result := <-sc; result.Err != nil {
- c.Err = result.Err
+ var err *model.AppError
+ if channel, err = app.GetChannel(id); err != nil {
+ c.Err = err
return
- } else {
- channel = result.Data.(*model.Channel)
}
- if result := <-app.Srv.Store.Channel().GetMemberCount(id, true); result.Err != nil {
- c.Err = result.Err
+ if channel.DeleteAt > 0 {
+ c.Err = model.NewLocAppError("getChannelStats", "api.channel.get_channel_extra_info.deleted.app_error", nil, "")
+ c.Err.StatusCode = http.StatusBadRequest
return
- } else {
- memberCount := result.Data.(int64)
-
- if channel.DeleteAt > 0 {
- c.Err = model.NewLocAppError("getChannelStats", "api.channel.get_channel_extra_info.deleted.app_error", nil, "")
- c.Err.StatusCode = http.StatusBadRequest
- return
- }
+ }
- if !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_READ_CHANNEL) {
- return
- }
+ if !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_READ_CHANNEL) {
+ return
+ }
- data := model.ChannelStats{ChannelId: channel.Id, MemberCount: memberCount}
- w.Write([]byte(data.ToJson()))
+ if memberCount, err := app.GetChannelMemberCount(id); err != nil {
+ c.Err = err
+ return
+ } else {
+ stats := model.ChannelStats{ChannelId: channel.Id, MemberCount: memberCount}
+ w.Write([]byte(stats.ToJson()))
}
}
@@ -705,22 +566,20 @@ func getChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-app.Srv.Store.Channel().GetMember(channelId, userId); result.Err != nil {
- c.Err = result.Err
+ if member, err := app.GetChannelMember(channelId, userId); err != nil {
+ c.Err = err
return
} else {
- member := result.Data.(model.ChannelMember)
w.Write([]byte(member.ToJson()))
}
}
func getMyChannelMembers(c *Context, w http.ResponseWriter, r *http.Request) {
- if result := <-app.Srv.Store.Channel().GetMembersForUser(c.TeamId, c.Session.UserId); result.Err != nil {
- c.Err = result.Err
+ if members, err := app.GetChannelMembersForUser(c.TeamId, c.Session.UserId); err != nil {
+ c.Err = err
return
} else {
- data := result.Data.(*model.ChannelMembers)
- w.Write([]byte(data.ToJson()))
+ w.Write([]byte(members.ToJson()))
}
}
@@ -736,47 +595,45 @@ func addMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- sc := app.Srv.Store.Channel().Get(id, true)
- ouc := app.Srv.Store.User().Get(c.Session.UserId)
- nuc := app.Srv.Store.User().Get(userId)
- if nresult := <-nuc; nresult.Err != nil {
- c.Err = model.NewLocAppError("addMember", "api.channel.add_member.find_user.app_error", nil, "")
+ var channel *model.Channel
+ var err *model.AppError
+ if channel, err = app.GetChannel(id); err != nil {
+ c.Err = err
return
- } else if cresult := <-sc; cresult.Err != nil {
- c.Err = model.NewLocAppError("addMember", "api.channel.add_member.find_channel.app_error", nil, "")
+ }
+
+ if channel.Type == model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) {
return
- } else {
- channel := cresult.Data.(*model.Channel)
- nUser := nresult.Data.(*model.User)
+ }
- if channel.Type == model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) {
- return
- }
+ if channel.Type == model.CHANNEL_PRIVATE && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) {
+ return
+ }
- if channel.Type == model.CHANNEL_PRIVATE && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) {
- return
- }
+ var nUser *model.User
+ if nUser, err = app.GetUser(userId); err != nil {
+ c.Err = model.NewLocAppError("addMember", "api.channel.add_member.find_user.app_error", nil, err.Error())
+ return
+ }
- if oresult := <-ouc; oresult.Err != nil {
- c.Err = model.NewLocAppError("addMember", "api.channel.add_member.user_adding.app_error", nil, "")
- return
- } else {
- oUser := oresult.Data.(*model.User)
+ cm, err := app.AddUserToChannel(nUser, channel)
+ if err != nil {
+ c.Err = err
+ return
+ }
- cm, err := app.AddUserToChannel(nUser, channel)
- if err != nil {
- c.Err = err
- return
- }
+ c.LogAudit("name=" + channel.Name + " user_id=" + userId)
- c.LogAudit("name=" + channel.Name + " user_id=" + userId)
+ var oUser *model.User
+ if oUser, err = app.GetUser(c.Session.UserId); err != nil {
+ c.Err = model.NewLocAppError("addMember", "api.channel.add_member.user_adding.app_error", nil, err.Error())
+ return
+ }
- go app.PostUserAddRemoveMessage(c.Session.UserId, channel.Id, channel.TeamId, fmt.Sprintf(utils.T("api.channel.add_member.added"), nUser.Username, oUser.Username), model.POST_ADD_REMOVE)
+ go app.PostUserAddRemoveMessage(c.Session.UserId, channel.Id, channel.TeamId, fmt.Sprintf(utils.T("api.channel.add_member.added"), nUser.Username, oUser.Username), model.POST_ADD_REMOVE)
- <-app.Srv.Store.Channel().UpdateLastViewedAt([]string{id}, oUser.Id)
- w.Write([]byte(cm.ToJson()))
- }
- }
+ app.UpdateChannelLastViewedAt([]string{id}, oUser.Id)
+ w.Write([]byte(cm.ToJson()))
}
func removeMember(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -791,78 +648,45 @@ func removeMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- sc := app.Srv.Store.Channel().Get(channelId, true)
- cmc := app.Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
- ouc := app.Srv.Store.User().Get(userIdToRemove)
-
- if oresult := <-ouc; oresult.Err != nil {
- c.Err = model.NewLocAppError("removeMember", "api.channel.remove_member.user.app_error", nil, "")
+ var channel *model.Channel
+ var err *model.AppError
+ if channel, err = app.GetChannel(channelId); err != nil {
+ c.Err = err
return
- } else {
- oUser := oresult.Data.(*model.User)
-
- if cresult := <-sc; cresult.Err != nil {
- c.Err = cresult.Err
- return
- } else if cmcresult := <-cmc; cmcresult.Err != nil {
- c.Err = cmcresult.Err
- return
- } else {
- channel := cresult.Data.(*model.Channel)
-
- if channel.Type == model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) {
- return
- }
-
- if channel.Type == model.CHANNEL_PRIVATE && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) {
- return
- }
-
- if err := RemoveUserFromChannel(userIdToRemove, c.Session.UserId, channel); err != nil {
- c.Err = model.NewLocAppError("updateChannel", "api.channel.remove_member.unable.app_error", nil, err.Message)
- return
- }
-
- c.LogAudit("name=" + channel.Name + " user_id=" + userIdToRemove)
-
- go app.PostUserAddRemoveMessage(c.Session.UserId, channel.Id, channel.TeamId, fmt.Sprintf(utils.T("api.channel.remove_member.removed"), oUser.Username), model.POST_ADD_REMOVE)
+ }
- result := make(map[string]string)
- result["channel_id"] = channel.Id
- result["removed_user_id"] = userIdToRemove
- w.Write([]byte(model.MapToJson(result)))
- }
+ if channel.Type == model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) {
+ return
}
-}
-func RemoveUserFromChannel(userIdToRemove string, removerUserId string, channel *model.Channel) *model.AppError {
- if channel.DeleteAt > 0 {
- return model.NewLocAppError("RemoveUserFromChannel", "api.channel.remove_user_from_channel.deleted.app_error", nil, "")
+ if channel.Type == model.CHANNEL_PRIVATE && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) {
+ return
}
- if channel.Name == model.DEFAULT_CHANNEL {
- return model.NewLocAppError("RemoveUserFromChannel", "api.channel.remove.default.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "")
+ if _, err = app.GetChannelMember(channel.Id, c.Session.UserId); err != nil {
+ c.Err = err
+ return
}
- if cmresult := <-app.Srv.Store.Channel().RemoveMember(channel.Id, userIdToRemove); cmresult.Err != nil {
- return cmresult.Err
+ if err = app.RemoveUserFromChannel(userIdToRemove, c.Session.UserId, channel); err != nil {
+ c.Err = model.NewLocAppError("removeMember", "api.channel.remove_member.unable.app_error", nil, err.Message)
+ return
}
- app.InvalidateCacheForUser(userIdToRemove)
- app.InvalidateCacheForChannel(channel.Id)
+ c.LogAudit("name=" + channel.Name + " user_id=" + userIdToRemove)
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", channel.Id, "", nil)
- message.Add("user_id", userIdToRemove)
- message.Add("remover_id", removerUserId)
- go app.Publish(message)
+ var user *model.User
+ if user, err = app.GetUser(userIdToRemove); err != nil {
+ c.Err = err
+ return
+ }
- // because the removed user no longer belongs to the channel we need to send a separate websocket event
- userMsg := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", "", userIdToRemove, nil)
- userMsg.Add("channel_id", channel.Id)
- userMsg.Add("remover_id", removerUserId)
- go app.Publish(userMsg)
+ go app.PostUserAddRemoveMessage(c.Session.UserId, channel.Id, channel.TeamId, fmt.Sprintf(utils.T("api.channel.remove_member.removed"), user.Username), model.POST_ADD_REMOVE)
- return nil
+ result := make(map[string]string)
+ result["channel_id"] = channel.Id
+ result["removed_user_id"] = userIdToRemove
+ w.Write([]byte(model.MapToJson(result)))
}
func updateNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -870,13 +694,13 @@ func updateNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) {
userId := data["user_id"]
if len(userId) != 26 {
- c.SetInvalidParam("updateMarkUnreadLevel", "user_id")
+ c.SetInvalidParam("updateNotifyProps", "user_id")
return
}
channelId := data["channel_id"]
if len(channelId) != 26 {
- c.SetInvalidParam("updateMarkUnreadLevel", "channel_id")
+ c.SetInvalidParam("updateNotifyProps", "channel_id")
return
}
@@ -884,33 +708,13 @@ func updateNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- result := <-app.Srv.Store.Channel().GetMember(channelId, userId)
- if result.Err != nil {
- c.Err = result.Err
- return
- }
-
- member := result.Data.(model.ChannelMember)
-
- // update whichever notify properties have been provided, but don't change the others
- if markUnread, exists := data["mark_unread"]; exists {
- member.NotifyProps["mark_unread"] = markUnread
- }
-
- if desktop, exists := data["desktop"]; exists {
- member.NotifyProps["desktop"] = desktop
- }
-
- if result := <-app.Srv.Store.Channel().UpdateMember(&member); result.Err != nil {
- c.Err = result.Err
+ member, err := app.UpdateChannelMemberNotifyProps(data, channelId, userId)
+ if err != nil {
+ c.Err = err
return
- } else {
- app.InvalidateCacheForUser(userId)
-
- // return the updated notify properties including any unchanged ones
- w.Write([]byte(model.MapToJson(member.NotifyProps)))
}
+ w.Write([]byte(model.MapToJson(member.NotifyProps)))
}
func searchMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -931,11 +735,10 @@ func searchMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-app.Srv.Store.Channel().SearchMore(c.Session.UserId, c.TeamId, props.Term); result.Err != nil {
- c.Err = result.Err
+ if channels, err := app.SearchChannelsUserNotIn(c.TeamId, c.Session.UserId, props.Term); err != nil {
+ c.Err = err
return
} else {
- channels := result.Data.(*model.ChannelList)
w.Write([]byte(channels.ToJson()))
}
}
@@ -949,22 +752,19 @@ func autocompleteChannels(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- var channels *model.ChannelList
-
- if result := <-app.Srv.Store.Channel().SearchInTeam(c.TeamId, term); result.Err != nil {
- c.Err = result.Err
+ if channels, err := app.SearchChannels(c.TeamId, term); err != nil {
+ c.Err = err
return
} else {
- channels = result.Data.(*model.ChannelList)
+ w.Write([]byte(channels.ToJson()))
}
- w.Write([]byte(channels.ToJson()))
}
func viewChannel(c *Context, w http.ResponseWriter, r *http.Request) {
view := model.ChannelViewFromJson(r.Body)
- if err := SetActiveChannel(c.Session.UserId, view.ChannelId); err != nil {
+ if err := app.SetActiveChannel(c.Session.UserId, view.ChannelId); err != nil {
c.Err = err
return
}
@@ -974,39 +774,11 @@ func viewChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- channelIds := []string{view.ChannelId}
-
- var pchan store.StoreChannel
- if len(view.PrevChannelId) > 0 {
- channelIds = append(channelIds, view.PrevChannelId)
-
- if *utils.Cfg.EmailSettings.SendPushNotifications && !c.Session.IsMobileApp() {
- pchan = app.Srv.Store.User().GetUnreadCountForChannel(c.Session.UserId, view.ChannelId)
- }
- }
-
- uchan := app.Srv.Store.Channel().UpdateLastViewedAt(channelIds, c.Session.UserId)
-
- if pchan != nil {
- if result := <-pchan; result.Err != nil {
- c.Err = result.Err
- return
- } else {
- if result.Data.(int64) > 0 {
- app.ClearPushNotification(c.Session.UserId, view.ChannelId)
- }
- }
- }
-
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
+ if err := app.ViewChannel(view, c.TeamId, c.Session.UserId, !c.Session.IsMobileApp()); err != nil {
+ c.Err = err
return
}
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, c.TeamId, "", c.Session.UserId, nil)
- message.Add("channel_id", view.ChannelId)
- go app.Publish(message)
-
ReturnStatusOK(w)
}
@@ -1024,13 +796,11 @@ func getChannelMembersByIds(c *Context, w http.ResponseWriter, r *http.Request)
return
}
- if result := <-app.Srv.Store.Channel().GetMembersByIds(channelId, userIds); result.Err != nil {
- c.Err = result.Err
+ if members, err := app.GetChannelMembersByIds(channelId, userIds); err != nil {
+ c.Err = err
return
} else {
- members := result.Data.(model.ChannelMembers)
w.Write([]byte(members.ToJson()))
- return
}
}
@@ -1046,35 +816,21 @@ func updateChannelMemberRoles(c *Context, w http.ResponseWriter, r *http.Request
return
}
- mchan := app.Srv.Store.Channel().GetMember(channelId, userId)
-
- newRoles := props["new_roles"]
- if !(model.IsValidUserRoles(newRoles)) {
- c.SetInvalidParam("updateChannelMemberRoles", "new_roles")
- return
- }
-
if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_MANAGE_CHANNEL_ROLES) {
return
}
- var member model.ChannelMember
- if result := <-mchan; result.Err != nil {
- c.Err = result.Err
+ newRoles := props["new_roles"]
+ if !(model.IsValidUserRoles(newRoles)) {
+ c.SetInvalidParam("updateChannelMemberRoles", "new_roles")
return
- } else {
- member = result.Data.(model.ChannelMember)
}
- member.Roles = newRoles
-
- if result := <-app.Srv.Store.Channel().UpdateMember(&member); result.Err != nil {
- c.Err = result.Err
+ if _, err := app.UpdateChannelMemberRoles(channelId, userId, newRoles); err != nil {
+ c.Err = err
return
}
- app.InvalidateCacheForUser(userId)
-
rdata := map[string]string{}
rdata["status"] = "ok"
w.Write([]byte(model.MapToJson(rdata)))
diff --git a/api/command_invite_people.go b/api/command_invite_people.go
index f3818628f..ef2449ebc 100644
--- a/api/command_invite_people.go
+++ b/api/command_invite_people.go
@@ -41,9 +41,6 @@ func (me *InvitePeopleProvider) DoCommand(c *Context, args *model.CommandArgs, m
return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: c.T("api.command.invite_people.email_off")}
}
- tchan := app.Srv.Store.Team().Get(c.TeamId)
- uchan := app.Srv.Store.User().Get(c.Session.UserId)
-
emailList := strings.Fields(message)
for i := len(emailList) - 1; i >= 0; i-- {
@@ -57,23 +54,10 @@ func (me *InvitePeopleProvider) DoCommand(c *Context, args *model.CommandArgs, m
return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: c.T("api.command.invite_people.no_email")}
}
- var team *model.Team
- if result := <-tchan; result.Err != nil {
- c.Err = result.Err
+ if err := app.InviteNewUsersToTeam(emailList, c.TeamId, c.Session.UserId, c.GetSiteURL()); err != nil {
+ c.Err = err
return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: c.T("api.command.invite_people.fail")}
- } else {
- team = result.Data.(*model.Team)
}
- var user *model.User
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
- return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: c.T("api.command.invite_people.fail")}
- } else {
- user = result.Data.(*model.User)
- }
-
- go InviteMembers(team, user.GetDisplayName(), emailList, c.GetSiteURL())
-
return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: c.T("api.command.invite_people.sent")}
}
diff --git a/api/context.go b/api/context.go
index 349cbd5b6..e77f6da24 100644
--- a/api/context.go
+++ b/api/context.go
@@ -26,9 +26,9 @@ type Context struct {
IpAddress string
Path string
Err *model.AppError
+ siteURL string
teamURLValid bool
teamURL string
- siteURL string
T goi18n.TranslateFunc
Locale string
TeamId string
diff --git a/api/deprecated.go b/api/deprecated.go
index bbaafdf15..765c3aac1 100644
--- a/api/deprecated.go
+++ b/api/deprecated.go
@@ -72,7 +72,7 @@ func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
}
go func() {
- if err := SetActiveChannel(c.Session.UserId, id); err != nil {
+ if err := app.SetActiveChannel(c.Session.UserId, id); err != nil {
l4g.Error(err.Error())
}
}()
@@ -155,7 +155,7 @@ func setActiveChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if err := SetActiveChannel(c.Session.UserId, channelId); err != nil {
+ if err := app.SetActiveChannel(c.Session.UserId, channelId); err != nil {
c.Err = err
return
}
diff --git a/api/file.go b/api/file.go
index b0cedde40..fdc9a8747 100644
--- a/api/file.go
+++ b/api/file.go
@@ -46,8 +46,6 @@ const (
RotatedCCW = 6
RotatedCCWMirrored = 7
RotatedCW = 8
-
- MaxImageSize = 6048 * 4032 // 24 megapixels, roughly 36MB as a raw image
)
func InitFile() {
@@ -162,7 +160,7 @@ func doUploadFile(teamId string, channelId string, userId string, rawFilename st
if info.IsImage() {
// Check dimensions before loading the whole thing into memory later on
- if info.Width*info.Height > MaxImageSize {
+ if info.Width*info.Height > model.MaxImageSize {
err := model.NewLocAppError("uploadFile", "api.file.upload_file.large_image.app_error", map[string]interface{}{"Filename": filename}, "")
err.StatusCode = http.StatusBadRequest
return nil, err
diff --git a/api/oauth.go b/api/oauth.go
index b378eb2a3..538831ee0 100644
--- a/api/oauth.go
+++ b/api/oauth.go
@@ -830,17 +830,22 @@ func CompleteSwitchWithOAuth(c *Context, w http.ResponseWriter, r *http.Request,
user = result.Data.(*model.User)
}
- RevokeAllSession(c, user.Id)
- if c.Err != nil {
+ if err := app.RevokeAllSessions(user.Id); err != nil {
+ c.Err = err
return
}
+ c.LogAuditWithUserId(user.Id, "Revoked all sessions for user")
if result := <-app.Srv.Store.User().UpdateAuthData(user.Id, service, &authData, ssoEmail, true); result.Err != nil {
c.Err = result.Err
return
}
- go sendSignInChangeEmail(c, user.Email, c.GetSiteURL(), strings.Title(service)+" SSO")
+ go func() {
+ if err := app.SendSignInChangeEmail(user.Email, strings.Title(service)+" SSO", user.Locale, c.GetSiteURL()); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
}
func deleteOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
diff --git a/api/slackimport.go b/api/slackimport.go
index 9d432b987..a7d50b1b9 100644
--- a/api/slackimport.go
+++ b/api/slackimport.go
@@ -413,7 +413,7 @@ func SlackUploadFile(sPost SlackPost, uploads map[string]*zip.File, teamId strin
}
func deactivateSlackBotUser(user *model.User) {
- _, err := UpdateActive(user, false)
+ _, err := app.UpdateActive(user, false)
if err != nil {
l4g.Warn(utils.T("api.slackimport.slack_deactivate_bot_user.failed_to_deactivate", err))
}
diff --git a/api/team.go b/api/team.go
index 6f907a513..574c22de5 100644
--- a/api/team.go
+++ b/api/team.go
@@ -5,11 +5,8 @@ package api
import (
"bytes"
- "fmt"
- "html/template"
"io"
"net/http"
- "net/url"
"strconv"
"strings"
@@ -18,7 +15,6 @@ import (
"github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
- "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
)
@@ -61,14 +57,12 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
}
var user *model.User
+ var err *model.AppError
if len(c.Session.UserId) > 0 {
- uchan := app.Srv.Store.User().Get(c.Session.UserId)
-
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
+ if user, err = app.GetUser(c.Session.UserId); err != nil {
+ c.Err = err
return
} else {
- user = result.Data.(*model.User)
team.Email = user.Email
}
}
@@ -94,66 +88,6 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(rteam.ToJson()))
}
-func LeaveTeam(team *model.Team, user *model.User) *model.AppError {
-
- var teamMember model.TeamMember
-
- if result := <-app.Srv.Store.Team().GetMember(team.Id, user.Id); result.Err != nil {
- return model.NewLocAppError("RemoveUserFromTeam", "api.team.remove_user_from_team.missing.app_error", nil, result.Err.Error())
- } else {
- teamMember = result.Data.(model.TeamMember)
- }
-
- var channelList *model.ChannelList
-
- if result := <-app.Srv.Store.Channel().GetChannels(team.Id, user.Id); result.Err != nil {
- if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" {
- channelList = &model.ChannelList{}
- } else {
- return result.Err
- }
-
- } else {
- channelList = result.Data.(*model.ChannelList)
- }
-
- for _, channel := range *channelList {
- if channel.Type != model.CHANNEL_DIRECT {
- app.InvalidateCacheForChannel(channel.Id)
- if result := <-app.Srv.Store.Channel().RemoveMember(channel.Id, user.Id); result.Err != nil {
- return result.Err
- }
- }
- }
-
- // Send the websocket message before we actually do the remove so the user being removed gets it.
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_LEAVE_TEAM, team.Id, "", "", nil)
- message.Add("user_id", user.Id)
- message.Add("team_id", team.Id)
- app.Publish(message)
-
- teamMember.Roles = ""
- teamMember.DeleteAt = model.GetMillis()
-
- if result := <-app.Srv.Store.Team().UpdateMember(&teamMember); result.Err != nil {
- return result.Err
- }
-
- if uua := <-app.Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
- return uua.Err
- }
-
- // delete the preferences that set the last channel used in the team and other team specific preferences
- if result := <-app.Srv.Store.Preference().DeleteCategory(user.Id, team.Id); result.Err != nil {
- return result.Err
- }
-
- app.RemoveAllSessionsForUserId(user.Id)
- app.InvalidateCacheForUser(user.Id)
-
- return nil
-}
-
func isTeamCreationAllowed(c *Context, email string) bool {
email = strings.ToLower(email)
@@ -164,8 +98,7 @@ func isTeamCreationAllowed(c *Context, email string) bool {
}
c.Err = nil
- if result := <-app.Srv.Store.User().GetByEmail(email); result.Err == nil {
- user := result.Data.(*model.User)
+ if user, err := app.GetUserByEmail(email); err == nil {
if len(user.AuthService) > 0 && len(*user.AuthData) > 0 {
return true
}
@@ -192,77 +125,50 @@ func isTeamCreationAllowed(c *Context, email string) bool {
}
func GetAllTeamListings(c *Context, w http.ResponseWriter, r *http.Request) {
- if result := <-app.Srv.Store.Team().GetAllTeamListing(); result.Err != nil {
- c.Err = result.Err
+ var teams []*model.Team
+ var err *model.AppError
+
+ if teams, err = app.GetAllOpenTeams(); err != nil {
+ c.Err = err
return
- } else {
- teams := result.Data.([]*model.Team)
- m := make(map[string]*model.Team)
- for _, v := range teams {
- m[v.Id] = v
- if !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
- m[v.Id].Sanitize()
- }
- c.Err = nil
- }
+ }
- w.Write([]byte(model.TeamMapToJson(m)))
+ m := make(map[string]*model.Team)
+ for _, v := range teams {
+ m[v.Id] = v
+ if !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
+ m[v.Id].Sanitize()
+ }
+ c.Err = nil
}
+
+ w.Write([]byte(model.TeamMapToJson(m)))
}
// Gets all teams which the current user can has access to. If the user is a System Admin, this will be all teams
// on the server. Otherwise, it will only be the teams of which the user is a member.
func getAll(c *Context, w http.ResponseWriter, r *http.Request) {
- var tchan store.StoreChannel
+ var teams []*model.Team
+ var err *model.AppError
+
if HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
- tchan = app.Srv.Store.Team().GetAll()
+ teams, err = app.GetAllTeams()
} else {
c.Err = nil
- tchan = app.Srv.Store.Team().GetTeamsByUserId(c.Session.UserId)
+ teams, err = app.GetTeamsForUser(c.Session.UserId)
}
- if result := <-tchan; result.Err != nil {
- c.Err = result.Err
+ if err != nil {
+ c.Err = err
return
- } else {
- teams := result.Data.([]*model.Team)
- m := make(map[string]*model.Team)
- for _, v := range teams {
- m[v.Id] = v
- }
-
- w.Write([]byte(model.TeamMapToJson(m)))
}
-}
-
-func revokeAllSessions(c *Context, w http.ResponseWriter, r *http.Request) {
- props := model.MapFromJson(r.Body)
- id := props["id"]
- if result := <-app.Srv.Store.Session().Get(id); result.Err != nil {
- c.Err = result.Err
- return
- } else {
- session := result.Data.(*model.Session)
-
- c.LogAudit("revoked_all=" + id)
-
- if session.IsOAuth {
- if err := app.RevokeAccessToken(session.Token); err != nil {
- c.Err = err
- return
- }
- } else {
- if result := <-app.Srv.Store.Session().Remove(session.Id); result.Err != nil {
- c.Err = result.Err
- return
- } else {
- app.RemoveAllSessionsForUserId(session.UserId)
- w.Write([]byte(model.MapToJson(props)))
- return
- }
- }
+ m := make(map[string]*model.Team)
+ for _, v := range teams {
+ m[v.Id] = v
}
+
+ w.Write([]byte(model.TeamMapToJson(m)))
}
func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -286,31 +192,15 @@ func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- tchan := app.Srv.Store.Team().Get(c.TeamId)
- uchan := app.Srv.Store.User().Get(c.Session.UserId)
-
- var team *model.Team
- if result := <-tchan; result.Err != nil {
- c.Err = result.Err
- return
- } else {
- team = result.Data.(*model.Team)
- }
-
- var user *model.User
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
- return
- } else {
- user = result.Data.(*model.User)
- }
-
emailList := make([]string, len(invites.Invites))
for _, invite := range invites.Invites {
emailList = append(emailList, invite["email"])
}
- InviteMembers(team, user.GetDisplayName(), emailList, c.GetSiteURL())
+ if err := app.InviteNewUsersToTeam(emailList, c.TeamId, c.Session.UserId, c.GetSiteURL()); err != nil {
+ c.Err = err
+ return
+ }
w.Write([]byte(invites.ToJson()))
}
@@ -324,31 +214,24 @@ func addUserToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- tchan := app.Srv.Store.Team().Get(c.TeamId)
- uchan := app.Srv.Store.User().Get(userId)
-
var team *model.Team
- if result := <-tchan; result.Err != nil {
- c.Err = result.Err
+ var err *model.AppError
+ if team, err = app.GetTeam(c.TeamId); err != nil {
+ c.Err = err
return
- } else {
- team = result.Data.(*model.Team)
}
- var user *model.User
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
+ if !HasPermissionToTeamContext(c, team.Id, model.PERMISSION_ADD_USER_TO_TEAM) {
return
- } else {
- user = result.Data.(*model.User)
}
- if !HasPermissionToTeamContext(c, team.Id, model.PERMISSION_ADD_USER_TO_TEAM) {
+ var user *model.User
+ if user, err = app.GetUser(userId); err != nil {
+ c.Err = err
return
}
- err := app.JoinUserToTeam(team, user)
- if err != nil {
+ if err := app.JoinUserToTeam(team, user); err != nil {
c.Err = err
return
}
@@ -365,23 +248,17 @@ func removeUserFromTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- tchan := app.Srv.Store.Team().Get(c.TeamId)
- uchan := app.Srv.Store.User().Get(userId)
-
var team *model.Team
- if result := <-tchan; result.Err != nil {
- c.Err = result.Err
+ var err *model.AppError
+ if team, err = app.GetTeam(c.TeamId); err != nil {
+ c.Err = err
return
- } else {
- team = result.Data.(*model.Team)
}
var user *model.User
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
+ if user, err = app.GetUser(userId); err != nil {
+ c.Err = err
return
- } else {
- user = result.Data.(*model.User)
}
if c.Session.UserId != user.Id {
@@ -390,8 +267,7 @@ func removeUserFromTeam(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- err := LeaveTeam(team, user)
- if err != nil {
+ if err := app.LeaveTeam(team, user); err != nil {
c.Err = err
return
}
@@ -400,73 +276,26 @@ func removeUserFromTeam(c *Context, w http.ResponseWriter, r *http.Request) {
}
func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request) {
-
params := model.MapFromJson(r.Body)
hash := params["hash"]
data := params["data"]
inviteId := params["invite_id"]
- teamId := ""
var team *model.Team
+ var err *model.AppError
if len(hash) > 0 {
- props := model.MapFromJson(strings.NewReader(data))
-
- if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) {
- c.Err = model.NewLocAppError("addUserToTeamFromInvite", "api.user.create_user.signup_link_invalid.app_error", nil, "")
- return
- }
-
- t, err := strconv.ParseInt(props["time"], 10, 64)
- if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours
- c.Err = model.NewLocAppError("addUserToTeamFromInvite", "api.user.create_user.signup_link_expired.app_error", nil, "")
- return
- }
-
- teamId = props["id"]
-
- // try to load the team to make sure it exists
- if result := <-app.Srv.Store.Team().Get(teamId); result.Err != nil {
- c.Err = result.Err
- return
- } else {
- team = result.Data.(*model.Team)
- }
- }
-
- if len(inviteId) > 0 {
- if result := <-app.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
- c.Err = result.Err
- return
- } else {
- team = result.Data.(*model.Team)
- teamId = team.Id
- }
- }
-
- if len(teamId) == 0 {
+ team, err = app.JoinUserToTeamByHash(c.Session.UserId, hash, data)
+ } else if len(inviteId) > 0 {
+ team, err = app.JoinUserToTeamByInviteId(inviteId, c.Session.UserId)
+ } else {
c.Err = model.NewLocAppError("addUserToTeamFromInvite", "api.user.create_user.signup_link_invalid.app_error", nil, "")
return
}
- uchan := app.Srv.Store.User().Get(c.Session.UserId)
-
- var user *model.User
- if result := <-uchan; result.Err != nil {
- c.Err = result.Err
+ if err != nil {
+ c.Err = err
return
- } else {
- user = result.Data.(*model.User)
- }
-
- tm := c.Session.GetTeamByTeamId(teamId)
-
- if tm == nil {
- err := app.JoinUserToTeam(team, user)
- if err != nil {
- c.Err = err
- return
- }
}
team.Sanitize()
@@ -474,20 +303,12 @@ func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request)
w.Write([]byte(team.ToJson()))
}
-func FindTeamByName(name string) bool {
- if result := <-app.Srv.Store.Team().GetByName(name); result.Err != nil {
- return false
- } else {
- return true
- }
-}
-
func findTeamByName(c *Context, w http.ResponseWriter, r *http.Request) {
m := model.MapFromJson(r.Body)
name := strings.ToLower(strings.TrimSpace(m["name"]))
- found := FindTeamByName(name)
+ found := app.FindTeamByName(name)
if found {
w.Write([]byte("true"))
@@ -500,12 +321,10 @@ func getTeamByName(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
teamname := params["team_name"]
- if result := <-app.Srv.Store.Team().GetByName(teamname); result.Err != nil {
- c.Err = result.Err
+ if team, err := app.GetTeamByName(teamname); err != nil {
+ c.Err = err
return
} else {
- team := result.Data.(*model.Team)
-
if team.Type != model.TEAM_OPEN && c.Session.GetTeamByTeamId(team.Id) == nil {
if !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
return
@@ -521,12 +340,11 @@ func getMyTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
if len(c.Session.TeamMembers) > 0 {
w.Write([]byte(model.TeamMembersToJson(c.Session.TeamMembers)))
} else {
- if result := <-app.Srv.Store.Team().GetTeamsForUser(c.Session.UserId); result.Err != nil {
- c.Err = result.Err
+ if members, err := app.GetTeamMembersForUser(c.Session.UserId); err != nil {
+ c.Err = err
return
} else {
- data := result.Data.([]*model.TeamMember)
- w.Write([]byte(model.TeamMembersToJson(data)))
+ w.Write([]byte(model.TeamMembersToJson(members)))
}
}
}
@@ -534,79 +352,11 @@ func getMyTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
func getMyTeamsUnread(c *Context, w http.ResponseWriter, r *http.Request) {
teamId := r.URL.Query().Get("id")
- if result := <-app.Srv.Store.Team().GetTeamsUnreadForUser(teamId, c.Session.UserId); result.Err != nil {
- c.Err = result.Err
+ if unreads, err := app.GetTeamsUnreadForUser(teamId, c.Session.UserId); err != nil {
+ c.Err = err
return
} else {
- data := result.Data.([]*model.ChannelUnread)
- var members []*model.TeamUnread
- membersMap := make(map[string]*model.TeamUnread)
-
- unreads := func(cu *model.ChannelUnread, tu *model.TeamUnread) *model.TeamUnread {
- tu.MentionCount += cu.MentionCount
-
- if cu.NotifyProps["mark_unread"] != model.CHANNEL_MARK_UNREAD_MENTION {
- tu.MsgCount += (cu.TotalMsgCount - cu.MsgCount)
- }
-
- return tu
- }
-
- for i := range data {
- id := data[i].TeamId
- if mu, ok := membersMap[id]; ok {
- membersMap[id] = unreads(data[i], mu)
- } else {
- membersMap[id] = unreads(data[i], &model.TeamUnread{
- MsgCount: 0,
- MentionCount: 0,
- TeamId: id,
- })
- }
- }
-
- for _, val := range membersMap {
- members = append(members, val)
- }
- w.Write([]byte(model.TeamsUnreadToJson(members)))
- }
-}
-
-func InviteMembers(team *model.Team, senderName string, invites []string, siteURL string) {
- for _, invite := range invites {
- if len(invite) > 0 {
- senderRole := utils.T("api.team.invite_members.member")
-
- subject := utils.T("api.templates.invite_subject",
- map[string]interface{}{"SenderName": senderName, "TeamDisplayName": team.DisplayName, "SiteName": utils.ClientCfg["SiteName"]})
-
- bodyPage := utils.NewHTMLTemplate("invite_body", model.DEFAULT_LOCALE)
- bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["Title"] = utils.T("api.templates.invite_body.title")
- bodyPage.Html["Info"] = template.HTML(utils.T("api.templates.invite_body.info",
- map[string]interface{}{"SenderStatus": senderRole, "SenderName": senderName, "TeamDisplayName": team.DisplayName}))
- bodyPage.Props["Button"] = utils.T("api.templates.invite_body.button")
- bodyPage.Html["ExtraInfo"] = template.HTML(utils.T("api.templates.invite_body.extra_info",
- map[string]interface{}{"TeamDisplayName": team.DisplayName, "TeamURL": siteURL + "/" + team.Name}))
-
- props := make(map[string]string)
- props["email"] = invite
- props["id"] = team.Id
- props["display_name"] = team.DisplayName
- props["name"] = team.Name
- props["time"] = fmt.Sprintf("%v", model.GetMillis())
- data := model.MapToJson(props)
- hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt))
- bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", siteURL, url.QueryEscape(data), url.QueryEscape(hash))
-
- if !utils.Cfg.EmailSettings.SendEmailNotifications {
- l4g.Info(utils.T("api.team.invite_members.sending.info"), invite, bodyPage.Props["Link"])
- }
-
- if err := utils.SendMail(invite, subject, bodyPage.Render()); err != nil {
- l4g.Error(utils.T("api.team.invite_members.send.error"), err)
- }
- }
+ w.Write([]byte(model.TeamsUnreadToJson(unreads)))
}
}
@@ -627,34 +377,22 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- var oldTeam *model.Team
- if result := <-app.Srv.Store.Team().Get(team.Id); result.Err != nil {
- c.Err = result.Err
- return
- } else {
- oldTeam = result.Data.(*model.Team)
- }
-
- oldTeam.DisplayName = team.DisplayName
- oldTeam.Description = team.Description
- oldTeam.InviteId = team.InviteId
- oldTeam.AllowOpenInvite = team.AllowOpenInvite
- oldTeam.CompanyName = team.CompanyName
- oldTeam.AllowedDomains = team.AllowedDomains
- //oldTeam.Type = team.Type
+ var err *model.AppError
+ var updatedTeam *model.Team
- if result := <-app.Srv.Store.Team().Update(oldTeam); result.Err != nil {
- c.Err = result.Err
+ updatedTeam, err = app.UpdateTeam(team)
+ if err != nil {
+ c.Err = err
return
}
- oldTeam.Sanitize()
+ updatedTeam.Sanitize()
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_UPDATE_TEAM, "", "", "", nil)
- message.Add("team", oldTeam.ToJson())
+ message.Add("team", updatedTeam.ToJson())
go app.Publish(message)
- w.Write([]byte(oldTeam.ToJson()))
+ w.Write([]byte(updatedTeam.ToJson()))
}
func updateMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -666,8 +404,6 @@ func updateMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- mchan := app.Srv.Store.Team().GetTeamsForUser(userId)
-
teamId := c.TeamId
newRoles := props["new_roles"]
@@ -680,74 +416,30 @@ func updateMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- var member *model.TeamMember
- if result := <-mchan; result.Err != nil {
- c.Err = result.Err
- return
- } else {
- members := result.Data.([]*model.TeamMember)
- for _, m := range members {
- if m.TeamId == teamId {
- member = m
- }
- }
- }
-
- if member == nil {
- c.Err = model.NewLocAppError("updateMemberRoles", "api.team.update_member_roles.not_a_member", nil, "userId="+userId+" teamId="+teamId)
- c.Err.StatusCode = http.StatusBadRequest
- return
- }
-
- member.Roles = newRoles
-
- if result := <-app.Srv.Store.Team().UpdateMember(member); result.Err != nil {
- c.Err = result.Err
+ if _, err := app.UpdateTeamMemberRoles(teamId, userId, newRoles); err != nil {
+ c.Err = err
return
}
- app.RemoveAllSessionsForUserId(userId)
-
rdata := map[string]string{}
rdata["status"] = "ok"
w.Write([]byte(model.MapToJson(rdata)))
}
-func PermanentDeleteTeam(team *model.Team) *model.AppError {
- team.DeleteAt = model.GetMillis()
- if result := <-app.Srv.Store.Team().Update(team); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.Channel().PermanentDeleteByTeam(team.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.Team().RemoveAllMembersByTeam(team.Id); result.Err != nil {
- return result.Err
- }
-
- if result := <-app.Srv.Store.Team().PermanentDelete(team.Id); result.Err != nil {
- return result.Err
- }
-
- return nil
-}
-
func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) {
if len(c.TeamId) == 0 {
return
}
- if result := <-app.Srv.Store.Team().Get(c.TeamId); result.Err != nil {
- c.Err = result.Err
+ if team, err := app.GetTeam(c.TeamId); err != nil {
+ c.Err = err
return
- } else if HandleEtag(result.Data.(*model.Team).Etag(), "Get My Team", w, r) {
+ } else if HandleEtag(team.Etag(), "Get My Team", w, r) {
return
} else {
- w.Header().Set(model.HEADER_ETAG_SERVER, result.Data.(*model.Team).Etag())
- w.Write([]byte(result.Data.(*model.Team).ToJson()))
+ w.Header().Set(model.HEADER_ETAG_SERVER, team.Etag())
+ w.Write([]byte(team.ToJson()))
return
}
}
@@ -759,24 +451,10 @@ func getTeamStats(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- tchan := app.Srv.Store.Team().GetTotalMemberCount(c.TeamId)
- achan := app.Srv.Store.Team().GetActiveMemberCount(c.TeamId)
-
- stats := &model.TeamStats{}
- stats.TeamId = c.TeamId
-
- if result := <-tchan; result.Err != nil {
- c.Err = result.Err
- return
- } else {
- stats.TotalMemberCount = result.Data.(int64)
- }
-
- if result := <-achan; result.Err != nil {
- c.Err = result.Err
+ stats, err := app.GetTeamStats(c.TeamId)
+ if err != nil {
+ c.Err = err
return
- } else {
- stats.ActiveMemberCount = result.Data.(int64)
}
w.Write([]byte(stats.ToJson()))
@@ -857,11 +535,10 @@ func getInviteInfo(c *Context, w http.ResponseWriter, r *http.Request) {
m := model.MapFromJson(r.Body)
inviteId := m["invite_id"]
- if result := <-app.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
- c.Err = result.Err
+ if team, err := app.GetTeamByInviteId(inviteId); err != nil {
+ c.Err = err
return
} else {
- team := result.Data.(*model.Team)
if !(team.Type == model.TEAM_OPEN) {
c.Err = model.NewLocAppError("getInviteInfo", "api.team.get_invite_info.not_open_team", nil, "id="+inviteId)
return
@@ -897,11 +574,10 @@ func getTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if result := <-app.Srv.Store.Team().GetMembers(c.TeamId, offset, limit); result.Err != nil {
- c.Err = result.Err
+ if members, err := app.GetTeamMembers(c.TeamId, offset, limit); err != nil {
+ c.Err = err
return
} else {
- members := result.Data.([]*model.TeamMember)
w.Write([]byte(model.TeamMembersToJson(members)))
return
}
@@ -922,11 +598,10 @@ func getTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if result := <-app.Srv.Store.Team().GetMember(c.TeamId, userId); result.Err != nil {
- c.Err = result.Err
+ if member, err := app.GetTeamMember(c.TeamId, userId); err != nil {
+ c.Err = err
return
} else {
- member := result.Data.(model.TeamMember)
w.Write([]byte(member.ToJson()))
return
}
@@ -945,11 +620,10 @@ func getTeamMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
- if result := <-app.Srv.Store.Team().GetMembersByIds(c.TeamId, userIds); result.Err != nil {
- c.Err = result.Err
+ if members, err := app.GetTeamMembersByIds(c.TeamId, userIds); err != nil {
+ c.Err = err
return
} else {
- members := result.Data.([]*model.TeamMember)
w.Write([]byte(model.TeamMembersToJson(members)))
return
}
diff --git a/api/team_test.go b/api/team_test.go
index 641f7b98d..fdc7e334b 100644
--- a/api/team_test.go
+++ b/api/team_test.go
@@ -191,7 +191,7 @@ func TestGetAllTeamListings(t *testing.T) {
}
}
- UpdateUserRoles(user, model.ROLE_SYSTEM_ADMIN.Id)
+ app.UpdateUserRoles(user.Id, model.ROLE_SYSTEM_ADMIN.Id)
Client.Login(user.Email, "passwd1")
Client.SetTeamId(team.Id)
@@ -244,7 +244,7 @@ func TestTeamPermDelete(t *testing.T) {
c.RequestId = model.NewId()
c.IpAddress = "test"
- err := PermanentDeleteTeam(team)
+ err := app.PermanentDeleteTeam(team)
if err != nil {
t.Fatal(err)
}
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)))
diff --git a/api/user_test.go b/api/user_test.go
index 56064232b..96d1fd3d0 100644
--- a/api/user_test.go
+++ b/api/user_test.go
@@ -508,7 +508,7 @@ func TestGetUser(t *testing.T) {
t.Fatal("shouldn't have accss")
}
- UpdateUserRoles(ruser.Data.(*model.User), model.ROLE_SYSTEM_ADMIN.Id)
+ app.UpdateUserRoles(ruser.Data.(*model.User).Id, model.ROLE_SYSTEM_ADMIN.Id)
Client.Login(user.Email, "passwd1")
@@ -1226,7 +1226,7 @@ func TestUserPermDelete(t *testing.T) {
c.RequestId = model.NewId()
c.IpAddress = "test"
- err := PermanentDeleteUser(user1)
+ err := app.PermanentDeleteUser(user1)
if err != nil {
t.Fatal(err)
}
diff --git a/app/channel.go b/app/channel.go
index aa84e12be..b8e02a149 100644
--- a/app/channel.go
+++ b/app/channel.go
@@ -5,6 +5,7 @@ package app
import (
"fmt"
+ "net/http"
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/model"
@@ -190,6 +191,128 @@ func CreateDirectChannel(userId string, otherUserId string) (*model.Channel, *mo
}
}
+func UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppError) {
+ if result := <-Srv.Store.Channel().Update(channel); result.Err != nil {
+ return nil, result.Err
+ } else {
+ InvalidateCacheForChannel(channel.Id)
+ return channel, nil
+ }
+}
+
+func UpdateChannelMemberRoles(channelId string, userId string, newRoles string) (*model.ChannelMember, *model.AppError) {
+ var member *model.ChannelMember
+ var err *model.AppError
+ if member, err = GetChannelMember(channelId, userId); err != nil {
+ return nil, err
+ }
+
+ member.Roles = newRoles
+
+ if result := <-Srv.Store.Channel().UpdateMember(member); result.Err != nil {
+ return nil, result.Err
+ }
+
+ InvalidateCacheForUser(userId)
+ return member, nil
+}
+
+func UpdateChannelMemberNotifyProps(data map[string]string, channelId string, userId string) (*model.ChannelMember, *model.AppError) {
+ var member *model.ChannelMember
+ var err *model.AppError
+ if member, err = GetChannelMember(channelId, userId); err != nil {
+ return nil, err
+ }
+
+ // update whichever notify properties have been provided, but don't change the others
+ if markUnread, exists := data["mark_unread"]; exists {
+ member.NotifyProps["mark_unread"] = markUnread
+ }
+
+ if desktop, exists := data["desktop"]; exists {
+ member.NotifyProps["desktop"] = desktop
+ }
+
+ if result := <-Srv.Store.Channel().UpdateMember(member); result.Err != nil {
+ return nil, result.Err
+ } else {
+ InvalidateCacheForUser(userId)
+ return member, nil
+ }
+}
+
+func DeleteChannel(channel *model.Channel, userId string) *model.AppError {
+ uc := Srv.Store.User().Get(userId)
+ scm := Srv.Store.Channel().GetMember(channel.Id, userId)
+ ihc := Srv.Store.Webhook().GetIncomingByChannel(channel.Id)
+ ohc := Srv.Store.Webhook().GetOutgoingByChannel(channel.Id)
+
+ if uresult := <-uc; uresult.Err != nil {
+ return uresult.Err
+ } else if scmresult := <-scm; scmresult.Err != nil {
+ return scmresult.Err
+ } else if ihcresult := <-ihc; ihcresult.Err != nil {
+ return ihcresult.Err
+ } else if ohcresult := <-ohc; ohcresult.Err != nil {
+ return ohcresult.Err
+ } else {
+ user := uresult.Data.(*model.User)
+ incomingHooks := ihcresult.Data.([]*model.IncomingWebhook)
+ outgoingHooks := ohcresult.Data.([]*model.OutgoingWebhook)
+ // Don't need to do anything with channel member, just wanted to confirm it exists
+
+ if channel.DeleteAt > 0 {
+ err := model.NewLocAppError("deleteChannel", "api.channel.delete_channel.deleted.app_error", nil, "")
+ err.StatusCode = http.StatusBadRequest
+ return err
+ }
+
+ if channel.Name == model.DEFAULT_CHANNEL {
+ err := model.NewLocAppError("deleteChannel", "api.channel.delete_channel.cannot.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "")
+ err.StatusCode = http.StatusBadRequest
+ return err
+ }
+
+ T := utils.GetUserTranslations(user.Locale)
+
+ post := &model.Post{
+ ChannelId: channel.Id,
+ Message: fmt.Sprintf(T("api.channel.delete_channel.archived"), user.Username),
+ Type: model.POST_CHANNEL_DELETED,
+ UserId: userId,
+ }
+
+ if _, err := CreatePost(post, channel.TeamId, false); err != nil {
+ l4g.Error(utils.T("api.channel.delete_channel.failed_post.error"), err)
+ }
+
+ now := model.GetMillis()
+ for _, hook := range incomingHooks {
+ if result := <-Srv.Store.Webhook().DeleteIncoming(hook.Id, now); result.Err != nil {
+ l4g.Error(utils.T("api.channel.delete_channel.incoming_webhook.error"), hook.Id)
+ }
+ }
+
+ for _, hook := range outgoingHooks {
+ if result := <-Srv.Store.Webhook().DeleteOutgoing(hook.Id, now); result.Err != nil {
+ l4g.Error(utils.T("api.channel.delete_channel.outgoing_webhook.error"), hook.Id)
+ }
+ }
+
+ if dresult := <-Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); dresult.Err != nil {
+ return dresult.Err
+ }
+ InvalidateCacheForChannel(channel.Id)
+
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_DELETED, channel.TeamId, "", "", nil)
+ message.Add("channel_id", channel.Id)
+
+ Publish(message)
+ }
+
+ return nil
+}
+
func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelMember, *model.AppError) {
if channel.DeleteAt > 0 {
return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user_to_channel.deleted.app_error", nil, "")
@@ -205,7 +328,7 @@ func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelM
if result := <-tmchan; result.Err != nil {
return nil, result.Err
} else {
- teamMember := result.Data.(model.TeamMember)
+ teamMember := result.Data.(*model.TeamMember)
if teamMember.DeleteAt > 0 {
return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.deleted.app_error", nil, "")
}
@@ -216,8 +339,8 @@ func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelM
return nil, result.Err
}
} else {
- channelMember := result.Data.(model.ChannelMember)
- return &channelMember, nil
+ channelMember := result.Data.(*model.ChannelMember)
+ return channelMember, nil
}
newMember := &model.ChannelMember{
@@ -396,6 +519,62 @@ func GetChannelByName(channelName, teamId string) (*model.Channel, *model.AppErr
}
}
+func GetChannelsForUser(teamId string, userId string) (*model.ChannelList, *model.AppError) {
+ if result := <-Srv.Store.Channel().GetChannels(teamId, userId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.ChannelList), nil
+ }
+}
+
+func GetChannelsUserNotIn(teamId string, userId string, offset int, limit int) (*model.ChannelList, *model.AppError) {
+ if result := <-Srv.Store.Channel().GetMoreChannels(teamId, userId, offset, limit); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.ChannelList), nil
+ }
+}
+
+func GetChannelMember(channelId string, userId string) (*model.ChannelMember, *model.AppError) {
+ if result := <-Srv.Store.Channel().GetMember(channelId, userId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.ChannelMember), nil
+ }
+}
+
+func GetChannelMembersByIds(channelId string, userIds []string) (*model.ChannelMembers, *model.AppError) {
+ if result := <-Srv.Store.Channel().GetMembersByIds(channelId, userIds); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.ChannelMembers), nil
+ }
+}
+
+func GetChannelMembersForUser(teamId string, userId string) (*model.ChannelMembers, *model.AppError) {
+ if result := <-Srv.Store.Channel().GetMembersForUser(teamId, userId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.ChannelMembers), nil
+ }
+}
+
+func GetChannelMemberCount(channelId string) (int64, *model.AppError) {
+ if result := <-Srv.Store.Channel().GetMemberCount(channelId, true); result.Err != nil {
+ return 0, result.Err
+ } else {
+ return result.Data.(int64), nil
+ }
+}
+
+func GetChannelCounts(teamId string, userId string) (*model.ChannelCounts, *model.AppError) {
+ if result := <-Srv.Store.Channel().GetChannelCounts(teamId, userId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.ChannelCounts), nil
+ }
+}
+
func JoinChannel(channel *model.Channel, userId string) *model.AppError {
userChan := Srv.Store.User().Get(userId)
memberChan := Srv.Store.Channel().GetMember(channel.Id, userId)
@@ -421,6 +600,76 @@ func JoinChannel(channel *model.Channel, userId string) *model.AppError {
return nil
}
+func LeaveChannel(channelId string, userId string) *model.AppError {
+ sc := Srv.Store.Channel().Get(channelId, true)
+ uc := Srv.Store.User().Get(userId)
+ ccm := Srv.Store.Channel().GetMemberCount(channelId, false)
+
+ if cresult := <-sc; cresult.Err != nil {
+ return cresult.Err
+ } else if uresult := <-uc; uresult.Err != nil {
+ return cresult.Err
+ } else if ccmresult := <-ccm; ccmresult.Err != nil {
+ return ccmresult.Err
+ } else {
+ channel := cresult.Data.(*model.Channel)
+ user := uresult.Data.(*model.User)
+ membersCount := ccmresult.Data.(int64)
+
+ if channel.Type == model.CHANNEL_DIRECT {
+ err := model.NewLocAppError("LeaveChannel", "api.channel.leave.direct.app_error", nil, "")
+ err.StatusCode = http.StatusBadRequest
+ return err
+ }
+
+ if channel.Type == model.CHANNEL_PRIVATE && membersCount == 1 {
+ err := model.NewLocAppError("LeaveChannel", "api.channel.leave.last_member.app_error", nil, "userId="+user.Id)
+ err.StatusCode = http.StatusBadRequest
+ return err
+ }
+
+ if err := RemoveUserFromChannel(userId, userId, channel); err != nil {
+ return err
+ }
+
+ go PostUserAddRemoveMessage(userId, channel.Id, channel.TeamId, fmt.Sprintf(utils.T("api.channel.leave.left"), user.Username), model.POST_JOIN_LEAVE)
+ }
+
+ return nil
+}
+
+func RemoveUserFromChannel(userIdToRemove string, removerUserId string, channel *model.Channel) *model.AppError {
+ if channel.DeleteAt > 0 {
+ err := model.NewLocAppError("RemoveUserFromChannel", "api.channel.remove_user_from_channel.deleted.app_error", nil, "")
+ err.StatusCode = http.StatusBadRequest
+ return err
+ }
+
+ if channel.Name == model.DEFAULT_CHANNEL {
+ return model.NewLocAppError("RemoveUserFromChannel", "api.channel.remove.default.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "")
+ }
+
+ if cmresult := <-Srv.Store.Channel().RemoveMember(channel.Id, userIdToRemove); cmresult.Err != nil {
+ return cmresult.Err
+ }
+
+ InvalidateCacheForUser(userIdToRemove)
+ InvalidateCacheForChannel(channel.Id)
+
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", channel.Id, "", nil)
+ message.Add("user_id", userIdToRemove)
+ message.Add("remover_id", removerUserId)
+ go Publish(message)
+
+ // because the removed user no longer belongs to the channel we need to send a separate websocket event
+ userMsg := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", "", userIdToRemove, nil)
+ userMsg.Add("channel_id", channel.Id)
+ userMsg.Add("remover_id", removerUserId)
+ go Publish(userMsg)
+
+ return nil
+}
+
func PostUserAddRemoveMessage(userId, channelId, teamId, message, postType string) *model.AppError {
post := &model.Post{
ChannelId: channelId,
@@ -434,3 +683,88 @@ func PostUserAddRemoveMessage(userId, channelId, teamId, message, postType strin
return nil
}
+
+func GetNumberOfChannelsOnTeam(teamId string) (int, *model.AppError) {
+ // Get total number of channels on current team
+ if result := <-Srv.Store.Channel().GetTeamChannels(teamId); result.Err != nil {
+ return 0, result.Err
+ } else {
+ return len(*result.Data.(*model.ChannelList)), nil
+ }
+}
+
+func SetActiveChannel(userId string, channelId string) *model.AppError {
+ status, err := GetStatus(userId)
+ if err != nil {
+ status = &model.Status{userId, model.STATUS_ONLINE, false, model.GetMillis(), channelId}
+ } else {
+ status.ActiveChannel = channelId
+ if !status.Manual {
+ status.Status = model.STATUS_ONLINE
+ }
+ status.LastActivityAt = model.GetMillis()
+ }
+
+ AddStatusCache(status)
+
+ return nil
+}
+
+func UpdateChannelLastViewedAt(channelIds []string, userId string) *model.AppError {
+ if result := <-Srv.Store.Channel().UpdateLastViewedAt(channelIds, userId); result.Err != nil {
+ return result.Err
+ }
+
+ return nil
+}
+
+func SearchChannels(teamId string, term string) (*model.ChannelList, *model.AppError) {
+ if result := <-Srv.Store.Channel().SearchInTeam(teamId, term); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.ChannelList), nil
+ }
+}
+
+func SearchChannelsUserNotIn(teamId string, userId string, term string) (*model.ChannelList, *model.AppError) {
+ if result := <-Srv.Store.Channel().SearchMore(userId, teamId, term); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.ChannelList), nil
+ }
+}
+
+func ViewChannel(view *model.ChannelView, teamId string, userId string, clearPushNotifications bool) *model.AppError {
+ channelIds := []string{view.ChannelId}
+
+ var pchan store.StoreChannel
+ if len(view.PrevChannelId) > 0 {
+ channelIds = append(channelIds, view.PrevChannelId)
+
+ if *utils.Cfg.EmailSettings.SendPushNotifications && clearPushNotifications {
+ pchan = Srv.Store.User().GetUnreadCountForChannel(userId, view.ChannelId)
+ }
+ }
+
+ uchan := Srv.Store.Channel().UpdateLastViewedAt(channelIds, userId)
+
+ if pchan != nil {
+ if result := <-pchan; result.Err != nil {
+ return result.Err
+ } else {
+ if result.Data.(int64) > 0 {
+ ClearPushNotification(userId, view.ChannelId)
+ }
+ }
+ }
+
+ if result := <-uchan; result.Err != nil {
+ return result.Err
+ }
+
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, teamId, "", userId, nil)
+ message.Add("channel_id", view.ChannelId)
+ go Publish(message)
+
+ return nil
+}
diff --git a/app/email.go b/app/email.go
new file mode 100644
index 000000000..007a24505
--- /dev/null
+++ b/app/email.go
@@ -0,0 +1,236 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "fmt"
+ "html/template"
+ "net/url"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+)
+
+func SendChangeUsernameEmail(oldUsername, newUsername, email, locale, siteURL string) *model.AppError {
+ T := utils.GetUserTranslations(locale)
+
+ subject := fmt.Sprintf("[%v] %v", utils.Cfg.TeamSettings.SiteName, T("api.templates.username_change_subject",
+ map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName}))
+
+ bodyPage := utils.NewHTMLTemplate("email_change_body", locale)
+ bodyPage.Props["SiteURL"] = siteURL
+ bodyPage.Props["Title"] = T("api.templates.username_change_body.title")
+ bodyPage.Html["Info"] = template.HTML(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 {
+ return model.NewLocAppError("SendChangeUsernameEmail", "api.user.send_email_change_username_and_forget.error", nil, err.Error())
+ }
+
+ return nil
+}
+
+func SendEmailChangeVerifyEmail(userId, newUserEmail, locale, siteURL string) *model.AppError {
+ T := utils.GetUserTranslations(locale)
+
+ 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, T("api.templates.email_change_verify_subject",
+ map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName}))
+
+ bodyPage := utils.NewHTMLTemplate("email_change_verify_body", locale)
+ bodyPage.Props["SiteURL"] = siteURL
+ bodyPage.Props["Title"] = T("api.templates.email_change_verify_body.title")
+ bodyPage.Props["Info"] = T("api.templates.email_change_verify_body.info",
+ map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName})
+ bodyPage.Props["VerifyUrl"] = link
+ bodyPage.Props["VerifyButton"] = T("api.templates.email_change_verify_body.button")
+
+ if err := utils.SendMail(newUserEmail, subject, bodyPage.Render()); err != nil {
+ return model.NewLocAppError("SendEmailChangeVerifyEmail", "api.user.send_email_change_verify_email_and_forget.error", nil, err.Error())
+ }
+
+ return nil
+}
+
+func SendEmailChangeEmail(oldEmail, newEmail, locale, siteURL string) *model.AppError {
+ T := utils.GetUserTranslations(locale)
+
+ subject := fmt.Sprintf("[%v] %v", utils.Cfg.TeamSettings.SiteName, T("api.templates.email_change_subject",
+ map[string]interface{}{"TeamDisplayName": utils.Cfg.TeamSettings.SiteName}))
+
+ bodyPage := utils.NewHTMLTemplate("email_change_body", locale)
+ bodyPage.Props["SiteURL"] = siteURL
+ bodyPage.Props["Title"] = T("api.templates.email_change_body.title")
+ bodyPage.Html["Info"] = template.HTML(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 {
+ return model.NewLocAppError("SendEmailChangeEmail", "api.user.send_email_change_email_and_forget.error", nil, err.Error())
+ }
+
+ return nil
+}
+
+func SendVerifyEmail(userId, userEmail, locale, siteURL string) *model.AppError {
+ T := utils.GetUserTranslations(locale)
+
+ 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 := T("api.templates.verify_subject",
+ map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]})
+
+ bodyPage := utils.NewHTMLTemplate("verify_body", locale)
+ bodyPage.Props["SiteURL"] = siteURL
+ bodyPage.Props["Title"] = T("api.templates.verify_body.title", map[string]interface{}{"ServerURL": url.Host})
+ bodyPage.Props["Info"] = T("api.templates.verify_body.info")
+ bodyPage.Props["VerifyUrl"] = link
+ bodyPage.Props["Button"] = T("api.templates.verify_body.button")
+
+ if err := utils.SendMail(userEmail, subject, bodyPage.Render()); err != nil {
+ return model.NewLocAppError("SendVerifyEmail", "api.user.send_verify_email_and_forget.failed.error", nil, err.Error())
+ }
+
+ return nil
+}
+
+func SendSignInChangeEmail(email, method, locale, siteURL string) *model.AppError {
+ T := utils.GetUserTranslations(locale)
+
+ subject := T("api.templates.singin_change_email.subject",
+ map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]})
+
+ bodyPage := utils.NewHTMLTemplate("signin_change_body", locale)
+ bodyPage.Props["SiteURL"] = siteURL
+ bodyPage.Props["Title"] = T("api.templates.signin_change_email.body.title")
+ bodyPage.Html["Info"] = template.HTML(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 {
+ return model.NewLocAppError("SendSignInChangeEmail", "api.user.send_sign_in_change_email_and_forget.error", nil, err.Error())
+ }
+
+ return nil
+}
+
+func SendWelcomeEmail(userId string, email string, verified bool, locale, siteURL string) *model.AppError {
+ T := utils.GetUserTranslations(locale)
+
+ rawUrl, _ := url.Parse(siteURL)
+
+ subject := T("api.templates.welcome_subject", map[string]interface{}{"ServerURL": rawUrl.Host})
+
+ bodyPage := utils.NewHTMLTemplate("welcome_body", locale)
+ bodyPage.Props["SiteURL"] = siteURL
+ bodyPage.Props["Title"] = T("api.templates.welcome_body.title", map[string]interface{}{"ServerURL": rawUrl.Host})
+ bodyPage.Props["Info"] = T("api.templates.welcome_body.info")
+ bodyPage.Props["Button"] = T("api.templates.welcome_body.button")
+ bodyPage.Props["Info2"] = T("api.templates.welcome_body.info2")
+ bodyPage.Props["Info3"] = T("api.templates.welcome_body.info3")
+ bodyPage.Props["SiteURL"] = siteURL
+
+ if *utils.Cfg.NativeAppSettings.AppDownloadLink != "" {
+ bodyPage.Props["AppDownloadInfo"] = 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 {
+ return model.NewLocAppError("SendWelcomeEmail", "api.user.send_welcome_email_and_forget.failed.error", nil, err.Error())
+ }
+
+ return nil
+}
+
+func SendPasswordChangeEmail(email, method, locale, siteURL string) *model.AppError {
+ T := utils.GetUserTranslations(locale)
+
+ subject := 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", locale)
+ bodyPage.Props["SiteURL"] = siteURL
+ bodyPage.Props["Title"] = T("api.templates.password_change_body.title")
+ bodyPage.Html["Info"] = template.HTML(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 {
+ return model.NewLocAppError("SendPasswordChangeEmail", "api.user.send_password_change_email_and_forget.error", nil, err.Error())
+ }
+
+ return nil
+}
+
+func SendMfaChangeEmail(email string, activated bool, locale, siteURL string) *model.AppError {
+ T := utils.GetUserTranslations(locale)
+
+ subject := T("api.templates.mfa_change_subject",
+ map[string]interface{}{"SiteName": utils.Cfg.TeamSettings.SiteName})
+
+ bodyPage := utils.NewHTMLTemplate("mfa_change_body", locale)
+ bodyPage.Props["SiteURL"] = siteURL
+
+ bodyText := ""
+ if activated {
+ bodyText = "api.templates.mfa_activated_body.info"
+ bodyPage.Props["Title"] = T("api.templates.mfa_activated_body.title")
+ } else {
+ bodyText = "api.templates.mfa_deactivated_body.info"
+ bodyPage.Props["Title"] = T("api.templates.mfa_deactivated_body.title")
+ }
+
+ bodyPage.Html["Info"] = template.HTML(T(bodyText,
+ map[string]interface{}{"SiteURL": siteURL}))
+
+ if err := utils.SendMail(email, subject, bodyPage.Render()); err != nil {
+ return model.NewLocAppError("SendMfaChangeEmail", "api.user.send_mfa_change_email.error", nil, err.Error())
+ }
+
+ return nil
+}
+
+func SendInviteEmails(team *model.Team, senderName string, invites []string, siteURL string) {
+ for _, invite := range invites {
+ if len(invite) > 0 {
+ senderRole := utils.T("api.team.invite_members.member")
+
+ subject := utils.T("api.templates.invite_subject",
+ map[string]interface{}{"SenderName": senderName, "TeamDisplayName": team.DisplayName, "SiteName": utils.ClientCfg["SiteName"]})
+
+ bodyPage := utils.NewHTMLTemplate("invite_body", model.DEFAULT_LOCALE)
+ bodyPage.Props["SiteURL"] = siteURL
+ bodyPage.Props["Title"] = utils.T("api.templates.invite_body.title")
+ bodyPage.Html["Info"] = template.HTML(utils.T("api.templates.invite_body.info",
+ map[string]interface{}{"SenderStatus": senderRole, "SenderName": senderName, "TeamDisplayName": team.DisplayName}))
+ bodyPage.Props["Button"] = utils.T("api.templates.invite_body.button")
+ bodyPage.Html["ExtraInfo"] = template.HTML(utils.T("api.templates.invite_body.extra_info",
+ map[string]interface{}{"TeamDisplayName": team.DisplayName, "TeamURL": siteURL + "/" + team.Name}))
+
+ props := make(map[string]string)
+ props["email"] = invite
+ props["id"] = team.Id
+ props["display_name"] = team.DisplayName
+ props["name"] = team.Name
+ props["time"] = fmt.Sprintf("%v", model.GetMillis())
+ data := model.MapToJson(props)
+ hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt))
+ bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", siteURL, url.QueryEscape(data), url.QueryEscape(hash))
+
+ if !utils.Cfg.EmailSettings.SendEmailNotifications {
+ l4g.Info(utils.T("api.team.invite_members.sending.info"), invite, bodyPage.Props["Link"])
+ }
+
+ if err := utils.SendMail(invite, subject, bodyPage.Render()); err != nil {
+ l4g.Error(utils.T("api.team.invite_members.send.error"), err)
+ }
+ }
+ }
+}
diff --git a/app/notification.go b/app/notification.go
index fc1d44f06..060810017 100644
--- a/app/notification.go
+++ b/app/notification.go
@@ -542,7 +542,6 @@ func ClearPushNotification(userId string, channelId string) *model.AppError {
}
func sendToPushProxy(msg model.PushNotification) *model.AppError {
-
msg.ServerId = utils.CfgDiagnosticId
tr := &http.Transport{
diff --git a/app/oauth.go b/app/oauth.go
index 862897b24..3e8b0b8d2 100644
--- a/app/oauth.go
+++ b/app/oauth.go
@@ -27,7 +27,7 @@ func RevokeAccessToken(token string) *model.AppError {
}
if session != nil {
- RemoveAllSessionsForUserId(session.UserId)
+ ClearSessionCacheForUser(session.UserId)
}
return nil
diff --git a/app/session.go b/app/session.go
index 3bb167891..289bb6a2d 100644
--- a/app/session.go
+++ b/app/session.go
@@ -14,6 +14,18 @@ import (
var sessionCache *utils.Cache = utils.NewLru(model.SESSION_CACHE_SIZE)
+func CreateSession(session *model.Session) (*model.Session, *model.AppError) {
+ if result := <-Srv.Store.Session().Save(session); result.Err != nil {
+ return nil, result.Err
+ } else {
+ session := result.Data.(*model.Session)
+
+ AddSessionToCache(session)
+
+ return session, nil
+ }
+}
+
func GetSession(token string) (*model.Session, *model.AppError) {
metrics := einterfaces.GetMetricsInterface()
@@ -51,16 +63,48 @@ func GetSession(token string) (*model.Session, *model.AppError) {
return session, nil
}
-func RemoveAllSessionsForUserId(userId string) {
+func GetSessions(userId string) ([]*model.Session, *model.AppError) {
+ if result := <-Srv.Store.Session().GetSessions(userId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.Session), nil
+ }
+}
+
+func RevokeAllSessions(userId string) *model.AppError {
+ if result := <-Srv.Store.Session().GetSessions(userId); result.Err != nil {
+ return result.Err
+ } else {
+ sessions := result.Data.([]*model.Session)
+
+ for _, session := range sessions {
+ if session.IsOAuth {
+ RevokeAccessToken(session.Token)
+ } else {
+ if result := <-Srv.Store.Session().Remove(session.Id); result.Err != nil {
+ return result.Err
+ }
+ }
+
+ RevokeWebrtcToken(session.Id)
+ }
+ }
+
+ ClearSessionCacheForUser(userId)
+
+ return nil
+}
+
+func ClearSessionCacheForUser(userId string) {
- RemoveAllSessionsForUserIdSkipClusterSend(userId)
+ ClearSessionCacheForUserSkipClusterSend(userId)
if einterfaces.GetClusterInterface() != nil {
- einterfaces.GetClusterInterface().RemoveAllSessionsForUserId(userId)
+ einterfaces.GetClusterInterface().ClearSessionCacheForUser(userId)
}
}
-func RemoveAllSessionsForUserIdSkipClusterSend(userId string) {
+func ClearSessionCacheForUserSkipClusterSend(userId string) {
keys := sessionCache.Keys()
for _, key := range keys {
@@ -132,7 +176,7 @@ func RevokeSession(session *model.Session) *model.AppError {
}
RevokeWebrtcToken(session.Id)
- RemoveAllSessionsForUserId(session.UserId)
+ ClearSessionCacheForUser(session.UserId)
return nil
}
diff --git a/app/session_test.go b/app/session_test.go
index 352395c76..aea31cf86 100644
--- a/app/session_test.go
+++ b/app/session_test.go
@@ -22,7 +22,7 @@ func TestCache(t *testing.T) {
t.Fatal("should have items")
}
- RemoveAllSessionsForUserId(session.UserId)
+ ClearSessionCacheForUser(session.UserId)
rkeys := sessionCache.Keys()
if len(rkeys) != len(keys)-1 {
diff --git a/app/team.go b/app/team.go
index 495e0773f..28d667268 100644
--- a/app/team.go
+++ b/app/team.go
@@ -4,6 +4,11 @@
package app
import (
+ "fmt"
+ "net/http"
+ "strconv"
+ "strings"
+
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/model"
@@ -24,6 +29,57 @@ func CreateTeam(team *model.Team) (*model.Team, *model.AppError) {
}
}
+func UpdateTeam(team *model.Team) (*model.Team, *model.AppError) {
+ var oldTeam *model.Team
+ var err *model.AppError
+ if oldTeam, err = GetTeam(team.Id); err != nil {
+ return nil, err
+ }
+
+ oldTeam.DisplayName = team.DisplayName
+ oldTeam.Description = team.Description
+ oldTeam.InviteId = team.InviteId
+ oldTeam.AllowOpenInvite = team.AllowOpenInvite
+ oldTeam.CompanyName = team.CompanyName
+ oldTeam.AllowedDomains = team.AllowedDomains
+
+ if result := <-Srv.Store.Team().Update(oldTeam); result.Err != nil {
+ return nil, result.Err
+ }
+
+ return oldTeam, nil
+}
+
+func UpdateTeamMemberRoles(teamId string, userId string, newRoles string) (*model.TeamMember, *model.AppError) {
+ var member *model.TeamMember
+ if result := <-Srv.Store.Team().GetTeamsForUser(userId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ members := result.Data.([]*model.TeamMember)
+ for _, m := range members {
+ if m.TeamId == teamId {
+ member = m
+ }
+ }
+ }
+
+ if member == nil {
+ err := model.NewLocAppError("UpdateTeamMemberRoles", "api.team.update_member_roles.not_a_member", nil, "userId="+userId+" teamId="+teamId)
+ err.StatusCode = http.StatusBadRequest
+ return nil, err
+ }
+
+ member.Roles = newRoles
+
+ if result := <-Srv.Store.Team().UpdateMember(member); result.Err != nil {
+ return nil, result.Err
+ }
+
+ ClearSessionCacheForUser(userId)
+
+ return member, nil
+}
+
func JoinUserToTeamById(teamId string, user *model.User) *model.AppError {
if result := <-Srv.Store.Team().Get(teamId); result.Err != nil {
return result.Err
@@ -32,6 +88,55 @@ func JoinUserToTeamById(teamId string, user *model.User) *model.AppError {
}
}
+func JoinUserToTeamByHash(userId string, hash string, data string) (*model.Team, *model.AppError) {
+ props := model.MapFromJson(strings.NewReader(data))
+
+ if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) {
+ return nil, model.NewLocAppError("JoinUserToTeamByHash", "api.user.create_user.signup_link_invalid.app_error", nil, "")
+ }
+
+ t, timeErr := strconv.ParseInt(props["time"], 10, 64)
+ if timeErr != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours
+ return nil, model.NewLocAppError("JoinUserToTeamByHash", "api.user.create_user.signup_link_expired.app_error", nil, "")
+ }
+
+ var team *model.Team
+ var err *model.AppError
+ if team, err = GetTeam(props["id"]); err != nil {
+ return nil, err
+ }
+
+ var user *model.User
+ if user, err = GetUser(userId); err != nil {
+ return nil, err
+ }
+
+ if err := JoinUserToTeam(team, user); err != nil {
+ return nil, err
+ }
+
+ return team, nil
+}
+
+func JoinUserToTeamByInviteId(inviteId string, userId string) (*model.Team, *model.AppError) {
+ var team *model.Team
+ var err *model.AppError
+ if team, err = GetTeamByInviteId(inviteId); err != nil {
+ return nil, err
+ }
+
+ var user *model.User
+ if user, err = GetUser(userId); err != nil {
+ return nil, err
+ }
+
+ if err := JoinUserToTeam(team, user); err != nil {
+ return nil, err
+ }
+
+ return team, nil
+}
+
func JoinUserToTeam(team *model.Team, user *model.User) *model.AppError {
tm := &model.TeamMember{
@@ -49,7 +154,7 @@ func JoinUserToTeam(team *model.Team, user *model.User) *model.AppError {
if etmr := <-Srv.Store.Team().GetMember(team.Id, user.Id); etmr.Err == nil {
// Membership alredy exists. Check if deleted and and update, otherwise do nothing
- rtm := etmr.Data.(model.TeamMember)
+ rtm := etmr.Data.(*model.TeamMember)
// Do nothing if already added
if rtm.DeleteAt == 0 {
@@ -75,12 +180,52 @@ func JoinUserToTeam(team *model.Team, user *model.User) *model.AppError {
l4g.Error(utils.T("api.user.create_user.joining.error"), user.Id, team.Id, err)
}
- RemoveAllSessionsForUserId(user.Id)
+ ClearSessionCacheForUser(user.Id)
InvalidateCacheForUser(user.Id)
return nil
}
+func GetTeam(teamId string) (*model.Team, *model.AppError) {
+ if result := <-Srv.Store.Team().Get(teamId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.Team), nil
+ }
+}
+
+func GetTeamByName(name string) (*model.Team, *model.AppError) {
+ if result := <-Srv.Store.Team().GetByName(name); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.Team), nil
+ }
+}
+
+func GetTeamByInviteId(inviteId string) (*model.Team, *model.AppError) {
+ if result := <-Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.Team), nil
+ }
+}
+
+func GetAllTeams() ([]*model.Team, *model.AppError) {
+ if result := <-Srv.Store.Team().GetAll(); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.Team), nil
+ }
+}
+
+func GetAllOpenTeams() ([]*model.Team, *model.AppError) {
+ if result := <-Srv.Store.Team().GetAllTeamListing(); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.Team), nil
+ }
+}
+
func GetTeamsForUser(userId string) ([]*model.Team, *model.AppError) {
if result := <-Srv.Store.Team().GetTeamsByUserId(userId); result.Err != nil {
return nil, result.Err
@@ -88,3 +233,206 @@ func GetTeamsForUser(userId string) ([]*model.Team, *model.AppError) {
return result.Data.([]*model.Team), nil
}
}
+
+func GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) {
+ if result := <-Srv.Store.Team().GetMember(teamId, userId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.TeamMember), nil
+ }
+}
+
+func GetTeamMembersForUser(userId string) ([]*model.TeamMember, *model.AppError) {
+ if result := <-Srv.Store.Team().GetTeamsForUser(userId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.TeamMember), nil
+ }
+}
+
+func GetTeamMembers(teamId string, offset int, limit int) ([]*model.TeamMember, *model.AppError) {
+ if result := <-Srv.Store.Team().GetMembers(teamId, offset, limit); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.TeamMember), nil
+ }
+}
+
+func GetTeamMembersByIds(teamId string, userIds []string) ([]*model.TeamMember, *model.AppError) {
+ if result := <-Srv.Store.Team().GetMembersByIds(teamId, userIds); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.TeamMember), nil
+ }
+}
+
+func LeaveTeam(team *model.Team, user *model.User) *model.AppError {
+ var teamMember *model.TeamMember
+ var err *model.AppError
+
+ if teamMember, err = GetTeamMember(team.Id, user.Id); err != nil {
+ return model.NewLocAppError("LeaveTeam", "api.team.remove_user_from_team.missing.app_error", nil, err.Error())
+ }
+
+ var channelList *model.ChannelList
+
+ if result := <-Srv.Store.Channel().GetChannels(team.Id, user.Id); result.Err != nil {
+ if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" {
+ channelList = &model.ChannelList{}
+ } else {
+ return result.Err
+ }
+
+ } else {
+ channelList = result.Data.(*model.ChannelList)
+ }
+
+ for _, channel := range *channelList {
+ if channel.Type != model.CHANNEL_DIRECT {
+ InvalidateCacheForChannel(channel.Id)
+ if result := <-Srv.Store.Channel().RemoveMember(channel.Id, user.Id); result.Err != nil {
+ return result.Err
+ }
+ }
+ }
+
+ // Send the websocket message before we actually do the remove so the user being removed gets it.
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_LEAVE_TEAM, team.Id, "", "", nil)
+ message.Add("user_id", user.Id)
+ message.Add("team_id", team.Id)
+ Publish(message)
+
+ teamMember.Roles = ""
+ teamMember.DeleteAt = model.GetMillis()
+
+ if result := <-Srv.Store.Team().UpdateMember(teamMember); result.Err != nil {
+ return result.Err
+ }
+
+ if uua := <-Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
+ return uua.Err
+ }
+
+ // delete the preferences that set the last channel used in the team and other team specific preferences
+ if result := <-Srv.Store.Preference().DeleteCategory(user.Id, team.Id); result.Err != nil {
+ return result.Err
+ }
+
+ ClearSessionCacheForUser(user.Id)
+ InvalidateCacheForUser(user.Id)
+
+ return nil
+}
+
+func InviteNewUsersToTeam(emailList []string, teamId, senderId, siteURL string) *model.AppError {
+ tchan := Srv.Store.Team().Get(teamId)
+ uchan := Srv.Store.User().Get(senderId)
+
+ var team *model.Team
+ if result := <-tchan; result.Err != nil {
+ return result.Err
+ } else {
+ team = result.Data.(*model.Team)
+ }
+
+ var user *model.User
+ if result := <-uchan; result.Err != nil {
+ return result.Err
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ SendInviteEmails(team, user.GetDisplayName(), emailList, siteURL)
+
+ return nil
+}
+
+func FindTeamByName(name string) bool {
+ if result := <-Srv.Store.Team().GetByName(name); result.Err != nil {
+ return false
+ } else {
+ return true
+ }
+}
+
+func GetTeamsUnreadForUser(teamId string, userId string) ([]*model.TeamUnread, *model.AppError) {
+ if result := <-Srv.Store.Team().GetTeamsUnreadForUser(teamId, userId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ data := result.Data.([]*model.ChannelUnread)
+ var members []*model.TeamUnread
+ membersMap := make(map[string]*model.TeamUnread)
+
+ unreads := func(cu *model.ChannelUnread, tu *model.TeamUnread) *model.TeamUnread {
+ tu.MentionCount += cu.MentionCount
+
+ if cu.NotifyProps["mark_unread"] != model.CHANNEL_MARK_UNREAD_MENTION {
+ tu.MsgCount += (cu.TotalMsgCount - cu.MsgCount)
+ }
+
+ return tu
+ }
+
+ for i := range data {
+ id := data[i].TeamId
+ if mu, ok := membersMap[id]; ok {
+ membersMap[id] = unreads(data[i], mu)
+ } else {
+ membersMap[id] = unreads(data[i], &model.TeamUnread{
+ MsgCount: 0,
+ MentionCount: 0,
+ TeamId: id,
+ })
+ }
+ }
+
+ for _, val := range membersMap {
+ members = append(members, val)
+ }
+
+ return members, nil
+ }
+}
+
+func PermanentDeleteTeam(team *model.Team) *model.AppError {
+ team.DeleteAt = model.GetMillis()
+ if result := <-Srv.Store.Team().Update(team); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.Channel().PermanentDeleteByTeam(team.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.Team().RemoveAllMembersByTeam(team.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.Team().PermanentDelete(team.Id); result.Err != nil {
+ return result.Err
+ }
+
+ return nil
+}
+
+func GetTeamStats(teamId string) (*model.TeamStats, *model.AppError) {
+ tchan := Srv.Store.Team().GetTotalMemberCount(teamId)
+ achan := Srv.Store.Team().GetActiveMemberCount(teamId)
+
+ stats := &model.TeamStats{}
+ stats.TeamId = teamId
+
+ if result := <-tchan; result.Err != nil {
+ return nil, result.Err
+ } else {
+ stats.TotalMemberCount = result.Data.(int64)
+ }
+
+ if result := <-achan; result.Err != nil {
+ return nil, result.Err
+ } else {
+ stats.ActiveMemberCount = result.Data.(int64)
+ }
+
+ return stats, nil
+}
diff --git a/app/user.go b/app/user.go
index 909c8cca9..8324417e8 100644
--- a/app/user.go
+++ b/app/user.go
@@ -15,11 +15,13 @@ import (
"image/png"
"io"
"io/ioutil"
+ "mime/multipart"
"net/http"
"strconv"
"strings"
l4g "github.com/alecthomas/log4go"
+ "github.com/disintegration/imaging"
"github.com/golang/freetype"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
@@ -132,8 +134,8 @@ func CreateUser(user *model.User) (*model.User, *model.AppError) {
ruser := result.Data.(*model.User)
if user.EmailVerified {
- if cresult := <-Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
- l4g.Error(utils.T("api.user.create_user.verified.error"), cresult.Err)
+ if err := VerifyUserEmail(ruser.Id); err != nil {
+ l4g.Error(utils.T("api.user.create_user.verified.error"), err)
}
}
@@ -334,6 +336,14 @@ func GetUsersNotInChannel(teamId string, channelId string, offset int, limit int
}
}
+func GetUsersByIds(userIds []string) (map[string]*model.User, *model.AppError) {
+ if result := <-Srv.Store.User().GetProfileByIds(userIds, true); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(map[string]*model.User), nil
+ }
+}
+
func ActivateMfa(userId, token string) *model.AppError {
mfaInterface := einterfaces.GetMfaInterface()
if mfaInterface == nil {
@@ -479,3 +489,348 @@ func GetProfileImage(user *model.User) ([]byte, *model.AppError) {
return img, nil
}
+
+func SetProfileImage(userId string, imageData *multipart.FileHeader) *model.AppError {
+ file, err := imageData.Open()
+ defer file.Close()
+ if err != nil {
+ return model.NewLocAppError("SetProfileImage", "api.user.upload_profile_user.open.app_error", nil, err.Error())
+ }
+
+ // Decode image config first to check dimensions before loading the whole thing into memory later on
+ config, _, err := image.DecodeConfig(file)
+ if err != nil {
+ return model.NewLocAppError("SetProfileImage", "api.user.upload_profile_user.decode_config.app_error", nil, err.Error())
+ } else if config.Width*config.Height > model.MaxImageSize {
+ return model.NewLocAppError("SetProfileImage", "api.user.upload_profile_user.too_large.app_error", nil, err.Error())
+ }
+
+ file.Seek(0, 0)
+
+ // Decode image into Image object
+ img, _, err := image.Decode(file)
+ if err != nil {
+ return model.NewLocAppError("SetProfileImage", "api.user.upload_profile_user.decode.app_error", nil, err.Error())
+ }
+
+ // 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 {
+ return model.NewLocAppError("SetProfileImage", "api.user.upload_profile_user.encode.app_error", nil, err.Error())
+ }
+
+ path := "users/" + userId + "/profile.png"
+
+ if err := WriteFile(buf.Bytes(), path); err != nil {
+ return model.NewLocAppError("SetProfileImage", "api.user.upload_profile_user.upload_profile.app_error", nil, "")
+ }
+
+ Srv.Store.User().UpdateLastPictureUpdate(userId)
+
+ if user, err := GetUser(userId); err != nil {
+ l4g.Error(utils.T("api.user.get_me.getting.error"), userId)
+ } else {
+ options := utils.Cfg.GetSanitizeOptions()
+ user.SanitizeProfile(options)
+
+ omitUsers := make(map[string]bool, 1)
+ omitUsers[userId] = true
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_UPDATED, "", "", "", omitUsers)
+ message.Add("user", user)
+
+ Publish(message)
+ }
+
+ return nil
+}
+
+func UpdateActive(user *model.User, active bool) (*model.User, *model.AppError) {
+ if active {
+ user.DeleteAt = 0
+ } else {
+ user.DeleteAt = model.GetMillis()
+ }
+
+ if result := <-Srv.Store.User().Update(user, true); result.Err != nil {
+ return nil, result.Err
+ } else {
+ if user.DeleteAt > 0 {
+ if err := RevokeAllSessions(user.Id); err != nil {
+ return nil, err
+ }
+ }
+
+ if extra := <-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)
+
+ if !active {
+ SetStatusOffline(ruser.Id, false)
+ }
+
+ return ruser, nil
+ }
+}
+
+func UpdateUser(user *model.User, siteURL string) (*model.User, *model.AppError) {
+ if result := <-Srv.Store.User().Update(user, false); result.Err != nil {
+ return nil, result.Err
+ } else {
+ rusers := result.Data.([2]*model.User)
+
+ if rusers[0].Email != rusers[1].Email {
+ go func() {
+ if err := SendEmailChangeEmail(rusers[1].Email, rusers[0].Email, rusers[0].Locale, siteURL); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
+
+ if utils.Cfg.EmailSettings.RequireEmailVerification {
+ go func() {
+ if err := SendEmailChangeVerifyEmail(rusers[0].Id, rusers[0].Email, rusers[0].Locale, siteURL); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
+ }
+ }
+
+ if rusers[0].Username != rusers[1].Username {
+ go func() {
+ if err := SendChangeUsernameEmail(rusers[1].Username, rusers[0].Username, rusers[0].Email, rusers[0].Locale, siteURL); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
+ }
+
+ InvalidateCacheForUser(user.Id)
+
+ return rusers[0], nil
+ }
+}
+
+func UpdatePassword(user *model.User, hashedPassword string) *model.AppError {
+ if result := <-Srv.Store.User().UpdatePassword(user.Id, hashedPassword); result.Err != nil {
+ return model.NewLocAppError("UpdatePassword", "api.user.update_password.failed.app_error", nil, result.Err.Error())
+ }
+
+ return nil
+}
+
+func UpdatePasswordSendEmail(user *model.User, hashedPassword, method, siteURL string) *model.AppError {
+ if err := UpdatePassword(user, hashedPassword); err != nil {
+ return err
+ }
+
+ go func() {
+ if err := SendPasswordChangeEmail(user.Email, method, user.Locale, siteURL); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
+
+ return nil
+}
+
+func CreatePasswordRecovery(userId string) (*model.PasswordRecovery, *model.AppError) {
+ recovery := &model.PasswordRecovery{}
+ recovery.UserId = userId
+
+ if result := <-Srv.Store.PasswordRecovery().SaveOrUpdate(recovery); result.Err != nil {
+ return nil, result.Err
+ }
+
+ return recovery, nil
+}
+
+func GetPasswordRecovery(code string) (*model.PasswordRecovery, *model.AppError) {
+ if result := <-Srv.Store.PasswordRecovery().GetByCode(code); result.Err != nil {
+ return nil, model.NewLocAppError("GetPasswordRecovery", "api.user.reset_password.invalid_link.app_error", nil, result.Err.Error())
+ } else {
+ return result.Data.(*model.PasswordRecovery), nil
+ }
+}
+
+func DeletePasswordRecoveryForUser(userId string) *model.AppError {
+ if result := <-Srv.Store.PasswordRecovery().Delete(userId); result.Err != nil {
+ return result.Err
+ }
+
+ return nil
+}
+
+func UpdateUserRoles(userId string, newRoles string) (*model.User, *model.AppError) {
+ var user *model.User
+ var err *model.AppError
+ if user, err = GetUser(userId); err != nil {
+ err.StatusCode = http.StatusBadRequest
+ return nil, err
+ }
+
+ user.Roles = newRoles
+ uchan := Srv.Store.User().Update(user, true)
+ schan := 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)
+ }
+
+ ClearSessionCacheForUser(user.Id)
+
+ 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 := <-Srv.Store.Session().PermanentDeleteSessionsByUser(user.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.OAuth().PermanentDeleteAuthDataByUser(user.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.Webhook().PermanentDeleteIncomingByUser(user.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.Webhook().PermanentDeleteOutgoingByUser(user.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.Command().PermanentDeleteByUser(user.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.Preference().PermanentDeleteByUser(user.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.Channel().PermanentDeleteMembersByUser(user.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.Post().PermanentDeleteByUser(user.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.User().PermanentDelete(user.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.Audit().PermanentDeleteByUser(user.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-Srv.Store.Team().RemoveAllMembersByUser(user.Id); result.Err != nil {
+ return result.Err
+ }
+
+ if result := <-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 := <-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 VerifyUserEmail(userId string) *model.AppError {
+ if err := (<-Srv.Store.User().VerifyEmail(userId)).Err; err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func SearchUsersInChannel(channelId string, term string, searchOptions map[string]bool) ([]*model.User, *model.AppError) {
+ if result := <-Srv.Store.User().SearchInChannel(channelId, term, searchOptions); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.User), nil
+ }
+}
+
+func SearchUsersNotInChannel(teamId string, channelId string, term string, searchOptions map[string]bool) ([]*model.User, *model.AppError) {
+ if result := <-Srv.Store.User().SearchNotInChannel(teamId, channelId, term, searchOptions); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.User), nil
+ }
+}
+
+func SearchUsersInTeam(teamId string, term string, searchOptions map[string]bool) ([]*model.User, *model.AppError) {
+ if result := <-Srv.Store.User().Search(teamId, term, searchOptions); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.User), nil
+ }
+}
+
+func AutocompleteUsersInChannel(teamId string, channelId string, term string, searchOptions map[string]bool) (*model.UserAutocompleteInChannel, *model.AppError) {
+ uchan := Srv.Store.User().SearchInChannel(channelId, term, searchOptions)
+ nuchan := Srv.Store.User().SearchNotInChannel(teamId, channelId, term, searchOptions)
+
+ autocomplete := &model.UserAutocompleteInChannel{}
+
+ if result := <-uchan; result.Err != nil {
+ return nil, result.Err
+ } else {
+ autocomplete.InChannel = result.Data.([]*model.User)
+ }
+
+ if result := <-nuchan; result.Err != nil {
+ return nil, result.Err
+ } else {
+ autocomplete.OutOfChannel = result.Data.([]*model.User)
+ }
+
+ return autocomplete, nil
+}
+
+func AutocompleteUsersInTeam(teamId string, term string, searchOptions map[string]bool) (*model.UserAutocompleteInTeam, *model.AppError) {
+ autocomplete := &model.UserAutocompleteInTeam{}
+
+ if result := <-Srv.Store.User().Search(teamId, term, searchOptions); result.Err != nil {
+ return nil, result.Err
+ } else {
+ autocomplete.InTeam = result.Data.([]*model.User)
+ }
+
+ return autocomplete, nil
+}
diff --git a/cmd/platform/channel.go b/cmd/platform/channel.go
index 2a10516af..fd2b097af 100644
--- a/cmd/platform/channel.go
+++ b/cmd/platform/channel.go
@@ -5,7 +5,6 @@ package main
import (
"errors"
- "github.com/mattermost/platform/api"
"github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
@@ -166,7 +165,7 @@ func removeUserFromChannel(channel *model.Channel, user *model.User, userArg str
CommandPrintErrorln("Can't find user '" + userArg + "'")
return
}
- if err := api.RemoveUserFromChannel(user.Id, "", channel); err != nil {
+ if err := app.RemoveUserFromChannel(user.Id, "", channel); err != nil {
CommandPrintErrorln("Unable to remove '" + userArg + "' from " + channel.Name + ". Error: " + err.Error())
}
}
diff --git a/cmd/platform/oldcommands.go b/cmd/platform/oldcommands.go
index faf086cb7..1ff65130c 100644
--- a/cmd/platform/oldcommands.go
+++ b/cmd/platform/oldcommands.go
@@ -319,8 +319,7 @@ func cmdInviteUser() {
}
invites := []string{flagEmail}
- c := getMockContext()
- api.InviteMembers(team, user.GetDisplayName(), invites, c.GetSiteURL())
+ app.SendInviteEmails(team, user.GetDisplayName(), invites, *utils.Cfg.ServiceSettings.SiteURL)
os.Exit(0)
}
@@ -369,7 +368,7 @@ func cmdAssignRole() {
}
if !user.IsInRole(flagRole) {
- api.UpdateUserRoles(user, flagRole)
+ app.UpdateUserRoles(user.Id, flagRole)
}
os.Exit(0)
@@ -547,7 +546,7 @@ func cmdLeaveChannel() {
channel = result.Data.(*model.Channel)
}
- err := api.RemoveUserFromChannel(user.Id, user.Id, channel)
+ err := app.RemoveUserFromChannel(user.Id, user.Id, channel)
if err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
@@ -712,7 +711,7 @@ func cmdLeaveTeam() {
user = result.Data.(*model.User)
}
- err := api.LeaveTeam(team, user)
+ err := app.LeaveTeam(team, user)
if err != nil {
l4g.Error("%v", err)
@@ -823,7 +822,7 @@ func cmdPermDeleteUser() {
flushLogAndExit(1)
}
- if err := api.PermanentDeleteUser(user); err != nil {
+ if err := app.PermanentDeleteUser(user); err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
} else {
@@ -866,7 +865,7 @@ func cmdPermDeleteTeam() {
flushLogAndExit(1)
}
- if err := api.PermanentDeleteTeam(team); err != nil {
+ if err := app.PermanentDeleteTeam(team); err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
} else {
@@ -896,7 +895,7 @@ func cmdPermDeleteAllUsers() {
flushLogAndExit(1)
}
- if err := api.PermanentDeleteAllUsers(); err != nil {
+ if err := app.PermanentDeleteAllUsers(); err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
} else {
@@ -1033,7 +1032,7 @@ func cmdActivateUser() {
l4g.Error("%v", utils.T("api.user.update_active.no_deactivate_ldap.app_error"))
}
- if _, err := api.UpdateActive(user, !flagUserSetInactive); err != nil {
+ if _, err := app.UpdateActive(user, !flagUserSetInactive); err != nil {
l4g.Error("%v", err)
}
diff --git a/cmd/platform/roles.go b/cmd/platform/roles.go
index 7b635c5a3..a65eb2bd6 100644
--- a/cmd/platform/roles.go
+++ b/cmd/platform/roles.go
@@ -5,7 +5,7 @@ package main
import (
"errors"
- "github.com/mattermost/platform/api"
+ "github.com/mattermost/platform/app"
"github.com/spf13/cobra"
)
@@ -49,7 +49,7 @@ func makeSystemAdminCmdF(cmd *cobra.Command, args []string) error {
return errors.New("Unable to find user '" + args[i] + "'")
}
- if _, err := api.UpdateUserRoles(user, "system_admin system_user"); err != nil {
+ if _, err := app.UpdateUserRoles(user.Id, "system_admin system_user"); err != nil {
return err
}
}
@@ -69,7 +69,7 @@ func makeMemberCmdF(cmd *cobra.Command, args []string) error {
return errors.New("Unable to find user '" + args[i] + "'")
}
- if _, err := api.UpdateUserRoles(user, "system_user"); err != nil {
+ if _, err := app.UpdateUserRoles(user.Id, "system_user"); err != nil {
return err
}
}
diff --git a/cmd/platform/team.go b/cmd/platform/team.go
index 43d0b2582..1dc5d46eb 100644
--- a/cmd/platform/team.go
+++ b/cmd/platform/team.go
@@ -6,7 +6,6 @@ import (
"errors"
"fmt"
- "github.com/mattermost/platform/api"
"github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/spf13/cobra"
@@ -125,7 +124,7 @@ func removeUserFromTeam(team *model.Team, user *model.User, userArg string) {
CommandPrintErrorln("Can't find user '" + userArg + "'")
return
}
- if err := api.LeaveTeam(team, user); err != nil {
+ if err := app.LeaveTeam(team, user); err != nil {
CommandPrintErrorln("Unable to remove '" + userArg + "' from " + team.Name + ". Error: " + err.Error())
}
}
@@ -200,5 +199,5 @@ func deleteTeamsCmdF(cmd *cobra.Command, args []string) error {
}
func deleteTeam(team *model.Team) *model.AppError {
- return api.PermanentDeleteTeam(team)
+ return app.PermanentDeleteTeam(team)
}
diff --git a/cmd/platform/user.go b/cmd/platform/user.go
index 4fa4cd36e..fa93e418c 100644
--- a/cmd/platform/user.go
+++ b/cmd/platform/user.go
@@ -6,7 +6,6 @@ import (
"errors"
"fmt"
- "github.com/mattermost/platform/api"
"github.com/mattermost/platform/app"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
@@ -175,7 +174,7 @@ func changeUserActiveStatus(user *model.User, userArg string, activate bool) {
CommandPrintErrorln(utils.T("api.user.update_active.no_deactivate_ldap.app_error"))
return
}
- if _, err := api.UpdateActive(user, activate); err != nil {
+ if _, err := app.UpdateActive(user, activate); err != nil {
CommandPrintErrorln("Unable to change activation status of user: " + userArg)
}
}
@@ -227,7 +226,7 @@ func userCreateCmdF(cmd *cobra.Command, args []string) error {
}
if system_admin {
- api.UpdateUserRoles(ruser, "system_user system_admin")
+ app.UpdateUserRoles(ruser.Id, "system_user system_admin")
}
CommandPrettyPrintln("Created User")
@@ -262,7 +261,7 @@ func inviteUser(email string, team *model.Team, teamArg string) {
CommandPrintErrorln("Can't find team '" + teamArg + "'")
return
}
- api.InviteMembers(team, "Administrator", invites, *utils.Cfg.ServiceSettings.SiteURL)
+ app.SendInviteEmails(team, "Administrator", invites, *utils.Cfg.ServiceSettings.SiteURL)
CommandPrettyPrintln("Invites may or may not have been sent.")
}
@@ -335,7 +334,7 @@ func deleteUserCmdF(cmd *cobra.Command, args []string) error {
return errors.New("Unable to find user '" + args[i] + "'")
}
- if err := api.PermanentDeleteUser(user); err != nil {
+ if err := app.PermanentDeleteUser(user); err != nil {
return err
}
}
@@ -365,7 +364,7 @@ func deleteAllUsersCommandF(cmd *cobra.Command, args []string) error {
}
}
- if err := api.PermanentDeleteAllUsers(); err != nil {
+ if err := app.PermanentDeleteAllUsers(); err != nil {
return err
} else {
CommandPrettyPrintln("Sucsessfull. All users deleted.")
diff --git a/einterfaces/cluster.go b/einterfaces/cluster.go
index 0d7bf7e86..6cf57308c 100644
--- a/einterfaces/cluster.go
+++ b/einterfaces/cluster.go
@@ -12,7 +12,7 @@ type ClusterInterface interface {
StopInterNodeCommunication()
GetClusterInfos() []*model.ClusterInfo
GetClusterStats() ([]*model.ClusterStats, *model.AppError)
- RemoveAllSessionsForUserId(userId string)
+ ClearSessionCacheForUser(userId string)
InvalidateCacheForUser(userId string)
InvalidateCacheForChannel(channelId string)
InvalidateCacheForChannelPosts(channelId string)
diff --git a/i18n/en.json b/i18n/en.json
index 79bf1b98e..cbfe0c807 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -2525,19 +2525,19 @@
},
{
"id": "api.user.send_email_change_email_and_forget.error",
- "translation": "Failed to send email change notification email successfully err=%v"
+ "translation": "Failed to send email change notification email successfully"
},
{
"id": "api.user.send_email_change_username_and_forget.error",
- "translation": "Failed to send username change notification email successfully err=%v"
+ "translation": "Failed to send username change notification email successfully"
},
{
"id": "api.user.send_email_change_verify_email_and_forget.error",
- "translation": "Failed to send email change verification email successfully err=%v"
+ "translation": "Failed to send email change verification email successfully"
},
{
"id": "api.user.send_password_change_email_and_forget.error",
- "translation": "Failed to send update password email successfully err=%v"
+ "translation": "Failed to send update password email successfully"
},
{
"id": "api.user.send_password_reset.find.app_error",
@@ -2553,15 +2553,15 @@
},
{
"id": "api.user.send_sign_in_change_email_and_forget.error",
- "translation": "Failed to send update password email successfully err=%v"
+ "translation": "Failed to send update password email successfully"
},
{
"id": "api.user.send_verify_email_and_forget.failed.error",
- "translation": "Failed to send verification email successfully err=%v"
+ "translation": "Failed to send verification email successfully"
},
{
"id": "api.user.send_welcome_email_and_forget.failed.error",
- "translation": "Failed to send welcome email successfully err=%v"
+ "translation": "Failed to send welcome email successfully"
},
{
"id": "api.user.update_active.no_deactivate_ldap.app_error",
diff --git a/model/file.go b/model/file.go
index c218c4246..20f6236de 100644
--- a/model/file.go
+++ b/model/file.go
@@ -8,6 +8,10 @@ import (
"io"
)
+const (
+ MaxImageSize = 6048 * 4032 // 24 megapixels, roughly 36MB as a raw image
+)
+
var (
IMAGE_EXTENSIONS = [5]string{".jpg", ".jpeg", ".gif", ".bmp", ".png"}
IMAGE_MIME_TYPES = map[string]string{".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif", ".bmp": "image/bmp", ".png": "image/png", ".tiff": "image/tiff"}
diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go
index 66562ae67..6ac69df5a 100644
--- a/store/sql_channel_store.go
+++ b/store/sql_channel_store.go
@@ -702,7 +702,7 @@ func (s SqlChannelStore) GetMember(channelId string, userId string) StoreChannel
result.Err = model.NewLocAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+channelId+"user_id="+userId+","+err.Error())
}
} else {
- result.Data = member
+ result.Data = &member
}
storeChannel <- result
@@ -1361,7 +1361,7 @@ func (s SqlChannelStore) GetMembersByIds(channelId string, userIds []string) Sto
if _, err := s.GetReplica().Select(&members, "SELECT * FROM ChannelMembers WHERE ChannelId = :ChannelId AND UserId IN ("+idQuery+")", props); err != nil {
result.Err = model.NewLocAppError("SqlChannelStore.GetMembersByIds", "store.sql_channel.get_members_by_ids.app_error", nil, "channelId="+channelId+" "+err.Error())
} else {
- result.Data = members
+ result.Data = &members
}
storeChannel <- result
diff --git a/store/sql_channel_store_test.go b/store/sql_channel_store_test.go
index 6186a242c..38446bf94 100644
--- a/store/sql_channel_store_test.go
+++ b/store/sql_channel_store_test.go
@@ -446,7 +446,7 @@ func TestChannelMemberStore(t *testing.T) {
t.Fatal("Member update time incorrect on delete")
}
- member := (<-store.Channel().GetMember(o1.ChannelId, o1.UserId)).Data.(model.ChannelMember)
+ member := (<-store.Channel().GetMember(o1.ChannelId, o1.UserId)).Data.(*model.ChannelMember)
if member.ChannelId != o1.ChannelId {
t.Fatal("should have go member")
}
@@ -918,7 +918,7 @@ func TestGetMember(t *testing.T) {
if result := <-store.Channel().GetMember(c1.Id, userId); result.Err != nil {
t.Fatal("shouldn't have errored when getting member", result.Err)
- } else if member := result.Data.(model.ChannelMember); member.ChannelId != c1.Id {
+ } else if member := result.Data.(*model.ChannelMember); member.ChannelId != c1.Id {
t.Fatal("should've gotten member of channel 1")
} else if member.UserId != userId {
t.Fatal("should've gotten member for user")
@@ -926,7 +926,7 @@ func TestGetMember(t *testing.T) {
if result := <-store.Channel().GetMember(c2.Id, userId); result.Err != nil {
t.Fatal("shouldn't have errored when getting member", result.Err)
- } else if member := result.Data.(model.ChannelMember); member.ChannelId != c2.Id {
+ } else if member := result.Data.(*model.ChannelMember); member.ChannelId != c2.Id {
t.Fatal("should've gotten member of channel 2")
} else if member.UserId != userId {
t.Fatal("should've gotten member for user")
@@ -1313,7 +1313,7 @@ func TestChannelStoreGetMembersByIds(t *testing.T) {
if r := <-store.Channel().GetMembersByIds(m1.ChannelId, []string{m1.UserId}); r.Err != nil {
t.Fatal(r.Err)
} else {
- rm1 := r.Data.(model.ChannelMembers)[0]
+ rm1 := (*r.Data.(*model.ChannelMembers))[0]
if rm1.ChannelId != m1.ChannelId {
t.Fatal("bad team id")
@@ -1330,7 +1330,7 @@ func TestChannelStoreGetMembersByIds(t *testing.T) {
if r := <-store.Channel().GetMembersByIds(m1.ChannelId, []string{m1.UserId, m2.UserId, model.NewId()}); r.Err != nil {
t.Fatal(r.Err)
} else {
- rm := r.Data.(model.ChannelMembers)
+ rm := (*r.Data.(*model.ChannelMembers))
if len(rm) != 2 {
t.Fatal("return wrong number of results")
diff --git a/store/sql_team_store.go b/store/sql_team_store.go
index 023ce8a5a..b0af895c5 100644
--- a/store/sql_team_store.go
+++ b/store/sql_team_store.go
@@ -301,7 +301,7 @@ func (s SqlTeamStore) GetAllTeamListing() StoreChannel {
var data []*model.Team
if _, err := s.GetReplica().Select(&data, query); err != nil {
- result.Err = model.NewLocAppError("SqlTeamStore.GetAllTeams", "store.sql_team.get_all_team_listing.app_error", nil, err.Error())
+ result.Err = model.NewLocAppError("SqlTeamStore.GetAllTeamListing", "store.sql_team.get_all_team_listing.app_error", nil, err.Error())
}
for _, team := range data {
@@ -438,7 +438,7 @@ func (s SqlTeamStore) GetMember(teamId string, userId string) StoreChannel {
result.Err = model.NewLocAppError("SqlTeamStore.GetMember", "store.sql_team.get_member.app_error", nil, "teamId="+teamId+" userId="+userId+" "+err.Error())
}
} else {
- result.Data = member
+ result.Data = &member
}
storeChannel <- result
diff --git a/store/sql_team_store_test.go b/store/sql_team_store_test.go
index 8a302a9e2..0ea499d7e 100644
--- a/store/sql_team_store_test.go
+++ b/store/sql_team_store_test.go
@@ -415,7 +415,7 @@ func TestGetTeamMember(t *testing.T) {
if r := <-store.Team().GetMember(m1.TeamId, m1.UserId); r.Err != nil {
t.Fatal(r.Err)
} else {
- rm1 := r.Data.(model.TeamMember)
+ rm1 := r.Data.(*model.TeamMember)
if rm1.TeamId != m1.TeamId {
t.Fatal("bad team id")
diff --git a/utils/config.go b/utils/config.go
index 3825d397d..72c30c01b 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -39,7 +39,7 @@ func GetSiteURL() string {
}
func SetSiteURL(url string) {
- siteURL = url
+ siteURL = strings.TrimRight(url, "/")
}
func FindConfigFile(fileName string) string {
diff --git a/web/web_test.go b/web/web_test.go
index 80a0282b4..11273c5dd 100644
--- a/web/web_test.go
+++ b/web/web_test.go
@@ -209,7 +209,7 @@ func TestIncomingWebhook(t *testing.T) {
store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
app.JoinUserToTeam(team, user)
- api.UpdateUserRoles(user, model.ROLE_SYSTEM_ADMIN.Id)
+ app.UpdateUserRoles(user.Id, model.ROLE_SYSTEM_ADMIN.Id)
ApiClient.Login(user.Email, "passwd1")
ApiClient.SetTeamId(team.Id)