added maximum votes limit per comment (#223)
* added maximum votes limit per comment * added 'max-votes' param description into README
This commit is contained in:
committed by
Umputun
parent
11d8338989
commit
f8e36551ea
@@ -124,6 +124,7 @@ _this is the recommended way to run remark42_
|
||||
| ssl.cert | SSL_CERT | | path to cert.pem file |
|
||||
| ssl.key | SSL_KEY | | path to key.pem file |
|
||||
| max-comment | MAX_COMMENT_SIZE | 2048 | comment's size limit |
|
||||
| max-votes | MAX_VOTES | `-1` | votes limit per comment, `-1` - unlimited |
|
||||
| low-score | LOW_SCORE | `-5` | low score threshold |
|
||||
| critical-score | CRITICAL_SCORE | `-10` | critical score threshold |
|
||||
| edit-time | EDIT_TIME | `5m` | edit window |
|
||||
|
||||
@@ -45,6 +45,7 @@ type ServerCommand struct {
|
||||
MaxBackupFiles int `long:"max-back" env:"MAX_BACKUP_FILES" default:"10" description:"max backups to keep"`
|
||||
ImageProxy bool `long:"img-proxy" env:"IMG_PROXY" description:"enable image proxy"`
|
||||
MaxCommentSize int `long:"max-comment" env:"MAX_COMMENT_SIZE" default:"2048" description:"max comment size"`
|
||||
MaxVotes int `long:"max-votes" env:"MAX_VOTES" default:"-1" description:"maximum number of votes per comment"`
|
||||
LowScore int `long:"low-score" env:"LOW_SCORE" default:"-5" description:"low score threshold"`
|
||||
CriticalScore int `long:"critical-score" env:"CRITICAL_SCORE" default:"-10" description:"critical score threshold"`
|
||||
ReadOnlyAge int `long:"read-age" env:"READONLY_AGE" default:"0" description:"read-only age of comments"`
|
||||
@@ -206,6 +207,7 @@ func (s *ServerCommand) newServerApp() (*serverApp, error) {
|
||||
EditDuration: s.EditDuration,
|
||||
AdminStore: adminStore,
|
||||
MaxCommentSize: s.MaxCommentSize,
|
||||
MaxVotes: s.MaxVotes,
|
||||
}
|
||||
|
||||
loadingCache, err := s.makeCache()
|
||||
|
||||
@@ -18,6 +18,7 @@ type DataStore struct {
|
||||
EditDuration time.Duration
|
||||
AdminStore admin.Store
|
||||
MaxCommentSize int
|
||||
MaxVotes int
|
||||
|
||||
// granular locks
|
||||
scopedLocks struct {
|
||||
@@ -28,6 +29,7 @@ type DataStore struct {
|
||||
}
|
||||
|
||||
const defaultCommentMaxSize = 2000
|
||||
const defaultVotesLimit = -1 // unlimited
|
||||
|
||||
// Create prepares comment and forward to Interface.Create
|
||||
func (s *DataStore) Create(comment store.Comment) (commentID string, err error) {
|
||||
@@ -97,6 +99,15 @@ func (s *DataStore) Vote(locator store.Locator, commentID string, userID string,
|
||||
return comment, errors.Errorf("user %s already voted for %s", userID, commentID)
|
||||
}
|
||||
|
||||
maxVotes := s.MaxVotes
|
||||
if s.MaxVotes <= 0 {
|
||||
maxVotes = defaultVotesLimit
|
||||
}
|
||||
|
||||
if maxVotes >= 0 && len(comment.Votes) >= maxVotes {
|
||||
return comment, errors.Errorf("maximum number of votes exceeded for comment %s", commentID)
|
||||
}
|
||||
|
||||
// reset vote if user changed to opposite
|
||||
if voted && v != val {
|
||||
delete(comment.Votes, userID)
|
||||
|
||||
@@ -116,6 +116,24 @@ func TestService_Vote(t *testing.T) {
|
||||
assert.Equal(t, map[string]bool{}, res[0].Votes, "vote reset ok")
|
||||
}
|
||||
|
||||
func TestService_VoteLimit(t *testing.T) {
|
||||
defer os.Remove(testDb)
|
||||
b := DataStore{Interface: prepStoreEngine(t), AdminStore: admin.NewStaticKeyStore("secret 123"), MaxVotes: 2}
|
||||
|
||||
_, err := b.Vote(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, "id-1", "user2", true)
|
||||
assert.Nil(t, err)
|
||||
|
||||
_, err = b.Vote(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, "id-1", "user3", true)
|
||||
assert.Nil(t, err)
|
||||
|
||||
_, err = b.Vote(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, "id-1", "user4", true)
|
||||
assert.NotNil(t, err, "vote limit reached")
|
||||
assert.True(t, strings.HasPrefix(err.Error(), "maximum number of votes exceeded for comment id-1"))
|
||||
|
||||
_, err = b.Vote(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, "id-2", "user4", true)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestService_VoteAggressive(t *testing.T) {
|
||||
defer os.Remove(testDb)
|
||||
b := DataStore{Interface: prepStoreEngine(t), AdminStore: admin.NewStaticKeyStore("secret 123")}
|
||||
|
||||
Reference in New Issue
Block a user