-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented antispam via feedback replyto ratelimiting (#341)
* Implemented feedback replyto ratelimiting and a different field for the name * fixed issues in the tests
- Loading branch information
1 parent
7e9730f
commit 647a370
Showing
12 changed files
with
372 additions
and
301 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,11 +62,13 @@ func messageWithHeaders(feedback *model.Feedback) *gomail.Message { | |
if feedback.Recipient != "" { | ||
m.SetHeader("To", feedback.Recipient) | ||
} else { | ||
m.SetHeader("To", "[email protected]") // should not ever happen as checked in the api | ||
m.SetAddressHeader("To", "[email protected]", "TCA Support") // should not ever happen as checked in the api | ||
} | ||
// ReplyTo | ||
if feedback.ReplyTo.Valid { | ||
m.SetHeader("Reply-To", feedback.ReplyTo.String) | ||
if feedback.ReplyToName.Valid && feedback.ReplyToEmail.Valid { | ||
m.SetAddressHeader("Reply-To", feedback.ReplyToEmail.String, feedback.ReplyToName.String) | ||
} else if feedback.ReplyToEmail.Valid { | ||
m.SetHeader("Reply-To", feedback.ReplyToEmail.String) | ||
} | ||
// Timestamp | ||
if feedback.Timestamp.Valid { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,31 +23,33 @@ func TestIterate(t *testing.T) { | |
|
||
func fullFeedback() *model.Feedback { | ||
return &model.Feedback{ | ||
EmailId: "magic-id", | ||
Recipient: "tca", | ||
ReplyTo: null.StringFrom("[email protected]"), | ||
Feedback: "This is a Test", | ||
ImageCount: 1, | ||
Latitude: null.FloatFrom(0), | ||
Longitude: null.FloatFrom(0), | ||
AppVersion: null.StringFrom("TCA 10.2"), | ||
OsVersion: null.StringFrom("Android 10.0"), | ||
Timestamp: null.TimeFrom(time.Now()), | ||
EmailId: "magic-id", | ||
Recipient: "tca", | ||
ReplyToEmail: null.StringFrom("[email protected]"), | ||
ReplyToName: null.StringFrom("Erika Mustermann"), | ||
Feedback: "This is a Test", | ||
ImageCount: 1, | ||
Latitude: null.FloatFrom(0), | ||
Longitude: null.FloatFrom(0), | ||
AppVersion: null.StringFrom("TCA 10.2"), | ||
OsVersion: null.StringFrom("Android 10.0"), | ||
Timestamp: null.TimeFrom(time.Now()), | ||
} | ||
} | ||
|
||
func emptyFeedback() *model.Feedback { | ||
return &model.Feedback{ | ||
EmailId: "", | ||
Recipient: "", | ||
ReplyTo: null.String{}, | ||
Feedback: "", | ||
ImageCount: 0, | ||
Latitude: null.Float{}, | ||
Longitude: null.Float{}, | ||
AppVersion: null.String{}, | ||
OsVersion: null.String{}, | ||
Timestamp: null.Time{}, | ||
EmailId: "", | ||
Recipient: "", | ||
ReplyToEmail: null.String{}, | ||
ReplyToName: null.String{}, | ||
Feedback: "", | ||
ImageCount: 0, | ||
Latitude: null.Float{}, | ||
Longitude: null.Float{}, | ||
AppVersion: null.String{}, | ||
OsVersion: null.String{}, | ||
Timestamp: null.Time{}, | ||
} | ||
} | ||
|
||
|
@@ -58,7 +60,7 @@ func TestHeaderInstantiationWithFullFeedback(t *testing.T) { | |
m := messageWithHeaders(fb) | ||
assert.Equal(t, []string{`"TUM Campus App" <[email protected]>`}, m.GetHeader("From")) | ||
assert.Equal(t, []string{fb.Recipient}, m.GetHeader("To")) | ||
assert.Equal(t, []string{"[email protected]"}, m.GetHeader("Reply-To")) | ||
assert.Equal(t, []string{"\"Erika Mustermann\" <[email protected]>"}, m.GetHeader("Reply-To")) | ||
assert.Equal(t, []string{fb.Timestamp.Time.Format(time.RFC1123Z)}, m.GetHeader("Date")) | ||
assert.Equal(t, []string{"Feedback via the TUM Campus App"}, m.GetHeader("Subject")) | ||
} | ||
|
@@ -68,7 +70,7 @@ func TestHeaderInstantiationWithEmptyFeedback(t *testing.T) { | |
require.NoError(t, os.Setenv("SMTP_FROM", "[email protected]")) | ||
m := messageWithHeaders(emptyFeedback()) | ||
assert.Equal(t, []string{`"TUM Campus App" <[email protected]>`}, m.GetHeader("From")) | ||
assert.Equal(t, []string{"[email protected]"}, m.GetHeader("To")) | ||
assert.Equal(t, []string{"\"TCA Support\" <[email protected]>"}, m.GetHeader("To")) | ||
assert.Equal(t, []string(nil), m.GetHeader("Reply-To")) | ||
// Date is set to now in messageWithHeaders => checking that this is actually now is a bit tricker | ||
dates := m.GetHeader("Date") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ import ( | |
"os" | ||
"path" | ||
"regexp" | ||
"sync" | ||
"testing" | ||
"time" | ||
|
||
|
@@ -99,10 +100,10 @@ func (s *FeedbackSuite) Test_CreateFeedback_OneFile() { | |
} | ||
}(cron.StorageDir) | ||
|
||
server := CampusServer{db: s.DB} | ||
server := CampusServer{db: s.DB, feedbackEmailLastReuestAt: &sync.Map{}} | ||
s.mock.ExpectBegin() | ||
returnedTime := time.Now() | ||
s.mock.ExpectQuery(regexp.QuoteMeta("SELECT count(*) FROM `feedback` WHERE receiver=? AND reply_to=? AND feedback=? AND app_version=?")). | ||
s.mock.ExpectQuery(regexp.QuoteMeta("SELECT count(*) FROM `feedback` WHERE receiver=? AND reply_to_email=? AND feedback=? AND app_version=?")). | ||
WithArgs("[email protected]", "[email protected]", "Hello with image", nil). | ||
WillReturnRows(sqlmock.NewRows([]string{"count(*)"})) | ||
s.mock.ExpectQuery(regexp.QuoteMeta("INSERT INTO `files` (`name`,`path`,`downloads`,`downloaded`) VALUES (?,?,?,?) RETURNING `url`,`file`")). | ||
|
@@ -111,8 +112,8 @@ func (s *FeedbackSuite) Test_CreateFeedback_OneFile() { | |
s.mock.ExpectQuery(regexp.QuoteMeta("INSERT INTO `files` (`name`,`path`,`downloads`,`downloaded`) VALUES (?,?,?,?) RETURNING `url`,`file`")). | ||
WithArgs("1.png", sqlmock.AnyArg(), 1, true). | ||
WillReturnRows(sqlmock.NewRows([]string{"url", "file"}).AddRow(nil, 1)) | ||
s.mock.ExpectQuery(regexp.QuoteMeta("INSERT INTO `feedback` (`image_count`,`email_id`,`receiver`,`reply_to`,`feedback`,`latitude`,`longitude`,`os_version`,`app_version`,`processed`) VALUES (?,?,?,?,?,?,?,?,?,?) RETURNING `timestamp`,`id`")). | ||
WithArgs(2, sqlmock.AnyArg(), "[email protected]", "[email protected]", "Hello with image", nil, nil, nil, nil, false). | ||
s.mock.ExpectQuery(regexp.QuoteMeta("INSERT INTO `feedback` (`image_count`,`email_id`,`receiver`,`reply_to_email`,`reply_to_name`,`feedback`,`latitude`,`longitude`,`os_version`,`app_version`,`processed`) VALUES (?,?,?,?,?,?,?,?,?,?,?) RETURNING `timestamp`,`id`")). | ||
WithArgs(2, sqlmock.AnyArg(), "[email protected]", "[email protected]", nil, "Hello with image", nil, nil, nil, nil, false). | ||
WillReturnRows(sqlmock.NewRows([]string{"timestamp", "id"}).AddRow(returnedTime, 1)) | ||
s.mock.ExpectCommit() | ||
|
||
|
@@ -146,13 +147,13 @@ func expectFileMatches(t *testing.T, file os.DirEntry, name string, returnedTime | |
func (s *FeedbackSuite) Test_CreateFeedback_NoImage() { | ||
cron.StorageDir = "test_no_image/" | ||
|
||
server := CampusServer{db: s.DB} | ||
server := CampusServer{db: s.DB, feedbackEmailLastReuestAt: &sync.Map{}} | ||
s.mock.ExpectBegin() | ||
s.mock.ExpectQuery(regexp.QuoteMeta("SELECT count(*) FROM `feedback` WHERE receiver=? AND reply_to=? AND feedback=? AND app_version=?")). | ||
s.mock.ExpectQuery(regexp.QuoteMeta("SELECT count(*) FROM `feedback` WHERE receiver=? AND reply_to_email=? AND feedback=? AND app_version=?")). | ||
WithArgs("[email protected]", "[email protected]", "Hello without image", nil). | ||
WillReturnRows(sqlmock.NewRows([]string{"count(*)"})) | ||
s.mock.ExpectQuery(regexp.QuoteMeta("INSERT INTO `feedback` (`image_count`,`email_id`,`receiver`,`reply_to`,`feedback`,`latitude`,`longitude`,`os_version`,`app_version`,`processed`) VALUES (?,?,?,?,?,?,?,?,?,?) RETURNING `timestamp`,`id`")). | ||
WithArgs(0, sqlmock.AnyArg(), "[email protected]", "[email protected]", "Hello without image", nil, nil, nil, nil, false). | ||
s.mock.ExpectQuery(regexp.QuoteMeta("INSERT INTO `feedback` (`image_count`,`email_id`,`receiver`,`reply_to_email`,`reply_to_name`,`feedback`,`latitude`,`longitude`,`os_version`,`app_version`,`processed`) VALUES (?,?,?,?,?,?,?,?,?,?,?) RETURNING `timestamp`,`id`")). | ||
WithArgs(0, sqlmock.AnyArg(), "[email protected]", "[email protected]", nil, "Hello without image", nil, nil, nil, nil, false). | ||
WillReturnRows(sqlmock.NewRows([]string{"timestamp", "id"}).AddRow(time.Now(), 1)) | ||
s.mock.ExpectCommit() | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package migration | ||
|
||
import ( | ||
"github.com/go-gormigrate/gormigrate/v2" | ||
"gorm.io/gorm" | ||
) | ||
|
||
// migrate20240405000000 | ||
// Split the reply-to fields of the feedback model into name and email | ||
func migrate20240405000000() *gormigrate.Migration { | ||
return &gormigrate.Migration{ | ||
ID: "20240405000000", | ||
Migrate: func(tx *gorm.DB) error { | ||
if err := tx.Exec("alter table feedback change reply_to reply_to_email text null").Error; err != nil { | ||
return err | ||
} | ||
if err := tx.Exec("alter table feedback add reply_to_name text null default null after reply_to_email").Error; err != nil { | ||
return err | ||
} | ||
return nil | ||
}, | ||
Rollback: func(tx *gorm.DB) error { | ||
if err := tx.Exec("alter table feedback change reply_to_email reply_to text null").Error; err != nil { | ||
return err | ||
} | ||
if err := tx.Exec("alter table feedback drop column reply_to_name").Error; err != nil { | ||
return err | ||
} | ||
return nil | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters