Example #1
0
func CreateDirectChannel(c *Context, otherUserId string) (*model.Channel, *model.AppError) {
	if len(otherUserId) != 26 {
		return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId)
	}

	uc := Srv.Store.User().Get(otherUserId)

	channel := new(model.Channel)

	channel.DisplayName = ""
	channel.Name = model.GetDMNameFromIds(otherUserId, c.Session.UserId)

	channel.TeamId = c.Session.TeamId
	channel.Description = ""
	channel.Type = model.CHANNEL_DIRECT

	if uresult := <-uc; uresult.Err != nil {
		return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId)
	}

	if sc, err := CreateChannel(c, channel, true); err != nil {
		return nil, err
	} else {
		cm := &model.ChannelMember{ChannelId: sc.Id, UserId: otherUserId,
			Roles: "", NotifyLevel: model.CHANNEL_NOTIFY_ALL}

		if cmresult := <-Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil {
			return nil, cmresult.Err
		}

		return sc, nil
	}
}
Example #2
0
func (me *msgProvider) DoCommand(c *Context, channelId string, message string) *model.CommandResponse {

	splitMessage := strings.SplitN(message, " ", 2)

	parsedMessage := ""
	targetUser := ""

	if len(splitMessage) > 1 {
		parsedMessage = strings.SplitN(message, " ", 2)[1]
	}
	targetUser = strings.SplitN(message, " ", 2)[0]
	targetUser = strings.TrimPrefix(targetUser, "@")

	if profileList := <-Srv.Store.User().GetProfiles(c.Session.TeamId); profileList.Err != nil {
		c.Err = profileList.Err
		return &model.CommandResponse{Text: c.T("api.command_msg.list.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
	} else {
		profileUsers := profileList.Data.(map[string]*model.User)
		for _, userProfile := range profileUsers {
			//Don't let users open DMs with themselves. It probably won't work out well.
			if userProfile.Id == c.Session.UserId {
				continue
			}
			if userProfile.Username == targetUser {
				targetChannelId := ""

				//Find the channel based on this user
				channelName := model.GetDMNameFromIds(c.Session.UserId, userProfile.Id)

				if channel := <-Srv.Store.Channel().GetByName(c.Session.TeamId, channelName); channel.Err != nil {
					if channel.Err.Id == "store.sql_channel.get_by_name.missing.app_error" {
						if directChannel, err := CreateDirectChannel(c, userProfile.Id); err != nil {
							c.Err = err
							return &model.CommandResponse{Text: c.T("api.command_msg.dm_fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
						} else {
							targetChannelId = directChannel.Id
						}
					} else {
						c.Err = channel.Err
						return &model.CommandResponse{Text: c.T("api.command_msg.dm_fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
					}
				} else {
					targetChannelId = channel.Data.(*model.Channel).Id
				}

				makeDirectChannelVisible(c.Session.TeamId, targetChannelId)
				if len(parsedMessage) > 0 {
					post := &model.Post{}
					post.Message = parsedMessage
					post.ChannelId = targetChannelId
					if _, err := CreatePost(c, post, true); err != nil {
						return &model.CommandResponse{Text: c.T("api.command_msg.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
					}
				}
				return &model.CommandResponse{GotoLocation: c.GetTeamURL() + "/channels/" + channelName, Text: c.T("api.command_msg.success"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
			}
		}
	}
	return &model.CommandResponse{Text: c.T("api.command_msg.missing.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
}
Example #3
0
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(),
	}
	cm2 := &model.ChannelMember{
		UserId:      otherUserId,
		NotifyProps: model.GetDefaultChannelNotifyProps(),
	}

	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 {
		return result.Data.(*model.Channel), nil
	}
}
Example #4
0
func (me *msgProvider) DoCommand(c *Context, args *model.CommandArgs, message string) *model.CommandResponse {

	splitMessage := strings.SplitN(message, " ", 2)

	parsedMessage := ""
	targetUsername := ""

	if len(splitMessage) > 1 {
		parsedMessage = strings.SplitN(message, " ", 2)[1]
	}
	targetUsername = strings.SplitN(message, " ", 2)[0]
	targetUsername = strings.TrimPrefix(targetUsername, "@")

	var userProfile *model.User
	if result := <-app.Srv.Store.User().GetByUsername(targetUsername); result.Err != nil {
		c.Err = result.Err
		return &model.CommandResponse{Text: c.T("api.command_msg.missing.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
	} else {
		userProfile = result.Data.(*model.User)
	}

	if userProfile.Id == c.Session.UserId {
		return &model.CommandResponse{Text: c.T("api.command_msg.missing.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
	}

	// Find the channel based on this user
	channelName := model.GetDMNameFromIds(c.Session.UserId, userProfile.Id)

	targetChannelId := ""
	if channel := <-app.Srv.Store.Channel().GetByName(c.TeamId, channelName); channel.Err != nil {
		if channel.Err.Id == "store.sql_channel.get_by_name.missing.app_error" {
			if directChannel, err := app.CreateDirectChannel(c.Session.UserId, userProfile.Id); err != nil {
				c.Err = err
				return &model.CommandResponse{Text: c.T("api.command_msg.dm_fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
			} else {
				targetChannelId = directChannel.Id
			}
		} else {
			c.Err = channel.Err
			return &model.CommandResponse{Text: c.T("api.command_msg.dm_fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
		}
	} else {
		targetChannelId = channel.Data.(*model.Channel).Id
	}

	app.MakeDirectChannelVisible(targetChannelId)
	if len(parsedMessage) > 0 {
		post := &model.Post{}
		post.Message = parsedMessage
		post.ChannelId = targetChannelId
		post.UserId = c.Session.UserId
		if _, err := app.CreatePost(post, c.TeamId, true); err != nil {
			return &model.CommandResponse{Text: c.T("api.command_msg.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
		}
	}

	return &model.CommandResponse{GotoLocation: c.GetTeamURL() + "/channels/" + channelName, Text: "", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
}
Example #5
0
func (m *MatterMail) getDirectChannelIDByName(client *model.Client, channelList *model.ChannelList, userName string) string {

	if m.user.Username == userName {
		m.eror.Printf("Impossible create a Direct channel, Mattermail user (%v) equals destination user (%v)\n", m.user.Username, userName)
		return ""
	}

	//result, err := client.GetProfilesForDirectMessageList(client.GetTeamId())
	result, err := client.SearchUsers(model.UserSearch{
		AllowInactive: false,
		TeamId:        client.GetTeamId(),
		Term:          userName,
	})

	if err != nil {
		m.eror.Println("Error on SearchUsers: ", err.Error())
		return ""
	}

	profiles := result.Data.([]*model.User)
	var userID string

	for _, p := range profiles {
		if p.Username == userName {
			userID = p.Id
			break
		}
	}

	if userID == "" {
		m.debg.Println("Did not find the username:"******""
	}

	dmName := model.GetDMNameFromIds(m.user.Id, userID)
	dmID := getChannelIDByName(channelList, dmName)

	if dmID != "" {
		return dmID
	}

	m.debg.Println("Create direct channel to user:"******"Error on CreateDirectChannel: ", err.Error())
		return ""
	}

	directChannel := result.Data.(*model.Channel)
	return directChannel.Id
}
Example #6
0
// SendDirectMessage sends a direct message to specified user
func (m *MMClient) SendDirectMessage(toUserId string, msg string) {
	m.log.Debugf("SendDirectMessage to %s, msg %s", toUserId, msg)
	// create DM channel (only happens on first message)
	_, err := m.Client.CreateDirectChannel(toUserId)
	if err != nil {
		m.log.Debugf("SendDirectMessage to %#v failed: %s", toUserId, err)
	}
	channelName := model.GetDMNameFromIds(toUserId, m.User.Id)

	// update our channels
	mmchannels, _ := m.Client.GetChannels("")
	m.Lock()
	m.Team.Channels = mmchannels.Data.(*model.ChannelList)
	m.Unlock()

	// build & send the message
	msg = strings.Replace(msg, "\r", "", -1)
	post := &model.Post{ChannelId: m.GetChannelId(channelName, ""), Message: msg}
	m.Client.CreatePost(post)
}
Example #7
0
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
	}
}
Example #8
0
func (s SqlChannelStore) CreateDirectChannel(userId string, otherUserId string) StoreChannel {
	channel := new(model.Channel)

	channel.DisplayName = ""
	channel.Name = model.GetDMNameFromIds(otherUserId, userId)

	channel.Header = ""
	channel.Type = model.CHANNEL_DIRECT

	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,
	}

	return s.SaveDirectChannel(channel, cm1, cm2)
}
Example #9
0
func CreateDirectChannel(c *Context, otherUserId string) (*model.Channel, *model.AppError) {
	if len(otherUserId) != 26 {
		return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId)
	}

	uc := Srv.Store.User().Get(otherUserId)

	channel := new(model.Channel)

	channel.DisplayName = ""
	channel.Name = model.GetDMNameFromIds(otherUserId, c.Session.UserId)

	channel.TeamId = c.Session.TeamId
	channel.Header = ""
	channel.Type = model.CHANNEL_DIRECT

	if uresult := <-uc; uresult.Err != nil {
		return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId)
	}

	cm1 := &model.ChannelMember{
		UserId:      c.Session.UserId,
		Roles:       model.CHANNEL_ROLE_ADMIN,
		NotifyProps: model.GetDefaultChannelNotifyProps(),
	}
	cm2 := &model.ChannelMember{
		UserId:      otherUserId,
		Roles:       "",
		NotifyProps: model.GetDefaultChannelNotifyProps(),
	}

	if result := <-Srv.Store.Channel().SaveDirectChannel(channel, cm1, cm2); result.Err != nil {
		return nil, result.Err
	} else {
		return result.Data.(*model.Channel), nil
	}
}
Example #10
0
func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) {
	if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks {
		c.Err = model.NewAppError("incomingWebhook", "Incoming webhooks have been disabled by the system admin.", "")
		c.Err.StatusCode = http.StatusNotImplemented
		return
	}

	params := mux.Vars(r)
	id := params["id"]

	hchan := api.Srv.Store.Webhook().GetIncoming(id)

	r.ParseForm()

	var props map[string]string
	if r.Header.Get("Content-Type") == "application/json" {
		props = model.MapFromJson(r.Body)
	} else {
		props = model.MapFromJson(strings.NewReader(r.FormValue("payload")))
	}

	text := props["text"]
	if len(text) == 0 {
		c.Err = model.NewAppError("incomingWebhook", "No text specified", "")
		return
	}

	channelName := props["channel"]

	var hook *model.IncomingWebhook
	if result := <-hchan; result.Err != nil {
		c.Err = model.NewAppError("incomingWebhook", "Invalid webhook", "err="+result.Err.Message)
		return
	} else {
		hook = result.Data.(*model.IncomingWebhook)
	}

	var channel *model.Channel
	var cchan store.StoreChannel

	if len(channelName) != 0 {
		if channelName[0] == '@' {
			if result := <-api.Srv.Store.User().GetByUsername(hook.TeamId, channelName[1:]); result.Err != nil {
				c.Err = model.NewAppError("incomingWebhook", "Couldn't find the user", "err="+result.Err.Message)
				return
			} else {
				channelName = model.GetDMNameFromIds(result.Data.(*model.User).Id, hook.UserId)
			}
		} else if channelName[0] == '#' {
			channelName = channelName[1:]
		}

		cchan = api.Srv.Store.Channel().GetByName(hook.TeamId, channelName)
	} else {
		cchan = api.Srv.Store.Channel().Get(hook.ChannelId)
	}

	overrideUsername := props["username"]
	overrideIconUrl := props["icon_url"]

	if result := <-cchan; result.Err != nil {
		c.Err = model.NewAppError("incomingWebhook", "Couldn't find the channel", "err="+result.Err.Message)
		return
	} else {
		channel = result.Data.(*model.Channel)
	}

	pchan := api.Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId)

	// create a mock session
	c.Session = model.Session{UserId: hook.UserId, TeamId: hook.TeamId, IsOAuth: false}

	if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN {
		c.Err = model.NewAppError("incomingWebhook", "Inappropriate channel permissions", "")
		return
	}

	if _, err := api.CreateWebhookPost(c, channel.Id, text, overrideUsername, overrideIconUrl); err != nil {
		c.Err = err
		return
	}

	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("ok"))
}
Example #11
0
func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) {
	if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks {
		c.Err = model.NewAppError("incomingWebhook", "Incoming webhooks have been disabled by the system admin.", "")
		c.Err.StatusCode = http.StatusNotImplemented
		return
	}

	params := mux.Vars(r)
	id := params["id"]

	hchan := api.Srv.Store.Webhook().GetIncoming(id)

	r.ParseForm()

	var parsedRequest *model.IncomingWebhookRequest
	if r.Header.Get("Content-Type") == "application/json" {
		parsedRequest = model.IncomingWebhookRequestFromJson(r.Body)
	} else {
		parsedRequest = model.IncomingWebhookRequestFromJson(strings.NewReader(r.FormValue("payload")))
	}

	if parsedRequest == nil {
		c.Err = model.NewAppError("incomingWebhook", "Unable to parse incoming data", "")
		return
	}

	text := parsedRequest.Text
	if len(text) == 0 && parsedRequest.Attachments == nil {
		c.Err = model.NewAppError("incomingWebhook", "No text specified", "")
		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
		webhookType = model.POST_SLACK_ATTACHMENT
	}

	var hook *model.IncomingWebhook
	if result := <-hchan; result.Err != nil {
		c.Err = model.NewAppError("incomingWebhook", "Invalid webhook", "err="+result.Err.Message)
		return
	} else {
		hook = result.Data.(*model.IncomingWebhook)
	}

	var channel *model.Channel
	var cchan store.StoreChannel

	if len(channelName) != 0 {
		if channelName[0] == '@' {
			if result := <-api.Srv.Store.User().GetByUsername(hook.TeamId, channelName[1:]); result.Err != nil {
				c.Err = model.NewAppError("incomingWebhook", "Couldn't find the user", "err="+result.Err.Message)
				return
			} else {
				channelName = model.GetDMNameFromIds(result.Data.(*model.User).Id, hook.UserId)
			}
		} else if channelName[0] == '#' {
			channelName = channelName[1:]
		}

		cchan = api.Srv.Store.Channel().GetByName(hook.TeamId, channelName)
	} else {
		cchan = api.Srv.Store.Channel().Get(hook.ChannelId)
	}

	overrideUsername := parsedRequest.Username
	overrideIconUrl := parsedRequest.IconURL

	if result := <-cchan; result.Err != nil {
		c.Err = model.NewAppError("incomingWebhook", "Couldn't find the channel", "err="+result.Err.Message)
		return
	} else {
		channel = result.Data.(*model.Channel)
	}

	pchan := api.Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId)

	// create a mock session
	c.Session = model.Session{UserId: hook.UserId, TeamId: hook.TeamId, IsOAuth: false}

	if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN {
		c.Err = model.NewAppError("incomingWebhook", "Inappropriate channel permissions", "")
		return
	}

	if _, err := api.CreateWebhookPost(c, 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"))
}
Example #12
0
func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	id := params["id"]

	hchan := api.Srv.Store.Webhook().GetIncoming(id)

	r.ParseForm()

	props := model.MapFromJson(strings.NewReader(r.FormValue("payload")))

	text := props["text"]
	if len(text) == 0 {
		c.Err = model.NewAppError("incomingWebhook", "No text specified", "")
		return
	}

	channelName := props["channel"]

	var hook *model.IncomingWebhook
	if result := <-hchan; result.Err != nil {
		c.Err = model.NewAppError("incomingWebhook", "Invalid webhook", "err="+result.Err.Message)
		return
	} else {
		hook = result.Data.(*model.IncomingWebhook)
	}

	var channel *model.Channel
	var cchan store.StoreChannel

	if len(channelName) != 0 {
		if channelName[0] == '@' {
			if result := <-api.Srv.Store.User().GetByUsername(hook.TeamId, channelName[1:]); result.Err != nil {
				c.Err = model.NewAppError("incomingWebhook", "Couldn't find the user", "err="+result.Err.Message)
				return
			} else {
				channelName = model.GetDMNameFromIds(result.Data.(*model.User).Id, hook.UserId)
			}
		} else if channelName[0] == '#' {
			channelName = channelName[1:]
		}

		cchan = api.Srv.Store.Channel().GetByName(hook.TeamId, channelName)
	} else {
		cchan = api.Srv.Store.Channel().Get(hook.ChannelId)
	}

	// parse links into Markdown format
	linkWithTextRegex := regexp.MustCompile(`<([^<\|]+)\|([^>]+)>`)
	text = linkWithTextRegex.ReplaceAllString(text, "[${2}](${1})")

	linkRegex := regexp.MustCompile(`<\s*(\S*)\s*>`)
	text = linkRegex.ReplaceAllString(text, "${1}")

	if result := <-cchan; result.Err != nil {
		c.Err = model.NewAppError("incomingWebhook", "Couldn't find the channel", "err="+result.Err.Message)
		return
	} else {
		channel = result.Data.(*model.Channel)
	}

	pchan := api.Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId)

	post := &model.Post{UserId: hook.UserId, ChannelId: channel.Id, Message: text}

	if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN {
		c.Err = model.NewAppError("incomingWebhook", "Inappropriate channel permissions", "")
		return
	}

	// create a mock session
	c.Session = model.Session{UserId: hook.UserId, TeamId: hook.TeamId, IsOAuth: false}

	if _, err := api.CreatePost(c, post, false); err != nil {
		c.Err = model.NewAppError("incomingWebhook", "Error creating post", "err="+err.Message)
		return
	}

	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("ok"))
}
Example #13
0
func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) {
	if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks {
		c.Err = model.NewAppError("incomingWebhook", "Incoming webhooks have been disabled by the system admin.", "")
		c.Err.StatusCode = http.StatusNotImplemented
		return
	}

	params := mux.Vars(r)
	id := params["id"]

	hchan := api.Srv.Store.Webhook().GetIncoming(id)

	r.ParseForm()

	var props map[string]string
	if r.Header.Get("Content-Type") == "application/json" {
		props = model.MapFromJson(r.Body)
	} else {
		props = model.MapFromJson(strings.NewReader(r.FormValue("payload")))
	}

	text := props["text"]
	if len(text) == 0 {
		c.Err = model.NewAppError("incomingWebhook", "No text specified", "")
		return
	}

	channelName := props["channel"]

	overrideUsername := props["username"]
	overrideIconUrl := props["icon_url"]

	var hook *model.IncomingWebhook
	if result := <-hchan; result.Err != nil {
		c.Err = model.NewAppError("incomingWebhook", "Invalid webhook", "err="+result.Err.Message)
		return
	} else {
		hook = result.Data.(*model.IncomingWebhook)
	}

	var channel *model.Channel
	var cchan store.StoreChannel

	if len(channelName) != 0 {
		if channelName[0] == '@' {
			if result := <-api.Srv.Store.User().GetByUsername(hook.TeamId, channelName[1:]); result.Err != nil {
				c.Err = model.NewAppError("incomingWebhook", "Couldn't find the user", "err="+result.Err.Message)
				return
			} else {
				channelName = model.GetDMNameFromIds(result.Data.(*model.User).Id, hook.UserId)
			}
		} else if channelName[0] == '#' {
			channelName = channelName[1:]
		}

		cchan = api.Srv.Store.Channel().GetByName(hook.TeamId, channelName)
	} else {
		cchan = api.Srv.Store.Channel().Get(hook.ChannelId)
	}

	// parse links into Markdown format
	linkWithTextRegex := regexp.MustCompile(`<([^<\|]+)\|([^>]+)>`)
	text = linkWithTextRegex.ReplaceAllString(text, "[${2}](${1})")

	linkRegex := regexp.MustCompile(`<\s*(\S*)\s*>`)
	text = linkRegex.ReplaceAllString(text, "${1}")

	if result := <-cchan; result.Err != nil {
		c.Err = model.NewAppError("incomingWebhook", "Couldn't find the channel", "err="+result.Err.Message)
		return
	} else {
		channel = result.Data.(*model.Channel)
	}

	pchan := api.Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId)

	post := &model.Post{UserId: hook.UserId, ChannelId: channel.Id, Message: text}
	post.AddProp("from_webhook", "true")

	if utils.Cfg.ServiceSettings.EnablePostUsernameOverride {
		if len(overrideUsername) != 0 {
			post.AddProp("override_username", overrideUsername)
		} else {
			post.AddProp("override_username", model.DEFAULT_WEBHOOK_USERNAME)
		}
	}

	if utils.Cfg.ServiceSettings.EnablePostIconOverride {
		if len(overrideIconUrl) != 0 {
			post.AddProp("override_icon_url", overrideIconUrl)
		} else {
			post.AddProp("override_icon_url", model.DEFAULT_WEBHOOK_ICON)
		}
	}

	if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN {
		c.Err = model.NewAppError("incomingWebhook", "Inappropriate channel permissions", "")
		return
	}

	// create a mock session
	c.Session = model.Session{UserId: hook.UserId, TeamId: hook.TeamId, IsOAuth: false}

	if _, err := api.CreatePost(c, post, false); err != nil {
		c.Err = model.NewAppError("incomingWebhook", "Error creating post", "err="+err.Message)
		return
	}

	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("ok"))
}
Example #14
0
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"))
}
Example #15
0
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 := Srv.Store.Webhook().GetIncoming(id)

	r.ParseForm()

	var parsedRequest *model.IncomingWebhookRequest
	contentType := r.Header.Get("Content-Type")
	if strings.Split(contentType, "; ")[0] == "application/x-www-form-urlencoded" {
		parsedRequest = model.IncomingWebhookRequestFromJson(strings.NewReader(r.FormValue("payload")))
	} else {
		parsedRequest = model.IncomingWebhookRequestFromJson(r.Body)
	}

	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, "")
		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
		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

	if len(channelName) != 0 {
		if channelName[0] == '@' {
			if result := <-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 {
				channelName = model.GetDMNameFromIds(result.Data.(*model.User).Id, hook.UserId)
			}
		} else if channelName[0] == '#' {
			channelName = channelName[1:]
		}

		cchan = Srv.Store.Channel().GetByName(hook.TeamId, channelName)
	} else {
		cchan = Srv.Store.Channel().Get(hook.ChannelId)
	}

	overrideUsername := parsedRequest.Username
	overrideIconUrl := parsedRequest.IconURL

	if result := <-cchan; 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)
	}

	pchan := Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId)

	// create a mock session
	c.Session = model.Session{
		UserId:      hook.UserId,
		TeamMembers: []*model.TeamMember{{TeamId: hook.TeamId, UserId: hook.UserId}},
		IsOAuth:     false,
	}

	if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN {
		c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.permissions.app_error", nil, "")
		return
	}

	if _, err := CreateWebhookPost(c, 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"))
}