Ejemplo n.º 1
0
func (grp *Group) GetSubscriberIDs(db *periwinkle.Tx) []string {
	subscriptions := grp.GetSubscriptions(db)
	addressIDs := make([]int64, len(subscriptions))
	for i, sub := range subscriptions {
		addressIDs[i] = sub.AddressID
	}
	var addresses []UserAddress
	if len(addressIDs) > 0 {
		if err := db.Where("id IN (?)", addressIDs).Find(&addresses).Error; err != nil {
			dbError(err)
		}
	} else {
		addresses = []UserAddress{}
	}
	userIDSet := map[string]bool{}
	for _, address := range addresses {
		userIDSet[address.UserID] = true
	}
	userIDs := make([]string, len(userIDSet))
	i := 0
	for userID := range userIDSet {
		userIDs[i] = userID
		i++
	}
	return userIDs
}
Ejemplo n.º 2
0
func (addr *UserAddress) GetSubscriptions(db *periwinkle.Tx) []Subscription {
	var subscriptions []Subscription
	if err := db.Where("address_id = ?", addr.ID).Find(&subscriptions).Error; err != nil {
		dbError(err)
	}
	return subscriptions
}
Ejemplo n.º 3
0
func IsAdmin(db *periwinkle.Tx, userID string, group Group) bool {
	subscriptions := group.GetSubscriptions(db)
	addressIDs := make([]int64, len(subscriptions))
	for i, subscription := range subscriptions {
		addressIDs[i] = subscription.AddressID
	}
	var addresses []UserAddress
	if len(addressIDs) > 0 {
		if result := db.Where("id IN (?)", addressIDs).Find(&addresses); result.Error != nil {
			if !result.RecordNotFound() {
				panic("cant find any subscriptions corresponding user address")
			}
		}
	} else {
		// no subscriptions so user cannot possibly be subscribed
		return false
	}
	for _, address := range addresses {
		if address.UserID == userID && address.Medium == "admin" {
			return true
		}
	}
	// could not find user in subscribed user addresses, therefore, he/she isn't subscribed
	return false
}
Ejemplo n.º 4
0
func (o *Group) Save(db *periwinkle.Tx) {
	if o.Subscriptions != nil {
		var oldSubscriptions []Subscription
		db.Model(o).Related(&oldSubscriptions)

		for _, oldsub := range oldSubscriptions {
			match := false

			for _, newsub := range o.Subscriptions {
				if newsub.AddressID == oldsub.AddressID {
					match = true
					break
				}
			}
			if !match {
				var o UserAddress
				db.First(&o, "id = ?", oldsub.AddressID)
				if o.Medium != "noop" && o.Medium != "admin" {
					if err := db.Where("address_id = ? AND group_id = ?", oldsub.AddressID, oldsub.GroupID).Delete(Subscription{}).Error; err != nil {
						dbError(err)
					}
				}
			}
		}

	}

	if err := db.Save(o).Error; err != nil {
		dbError(err)
	}

}
Ejemplo n.º 5
0
func GetGroupsByMember(db *periwinkle.Tx, user User) []Group {
	subscriptions := user.GetSubscriptions(db)
	var groupIDs []string
	for _, sub := range subscriptions {
		groupIDs = append(groupIDs, sub.GroupID)
	}
	var groups []Group
	if len(groupIDs) > 0 {
		if err := db.Where("id IN (?)", groupIDs).Find(&groups).Error; err != nil {
			dbError(err)
		}
	} else {
		groups = make([]Group, 0)
	}
	groupsByID := make(map[string]Group)
	for _, group := range groups {
		groupsByID[group.ID] = group
	}

	groupset := map[string]Group{}
	for _, sub := range subscriptions {
		// only add group if user is confirmed member or
		// if group allows non confirmed members to see that it exists
		if sub.Confirmed || groupsByID[sub.GroupID].ExistenceConfirmed == 2 {
			groupset[sub.GroupID] = groupsByID[sub.GroupID]
		}
	}
	var finalgroups []Group
	for _, group := range groupset {
		finalgroups = append(finalgroups, group)
	}

	return finalgroups
}
Ejemplo n.º 6
0
func (u *User) populate(db *periwinkle.Tx) {
	db.Where(`user_id = ?`, u.ID).Model(UserAddress{}).Find(&u.Addresses)
	addressIDs := make([]int64, len(u.Addresses))
	for i, address := range u.Addresses {
		addressIDs[i] = address.ID
	}
}
Ejemplo n.º 7
0
func (grp *Group) GetSubscriptions(db *periwinkle.Tx) []Subscription {
	var subscriptions []Subscription
	if result := db.Where("group_id = ?", grp.ID).Find(&subscriptions); result.Error != nil {
		if result.RecordNotFound() {
			return []Subscription{}
		}
		dbError(result.Error)
	}
	return subscriptions
}
Ejemplo n.º 8
0
func GetTwilioPoolByUserID(db *periwinkle.Tx, userid string) []TwilioPool {

	var o []TwilioPool
	if result := db.Where("user_id = ?", userid).Find(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		dbError(result.Error)
	}
	return o
}
Ejemplo n.º 9
0
func GetAddressesByUserAndMedium(db *periwinkle.Tx, userID string, medium string) []UserAddress {
	userID = strings.ToLower(userID)
	var o []UserAddress
	if result := db.Where("user_id=? AND medium=?", userID, medium).Find(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		dbError(result.Error)
	}
	return o
}
Ejemplo n.º 10
0
func GetTwilioNumberByID(db *periwinkle.Tx, id int64) *TwilioNumber {

	var twilio_num TwilioNumber

	if result := db.Where("id = ?", id).First(&twilio_num); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		dbError(result.Error)
	}

	return &twilio_num
}
Ejemplo n.º 11
0
func (u *User) GetSubscriptions(db *periwinkle.Tx) []Subscription {
	db.Model(u).Related(&u.Addresses)
	addressIDs := make([]int64, len(u.Addresses))
	for i, address := range u.Addresses {
		addressIDs[i] = address.ID
	}
	var subscriptions []Subscription
	if len(addressIDs) > 0 {
		if result := db.Where("address_id IN (?)", addressIDs).Find(&subscriptions); result.Error != nil {
			if !result.RecordNotFound() {
				dbError(result.Error)
			}
		}
	} else {
		subscriptions = make([]Subscription, 0)
	}
	return subscriptions
}
Ejemplo n.º 12
0
func (u *User) GetFrontEndSubscriptions(db *periwinkle.Tx) []Subscription {
	var addresses []UserAddress
	db.Where(`user_id = ? AND medium != "noop" AND medium != "admin"`, u.ID).Model(UserAddress{}).Find(&addresses)
	addressIDs := make([]int64, len(u.Addresses))
	for i, address := range addresses {
		addressIDs[i] = address.ID
	}
	var subscriptions []Subscription
	if len(addressIDs) > 0 {
		if result := db.Where("address_id IN (?)", addressIDs).Find(&subscriptions); result.Error != nil {
			if !result.RecordNotFound() {
				dbError(result.Error)
			}
		}
	} else {
		subscriptions = make([]Subscription, 0)
	}
	return subscriptions
}
Ejemplo n.º 13
0
func GetTwilioNumberByUserAndGroup(db *periwinkle.Tx, userid string, groupid string) string {

	var o TwilioPool
	if result := db.Where(&TwilioPool{UserID: userid, GroupID: groupid}).First(&o); result.Error != nil {
		if result.RecordNotFound() {
			return ""
		}
		dbError(result.Error)
	}

	var twilioNum TwilioNumber
	if result := db.Where("id = ?", o.NumberID).First(&twilioNum); result.Error != nil {
		if result.RecordNotFound() {
			return ""
		}
		dbError(result.Error)
	}

	return twilioNum.Number
}
Ejemplo n.º 14
0
func DeleteUnusedTwilioNumber(db *periwinkle.Tx, num string) locale.Error {
	var twilioNum TwilioNumber
	if result := db.Where("number = ?", num).First(&twilioNum); result.Error != nil {
		if result.RecordNotFound() {
			periwinkle.Logf("The number is already deleted!!!")
			return nil
		}
		dbError(result.Error)
		return locale.UntranslatedError(result.Error)
	}

	var twilioPool TwilioPool
	result := db.Where("number_id = ?", twilioNum.ID).First(&twilioPool)
	if result.Error != nil {
		if result.RecordNotFound() {

			o := db.Where("number = ?", num).Delete(&TwilioNumber{})
			if o.Error != nil {
				dbError(o.Error)
				return locale.UntranslatedError(o.Error)
			}
			periwinkle.Logf("The number is deleted")
			return nil
		}
		dbError(result.Error)
		return locale.UntranslatedError(result.Error)
	}
	periwinkle.Logf("The number is used for a twilio pool")
	return nil
}
Ejemplo n.º 15
0
func GetGroupByUserAndTwilioNumber(db *periwinkle.Tx, userid string, twilioNum string) *Group {

	var num TwilioNumber

	if result := db.Where("number = ?", twilioNum).First(&num); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		dbError(result.Error)
	}

	var o TwilioPool

	if result := db.Where(&TwilioPool{UserID: userid, NumberID: num.ID}).First(&o); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		dbError(result.Error)
	}

	var group Group

	if result := db.Where("id = ?", o.GroupID).First(&group); result.Error != nil {
		if result.RecordNotFound() {
			return nil
		}
		dbError(result.Error)
	}

	return &group
}
Ejemplo n.º 16
0
func GetPublicAndSubscribedGroups(db *periwinkle.Tx, user User) []Group {
	groups := GetGroupsByMember(db, user)
	// also get public groups
	var publicgroups []Group
	if result := db.Where(&Group{ExistencePublic: 1}).Find(&publicgroups); result.Error != nil {
		if !result.RecordNotFound() {
			dbError(result.Error)
		}
	}
	// merge public groups and subscribed groups
	for _, publicgroup := range publicgroups {
		for _, group := range groups {
			if group.ID == publicgroup.ID {
				break
			}
		}
		groups = append(groups, publicgroup)
	}

	// return them
	return groups
}
Ejemplo n.º 17
0
func AssignTwilioNumber(db *periwinkle.Tx, userid string, groupid string, twilioNum string) *TwilioPool {

	num := TwilioNumber{}
	err := db.Where(TwilioNumber{Number: twilioNum}).FirstOrCreate(&num).Error

	if err != nil {
		dbError(err)
	}

	o := TwilioPool{
		UserID:   userid,
		GroupID:  groupid,
		NumberID: num.ID,
	}

	if err := db.Create(&o).Error; err != nil {
		dbError(err)
	}

	return &o

}
Ejemplo n.º 18
0
func (usr *User) Save(db *periwinkle.Tx) {
	usr.ID = strings.ToLower(usr.ID)
	if usr.Addresses != nil {
		var oldAddresses []UserAddress
		db.Model(usr).Related(&oldAddresses)

		deleteAddressIDs := []int64{}
		for o := range oldAddresses {
			oldAddr := &oldAddresses[o]
			match := false
			for n := range usr.Addresses {
				newAddr := &usr.Addresses[n]
				if newAddr.Medium == oldAddr.Medium && newAddr.Address == oldAddr.Address {
					newAddr.ID = oldAddr.ID
					match = true
				}
			}
			if !match && oldAddr.Medium != "noop" && oldAddr.Medium != "admin" {
				deleteAddressIDs = append(deleteAddressIDs, oldAddr.ID)
			}
		}

		if err := db.Save(usr).Error; err != nil {
			dbError(err)
		}
		if len(deleteAddressIDs) > 0 {
			if err := db.Where("id IN (?)", deleteAddressIDs).Delete(UserAddress{}).Error; err != nil {
				dbError(err)
			}
		}
	} else {
		if err := db.Save(usr).Error; err != nil {
			dbError(err)
		}
	}
}
Ejemplo n.º 19
0
func HandleEmail(r io.Reader, name string, db *periwinkle.Tx, cfg *periwinkle.Cfg) postfixpipe.ExitStatus {
	mdWriter := cfg.Mailstore.NewMail()
	if mdWriter == nil {
		periwinkle.Logf("Could not open maildir for writing: %q\n", cfg.Mailstore)
		return postfixpipe.EX_IOERR
	}

	// As we read the message, also write it to the maildir
	defer func() {
		if mdWriter != nil {
			mdWriter.Cancel()
		}
	}()
	r = io.TeeReader(r, mdWriter)

	// Read the message
	msg, err := mail.ReadMessage(r)
	if err != nil {
		return postfixpipe.EX_NOINPUT
	}

	// Figure out which group it was to
	group := backend.GetGroupByID(db, name)
	if group == nil {
		return postfixpipe.EX_NOUSER
	}

	// Figure out who sent it
	//user_email := msg.Header.Get("From")
	//user := backend.GetUserByAddress(db, "email", user_email)
	// check permissions
	//if user == nil || !CanPost(db, group, user.ID) {
	//	return postfixpipe.EX_NOPERM
	//}
	// Add it to the database
	backend.NewMessage(
		db,
		msg.Header.Get("Message-Id"),
		*group,
		mdWriter.Unique())
	mdWriter.Close()
	mdWriter = nil

	// Generate the list of who we're sending it to
	var forwardAry []string
	{
		// collect IDs of addresses subscribed to the group
		addressIDs := make([]int64, len(group.Subscriptions))
		for i := range group.Subscriptions {
			addressIDs[i] = group.Subscriptions[i].AddressID
		}

		// fetch all of those addresses
		var addressList []backend.UserAddress
		if len(addressIDs) > 0 {
			db.Where("id IN (?)", addressIDs).Find(&addressList)
		} else {
			addressList = make([]backend.UserAddress, 0)
		}

		// convert that list into a set
		forwardSet := make(map[string]bool, len(addressList))
		for _, addr := range addressList {
			if addr.Medium != "noop" && addr.Medium != "admin" {
				forwardSet[addr.AsEmailAddress()] = true
			}
		}

		// prune addresses that (should) already have the message
		for _, header := range []string{"To", "From", "Cc"} {
			addresses, err := msg.Header.AddressList(header)
			if err != nil {
				periwinkle.Logf("Parsing %q Header: %v\n", header, err)
			}
			for _, addr := range addresses {
				delete(forwardSet, addr.Address)
			}
		}
		// TODO: also prune addresses that belong to user.

		// convert the set into an array
		forwardAry = make([]string, len(forwardSet))
		i := uint(0)
		for addr := range forwardSet {
			forwardAry[i] = addr
			i++
		}
	}

	periwinkle.Logf("Forwarding message to group %q to user addresses %#v", group.ID, forwardAry)

	// format the message
	msg822 := []byte{}
	for k := range msg.Header {
		msg822 = append(msg822, []byte(fmt.Sprintf("%s: %s\r\n", k, msg.Header.Get(k)))...)
	}
	msg822 = append(msg822, []byte("\r\n")...)
	body, _ := ioutil.ReadAll(msg.Body) // TODO: error handling
	msg822 = append(msg822, body...)

	if len(forwardAry) > 0 {
		// send the message out
		err = smtp.SendMail("localhost:25",
			smtp.PlainAuth("", "", "", ""),
			msg.Header.Get("From"),
			forwardAry,
			msg822)
		if err != nil {
			periwinkle.Logf("Error sending: %v", err)
			return postfixpipe.EX_UNAVAILABLE
		}
	}
	return postfixpipe.EX_OK
}
Ejemplo n.º 20
0
func (o *TwilioSMSMessage) Delete(db *periwinkle.Tx) {
	if err := db.Where("message_s_id = ?", o.MessageSID).Delete(TwilioSMSMessage{}).Error; err != nil {
		dbError(err)
	}
}
Ejemplo n.º 21
0
func (sub *Subscription) Delete(db *periwinkle.Tx) {
	if err := db.Where("address_id = ? AND group_id = ?", sub.AddressID, sub.GroupID).Delete(Subscription{}).Error; err != nil {
		dbError(err)
	}
}