diff --git a/api/comment_new.go b/api/comment_new.go index c2ccfb0..b19fe8a 100644 --- a/api/comment_new.go +++ b/api/comment_new.go @@ -78,12 +78,13 @@ func commentNewHandler(w http.ResponseWriter, r *http.Request) { } // logic: (empty column indicates the value doesn't matter) - // | anonymous | moderator | requireIdentification | requireModeration | approved? | - // |-----------+-----------+-----------------------+-------------------+-----------| - // | yes | | | | no | - // | no | yes | | | yes | - // | no | no | | yes | yes | - // | no | no | | no | no | + // | anonymous | moderator | requireIdentification | requireModeration | moderateAllAnonymous | approved? | + // |-----------+-----------+-----------------------+-------------------+----------------------+-----------| + // | yes | | | | no | yes | + // | yes | | | | yes | no | + // | no | yes | | | | yes | + // | no | no | | yes | | yes | + // | no | no | | no | | no | var commenterHex string var state string @@ -93,7 +94,11 @@ func commentNewHandler(w http.ResponseWriter, r *http.Request) { if isSpam(*x.Domain, getIp(r), getUserAgent(r), "Anonymous", "", "", *x.Markdown) { state = "flagged" } else { - state = "unapproved" + if d.ModerateAllAnonymous { + state = "unapproved" + } else { + state = "approved" + } } } else { c, err := commenterGetByCommenterToken(*x.CommenterToken) diff --git a/api/domain.go b/api/domain.go index ebec5e5..98a72e7 100644 --- a/api/domain.go +++ b/api/domain.go @@ -14,5 +14,6 @@ type domain struct { AutoSpamFilter bool `json:"autoSpamFilter"` RequireModeration bool `json:"requireModeration"` RequireIdentification bool `json:"requireIdentification"` + ModerateAllAnonymous bool `json:"moderateAllAnonymous"` Moderators []moderator `json:"moderators"` } diff --git a/api/domain_get.go b/api/domain_get.go index b881ecc..ea9447a 100644 --- a/api/domain_get.go +++ b/api/domain_get.go @@ -8,7 +8,7 @@ func domainGet(dmn string) (domain, error) { } statement := ` - SELECT domain, ownerHex, name, creationDate, state, importedComments, autoSpamFilter, requireModeration, requireIdentification + SELECT domain, ownerHex, name, creationDate, state, importedComments, autoSpamFilter, requireModeration, requireIdentification, moderateAllAnonymous FROM domains WHERE domain = $1; ` @@ -16,7 +16,7 @@ func domainGet(dmn string) (domain, error) { var err error d := domain{} - if err = row.Scan(&d.Domain, &d.OwnerHex, &d.Name, &d.CreationDate, &d.State, &d.ImportedComments, &d.AutoSpamFilter, &d.RequireModeration, &d.RequireIdentification); err != nil { + if err = row.Scan(&d.Domain, &d.OwnerHex, &d.Name, &d.CreationDate, &d.State, &d.ImportedComments, &d.AutoSpamFilter, &d.RequireModeration, &d.RequireIdentification, &d.ModerateAllAnonymous); err != nil { return d, errorNoSuchDomain } diff --git a/api/domain_list.go b/api/domain_list.go index 8699381..5311e0e 100644 --- a/api/domain_list.go +++ b/api/domain_list.go @@ -10,7 +10,7 @@ func domainList(ownerHex string) ([]domain, error) { } statement := ` - SELECT domain, ownerHex, name, creationDate, state, importedComments, autoSpamFilter, requireModeration, requireIdentification + SELECT domain, ownerHex, name, creationDate, state, importedComments, autoSpamFilter, requireModeration, requireIdentification, moderateAllAnonymous FROM domains WHERE ownerHex=$1; ` @@ -24,7 +24,7 @@ func domainList(ownerHex string) ([]domain, error) { domains := []domain{} for rows.Next() { d := domain{} - if err = rows.Scan(&d.Domain, &d.OwnerHex, &d.Name, &d.CreationDate, &d.State, &d.ImportedComments, &d.AutoSpamFilter, &d.RequireModeration, &d.RequireIdentification); err != nil { + if err = rows.Scan(&d.Domain, &d.OwnerHex, &d.Name, &d.CreationDate, &d.State, &d.ImportedComments, &d.AutoSpamFilter, &d.RequireModeration, &d.RequireIdentification, &d.ModerateAllAnonymous); err != nil { logger.Errorf("cannot Scan domain: %v", err) return nil, errorInternal } diff --git a/api/domain_update.go b/api/domain_update.go index 4b4ac9c..e6c7cbf 100644 --- a/api/domain_update.go +++ b/api/domain_update.go @@ -7,11 +7,11 @@ import ( func domainUpdate(d domain) error { statement := ` UPDATE domains - SET name=$2, state=$3, autoSpamFilter=$4, requireModeration=$5, requireIdentification=$6 + SET name=$2, state=$3, autoSpamFilter=$4, requireModeration=$5, requireIdentification=$6, moderateAllAnonymous=$7 WHERE domain=$1; ` - _, err := db.Exec(statement, d.Domain, d.Name, d.State, d.AutoSpamFilter, d.RequireModeration, d.RequireIdentification) + _, err := db.Exec(statement, d.Domain, d.Name, d.State, d.AutoSpamFilter, d.RequireModeration, d.RequireIdentification, d.ModerateAllAnonymous) if err != nil { logger.Errorf("cannot update non-moderators: %v", err) return errorInternal diff --git a/db/20190122235525-anonymous-moderation-default.sql b/db/20190122235525-anonymous-moderation-default.sql new file mode 100644 index 0000000..a87a44e --- /dev/null +++ b/db/20190122235525-anonymous-moderation-default.sql @@ -0,0 +1,4 @@ +-- Allow the owner to change whether anonymous comments are put into moderation by default. + +ALTER TABLE domains + ADD COLUMN moderateAllAnonymous BOOLEAN DEFAULT true; diff --git a/frontend/dashboard.html b/frontend/dashboard.html index a1285f1..721c5c1 100644 --- a/frontend/dashboard.html +++ b/frontend/dashboard.html @@ -205,13 +205,21 @@
- - + +
Enabling this would require all commenters to authenticate themselves (using their Google account, for example). Disabling would allow anonymous comments.
+
+ + +
+ Enabling this would require a moderator to approve anonymous comments. This is recommended as a lot of spam is often from anonymous comments. +
+
+
diff --git a/frontend/js/commento.js b/frontend/js/commento.js index fd595a7..0791576 100644 --- a/frontend/js/commento.js +++ b/frontend/js/commento.js @@ -465,7 +465,7 @@ commentsArea.innerHTML = ""; if (isLocked || isFrozen) { - if (isAuthenticated) { + if (isAuthenticated || chosenAnonymous) { append(mainArea, messageCreate("This thread is locked. You cannot add new comments.")); } else { append(mainArea, textareaCreate("root")); @@ -1408,15 +1408,9 @@ isLocked = !isLocked; lock.disabled = true; - pageUpdate(function(success) { - if (success) { - lock.disabled = false; - if (isLocked) { - lock.innerHTML = "Unlock Thread"; - } else { - lock.innerHTML = "Lock Thread"; - } - } + pageUpdate(function() { + lock.disabled = false; + refreshAll(); }); } @@ -1434,16 +1428,14 @@ stickyCommentHex = commentHex; } - pageUpdate(function(success) { - if (success) { - var sticky = $(ID_STICKY + commentHex); - if (stickyCommentHex === commentHex) { - classRemove(sticky, "option-sticky"); - classAdd(sticky, "option-unsticky"); - } else { - classRemove(sticky, "option-unsticky"); - classAdd(sticky, "option-sticky"); - } + pageUpdate(function() { + var sticky = $(ID_STICKY + commentHex); + if (stickyCommentHex === commentHex) { + classRemove(sticky, "option-sticky"); + classAdd(sticky, "option-unsticky"); + } else { + classRemove(sticky, "option-unsticky"); + classAdd(sticky, "option-sticky"); } }); } diff --git a/frontend/js/dashboard-domain.js b/frontend/js/dashboard-domain.js index 1aacad0..bf5bf52 100644 --- a/frontend/js/dashboard-domain.js +++ b/frontend/js/dashboard-domain.js @@ -91,6 +91,8 @@ resp.domains[i].viewsLast30Days = global.numberify(0); resp.domains[i].commentsLast30Days = global.numberify(0); + + resp.domains[i].allowAnonymous = !resp.domains[i].requireIdentification; for (var j = 0; j < resp.domains[i].moderators.length; j++) { resp.domains[i].moderators[j].timeAgo = global.timeSince( @@ -109,6 +111,7 @@ // Updates a domain with the backend. global.domainUpdate = function(domain, callback) { + domain.requireIdentification = !domain.allowAnonymous; var json = { "ownerToken": global.cookieGet("commentoOwnerToken"), "domain": domain, diff --git a/frontend/sass/dashboard-main.scss b/frontend/sass/dashboard-main.scss index d5bd11c..149aa29 100644 --- a/frontend/sass/dashboard-main.scss +++ b/frontend/sass/dashboard-main.scss @@ -623,6 +623,10 @@ body { border: none; } +.indent { + padding-left: 32px; +} + .button { @extend .shadow; height: 40px;