From a47a0318a7fed186e37e084891749383859bd480 Mon Sep 17 00:00:00 2001 From: Azareal Date: Tue, 24 Mar 2020 12:07:30 +1000 Subject: [PATCH] increase the number of agents on the ua chart optimise mfaVerifySession reduce boilerplate for populating the menu items shorten ua phrases for semrush and aspiegel rename account_username_updated phrase to account_name_updated --- cmd/query_gen/main.go | 39 ++++++--- common/subscription.go | 2 +- install/install.go | 4 +- langs/english.json | 6 +- query_gen/querygen.go | 4 +- routes/account.go | 98 ++++++++++++----------- routes/panel/analytics.go | 2 +- templates/account_own_edit.html | 6 +- themes/nox/overrides/login.html | 4 +- themes/tempra_simple/overrides/login.html | 6 +- 10 files changed, 95 insertions(+), 76 deletions(-) diff --git a/cmd/query_gen/main.go b/cmd/query_gen/main.go index 5c66fd90..8c2c7b08 100644 --- a/cmd/query_gen/main.go +++ b/cmd/query_gen/main.go @@ -223,28 +223,43 @@ func seedTables(a qgen.Adapter) error { order := 0 mOrder := "mid, name, htmlID, cssClass, position, path, aria, tooltip, guestOnly, memberOnly, staffOnly, adminOnly" addMenuItem := func(data map[string]interface{}) { + if data["mid"] == nil { + data["mid"] = 1 + } + if data["position"] == nil { + data["position"] = "left" + } cols, values := qgen.InterfaceMapToInsertStrings(data, mOrder) qgen.Install.SimpleInsert("menu_items", cols+", order", values+","+strconv.Itoa(order)) order++ } - addMenuItem(si{"mid": 1, "name": "{lang.menu_forums}", "htmlID": "menu_forums", "position": "left", "path": "/forums/", "aria": "{lang.menu_forums_aria}", "tooltip": "{lang.menu_forums_tooltip}"}) + addMenuItem(si{"name": "{lang.menu_forums}", "htmlID": "menu_forums", "path": "/forums/", "aria": "{lang.menu_forums_aria}", "tooltip": "{lang.menu_forums_tooltip}"}) - addMenuItem(si{"mid": 1, "name": "{lang.menu_topics}", "htmlID": "menu_topics", "cssClass": "menu_topics", "position": "left", "path": "/topics/", "aria": "{lang.menu_topics_aria}", "tooltip": "{lang.menu_topics_tooltip}"}) + addMenuItem(si{"name": "{lang.menu_topics}", "htmlID": "menu_topics", "cssClass": "menu_topics", "path": "/topics/", "aria": "{lang.menu_topics_aria}", "tooltip": "{lang.menu_topics_tooltip}"}) - addMenuItem(si{"mid": 1, "htmlID": "general_alerts", "cssClass": "menu_alerts", "position": "right", "tmplName": "menu_alerts"}) + addMenuItem(si{"htmlID": "general_alerts", "cssClass": "menu_alerts", "position": "right", "tmplName": "menu_alerts"}) - addMenuItem(si{"mid": 1, "name": "{lang.menu_account}", "cssClass": "menu_account", "position": "left", "path": "/user/edit/", "aria": "{lang.menu_account_aria}", "tooltip": "{lang.menu_account_tooltip}", "memberOnly": true}) + addMenuItem(si{"name": "{lang.menu_account}", "cssClass": "menu_account", "path": "/user/edit/", "aria": "{lang.menu_account_aria}", "tooltip": "{lang.menu_account_tooltip}", "memberOnly": true}) - addMenuItem(si{"mid": 1, "name": "{lang.menu_profile}", "cssClass": "menu_profile", "position": "left", "path": "{me.Link}", "aria": "{lang.menu_profile_aria}", "tooltip": "{lang.menu_profile_tooltip}", "memberOnly": true}) + addMenuItem(si{"name": "{lang.menu_profile}", "cssClass": "menu_profile", "path": "{me.Link}", "aria": "{lang.menu_profile_aria}", "tooltip": "{lang.menu_profile_tooltip}", "memberOnly": true}) - addMenuItem(si{"mid": 1, "name": "{lang.menu_panel}", "cssClass": "menu_panel menu_account", "position": "left", "path": "/panel/", "aria": "{lang.menu_panel_aria}", "tooltip": "{lang.menu_panel_tooltip}", "memberOnly": true, "staffOnly": true}) + addMenuItem(si{"name": "{lang.menu_panel}", "cssClass": "menu_panel menu_account", "path": "/panel/", "aria": "{lang.menu_panel_aria}", "tooltip": "{lang.menu_panel_tooltip}", "memberOnly": true, "staffOnly": true}) - addMenuItem(si{"mid": 1, "name": "{lang.menu_logout}", "cssClass": "menu_logout", "position": "left", "path": "/accounts/logout/?s={me.Session}", "aria": "{lang.menu_logout_aria}", "tooltip": "{lang.menu_logout_tooltip}", "memberOnly": true}) + addMenuItem(si{"name": "{lang.menu_logout}", "cssClass": "menu_logout", "path": "/accounts/logout/?s={me.Session}", "aria": "{lang.menu_logout_aria}", "tooltip": "{lang.menu_logout_tooltip}", "memberOnly": true}) - addMenuItem(si{"mid": 1, "name": "{lang.menu_register}", "cssClass": "menu_register", "position": "left", "path": "/accounts/create/", "aria": "{lang.menu_register_aria}", "tooltip": "{lang.menu_register_tooltip}", "guestOnly": true}) + addMenuItem(si{"name": "{lang.menu_register}", "cssClass": "menu_register", "path": "/accounts/create/", "aria": "{lang.menu_register_aria}", "tooltip": "{lang.menu_register_tooltip}", "guestOnly": true}) - addMenuItem(si{"mid": 1, "name": "{lang.menu_login}", "cssClass": "menu_login", "position": "left", "path": "/accounts/login/", "aria": "{lang.menu_login_aria}", "tooltip": "{lang.menu_login_tooltip}", "guestOnly": true}) + addMenuItem(si{"name": "{lang.menu_login}", "cssClass": "menu_login", "path": "/accounts/login/", "aria": "{lang.menu_login_aria}", "tooltip": "{lang.menu_login_tooltip}", "guestOnly": true}) + + var fSet []string + for _, table := range tables { + fSet = append(fSet, "'"+table+"'") + } + qgen.Install.SimpleBulkInsert("tables", "name", fSet) + /*for _, table := range tables { + qgen.Install.SimpleInsert("tables", "name", "'"+table+"'") + }*/ return nil } @@ -307,10 +322,10 @@ func writeUpdates(a qgen.Adapter) error { func writeDeletes(a qgen.Adapter) error { b := a.Builder() - //b.Delete("deleteForumPermsByForum").Table("forums_permissions").Where("fid = ?").Parse() + //b.Delete("deleteForumPermsByForum").Table("forums_permissions").Where("fid=?").Parse() b.Delete("deleteActivityStreamMatch").Table("activity_stream_matches").Where("watcher = ? AND asid = ?").Parse() - //b.Delete("deleteActivityStreamMatchesByWatcher").Table("activity_stream_matches").Where("watcher = ?").Parse() + //b.Delete("deleteActivityStreamMatchesByWatcher").Table("activity_stream_matches").Where("watcher=?").Parse() return nil } @@ -347,7 +362,7 @@ func writeInsertInnerJoins(a qgen.Adapter) error { return nil } -func writeFile(name string, content string) (err error) { +func writeFile(name, content string) (err error) { f, err := os.Create(name) if err != nil { return err diff --git a/common/subscription.go b/common/subscription.go index a532df14..d559ab10 100644 --- a/common/subscription.go +++ b/common/subscription.go @@ -25,7 +25,7 @@ func NewDefaultSubscriptionStore() (*DefaultSubscriptionStore, error) { acc := qgen.NewAcc() ast := "activity_subscriptions" return &DefaultSubscriptionStore{ - add: acc.Insert(ast).Columns("user, targetID, targetType, level").Fields("?,?,?,2").Prepare(), + add: acc.Insert(ast).Columns("user,targetID,targetType,level").Fields("?,?,?,2").Prepare(), delete: acc.Delete(ast).Where("user=? AND targetID=? AND targetType=?").Prepare(), deleteResource: acc.Delete(ast).Where("targetID=? AND targetType=?").Prepare(), }, acc.FirstError() diff --git a/install/install.go b/install/install.go index 73f89da2..c7a46f0b 100644 --- a/install/install.go +++ b/install/install.go @@ -3,7 +3,7 @@ package install import ( "fmt" - "github.com/Azareal/Gosora/query_gen" + qgen "github.com/Azareal/Gosora/query_gen" ) var adapters = make(map[string]InstallAdapter) @@ -11,7 +11,7 @@ var adapters = make(map[string]InstallAdapter) type InstallAdapter interface { Name() string DefaultPort() string - SetConfig(dbHost string, dbUsername string, dbPassword string, dbName string, dbPort string) + SetConfig(dbHost, dbUsername, dbPassword, dbName, dbPort string) InitDatabase() error TableDefs() error InitialData() error diff --git a/langs/english.json b/langs/english.json index 3bb970e2..6ebe62dd 100644 --- a/langs/english.json +++ b/langs/english.json @@ -223,13 +223,13 @@ "alexa":"Alexa", "lynx":"Lynx", - "semrush":"SemrushBot", + "semrush":"Semrush", "dotbot":"DotBot", "ahrefs":"Ahrefs", "proximic":"Comscore", "majestic":"MJ12bot", "blexbot":"BLEXBot", - "aspiegel":"AspiegelBot", + "aspiegel":"Aspiegel", "mail_ru":"Mail.ru bot", "zgrab":"Zgrab App Scanner", "curl":"curl", @@ -341,7 +341,7 @@ "account_banned":"Your account has been suspended. Some of your permissions may have been revoked.", "account_inactive":"Your account hasn't been activated yet. Some features may remain unavailable until it is.", "account_avatar_updated":"Your avatar was successfully updated.", - "account_username_updated":"Your username was successfully updated.", + "account_name_updated":"Your name was successfully updated.", "account_mail_disabled":"The mail system is currently disabled.", "account_mail_verify_success":"Your email was successfully verified.", "account_mfa_setup_success":"Two-factor authentication was successfully setup for your account.", diff --git a/query_gen/querygen.go b/query_gen/querygen.go index af8a402a..a0f59be7 100644 --- a/query_gen/querygen.go +++ b/query_gen/querygen.go @@ -135,14 +135,14 @@ type Adapter interface { // TODO: Some way to add indices and keys // TODO: Test this AddColumn(name, table string, col DBTableColumn, key *DBTableKey) (string, error) - DropColumn(name, table, colname string) (string, error) + DropColumn(name, table, colName string) (string, error) RenameColumn(name, table, oldName, newName string) (string, error) ChangeColumn(name, table, colName string, col DBTableColumn) (string, error) SetDefaultColumn(name, table, colName, colType, defaultStr string) (string, error) AddIndex(name, table, iname, colname string) (string, error) AddKey(name, table, col string, key DBTableKey) (string, error) RemoveIndex(name, table, col string) (string, error) - AddForeignKey(name, table, col, ftable, fcolumn string, cascade bool) (out string, e error) + AddForeignKey(name, table, col, ftable, fcol string, cascade bool) (out string, e error) SimpleInsert(name, table, cols, fields string) (string, error) SimpleBulkInsert(name, table, cols string, fieldSet []string) (string, error) SimpleUpdate(b *updatePrebuilder) (string, error) diff --git a/routes/account.go b/routes/account.go index 1661509e..4f3e97d9 100644 --- a/routes/account.go +++ b/routes/account.go @@ -20,9 +20,9 @@ import ( // A blank list to fill out that parameter in Page for routes which don't use it var tList []interface{} -func AccountLogin(w http.ResponseWriter, r *http.Request, user *c.User, h *c.Header) c.RouteError { - if user.Loggedin { - return c.LocalError("You're already logged in.", w, r, user) +func AccountLogin(w http.ResponseWriter, r *http.Request, u *c.User, h *c.Header) c.RouteError { + if u.Loggedin { + return c.LocalError("You're already logged in.", w, r, u) } h.Title = p.GetTitlePhrase("login") return renderTemplate("login", w, r, h, c.Page{h, tList, nil}) @@ -123,21 +123,25 @@ func mfaGetCookies(r *http.Request) (uid int, provSession, signedSession string, } func mfaVerifySession(provSession, signedSession string, uid int) bool { + bProvSession := []byte(provSession) + bSignedSession := []byte(signedSession) + bUid := []byte(strconv.Itoa(uid)) + h := sha256.New() h.Write([]byte(c.SessionSigningKeyBox.Load().(string))) - h.Write([]byte(provSession)) - h.Write([]byte(strconv.Itoa(uid))) + h.Write(bProvSession) + h.Write(bUid) expected := hex.EncodeToString(h.Sum(nil)) - if subtle.ConstantTimeCompare([]byte(signedSession), []byte(expected)) == 1 { + if subtle.ConstantTimeCompare(bSignedSession, []byte(expected)) == 1 { return true } h = sha256.New() h.Write([]byte(c.OldSessionSigningKeyBox.Load().(string))) - h.Write([]byte(provSession)) - h.Write([]byte(strconv.Itoa(uid))) + h.Write(bProvSession) + h.Write(bUid) expected = hex.EncodeToString(h.Sum(nil)) - return subtle.ConstantTimeCompare([]byte(signedSession), []byte(expected)) == 1 + return subtle.ConstantTimeCompare(bSignedSession, []byte(expected)) == 1 } func AccountLoginMFAVerify(w http.ResponseWriter, r *http.Request, u *c.User, h *c.Header) c.RouteError { @@ -354,26 +358,26 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user *c.User) } // TODO: Figure a way of making this into middleware? -func accountEditHead(titlePhrase string, w http.ResponseWriter, r *http.Request, user *c.User, h *c.Header) { +func accountEditHead(titlePhrase string, w http.ResponseWriter, r *http.Request, u *c.User, h *c.Header) { h.Title = p.GetTitlePhrase(titlePhrase) h.Path = "/user/edit/" h.AddSheet(h.Theme.Name + "/account.css") h.AddScriptAsync("account.js") } -func AccountEdit(w http.ResponseWriter, r *http.Request, user *c.User, header *c.Header) c.RouteError { - accountEditHead("account", w, r, user, header) +func AccountEdit(w http.ResponseWriter, r *http.Request, u *c.User, h *c.Header) c.RouteError { + accountEditHead("account", w, r, u, h) if r.FormValue("avatar_updated") == "1" { - header.AddNotice("account_avatar_updated") - } else if r.FormValue("username_updated") == "1" { - header.AddNotice("account_username_updated") + h.AddNotice("account_avatar_updated") + } else if r.FormValue("name_updated") == "1" { + h.AddNotice("account_name_updated") } else if r.FormValue("mfa_setup_success") == "1" { - header.AddNotice("account_mfa_setup_success") + h.AddNotice("account_mfa_setup_success") } // TODO: Find a more efficient way of doing this mfaSetup := false - _, err := c.MFAstore.Get(user.ID) + _, err := c.MFAstore.Get(u.ID) if err != sql.ErrNoRows && err != nil { return c.InternalError(err, w, r) } else if err != sql.ErrNoRows { @@ -381,13 +385,13 @@ func AccountEdit(w http.ResponseWriter, r *http.Request, user *c.User, header *c } // Normalise the score so that the user sees their relative progress to the next level rather than showing them their total score - prevScore := c.GetLevelScore(user.Level) - currentScore := user.Score - prevScore - nextScore := c.GetLevelScore(user.Level+1) - prevScore + prevScore := c.GetLevelScore(u.Level) + currentScore := u.Score - prevScore + nextScore := c.GetLevelScore(u.Level+1) - prevScore perc := int(math.Ceil((float64(nextScore) / float64(currentScore)) * 100)) - pi := c.Account{header, "dashboard", "account_own_edit", c.AccountDashPage{header, mfaSetup, currentScore, nextScore, user.Level + 1, perc * 2}} - return renderTemplate("account", w, r, header, pi) + pi := c.Account{h, "dashboard", "account_own_edit", c.AccountDashPage{h, mfaSetup, currentScore, nextScore, u.Level + 1, perc * 2}} + return renderTemplate("account", w, r, h, pi) } //edit_password @@ -481,16 +485,16 @@ func AccountEditUsernameSubmit(w http.ResponseWriter, r *http.Request, u *c.User return ferr } - newUsername := c.SanitiseSingleLine(r.PostFormValue("account-new-username")) - if newUsername == "" { + newName := c.SanitiseSingleLine(r.PostFormValue("new-name")) + if newName == "" { return c.LocalError("You can't leave your username blank", w, r, u) } - err := u.ChangeName(newUsername) + err := u.ChangeName(newName) if err != nil { - return c.LocalError("Unable to change the username. Does someone else already have this name?", w, r, u) + return c.LocalError("Unable to change names. Does someone else already have this name?", w, r, u) } - http.Redirect(w, r, "/user/edit/?username_updated=1", http.StatusSeeOther) + http.Redirect(w, r, "/user/edit/?name_updated=1", http.StatusSeeOther) return nil } @@ -568,18 +572,18 @@ func AccountEditMFASetupSubmit(w http.ResponseWriter, r *http.Request, user *c.U } // TODO: Implement this -func AccountEditMFADisableSubmit(w http.ResponseWriter, r *http.Request, user *c.User) c.RouteError { - _, ferr := c.SimpleUserCheck(w, r, user) +func AccountEditMFADisableSubmit(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError { + _, ferr := c.SimpleUserCheck(w, r, u) if ferr != nil { return ferr } // Flash an error if mfa is already setup - mfaItem, err := c.MFAstore.Get(user.ID) + mfaItem, err := c.MFAstore.Get(u.ID) if err != sql.ErrNoRows && err != nil { return c.InternalError(err, w, r) } else if err == sql.ErrNoRows { - return c.LocalError("You don't have two-factor enabled on your account", w, r, user) + return c.LocalError("You don't have two-factor enabled on your account", w, r, u) } err = mfaItem.Delete() @@ -603,16 +607,16 @@ func AccountEditPrivacy(w http.ResponseWriter, r *http.Request, u *c.User, h *c. return renderTemplate("account", w, r, h, pi) } -func AccountEditPrivacySubmit(w http.ResponseWriter, r *http.Request, user *c.User) c.RouteError { - //headerLite, _ := c.SimpleUserCheck(w, r, user) +func AccountEditPrivacySubmit(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError { + //headerLite, _ := c.SimpleUserCheck(w, r, u) sEnableEmbeds := r.FormValue("enable_embeds") enableEmbeds, err := strconv.Atoi(sEnableEmbeds) if err != nil { - return c.LocalError("enable_embeds must be 0 or 1", w, r, user) + return c.LocalError("enable_embeds must be 0 or 1", w, r, u) } if sEnableEmbeds != r.FormValue("o_enable_embeds") { - err = user.UpdatePrivacy(enableEmbeds) + err = u.UpdatePrivacy(enableEmbeds) if err != nil { return c.InternalError(err, w, r) } @@ -622,17 +626,17 @@ func AccountEditPrivacySubmit(w http.ResponseWriter, r *http.Request, user *c.Us return nil } -func AccountEditEmail(w http.ResponseWriter, r *http.Request, user *c.User, h *c.Header) c.RouteError { - accountEditHead("account_email", w, r, user, h) - emails, err := c.Emails.GetEmailsByUser(user) +func AccountEditEmail(w http.ResponseWriter, r *http.Request, u *c.User, h *c.Header) c.RouteError { + accountEditHead("account_email", w, r, u, h) + emails, err := c.Emails.GetEmailsByUser(u) if err != nil { return c.InternalError(err, w, r) } // Was this site migrated from another forum software? Most of them don't have multiple emails for a single user. // This also applies when the admin switches site.EnableEmails on after having it off for a while. - if len(emails) == 0 && user.Email != "" { - emails = append(emails, c.Email{UserID: user.ID, Email: user.Email, Validated: false, Primary: true}) + if len(emails) == 0 && u.Email != "" { + emails = append(emails, c.Email{UserID: u.ID, Email: u.Email, Validated: false, Primary: true}) } if !c.Site.EnableEmails { @@ -677,22 +681,22 @@ func AccountEditEmailAddSubmit(w http.ResponseWriter, r *http.Request, user *c.U return nil } -func AccountEditEmailRemoveSubmit(w http.ResponseWriter, r *http.Request, user *c.User) c.RouteError { - headerLite, _ := c.SimpleUserCheck(w, r, user) +func AccountEditEmailRemoveSubmit(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError { + headerLite, _ := c.SimpleUserCheck(w, r, u) email := r.PostFormValue("email") // Quick and dirty check - _, err := c.Emails.Get(user, email) + _, err := c.Emails.Get(u, email) if err == sql.ErrNoRows { - return c.LocalError("This email isn't set on this user.", w, r, user) + return c.LocalError("This email isn't set on this user.", w, r, u) } else if err != nil { return c.InternalError(err, w, r) } - if headerLite.Settings["activation_type"] == 2 && user.Email == email { - return c.LocalError("You can't remove your primary email when mandatory email activation is enabled.", w, r, user) + if headerLite.Settings["activation_type"] == 2 && u.Email == email { + return c.LocalError("You can't remove your primary email when mandatory email activation is enabled.", w, r, u) } - err = c.Emails.Delete(user.ID, email) + err = c.Emails.Delete(u.ID, email) if err != nil { return c.InternalError(err, w, r) } diff --git a/routes/panel/analytics.go b/routes/panel/analytics.go index 288e3910..b1a120d9 100644 --- a/routes/panel/analytics.go +++ b/routes/panel/analytics.go @@ -1164,7 +1164,7 @@ func AnalyticsAgents(w http.ResponseWriter, r *http.Request, user *c.User) c.Rou } vList = append(vList, viewList) legendList = append(legendList, lName) - if i >= 6 { + if i >= 7 { break } i++ diff --git a/templates/account_own_edit.html b/templates/account_own_edit.html index 1e1b491d..60aad3cc 100644 --- a/templates/account_own_edit.html +++ b/templates/account_own_edit.html @@ -5,13 +5,13 @@
- +
- + {{if .CurrentUser.Perms.UploadAvatars}} - + {{else if .CurrentUser.RawAvatar}}{{end}} diff --git a/themes/nox/overrides/login.html b/themes/nox/overrides/login.html index 663f68ab..33c32a3d 100644 --- a/themes/nox/overrides/login.html +++ b/themes/nox/overrides/login.html @@ -7,11 +7,11 @@