Made it harder to parse the antispam script.

Used Unicode magic to make it harder to parse the antispam trap question.
Added more shady email substrings.
Tweaked the contributing guidelines, no more await allowed... For now.
Might already have Git, note that.
Added the the_form class to the login form, registration form and login mfa form.
Made the titles on the Control Panel Dashboard and Debug page a little softer on Cosora.

Added the quick topic form to Nox.
Made the topic pages somewhat usable on Nox.
This commit is contained in:
Azareal 2018-07-05 19:54:01 +10:00
parent 3043ce083d
commit 0f2503a20c
14 changed files with 518 additions and 369 deletions

View File

@ -6,6 +6,8 @@ Other uses may arise in the future, e.g. commercial licensing, although that's c
Try to prefix commits which introduce a lot of bugs or otherwise has a large impact on the usability of Gosora with UNSTABLE.
If anything seems suspect, then feel free to bring up an alternative, although I'd rather not get hung up on the little details, if it's something which is purely a matter of opinion.
# Coding Standards
All code must be unit tested where ever possible with the exception of JavaScript which is untestable with our current technologies, tread with caution there.
@ -32,6 +34,8 @@ Always use strict mode.
Don't worry about ES5, we're targetting modern browsers. If we decide to backport code to older browsers, then we'll transpile the files.
Please don't use await. It incurs too much of a cognitive overhead as to where and when you can use it.
To keep consistency with Go code, variables must be camelCase.
# JSON

View File

@ -39,7 +39,7 @@ Other modern features like alerts, likes, advanced dashboard with live stats (CP
Go 1.10 or newer - You will need to install this. Pick the .msi, if you want everything sorted out for you rather than having to go around updating the environment settings. https://golang.org/doc/install
Git - You may need this for downloading updates via the updater. More to come on this here. https://git-scm.com/downloads
Git - You may need this for downloading updates via the updater. You might already have this installed on your server. More to come on this here. https://git-scm.com/downloads
MySQL Database - You will need to setup a MySQL Database somewhere. A MariaDB Database works equally well and is much faster than MySQL. You could use something like WNMP / XAMPP which have a little PHP script called PhpMyAdmin for managing MySQL databases or you could install MariaDB directly.

View File

@ -247,7 +247,7 @@ func NameToSlug(name string) (slug string) {
func HasSuspiciousEmail(email string) bool {
lowEmail := strings.ToLower(email)
// TODO: Use a more flexible blacklist, perhaps with a similar mechanism to the HTML tag registration system in PreparseMessage()
if strings.Contains(lowEmail, "casino") || strings.Contains(lowEmail, "viagra") {
if strings.Contains(lowEmail, "casino") || strings.Contains(lowEmail, "viagra") || strings.Contains(lowEmail, "pharma") || strings.Contains(lowEmail, "pill") {
return true
}

File diff suppressed because it is too large Load Diff

View File

@ -361,7 +361,7 @@
"register_account_email":"Email",
"register_account_password":"Password",
"register_account_confirm_password":"Confirm Password",
"register_account_anti_spam":"Are you a spambot?",
"register_account_anti_spam":"Are you a spambot?",
"register_submit_button":"Create Account",
"account_menu_head":"My Account",

View File

@ -137,6 +137,19 @@ func createTables(adapter qgen.Adapter) error {
[]qgen.DBTableKey{},
)
// TODO: Allow for patterns in domains, if the bots try to shake things up there?
/*
qgen.Install.CreateTable("email_domain_blacklist", "", "",
[]qgen.DBTableColumn{
qgen.DBTableColumn{"domain", "varchar", 200, false, false, ""},
qgen.DBTableColumn{"gtld", "boolean", 0, false, false, "0"},
},
[]qgen.DBTableKey{
qgen.DBTableKey{"domain", "primary"},
},
)
*/
qgen.Install.CreateTable("forums", "utf8mb4", "utf8mb4_general_ci",
[]qgen.DBTableColumn{
qgen.DBTableColumn{"fid", "int", 0, false, true, ""},

View File

@ -14,6 +14,7 @@ func routes() {
apiGroup := newRouteGroup("/api/",
View("routeAPI", "/api/"),
View("routeAPIPhrases", "/api/phrases/"), // TODO: Be careful with exposing the panel phrases here
View("routeJSAntispam", "/api/watches/"),
)
addRouteGroup(apiGroup)

View File

@ -7,6 +7,8 @@
package main
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"net/http"
"strconv"
@ -186,3 +188,19 @@ func routeAPIPhrases(w http.ResponseWriter, r *http.Request, user common.User) c
return nil
}
// A dedicated function so we can shake things up every now and then to make the token harder to parse
// TODO: Are we sure we want to do this by ID, just in case we reuse this and have multiple antispams on the page?
func routeJSAntispam(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
h := sha256.New()
h.Write([]byte(common.JSTokenBox.Load().(string)))
h.Write([]byte(user.LastIP))
jsToken := hex.EncodeToString(h.Sum(nil))
var innerCode = "`document.getElementByld('golden-watch').value = '" + jsToken + "';`"
w.Write([]byte(`let hihi = ` + innerCode + `;
hihi = hihi.replace('ld','Id');
eval(hihi);`))
return nil
}

View File

@ -201,11 +201,7 @@ func AccountRegister(w http.ResponseWriter, r *http.Request, user common.User) c
}
header.Title = common.GetTitlePhrase("register")
h := sha256.New()
h.Write([]byte(common.JSTokenBox.Load().(string)))
h.Write([]byte(user.LastIP))
jsToken := hex.EncodeToString(h.Sum(nil))
pi := common.Page{header, tList, jsToken}
pi := common.Page{header, tList, nil}
if common.RunPreRenderHook("pre_render_register", w, r, &user, &pi) {
return nil
}
@ -237,7 +233,7 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.U
h := sha256.New()
h.Write([]byte(common.JSTokenBox.Load().(string)))
h.Write([]byte(user.LastIP))
if r.PostFormValue("antispam") != hex.EncodeToString(h.Sum(nil)) {
if r.PostFormValue("golden-watch") != hex.EncodeToString(h.Sum(nil)) {
regError("You might be a machine", "js-antispam")
}

View File

@ -3,7 +3,7 @@
<div class="rowblock rowhead">
<div class="rowitem"><h1>{{lang "login_head"}}</h1></div>
</div>
<div class="rowblock">
<div class="rowblock the_form">
<form action="/accounts/login/submit/" method="post">
<div class="formrow login_name_row">
<div class="formitem formlabel"><a id="login_name_label">{{lang "login_account_name"}}</a></div>

View File

@ -3,7 +3,7 @@
<div class="rowblock rowhead">
<div class="rowitem"><h1>{{lang "login_mfa_verify_head"}}</h1></div>
</div>
<div class="rowblock">
<div class="rowblock the_form">
<form action="/accounts/mfa_verify/submit/" method="post">
<div class="formrow real_first_child">
<div class="formitem formlabel"><a>{{lang "login_mfa_verify_explanation"}}</a></div>

View File

@ -3,7 +3,7 @@
<div class="rowblock rowhead">
<div class="rowitem"><h1>{{lang "register_head"}}</h1></div>
</div>
<div class="rowblock">
<div class="rowblock the_form">
<form action="/accounts/create/submit/" method="post">
<div class="formrow">
<div class="formitem formlabel"><a id="username_label">{{lang "register_account_name"}}</a></div>
@ -31,11 +31,20 @@
<div class="formrow register_button_row">
<div class="formitem"><button name="register-button" class="formbutton">{{lang "register_submit_button"}}</button></div>
</div>
<input id="js-antispam" name="antispam" value="nananana" type="hidden" />
<input id="golden-watch" name="golden-watch" value="$500" type="hidden" />
</form>
</div>
</main>
<script>{{/** TODO: Are we sure we want to do this by ID, just in case we reuse this and have multiple antispams on the page? **/}}
document.getElementById("js-antispam").value = "{{.Something}}";
<script>
fetch("/api/watches/")
.then(response => {
if(response.status!==200) {
console.log("error");
console.log("response:", response);
return;
}
response.text().then(data => eval(data));
})
.catch(err => console.log("err:", err));
</script>
{{template "footer.html" . }}

View File

@ -50,6 +50,11 @@
margin-top: 14px;
}
#panel_dashboard_right .colstack_head h1 {
font-size: 17px;
color: hsl(0,0%,40%);
}
.complex_rowlist {
background-color: inherit !important;
border: none !important;

View File

@ -109,7 +109,12 @@ li a {
.sidebar {
width: 320px;
}
.rowblock:not(.topic_list):not(.rowhead):not(.opthead) .rowitem {
.the_form {
border-radius: 3px;
background-color: #444444;
padding: 16px;
}
.rowblock:not(.topic_list):not(.rowhead):not(.opthead) .rowitem:not(.post_item) {
border-radius: 3px;
background-color: #444444;
display: flex;
@ -118,11 +123,6 @@ li a {
.sidebar .rowblock:not(.topic_list):not(.rowhead):not(.opthead) .rowitem {
margin-left: 12px;
}
.colstack_right .colstack_item.the_form {
border-radius: 3px;
background-color: #444444;
padding: 16px;
}
.colstack_right .colstack_item:not(.colstack_head):not(.rowhead) .rowitem {
border-radius: 3px;
background-color: #444444;
@ -175,6 +175,50 @@ h2 {
margin-left: 8px;
}
.topic_create_form {
display: flex !important;
}
.quick_reply_form, .topic_reply_form, .topic_create_form {
background-color: #444444;
border-radius: 3px;
}
.quick_create_form {
margin-bottom: 8px;
padding: 16px;
}
.quick_create_form .little_row_avatar {
border-radius: 36px;
margin-left: 4px;
margin-right: 20px;
height: 48px;
width: 48px;
}
.quick_create_form .main_form {
width: 80%;
}
.quick_create_form .topic_meta {
display: flex;
}
.quick_create_form .topic_meta .topic_name_row {
margin-left: 8px;
margin-bottom: 8px;
width: 100%;
}
.quick_create_form .topic_meta .topic_name_row input {
width: 100%;
}
.quick_create_form .topic_content_row textarea {
width: 100%;
height: 60px;
}
.quick_create_form .quick_button_row .formitem {
display: flex;
margin-top: 6px;
}
.quick_create_form .quick_button_row button, .quick_create_form .quick_button_row label {
margin-right: 8px;
}
.more_topic_block_initial {
display: none;
}
@ -184,6 +228,9 @@ h2 {
.hide_ajax_topic {
display: none !important;
}
.auto_hide, .show_on_edit {
display: none;
}
.topic_row:not(:last-child) {
margin-bottom: 8px;
@ -358,6 +405,56 @@ button, .formbutton {
display: flex;
}
.post_item {
display: flex;
margin-bottom: 12px;
}
.userinfo {
margin-right: 12px;
padding: 16px;
background-color: #444444;
border-radius: 3px;
width: 120px;
display: flex;
flex-direction: column;
}
.avatar_item {
border-radius: 24px;
height: 48px;
width: 48px;
background-size: 56px;
margin-left: auto;
margin-right: auto;
}
.the_name {
margin-left: auto;
margin-right: auto;
white-space: nowrap;
display: block;
font-size: 17px;
margin-top: 8px;
line-height: 16px;
}
.tag_block {
display: flex;
}
.post_tag {
white-space: nowrap;
margin-left: auto;
margin-right: auto;
display: block;
}
.post_item .content_container {
padding: 16px;
background-color: #444444;
border-radius: 3px;
width: 100%;
}
.topic_reply_container {
display: flex;
}
.footer .widget {
padding: 12px;
border-bottom: 1px solid #555555;