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:
parent
3043ce083d
commit
0f2503a20c
|
@ -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.
|
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
|
# 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.
|
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.
|
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.
|
To keep consistency with Go code, variables must be camelCase.
|
||||||
|
|
||||||
# JSON
|
# JSON
|
||||||
|
|
|
@ -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
|
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.
|
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.
|
||||||
|
|
||||||
|
|
|
@ -247,7 +247,7 @@ func NameToSlug(name string) (slug string) {
|
||||||
func HasSuspiciousEmail(email string) bool {
|
func HasSuspiciousEmail(email string) bool {
|
||||||
lowEmail := strings.ToLower(email)
|
lowEmail := strings.ToLower(email)
|
||||||
// TODO: Use a more flexible blacklist, perhaps with a similar mechanism to the HTML tag registration system in PreparseMessage()
|
// 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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
702
gen_router.go
702
gen_router.go
File diff suppressed because it is too large
Load Diff
|
@ -361,7 +361,7 @@
|
||||||
"register_account_email":"Email",
|
"register_account_email":"Email",
|
||||||
"register_account_password":"Password",
|
"register_account_password":"Password",
|
||||||
"register_account_confirm_password":"Confirm 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",
|
"register_submit_button":"Create Account",
|
||||||
|
|
||||||
"account_menu_head":"My Account",
|
"account_menu_head":"My Account",
|
||||||
|
|
|
@ -137,6 +137,19 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
[]qgen.DBTableKey{},
|
[]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.Install.CreateTable("forums", "utf8mb4", "utf8mb4_general_ci",
|
||||||
[]qgen.DBTableColumn{
|
[]qgen.DBTableColumn{
|
||||||
qgen.DBTableColumn{"fid", "int", 0, false, true, ""},
|
qgen.DBTableColumn{"fid", "int", 0, false, true, ""},
|
||||||
|
|
|
@ -14,6 +14,7 @@ func routes() {
|
||||||
apiGroup := newRouteGroup("/api/",
|
apiGroup := newRouteGroup("/api/",
|
||||||
View("routeAPI", "/api/"),
|
View("routeAPI", "/api/"),
|
||||||
View("routeAPIPhrases", "/api/phrases/"), // TODO: Be careful with exposing the panel phrases here
|
View("routeAPIPhrases", "/api/phrases/"), // TODO: Be careful with exposing the panel phrases here
|
||||||
|
View("routeJSAntispam", "/api/watches/"),
|
||||||
)
|
)
|
||||||
addRouteGroup(apiGroup)
|
addRouteGroup(apiGroup)
|
||||||
|
|
||||||
|
|
18
routes.go
18
routes.go
|
@ -7,6 +7,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -186,3 +188,19 @@ func routeAPIPhrases(w http.ResponseWriter, r *http.Request, user common.User) c
|
||||||
|
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -201,11 +201,7 @@ func AccountRegister(w http.ResponseWriter, r *http.Request, user common.User) c
|
||||||
}
|
}
|
||||||
header.Title = common.GetTitlePhrase("register")
|
header.Title = common.GetTitlePhrase("register")
|
||||||
|
|
||||||
h := sha256.New()
|
pi := common.Page{header, tList, nil}
|
||||||
h.Write([]byte(common.JSTokenBox.Load().(string)))
|
|
||||||
h.Write([]byte(user.LastIP))
|
|
||||||
jsToken := hex.EncodeToString(h.Sum(nil))
|
|
||||||
pi := common.Page{header, tList, jsToken}
|
|
||||||
if common.RunPreRenderHook("pre_render_register", w, r, &user, &pi) {
|
if common.RunPreRenderHook("pre_render_register", w, r, &user, &pi) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -237,7 +233,7 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.U
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
h.Write([]byte(common.JSTokenBox.Load().(string)))
|
h.Write([]byte(common.JSTokenBox.Load().(string)))
|
||||||
h.Write([]byte(user.LastIP))
|
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")
|
regError("You might be a machine", "js-antispam")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem"><h1>{{lang "login_head"}}</h1></div>
|
<div class="rowitem"><h1>{{lang "login_head"}}</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock the_form">
|
||||||
<form action="/accounts/login/submit/" method="post">
|
<form action="/accounts/login/submit/" method="post">
|
||||||
<div class="formrow login_name_row">
|
<div class="formrow login_name_row">
|
||||||
<div class="formitem formlabel"><a id="login_name_label">{{lang "login_account_name"}}</a></div>
|
<div class="formitem formlabel"><a id="login_name_label">{{lang "login_account_name"}}</a></div>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem"><h1>{{lang "login_mfa_verify_head"}}</h1></div>
|
<div class="rowitem"><h1>{{lang "login_mfa_verify_head"}}</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock the_form">
|
||||||
<form action="/accounts/mfa_verify/submit/" method="post">
|
<form action="/accounts/mfa_verify/submit/" method="post">
|
||||||
<div class="formrow real_first_child">
|
<div class="formrow real_first_child">
|
||||||
<div class="formitem formlabel"><a>{{lang "login_mfa_verify_explanation"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "login_mfa_verify_explanation"}}</a></div>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem"><h1>{{lang "register_head"}}</h1></div>
|
<div class="rowitem"><h1>{{lang "register_head"}}</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock the_form">
|
||||||
<form action="/accounts/create/submit/" method="post">
|
<form action="/accounts/create/submit/" method="post">
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a id="username_label">{{lang "register_account_name"}}</a></div>
|
<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="formrow register_button_row">
|
||||||
<div class="formitem"><button name="register-button" class="formbutton">{{lang "register_submit_button"}}</button></div>
|
<div class="formitem"><button name="register-button" class="formbutton">{{lang "register_submit_button"}}</button></div>
|
||||||
</div>
|
</div>
|
||||||
<input id="js-antispam" name="antispam" value="nananana" type="hidden" />
|
<input id="golden-watch" name="golden-watch" value="$500" type="hidden" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</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? **/}}
|
<script>
|
||||||
document.getElementById("js-antispam").value = "{{.Something}}";
|
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>
|
</script>
|
||||||
{{template "footer.html" . }}
|
{{template "footer.html" . }}
|
||||||
|
|
|
@ -50,6 +50,11 @@
|
||||||
margin-top: 14px;
|
margin-top: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#panel_dashboard_right .colstack_head h1 {
|
||||||
|
font-size: 17px;
|
||||||
|
color: hsl(0,0%,40%);
|
||||||
|
}
|
||||||
|
|
||||||
.complex_rowlist {
|
.complex_rowlist {
|
||||||
background-color: inherit !important;
|
background-color: inherit !important;
|
||||||
border: none !important;
|
border: none !important;
|
||||||
|
|
|
@ -109,7 +109,12 @@ li a {
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 320px;
|
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;
|
border-radius: 3px;
|
||||||
background-color: #444444;
|
background-color: #444444;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -118,11 +123,6 @@ li a {
|
||||||
.sidebar .rowblock:not(.topic_list):not(.rowhead):not(.opthead) .rowitem {
|
.sidebar .rowblock:not(.topic_list):not(.rowhead):not(.opthead) .rowitem {
|
||||||
margin-left: 12px;
|
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 {
|
.colstack_right .colstack_item:not(.colstack_head):not(.rowhead) .rowitem {
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background-color: #444444;
|
background-color: #444444;
|
||||||
|
@ -175,6 +175,50 @@ h2 {
|
||||||
margin-left: 8px;
|
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 {
|
.more_topic_block_initial {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -184,6 +228,9 @@ h2 {
|
||||||
.hide_ajax_topic {
|
.hide_ajax_topic {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
.auto_hide, .show_on_edit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.topic_row:not(:last-child) {
|
.topic_row:not(:last-child) {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
@ -358,6 +405,56 @@ button, .formbutton {
|
||||||
display: flex;
|
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 {
|
.footer .widget {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
border-bottom: 1px solid #555555;
|
border-bottom: 1px solid #555555;
|
||||||
|
|
Loading…
Reference in New Issue