예제 #1
0
// Examples of postmark inbound messages
// [email protected]
// [email protected]
func (m *Mail) Persist() error {

	accountId, err := m.getSocialIdFromEmail()
	if err != nil {
		return err
	}

	if strings.HasPrefix(m.OriginalRecipient, "post") {

		err := m.persistPost(accountId)

		if err != nil && err != errCannotOpen {
			return err
		}
		if err == errCannotOpen {
			runner.MustGetLogger().Error("possible abuse mail: %+v", m)
		}
		return nil
	}

	if strings.HasPrefix(m.OriginalRecipient, "reply") {

		err := m.persistReply(accountId)

		if err != nil && err != errCannotOpen {
			return err
		}

		return nil
	}

	return errInvalidMailPrefix

}
예제 #2
0
// NewBadRequest is creating a new http response with predifined
// http response properties
func NewBadRequest(err error) (int, http.Header, interface{}, error) {
	l := runner.MustGetLogger()
	l = l.New("response")
	l.SetCallDepth(2) // get previous error line

	return NewBadRequestWithLogger(l, err)
}
예제 #3
0
// getAccount tries to retrieve account information from incoming request,
// should always return a valid account, not nil
func getAccount(r *http.Request, groupName string) *models.Account {
	clientID := getClientID(r)

	// if cookie doenst exists return empty account
	if clientID == "" {
		return models.NewAccount()
	}

	session, err := models.Cache.Session.ById(clientID)
	if err != nil {
		return models.NewAccount()
	}

	// if session doesnt have username, return empty account
	if session.Username == "" {
		return models.NewAccount()
	}

	acc, err := makeSureAccount(groupName, session.Username)
	if err != nil {
		if err != bongo.RecordNotFound && err != mgo.ErrNotFound {
			runner.MustGetLogger().Error("Err while getting account: %s, err :%s", session.Username, err.Error())
		}

		return models.NewAccount()
	}

	groupChannel, err := models.Cache.Channel.ByGroupName(groupName)
	if err != nil {
		if err != bongo.RecordNotFound && err != models.ErrGroupNotFound {
			runner.MustGetLogger().Error("Err while getting group channel: %s, err :%s", groupName, err.Error())

			return models.NewAccount()
		}

		// for creating the group channel for the first time, we should not return
		// here with empty account
		return acc
	}

	if err := makeSureMembership(groupChannel, acc.Id); err != nil {
		runner.MustGetLogger().Error("Err while making sure account: %s, err :%s", groupName, err.Error())
		return models.NewAccount()
	}

	return acc
}
예제 #4
0
// NewAccessDenied sends access denied response back to client
//
// here not to leak info about the resource do send NotFound err
func NewAccessDenied(err error) (int, http.Header, interface{}, error) {
	l := runner.MustGetLogger()
	l = l.New("response")
	l.SetCallDepth(1) // get previous error line
	l.Error("Access Denied Err: %s", err.Error())

	return NewNotFound()
}
예제 #5
0
func RemoveMulti(u *url.URL, h http.Header, participants []*models.ChannelParticipant, context *models.Context) (int, http.Header, interface{}, error) {
	query := context.OverrideQuery(request.GetQuery(u))

	if err := checkChannelPrerequisites(
		query.Id,
		query.AccountId,
		participants,
	); err != nil {
		return response.NewBadRequest(err)
	}

	ch := models.NewChannel()
	err := ch.ById(query.Id)
	if err != nil {
		return response.NewBadRequest(err)
	}
	if ch.TypeConstant == models.Channel_TYPE_BOT {
		return response.NewBadRequest(errors.New("can not remove participants for bot channel"))
	}

	isAdmin, err := modelhelper.IsAdmin(context.Client.Account.Nick, context.GroupName)
	if err != nil {
		return response.NewBadRequest(err)
	}

	for i := range participants {
		// if the requester is trying to remove some other user than themselves, and they are not the channel owner
		// return bad request
		if participants[i].AccountId != query.AccountId && query.AccountId != ch.CreatorId {

			if !isAdmin {
				return response.NewBadRequest(fmt.Errorf("User is not allowed to kick other users"))
			}

		}

		participants[i].ChannelId = query.Id
		if err := participants[i].Delete(); err != nil {
			return response.NewBadRequest(err)
		}

		if err := addLeaveActivity(query.Id, query.AccountId, participants[i]); err != nil {
			return response.NewBadRequest(err)
		}
	}

	// this could be moved into another worker, but i did not want to create a new worker that will be used
	// for just a few times
	go func() {
		if err := DeleteDesertedChannelMessages(query.Id); err != nil {
			runner.MustGetLogger().Error("Could not delete channel messages: %s", err.Error())
		}
	}()

	go notifyParticipants(ch, models.ChannelParticipant_Removed_From_Channel_Event, participants)

	return response.NewOK(participants)
}
예제 #6
0
func NewController(rmqConn *rabbitmq.RabbitMQ, pubnub *models.PubNub, broker *models.Broker) *Controller {

	return &Controller{
		Pubnub:  pubnub,
		Broker:  broker,
		logger:  runner.MustGetLogger(),
		rmqConn: rmqConn.Conn(),
	}
}
예제 #7
0
// NewInvalidRequest sends bad request response back to client.
// Unlike NewBadRequest method, errors are exposed to users.
// For this reason it is used for returning input validation errors
func NewInvalidRequest(err error) (int, http.Header, interface{}, error) {

	if err == nil {
		err = errors.New("request is not valid")
	}

	// make sure errors are outputted
	runner.MustGetLogger().Error("Invalid Request: %s", err)

	return http.StatusBadRequest, nil, nil, BadRequest{err}
}
예제 #8
0
func decorateContainers(containers []*models.ChannelMessageContainer, messages []models.ChannelMessage, accountId int64) {
	log := runner.MustGetLogger()
	var err error
	for i, message := range messages {
		d := models.NewChannelMessage()
		*d = message

		containers[i], err = d.BuildEmptyMessageContainer()
		if err != nil {
			log.Error("Could not create message container for message %d: %s", containers[i].Message.Id, err)
			continue
		}
	}
}
예제 #9
0
func Parse(u *url.URL, h http.Header, req *models.Mail) (int, http.Header, interface{}, error) {
	if err := req.Validate(); err != nil {
		runner.MustGetLogger().Error("mail parse validate err : %S", err.Error())
		// faily silently, we dont want mail parser service to retry on
		// the failed validation
		return response.NewDefaultOK()
	}

	if err := req.Persist(); err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewDefaultOK()
}
예제 #10
0
// HandleResultAndError wraps the function calls and get its reponse,
// assuming the second parameter as error checks it if it is null or not
// if err nor found, returns OK response
func HandleResultAndError(res interface{}, err error) (int, http.Header, interface{}, error) {
	if err == bongo.RecordNotFound {
		return NewNotFound()
	}

	l := runner.MustGetLogger()
	l = l.New("response")
	l.SetCallDepth(2) // get 2 previous call stack

	if err != nil {
		return NewBadRequestWithLogger(l, err)
	}

	return NewOK(res)
}
예제 #11
0
func parseLocation(c *models.Context) *string {
	record, err := helper.MustGetGeoIPDB().City(c.Client.IP)
	if err != nil {
		runner.MustGetLogger().Error("Err while parsing ip, err :%s", err.Error())

	} else {
		city := record.City.Names["en"]
		country := record.Country.Names["en"]
		if city != "" {
			location := fmt.Sprintf("%s, %s", city, country)
			return &location
		} else {
			location := fmt.Sprintf("%s", country)
			return &location
		}
	}
	return nil
}
예제 #12
0
func notifyParticipants(channel *models.Channel, event string, participants []*models.ChannelParticipant) {
	pe := models.NewParticipantEvent()
	pe.Id = channel.Id
	pe.Participants = participants
	pe.ChannelToken = channel.Token
	logger := runner.MustGetLogger()

	for _, participant := range participants {
		acc, err := models.Cache.Account.ById(participant.AccountId)
		if err != nil {
			logger.Error("Could not fetch account: %s", err)
		}
		pe.Tokens = append(pe.Tokens, acc.Token)
	}

	if err := bongo.B.PublishEvent(event, pe); err != nil {
		logger.Error("Could not notify channel participants: %s", err.Error())
	}

}
예제 #13
0
	Type           string
	Name           string
	CollectMetrics bool
	Metrics        *kmetrics.Metrics

	// used for external requests
	Params    map[string]string
	Cookie    string
	Cookies   []*http.Cookie
	Body      interface{}
	Headers   map[string]string
	Ratelimit *throttled.HTTPRateLimiter
}

var throttleErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
	runner.MustGetLogger().Error("Throttling error: %s", err)

	writeJSONError(w, errGeneric)
}

var throttleDenyHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	writeJSONError(w, response.LimitRateExceededError{})
})

// getAccount tries to retrieve account information from incoming request,
// should always return a valid account, not nil
func getAccount(r *http.Request, groupName string) *models.Account {
	clientID := getClientID(r)

	// if cookie doenst exists return empty account
	if clientID == "" {