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 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 updateNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) { data := model.MapFromJson(r.Body) userId := data["user_id"] if len(userId) != 26 { c.SetInvalidParam("updateMarkUnreadLevel", "user_id") return } channelId := data["channel_id"] if len(channelId) != 26 { c.SetInvalidParam("updateMarkUnreadLevel", "channel_id") return } if !HasPermissionToUser(c, userId) { 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 return } else { app.InvalidateCacheForUser(userId) // return the updated notify properties including any unchanged ones w.Write([]byte(model.MapToJson(member.NotifyProps))) } }
func updateChannelMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) channelId := params["channel_id"] props := model.MapFromJson(r.Body) userId := props["user_id"] if len(userId) != 26 { c.SetInvalidParam("updateChannelMemberRoles", "user_id") 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 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 return } app.InvalidateCacheForUser(userId) rdata := map[string]string{} rdata["status"] = "ok" w.Write([]byte(model.MapToJson(rdata))) }
func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.disabled.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } params := mux.Vars(r) id := params["id"] hchan := app.Srv.Store.Webhook().GetIncoming(id) r.ParseForm() var payload io.Reader contentType := r.Header.Get("Content-Type") if strings.Split(contentType, "; ")[0] == "application/x-www-form-urlencoded" { payload = strings.NewReader(r.FormValue("payload")) } else { payload = r.Body } if utils.Cfg.LogSettings.EnableWebhookDebugging { var err error payload, err = utils.DebugReader( payload, utils.T("api.webhook.incoming.debug"), ) if err != nil { c.Err = model.NewLocAppError( "incomingWebhook", "api.webhook.incoming.debug.error", nil, err.Error(), ) return } } parsedRequest := model.IncomingWebhookRequestFromJson(payload) if parsedRequest == nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.parse.app_error", nil, "") return } text := parsedRequest.Text if len(text) == 0 && parsedRequest.Attachments == nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.text.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } textSize := utf8.RuneCountInString(text) if textSize > model.POST_MESSAGE_MAX_RUNES { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.text.length.app_error", map[string]interface{}{"Max": model.POST_MESSAGE_MAX_RUNES, "Actual": textSize}, "") c.Err.StatusCode = http.StatusBadRequest return } channelName := parsedRequest.ChannelName webhookType := parsedRequest.Type // attachments is in here for slack compatibility if parsedRequest.Attachments != nil { if len(parsedRequest.Props) == 0 { parsedRequest.Props = make(model.StringInterface) } parsedRequest.Props["attachments"] = parsedRequest.Attachments attachmentSize := utf8.RuneCountInString(model.StringInterfaceToJson(parsedRequest.Props)) // Minus 100 to leave room for setting post type in the Props if attachmentSize > model.POST_PROPS_MAX_RUNES-100 { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.attachment.app_error", map[string]interface{}{"Max": model.POST_PROPS_MAX_RUNES - 100, "Actual": attachmentSize}, "") c.Err.StatusCode = http.StatusBadRequest return } webhookType = model.POST_SLACK_ATTACHMENT } var hook *model.IncomingWebhook if result := <-hchan; result.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.invalid.app_error", nil, "err="+result.Err.Message) return } else { hook = result.Data.(*model.IncomingWebhook) } var channel *model.Channel var cchan store.StoreChannel var directUserId string if len(channelName) != 0 { if channelName[0] == '@' { if result := <-app.Srv.Store.User().GetByUsername(channelName[1:]); result.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.user.app_error", nil, "err="+result.Err.Message) return } else { directUserId = result.Data.(*model.User).Id channelName = model.GetDMNameFromIds(directUserId, hook.UserId) } } else if channelName[0] == '#' { channelName = channelName[1:] } cchan = app.Srv.Store.Channel().GetByName(hook.TeamId, channelName) } else { cchan = app.Srv.Store.Channel().Get(hook.ChannelId, true) } overrideUsername := parsedRequest.Username overrideIconUrl := parsedRequest.IconURL result := <-cchan if result.Err != nil && result.Err.Id == store.MISSING_CHANNEL_ERROR && directUserId != "" { newChanResult := <-app.Srv.Store.Channel().CreateDirectChannel(directUserId, hook.UserId) if newChanResult.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.channel.app_error", nil, "err="+newChanResult.Err.Message) return } else { channel = newChanResult.Data.(*model.Channel) app.InvalidateCacheForUser(directUserId) app.InvalidateCacheForUser(hook.UserId) } } else if result.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.channel.app_error", nil, "err="+result.Err.Message) return } else { channel = result.Data.(*model.Channel) } // create a mock session c.Session = model.Session{ UserId: hook.UserId, TeamMembers: []*model.TeamMember{{ TeamId: hook.TeamId, UserId: hook.UserId, Roles: model.ROLE_CHANNEL_USER.Id, }}, IsOAuth: false, } c.TeamId = hook.TeamId if channel.Type != model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_READ_CHANNEL) { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.permissions.app_error", nil, "") return } c.Err = nil if _, err := app.CreateWebhookPost(hook.UserId, hook.TeamId, channel.Id, text, overrideUsername, overrideIconUrl, parsedRequest.Props, webhookType); err != nil { c.Err = err return } w.Header().Set("Content-Type", "text/plain") w.Write([]byte("ok")) }