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 }
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 }
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 }
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) } }
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 }
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 } }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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) } } }
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 }
func (o *TwilioSMSMessage) Delete(db *periwinkle.Tx) { if err := db.Where("message_s_id = ?", o.MessageSID).Delete(TwilioSMSMessage{}).Error; err != nil { dbError(err) } }
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) } }