func sendReactionEvent(event string, channelId string, reaction *model.Reaction, postHadReactions bool) { // send out that a reaction has been added/removed go func() { message := model.NewWebSocketEvent(event, "", channelId, "", nil) message.Add("reaction", reaction.ToJson()) app.Publish(message) }() // send out that a post was updated if post.HasReactions has changed go func() { var post *model.Post if result := <-app.Srv.Store.Post().Get(reaction.PostId); result.Err != nil { l4g.Warn(utils.T("api.reaction.send_reaction_event.post.app_error")) return } else { post = result.Data.(*model.PostList).Posts[reaction.PostId] } if post.HasReactions != postHadReactions { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_EDITED, "", channelId, "", nil) message.Add("post", post.ToJson()) app.Publish(message) } }() }
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.Name == model.DEFAULT_CHANNEL { return model.NewLocAppError("RemoveUserFromChannel", "api.channel.remove.default.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "") } if cmresult := <-app.Srv.Store.Channel().RemoveMember(channel.Id, userIdToRemove); cmresult.Err != nil { return cmresult.Err } app.InvalidateCacheForUser(userIdToRemove) app.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 app.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 app.Publish(userMsg) return nil }
func RemoveUserFromChannel(userIdToRemove string, removerUserId string, channel *model.Channel) *model.AppError { if channel.DeleteAt > 0 { return model.NewLocAppError("updateChannel", "api.channel.remove_user_from_channel.deleted.app_error", nil, "") } if cmresult := <-Srv.Store.Channel().RemoveMember(channel.Id, userIdToRemove); cmresult.Err != nil { return cmresult.Err } InvalidateCacheForUser(userIdToRemove) Srv.Store.User().InvalidateProfilesInChannelCache(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 makeDirectChannelVisible(teamId string, channelId string) { var members []model.ChannelMember if result := <-Srv.Store.Channel().GetMembers(channelId); result.Err != nil { l4g.Error(utils.T("api.post.make_direct_channel_visible.get_members.error"), channelId, result.Err.Message) return } else { members = result.Data.([]model.ChannelMember) } if len(members) != 2 { l4g.Error(utils.T("api.post.make_direct_channel_visible.get_2_members.error"), channelId) return } // make sure the channel is visible to both members for i, member := range members { otherUserId := members[1-i].UserId if result := <-Srv.Store.Preference().Get(member.UserId, model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, otherUserId); result.Err != nil { // create a new preference since one doesn't exist yet preference := &model.Preference{ UserId: member.UserId, Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, Name: otherUserId, Value: "true", } if saveResult := <-Srv.Store.Preference().Save(&model.Preferences{*preference}); saveResult.Err != nil { l4g.Error(utils.T("api.post.make_direct_channel_visible.save_pref.error"), member.UserId, otherUserId, saveResult.Err.Message) } else { message := model.NewWebSocketEvent(teamId, channelId, member.UserId, model.WEBSOCKET_EVENT_PREFERENCE_CHANGED) message.Add("preference", preference.ToJson()) go Publish(message) } } else { preference := result.Data.(model.Preference) if preference.Value != "true" { // update the existing preference to make the channel visible preference.Value = "true" if updateResult := <-Srv.Store.Preference().Save(&model.Preferences{preference}); updateResult.Err != nil { l4g.Error(utils.T("api.post.make_direct_channel_visible.update_pref.error"), member.UserId, otherUserId, updateResult.Err.Message) } else { message := model.NewWebSocketEvent(teamId, channelId, member.UserId, model.WEBSOCKET_EVENT_PREFERENCE_CHANGED) message.Add("preference", preference.ToJson()) go Publish(message) } } } } }
func MakeDirectChannelVisible(channelId string) *model.AppError { var members []model.ChannelMember if result := <-Srv.Store.Channel().GetMembers(channelId); result.Err != nil { return result.Err } else { members = result.Data.([]model.ChannelMember) } if len(members) != 2 { return model.NewLocAppError("MakeDirectChannelVisible", "api.post.make_direct_channel_visible.get_2_members.error", map[string]interface{}{"ChannelId": channelId}, "") } // make sure the channel is visible to both members for i, member := range members { otherUserId := members[1-i].UserId if result := <-Srv.Store.Preference().Get(member.UserId, model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, otherUserId); result.Err != nil { // create a new preference since one doesn't exist yet preference := &model.Preference{ UserId: member.UserId, Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, Name: otherUserId, Value: "true", } if saveResult := <-Srv.Store.Preference().Save(&model.Preferences{*preference}); saveResult.Err != nil { return saveResult.Err } else { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", member.UserId, nil) message.Add("preference", preference.ToJson()) go Publish(message) } } else { preference := result.Data.(model.Preference) if preference.Value != "true" { // update the existing preference to make the channel visible preference.Value = "true" if updateResult := <-Srv.Store.Preference().Save(&model.Preferences{preference}); updateResult.Err != nil { return updateResult.Err } else { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", member.UserId, nil) message.Add("preference", preference.ToJson()) go Publish(message) } } } } return nil }
func setCollapsePreference(c *Context, isCollapse bool) *model.CommandResponse { pref := model.Preference{ UserId: c.Session.UserId, Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, Name: model.PREFERENCE_NAME_COLLAPSE_SETTING, Value: strconv.FormatBool(isCollapse), } if result := <-app.Srv.Store.Preference().Save(&model.Preferences{pref}); result.Err != nil { return &model.CommandResponse{Text: c.T("api.command_expand_collapse.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } socketMessage := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", c.Session.UserId, nil) socketMessage.Add("preference", pref.ToJson()) go app.Publish(socketMessage) var rmsg string if isCollapse { rmsg = c.T("api.command_collapse.success") } else { rmsg = c.T("api.command_expand.success") } return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: rmsg} }
func SetStatusAwayIfNeeded(userId string) { status, err := GetStatus(userId) if err != nil { status = &model.Status{userId, model.STATUS_OFFLINE, 0} } if status.Status == model.STATUS_AWAY { return } if !IsUserAway(status.LastActivityAt) { return } status.Status = model.STATUS_AWAY statusCache.Add(status.UserId, status) if result := <-Srv.Store.Status().SaveOrUpdate(status); result.Err != nil { l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) } event := model.NewWebSocketEvent("", "", status.UserId, model.WEBSOCKET_EVENT_STATUS_CHANGE) event.Add("status", model.STATUS_AWAY) go Publish(event) }
func CreateDirectChannel(userId string, otherUserId string) (*model.Channel, *model.AppError) { uc := Srv.Store.User().Get(otherUserId) if uresult := <-uc; uresult.Err != nil { return nil, model.NewLocAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, otherUserId) } if result := <-Srv.Store.Channel().CreateDirectChannel(userId, otherUserId); result.Err != nil { if result.Err.Id == store.CHANNEL_EXISTS_ERROR { return result.Data.(*model.Channel), nil } else { return nil, result.Err } } else { channel := result.Data.(*model.Channel) InvalidateCacheForUser(userId) InvalidateCacheForUser(otherUserId) message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_DIRECT_ADDED, "", channel.Id, "", nil) message.Add("teammate_id", otherUserId) go Publish(message) return channel, nil } }
func SetStatusOnline(userId string, sessionId string, manual bool) { broadcast := false var oldStatus string = model.STATUS_OFFLINE var oldTime int64 = 0 var oldManual bool = false var status *model.Status var err *model.AppError if status, err = GetStatus(userId); err != nil { status = &model.Status{userId, model.STATUS_ONLINE, false, model.GetMillis(), ""} broadcast = true } else { if status.Manual && !manual { return // manually set status always overrides non-manual one } if status.Status != model.STATUS_ONLINE { broadcast = true } oldStatus = status.Status oldTime = status.LastActivityAt oldManual = status.Manual status.Status = model.STATUS_ONLINE status.Manual = false // for "online" there's no manual setting status.LastActivityAt = model.GetMillis() } AddStatusCache(status) // Only update the database if the status has changed, the status has been manually set, // or enough time has passed since the previous action if status.Status != oldStatus || status.Manual != oldManual || status.LastActivityAt-oldTime > model.STATUS_MIN_UPDATE_TIME { achan := Srv.Store.Session().UpdateLastActivityAt(sessionId, status.LastActivityAt) var schan store.StoreChannel if broadcast { schan = Srv.Store.Status().SaveOrUpdate(status) } else { schan = Srv.Store.Status().UpdateLastActivityAt(status.UserId, status.LastActivityAt) } if result := <-achan; result.Err != nil { l4g.Error(utils.T("api.status.last_activity.error"), userId, sessionId, result.Err) } if result := <-schan; result.Err != nil { l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) } } if broadcast { event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil) event.Add("status", model.STATUS_ONLINE) event.Add("user_id", status.UserId) go Publish(event) } }
func setLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) id := params["channel_id"] data := model.StringInterfaceFromJson(r.Body) newLastViewedAt := int64(data["last_viewed_at"].(float64)) Srv.Store.Channel().SetLastViewedAt(id, c.Session.UserId, newLastViewedAt) preference := model.Preference{ UserId: c.Session.UserId, Category: model.PREFERENCE_CATEGORY_LAST, Name: model.PREFERENCE_NAME_LAST_CHANNEL, Value: id, } Srv.Store.Preference().Save(&model.Preferences{preference}) message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, c.TeamId, "", c.Session.UserId, nil) message.Add("channel_id", id) go Publish(message) result := make(map[string]string) result["id"] = id w.Write([]byte(model.MapToJson(result))) }
func (h *Hub) Register(webConn *WebConn) { h.register <- webConn msg := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_HELLO, "", "", webConn.UserId, nil) msg.Add("server_version", fmt.Sprintf("%v.%v.%v", model.CurrentVersion, model.BuildNumber, utils.CfgHash)) go Publish(msg) }
func SetStatusAwayIfNeeded(userId string, manual bool) { l4g.Debug(userId, "away") status, err := GetStatus(userId) if err != nil { status = &model.Status{userId, model.STATUS_OFFLINE, manual, 0} } if !manual && status.Manual { return // manually set status always overrides non-manual one } if !manual { if status.Status == model.STATUS_AWAY { return } if !IsUserAway(status.LastActivityAt) { return } } status.Status = model.STATUS_AWAY status.Manual = manual AddStatusCache(status) if result := <-Srv.Store.Status().SaveOrUpdate(status); result.Err != nil { l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) } event := model.NewWebSocketEvent("", "", status.UserId, model.WEBSOCKET_EVENT_STATUS_CHANGE) event.Add("status", model.STATUS_AWAY) go Publish(event) }
func LeaveTeam(team *model.Team, user *model.User) *model.AppError { var teamMember model.TeamMember if result := <-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 := <-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 } RemoveAllSessionsForUserId(user.Id) InvalidateCacheForUser(user.Id) return nil }
func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) id := params["channel_id"] data := model.StringInterfaceFromJson(r.Body) var active bool var ok bool if active, ok = data["active"].(bool); !ok { active = true } doClearPush := false if *utils.Cfg.EmailSettings.SendPushNotifications && !c.Session.IsMobileApp() && active { if result := <-Srv.Store.User().GetUnreadCountForChannel(c.Session.UserId, id); result.Err != nil { l4g.Error(utils.T("api.channel.update_last_viewed_at.get_unread_count_for_channel.error"), c.Session.UserId, id, result.Err.Error()) } else { if result.Data.(int64) > 0 { doClearPush = true } } } go func() { if err := SetActiveChannel(c.Session.UserId, id); err != nil { l4g.Error(err.Error()) } }() Srv.Store.Channel().UpdateLastViewedAt(id, c.Session.UserId) // Must be after update so that unread count is correct if doClearPush { go clearPushNotification(c.Session.UserId, id) } preference := model.Preference{ UserId: c.Session.UserId, Category: model.PREFERENCE_CATEGORY_LAST, Name: model.PREFERENCE_NAME_LAST_CHANNEL, Value: id, } Srv.Store.Preference().Save(&model.Preferences{preference}) message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, c.TeamId, "", c.Session.UserId, nil) message.Add("channel_id", id) go Publish(message) result := make(map[string]string) result["id"] = id w.Write([]byte(model.MapToJson(result))) }
func LeaveTeam(team *model.Team, user *model.User) *model.AppError { var teamMember model.TeamMember if result := <-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 channelMembers *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" { channelMembers = &model.ChannelList{make([]*model.Channel, 0), make(map[string]*model.ChannelMember)} } else { return result.Err } } else { channelMembers = result.Data.(*model.ChannelList) } for _, channel := range channelMembers.Channels { if channel.Type != model.CHANNEL_DIRECT { if result := <-Srv.Store.Channel().RemoveMember(channel.Id, user.Id); result.Err != nil { return result.Err } InvalidateCacheForChannel(channel.Id) } } 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 } RemoveAllSessionsForUserId(user.Id) InvalidateCacheForUser(user.Id) message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_LEAVE_TEAM, team.Id, "", "", nil) message.Add("user_id", user.Id) go Publish(message) return nil }
func JoinUserToTeam(team *model.Team, user *model.User) *model.AppError { tm := &model.TeamMember{ TeamId: team.Id, UserId: user.Id, Roles: model.ROLE_TEAM_USER.Id, } channelRole := model.ROLE_CHANNEL_USER.Id if team.Email == user.Email { tm.Roles = model.ROLE_TEAM_USER.Id + " " + model.ROLE_TEAM_ADMIN.Id channelRole = model.ROLE_CHANNEL_USER.Id + " " + model.ROLE_CHANNEL_ADMIN.Id } 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) // Do nothing if already added if rtm.DeleteAt == 0 { return nil } if tmr := <-Srv.Store.Team().UpdateMember(tm); tmr.Err != nil { return tmr.Err } } else { // Membership appears to be missing. Lets try to add. if tmr := <-Srv.Store.Team().SaveMember(tm); tmr.Err != nil { return tmr.Err } } if uua := <-Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil { return uua.Err } // Soft error if there is an issue joining the default channels if err := JoinDefaultChannels(team.Id, user, channelRole); err != nil { l4g.Error(utils.T("api.user.create_user.joining.error"), user.Id, team.Id, err) } RemoveAllSessionsForUserId(user.Id) InvalidateCacheForUser(user.Id) // This message goes to everyone, so the teamId, channelId and userId are irrelevant message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_NEW_USER, "", "", "", nil) message.Add("user_id", user.Id) go 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, "") } if channel.Type != model.CHANNEL_OPEN && channel.Type != model.CHANNEL_PRIVATE { return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "") } tmchan := Srv.Store.Team().GetMember(channel.TeamId, user.Id) cmchan := Srv.Store.Channel().GetMember(channel.Id, user.Id) if result := <-tmchan; result.Err != nil { return nil, result.Err } else { 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, "") } } if result := <-cmchan; result.Err != nil { if result.Err.Id != store.MISSING_CHANNEL_MEMBER_ERROR { return nil, result.Err } } else { channelMember := result.Data.(model.ChannelMember) return &channelMember, nil } newMember := &model.ChannelMember{ ChannelId: channel.Id, UserId: user.Id, NotifyProps: model.GetDefaultChannelNotifyProps(), Roles: model.ROLE_CHANNEL_USER.Id, } if result := <-Srv.Store.Channel().SaveMember(newMember); result.Err != nil { l4g.Error("Failed to add member user_id=%v channel_id=%v err=%v", user.Id, channel.Id, result.Err) return nil, model.NewLocAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.app_error", nil, "") } go func() { InvalidateCacheForUser(user.Id) Srv.Store.User().InvalidateProfilesInChannelCache(channel.Id) message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_ADDED, "", channel.Id, "", nil) message.Add("user_id", user.Id) message.Add("team_id", channel.TeamId) go Publish(message) }() return newMember, nil }
func SetStatusOffline(userId string) { status := &model.Status{userId, model.STATUS_OFFLINE, model.GetMillis()} statusCache.Add(status.UserId, status) if result := <-Srv.Store.Status().SaveOrUpdate(status); result.Err != nil { l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) } event := model.NewWebSocketEvent("", "", status.UserId, model.WEBSOCKET_EVENT_STATUS_CHANGE) event.Add("status", model.STATUS_OFFLINE) go Publish(event) }
func webrtcMessage(req *model.WebSocketRequest) (map[string]interface{}, *model.AppError) { var ok bool var toUserId string if toUserId, ok = req.Data["to_user_id"].(string); !ok || len(toUserId) != 26 { return nil, NewInvalidWebSocketParamError(req.Action, "to_user_id") } event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_WEBRTC, "", "", toUserId, nil) event.Data = req.Data go Publish(event) return nil, nil }
func CreateUser(user *model.User) (*model.User, *model.AppError) { user.Roles = model.ROLE_SYSTEM_USER.Id // Below is a special case where the first user in the entire // system is granted the system_admin role if result := <-Srv.Store.User().GetTotalUsersCount(); result.Err != nil { return nil, result.Err } else { count := result.Data.(int64) if count <= 0 { user.Roles = model.ROLE_SYSTEM_ADMIN.Id + " " + model.ROLE_SYSTEM_USER.Id } } user.MakeNonNil() user.Locale = *utils.Cfg.LocalizationSettings.DefaultClientLocale if err := utils.IsPasswordValid(user.Password); user.AuthService == "" && err != nil { return nil, err } if result := <-Srv.Store.User().Save(user); result.Err != nil { l4g.Error(utils.T("api.user.create_user.save.error"), result.Err) return nil, result.Err } else { 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) } } pref := model.Preference{UserId: ruser.Id, Category: model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, Name: ruser.Id, Value: "0"} if presult := <-Srv.Store.Preference().Save(&model.Preferences{pref}); presult.Err != nil { l4g.Error(utils.T("api.user.create_user.tutorial.error"), presult.Err.Message) } ruser.Sanitize(map[string]bool{}) // This message goes to everyone, so the teamId, channelId and userId are irrelevant message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_NEW_USER, "", "", "", nil) message.Add("user_id", ruser.Id) go Publish(message) return ruser, nil } }
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 { c.Err = err return } if len(view.ChannelId) == 0 { ReturnStatusOK(w) 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 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) }
func SetStatusOnline(userId string, sessionId string, manual bool) { broadcast := false var status *model.Status var err *model.AppError if status, err = GetStatus(userId); err != nil { status = &model.Status{userId, model.STATUS_ONLINE, false, model.GetMillis(), ""} broadcast = true } else { if status.Manual && !manual { return // manually set status always overrides non-manual one } if status.Status != model.STATUS_ONLINE { broadcast = true } status.Status = model.STATUS_ONLINE status.Manual = false // for "online" there's no manually or auto set status.LastActivityAt = model.GetMillis() } AddStatusCache(status) achan := Srv.Store.Session().UpdateLastActivityAt(sessionId, model.GetMillis()) var schan store.StoreChannel if broadcast { schan = Srv.Store.Status().SaveOrUpdate(status) } else { schan = Srv.Store.Status().UpdateLastActivityAt(status.UserId, status.LastActivityAt) } if result := <-achan; result.Err != nil { l4g.Error(utils.T("api.status.last_activity.error"), userId, sessionId, result.Err) } if result := <-schan; result.Err != nil { l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) } if broadcast { event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", "", nil) event.Add("status", model.STATUS_ONLINE) event.Add("user_id", status.UserId) go Publish(event) } }
func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) { team := model.TeamFromJson(r.Body) if team == nil { c.SetInvalidParam("updateTeam", "team") return } team.Id = c.TeamId if !HasPermissionToTeamContext(c, team.Id, model.PERMISSION_MANAGE_TEAM) { c.Err = model.NewLocAppError("updateTeam", "api.team.update_team.permissions.app_error", nil, "userId="+c.Session.UserId) c.Err.StatusCode = http.StatusForbidden return } var oldTeam *model.Team if result := <-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 if result := <-Srv.Store.Team().Update(oldTeam); result.Err != nil { c.Err = result.Err return } oldTeam.Sanitize() message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_UPDATE_TEAM, "", "", "", nil) message.Add("team", oldTeam.ToJson()) go Publish(message) w.Write([]byte(oldTeam.ToJson())) }
func RemoveUserFromChannel(userIdToRemove string, removerUserId string, channel *model.Channel) *model.AppError { if channel.DeleteAt > 0 { return model.NewLocAppError("updateChannel", "api.channel.remove_user_from_channel.deleted.app_error", nil, "") } if cmresult := <-Srv.Store.Channel().RemoveMember(channel.Id, userIdToRemove); cmresult.Err != nil { return cmresult.Err } InvalidateCacheForUser(userIdToRemove) message := model.NewWebSocketEvent(channel.TeamId, channel.Id, userIdToRemove, model.WEBSOCKET_EVENT_USER_REMOVED) message.Add("remover_id", removerUserId) go Publish(message) return nil }
func setCollapsePreference(c *Context, value string) *model.CommandResponse { pref := model.Preference{ UserId: c.Session.UserId, Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, Name: model.PREFERENCE_NAME_COLLAPSE_SETTING, Value: value, } if result := <-Srv.Store.Preference().Save(&model.Preferences{pref}); result.Err != nil { return &model.CommandResponse{Text: c.T("api.command_expand_collapse.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } socketMessage := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", c.Session.UserId, nil) socketMessage.Add("preference", pref.ToJson()) go Publish(socketMessage) return &model.CommandResponse{} }
func SetStatusOffline(userId string, manual bool) { status, err := GetStatus(userId) if err == nil && status.Manual && !manual { return // manually set status always overrides non-manual one } status = &model.Status{userId, model.STATUS_OFFLINE, manual, model.GetMillis(), ""} AddStatusCache(status) if result := <-Srv.Store.Status().SaveOrUpdate(status); result.Err != nil { l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) } event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", "", nil) event.Add("status", model.STATUS_OFFLINE) event.Add("user_id", status.UserId) go Publish(event) }
func SendEphemeralPost(teamId, userId string, post *model.Post) { post.Type = model.POST_EPHEMERAL // fill in fields which haven't been specified which have sensible defaults if post.Id == "" { post.Id = model.NewId() } if post.CreateAt == 0 { post.CreateAt = model.GetMillis() } if post.Props == nil { post.Props = model.StringInterface{} } message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_EPHEMERAL_MESSAGE, "", post.ChannelId, userId, nil) message.Add("post", post.ToJson()) go Publish(message) }
func SetStatusOnline(userId string, sessionId string) { broadcast := false var status *model.Status var err *model.AppError if status, err = GetStatus(userId); err != nil { status = &model.Status{userId, model.STATUS_ONLINE, model.GetMillis()} broadcast = true } else { if status.Status != model.STATUS_ONLINE { broadcast = true } status.Status = model.STATUS_ONLINE status.LastActivityAt = model.GetMillis() } statusCache.Add(status.UserId, status) achan := Srv.Store.Session().UpdateLastActivityAt(sessionId, model.GetMillis()) var schan store.StoreChannel if broadcast { schan = Srv.Store.Status().SaveOrUpdate(status) } else { schan = Srv.Store.Status().UpdateLastActivityAt(status.UserId, status.LastActivityAt) } if result := <-achan; result.Err != nil { l4g.Error(utils.T("api.status.last_activity.error"), userId, sessionId, result.Err) } if result := <-schan; result.Err != nil { l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) } if broadcast { event := model.NewWebSocketEvent("", "", status.UserId, model.WEBSOCKET_EVENT_STATUS_CHANGE) event.Add("status", model.STATUS_ONLINE) go Publish(event) } }
func CreateDirectChannel(userId string, otherUserId string) (*model.Channel, *model.AppError) { uc := Srv.Store.User().Get(otherUserId) channel := new(model.Channel) channel.DisplayName = "" channel.Name = model.GetDMNameFromIds(otherUserId, userId) channel.Header = "" channel.Type = model.CHANNEL_DIRECT if uresult := <-uc; uresult.Err != nil { return nil, model.NewLocAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, otherUserId) } cm1 := &model.ChannelMember{ UserId: userId, NotifyProps: model.GetDefaultChannelNotifyProps(), Roles: model.ROLE_CHANNEL_USER.Id, } cm2 := &model.ChannelMember{ UserId: otherUserId, NotifyProps: model.GetDefaultChannelNotifyProps(), Roles: model.ROLE_CHANNEL_USER.Id, } if result := <-Srv.Store.Channel().SaveDirectChannel(channel, cm1, cm2); result.Err != nil { if result.Err.Id == store.CHANNEL_EXISTS_ERROR { return result.Data.(*model.Channel), nil } else { return nil, result.Err } } else { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_DIRECT_ADDED, "", channel.Id, "", nil) message.Add("teammate_id", otherUserId) go Publish(message) return result.Data.(*model.Channel), nil } }
func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) id := params["channel_id"] Srv.Store.Channel().UpdateLastViewedAt(id, c.Session.UserId) preference := model.Preference{ UserId: c.Session.UserId, Category: model.PREFERENCE_CATEGORY_LAST, Name: model.PREFERENCE_NAME_LAST_CHANNEL, Value: id, } Srv.Store.Preference().Save(&model.Preferences{preference}) message := model.NewWebSocketEvent(c.TeamId, id, c.Session.UserId, model.WEBSOCKET_EVENT_CHANNEL_VIEWED) message.Add("channel_id", id) go Publish(message) result := make(map[string]string) result["id"] = id w.Write([]byte(model.MapToJson(result))) }