From 57052520297ee03d631c328105f425a12dfc5aa8 Mon Sep 17 00:00:00 2001 From: Azareal Date: Sun, 6 Oct 2019 10:34:09 +1000 Subject: [PATCH] Add UseConvos permission. Use UseConvos permission instead of ban flags in convo perm checks. Stop users without the UseConvos permission from editing convo replies, although they can still delete them for privacy reasons. Shorten some things and reduce the amount of boilerplate. Add a few misc parser test cases. Fix footer and tweak indentation. --- cmd/query_gen/main.go | 96 ++++---- common/permissions.go | 13 +- common/settings.go | 24 +- general_test.go | 222 ++++++------------- langs/english.json | 3 +- main.go | 55 ++--- misc_test.go | 226 +++++++++---------- parser_test.go | 448 +++++++++++++++++++------------------- plugin_test.go | 349 +++++++++++++---------------- routes/account.go | 151 ++++++------- routes/convos.go | 38 ++-- routes/forum_list.go | 14 +- routes/misc.go | 24 +- routes/panel/groups.go | 5 +- routes/panel/settings.go | 39 ++-- routes/panel/themes.go | 100 ++++----- routes/poll.go | 5 +- routes/topic_list.go | 16 +- schema/mssql/inserts.sql | 8 +- schema/mysql/inserts.sql | 8 +- schema/pgsql/inserts.sql | 8 +- templates/footer.html | 8 +- templates/panel_menu.html | 2 +- tickloop.go | 50 ++--- 24 files changed, 868 insertions(+), 1044 deletions(-) diff --git a/cmd/query_gen/main.go b/cmd/query_gen/main.go index a2d8fcc4..3af9723d 100644 --- a/cmd/query_gen/main.go +++ b/cmd/query_gen/main.go @@ -8,15 +8,14 @@ import ( "runtime/debug" "strconv" - "github.com/Azareal/Gosora/query_gen" + qgen "github.com/Azareal/Gosora/query_gen" ) // TODO: Make sure all the errors in this file propagate upwards properly func main() { // Capture panics instead of closing the window at a superhuman speed before the user can read the message on Windows defer func() { - r := recover() - if r != nil { + if r := recover(); r != nil { fmt.Println(r) debug.PrintStack() return @@ -109,6 +108,8 @@ func writeStatements(adapter qgen.Adapter) error { return nil } +type si = map[string]interface{} + func seedTables(adapter qgen.Adapter) error { qgen.Install.AddIndex("topics", "parentID", "parentID") qgen.Install.AddIndex("replies", "tid", "tid") @@ -156,6 +157,9 @@ func seedTables(adapter qgen.Adapter) error { Non-staff Global Permissions: UploadFiles UploadAvatars + UseConvos + // CreateConvo ? + // CreateConvoReply ? Forum Permissions: ViewTopic @@ -172,11 +176,11 @@ func seedTables(adapter qgen.Adapter) error { */ // TODO: Set the permissions on a struct and then serialize the struct and insert that instead of writing raw JSON - qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms, is_mod, is_admin, tag", `'Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,"Admin"`) + qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms, is_mod, is_admin, tag", `'Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,"Admin"`) - qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms, is_mod, tag", `'Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,"Mod"`) + qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms, is_mod, tag", `'Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,"Mod"`) - qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms", `'Member','{"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'`) + qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms", `'Member','{"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'`) qgen.Install.SimpleInsert("users_groups", "name, permissions, plugin_perms, is_banned", `'Banned','{"ViewTopic":true}','{}',1`) @@ -223,31 +227,31 @@ func seedTables(adapter qgen.Adapter) error { qgen.Install.SimpleInsert("menus", "", "") // Go maps have a random iteration order, so we have to do this, otherwise the schema files will become unstable and harder to audit - var order = 0 - var mOrder = "mid, name, htmlID, cssClass, position, path, aria, tooltip, guestOnly, memberOnly, staffOnly, adminOnly" - var addMenuItem = func(data map[string]interface{}) { + order := 0 + mOrder := "mid, name, htmlID, cssClass, position, path, aria, tooltip, guestOnly, memberOnly, staffOnly, adminOnly" + addMenuItem := func(data map[string]interface{}) { cols, values := qgen.InterfaceMapToInsertStrings(data, mOrder) qgen.Install.SimpleInsert("menu_items", cols+", order", values+","+strconv.Itoa(order)) order++ } - addMenuItem(map[string]interface{}{"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{"mid": 1, "name": "{lang.menu_forums}", "htmlID": "menu_forums", "position": "left", "path": "/forums/", "aria": "{lang.menu_forums_aria}", "tooltip": "{lang.menu_forums_tooltip}"}) - addMenuItem(map[string]interface{}{"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{"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(map[string]interface{}{"mid": 1, "htmlID": "general_alerts", "cssClass": "menu_alerts", "position": "right", "tmplName": "menu_alerts"}) + addMenuItem(si{"mid": 1, "htmlID": "general_alerts", "cssClass": "menu_alerts", "position": "right", "tmplName": "menu_alerts"}) - addMenuItem(map[string]interface{}{"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{"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(map[string]interface{}{"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{"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(map[string]interface{}{"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{"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(map[string]interface{}{"mid": 1, "name": "{lang.menu_logout}", "cssClass": "menu_logout", "position": "left", "path": "/accounts/logout/?session={me.Session}", "aria": "{lang.menu_logout_aria}", "tooltip": "{lang.menu_logout_tooltip}", "memberOnly": 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(map[string]interface{}{"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{"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(map[string]interface{}{"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{"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}) return nil } @@ -263,77 +267,77 @@ func seedTables(adapter qgen.Adapter) error { type LitStr string -func writeSelects(adapter qgen.Adapter) error { - build := adapter.Builder() +func writeSelects(a qgen.Adapter) error { + b := a.Builder() // Looking for getTopic? Your statement is in another castle - //build.Select("isPluginInstalled").Table("plugins").Columns("installed").Where("uname = ?").Parse() + //b.Select("isPluginInstalled").Table("plugins").Columns("installed").Where("uname = ?").Parse() - build.Select("forumEntryExists").Table("forums").Columns("fid").Where("name = ''").Orderby("fid ASC").Limit("0,1").Parse() + b.Select("forumEntryExists").Table("forums").Columns("fid").Where("name = ''").Orderby("fid ASC").Limit("0,1").Parse() - build.Select("groupEntryExists").Table("users_groups").Columns("gid").Where("name = ''").Orderby("gid ASC").Limit("0,1").Parse() + b.Select("groupEntryExists").Table("users_groups").Columns("gid").Where("name = ''").Orderby("gid ASC").Limit("0,1").Parse() return nil } -func writeLeftJoins(adapter qgen.Adapter) error { - adapter.SimpleLeftJoin("getForumTopics", "topics", "users", "topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, users.name, users.avatar", "topics.createdBy = users.uid", "topics.parentID = ?", "topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy desc", "") +func writeLeftJoins(a qgen.Adapter) error { + a.SimpleLeftJoin("getForumTopics", "topics", "users", "topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, users.name, users.avatar", "topics.createdBy = users.uid", "topics.parentID = ?", "topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy desc", "") return nil } -func writeInnerJoins(adapter qgen.Adapter) (err error) { +func writeInnerJoins(a qgen.Adapter) (err error) { return nil } -func writeInserts(adapter qgen.Adapter) error { - build := adapter.Builder() +func writeInserts(a qgen.Adapter) error { + b := a.Builder() - build.Insert("addForumPermsToForum").Table("forums_permissions").Columns("gid,fid,preset,permissions").Fields("?,?,?,?").Parse() + b.Insert("addForumPermsToForum").Table("forums_permissions").Columns("gid,fid,preset,permissions").Fields("?,?,?,?").Parse() return nil } -func writeUpdates(adapter qgen.Adapter) error { - build := adapter.Builder() +func writeUpdates(a qgen.Adapter) error { + b := a.Builder() - build.Update("updateEmail").Table("emails").Set("email = ?, uid = ?, validated = ?, token = ?").Where("email = ?").Parse() + b.Update("updateEmail").Table("emails").Set("email = ?, uid = ?, validated = ?, token = ?").Where("email = ?").Parse() - build.Update("setTempGroup").Table("users").Set("temp_group = ?").Where("uid = ?").Parse() + b.Update("setTempGroup").Table("users").Set("temp_group = ?").Where("uid = ?").Parse() - build.Update("bumpSync").Table("sync").Set("last_update = UTC_TIMESTAMP()").Parse() + b.Update("bumpSync").Table("sync").Set("last_update = UTC_TIMESTAMP()").Parse() return nil } -func writeDeletes(adapter qgen.Adapter) error { - build := adapter.Builder() +func writeDeletes(a qgen.Adapter) error { + b := a.Builder() - //build.Delete("deleteForumPermsByForum").Table("forums_permissions").Where("fid = ?").Parse() + //b.Delete("deleteForumPermsByForum").Table("forums_permissions").Where("fid = ?").Parse() - build.Delete("deleteActivityStreamMatch").Table("activity_stream_matches").Where("watcher = ? AND asid = ?").Parse() - //build.Delete("deleteActivityStreamMatchesByWatcher").Table("activity_stream_matches").Where("watcher = ?").Parse() + b.Delete("deleteActivityStreamMatch").Table("activity_stream_matches").Where("watcher = ? AND asid = ?").Parse() + //b.Delete("deleteActivityStreamMatchesByWatcher").Table("activity_stream_matches").Where("watcher = ?").Parse() return nil } -func writeSimpleCounts(adapter qgen.Adapter) error { +func writeSimpleCounts(a qgen.Adapter) error { return nil } -func writeInsertSelects(adapter qgen.Adapter) error { - /*adapter.SimpleInsertSelect("addForumPermsToForumAdmins", +func writeInsertSelects(a qgen.Adapter) error { + /*a.SimpleInsertSelect("addForumPermsToForumAdmins", qgen.DB_Insert{"forums_permissions", "gid, fid, preset, permissions", ""}, qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 1", "", ""}, )*/ - /*adapter.SimpleInsertSelect("addForumPermsToForumStaff", + /*a.SimpleInsertSelect("addForumPermsToForumStaff", qgen.DB_Insert{"forums_permissions", "gid, fid, preset, permissions", ""}, qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 1", "", ""}, )*/ - /*adapter.SimpleInsertSelect("addForumPermsToForumMembers", + /*a.SimpleInsertSelect("addForumPermsToForumMembers", qgen.DB_Insert{"forums_permissions", "gid, fid, preset, permissions", ""}, qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 0 AND is_banned = 0", "", ""}, )*/ @@ -342,11 +346,11 @@ func writeInsertSelects(adapter qgen.Adapter) error { } // nolint -func writeInsertLeftJoins(adapter qgen.Adapter) error { +func writeInsertLeftJoins(a qgen.Adapter) error { return nil } -func writeInsertInnerJoins(adapter qgen.Adapter) error { +func writeInsertInnerJoins(a qgen.Adapter) error { return nil } diff --git a/common/permissions.go b/common/permissions.go index 9f782311..e4b454ba 100644 --- a/common/permissions.go +++ b/common/permissions.go @@ -4,8 +4,8 @@ import ( "encoding/json" "log" - "github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/common/phrases" + qgen "github.com/Azareal/Gosora/query_gen" ) // TODO: Refactor the perms system @@ -39,6 +39,7 @@ var GlobalPermList = []string{ "ViewIPs", "UploadFiles", "UploadAvatars", + "UseConvos", } // Permission Structure: ActionComponent[Subcomponent]Flag @@ -65,8 +66,9 @@ type Perms struct { ViewIPs bool // Global non-staff permissions - UploadFiles bool + UploadFiles bool UploadAvatars bool + UseConvos bool // Forum permissions ViewTopic bool @@ -91,7 +93,7 @@ type Perms struct { func init() { BlankPerms = Perms{ - //ExtData: make(map[string]bool), + //ExtData: make(map[string]bool), } GuestPerms = Perms{ @@ -120,8 +122,9 @@ func init() { ViewAdminLogs: true, ViewIPs: true, - UploadFiles: true, + UploadFiles: true, UploadAvatars: true, + UseConvos: true, ViewTopic: true, LikeItem: true, @@ -188,7 +191,7 @@ func RebuildGroupPermissions(group *Group) error { } tmpPerms := Perms{ - //ExtData: make(map[string]bool), + //ExtData: make(map[string]bool), } err = json.Unmarshal(permstr, &tmpPerms) if err != nil { diff --git a/common/settings.go b/common/settings.go index d4e8eb9b..0172250e 100644 --- a/common/settings.go +++ b/common/settings.go @@ -54,14 +54,14 @@ func init() { }) } -func (setting *Setting) Copy() (out *Setting) { +func (s *Setting) Copy() (out *Setting) { out = &Setting{Name: ""} - *out = *setting + *out = *s return out } func LoadSettings() error { - var sBox = SettingMap(make(map[string]interface{})) + sBox := SettingMap(make(map[string]interface{})) settings, err := sBox.BypassGetAll() if err != nil { return err @@ -122,9 +122,9 @@ func (sBox SettingMap) ParseSetting(sname string, scontent string, stype string, } func (sBox SettingMap) BypassGet(name string) (*Setting, error) { - setting := &Setting{Name: name} - err := settingStmts.get.QueryRow(name).Scan(&setting.Content, &setting.Type, &setting.Constraint) - return setting, err + s := &Setting{Name: name} + err := settingStmts.get.QueryRow(name).Scan(&s.Content, &s.Type, &s.Constraint) + return s, err } func (sBox SettingMap) BypassGetAll() (settingList []*Setting, err error) { @@ -135,18 +135,18 @@ func (sBox SettingMap) BypassGetAll() (settingList []*Setting, err error) { defer rows.Close() for rows.Next() { - setting := &Setting{Name: ""} - err := rows.Scan(&setting.Name, &setting.Content, &setting.Type, &setting.Constraint) + s := &Setting{Name: ""} + err := rows.Scan(&s.Name, &s.Content, &s.Type, &s.Constraint) if err != nil { return nil, err } - settingList = append(settingList, setting) + settingList = append(settingList, s) } return settingList, rows.Err() } func (sBox SettingMap) Update(name string, content string) RouteError { - setting, err := sBox.BypassGet(name) + s, err := sBox.BypassGet(name) if err == ErrNoRows { return FromError(err) } else if err != nil { @@ -154,7 +154,7 @@ func (sBox SettingMap) Update(name string, content string) RouteError { } // TODO: Why is this here and not in a common function? - if setting.Type == "bool" { + if s.Type == "bool" { if content == "on" || content == "1" { content = "1" } else { @@ -162,7 +162,7 @@ func (sBox SettingMap) Update(name string, content string) RouteError { } } - err = sBox.ParseSetting(name, content, setting.Type, setting.Constraint) + err = sBox.ParseSetting(name, content, s.Type, s.Constraint) if err != nil { return FromError(err) } diff --git a/general_test.go b/general_test.go index 657508d7..6d767185 100644 --- a/general_test.go +++ b/general_test.go @@ -374,8 +374,7 @@ func BenchmarkBadRouteGuestRouteParallelWithRouter(b *testing.B) { func binit(b *testing.B) { b.ReportAllocs() - err := gloinit() - if err != nil { + if err := gloinit(); err != nil { b.Fatal(err) } } @@ -785,8 +784,7 @@ func BenchmarkRoutesSerial(b *testing.B) { func BenchmarkQueryTopicParallel(b *testing.B) { b.ReportAllocs() - err := gloinit() - if err != nil { + if err := gloinit(); err != nil { b.Fatal(err) } @@ -807,8 +805,7 @@ func BenchmarkQueryTopicParallel(b *testing.B) { func BenchmarkQueryPreparedTopicParallel(b *testing.B) { b.ReportAllocs() - err := gloinit() - if err != nil { + if err := gloinit(); err != nil { b.Fatal(err) } @@ -836,8 +833,7 @@ func BenchmarkQueryPreparedTopicParallel(b *testing.B) { func BenchmarkUserGet(b *testing.B) { b.ReportAllocs() - err := gloinit() - if err != nil { + if err := gloinit(); err != nil { b.Fatal(err) } @@ -855,8 +851,7 @@ func BenchmarkUserGet(b *testing.B) { func BenchmarkUserBypassGet(b *testing.B) { b.ReportAllocs() - err := gloinit() - if err != nil { + if err := gloinit(); err != nil { b.Fatal(err) } @@ -972,149 +967,62 @@ func BenchmarkParserSerial(b *testing.B) { func BenchmarkBBCodePluginWithRegexpSerial(b *testing.B) { b.ReportAllocs() - b.Run("empty_post", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeRegexParse("") - } - }) - b.Run("short_post", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeRegexParse("Hey everyone, how's it going?") - } - }) - b.Run("one_smily", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeRegexParse("Hey everyone, how's it going? :)") - } - }) - b.Run("five_smilies", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeRegexParse("Hey everyone, how's it going? :):):):):)") - } - }) - b.Run("ten_smilies", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeRegexParse("Hey everyone, how's it going? :):):):):):):):):):)") - } - }) - b.Run("twenty_smilies", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeRegexParse("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") - } - }) - b.Run("one_bold", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeRegexParse("[b]H[/b]ey everyone, how's it going?") - } - }) - b.Run("five_bold", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeRegexParse("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b]eryone, how's it going?") - } - }) - b.Run("ten_bold", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeRegexParse("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b][b]e[/b][b]r[/b][b]y[/b][b]o[/b][b]n[/b]e, how's it going?") - } - }) + f := func(name string, msg string) { + b.Run(name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = bbcodeRegexParse(msg) + } + }) + } + f("empty_post","") + f("short_post","Hey everyone, how's it going?") + f("one_smily","Hey everyone, how's it going? :)") + f("five_smilies","Hey everyone, how's it going? :):):):):)") + f("ten_smilies","Hey everyone, how's it going? :):):):):):):):):):)") + f("twenty_smilies","Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") + f("one_bold","[b]H[/b]ey everyone, how's it going?") + f("five_bold","[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b]eryone, how's it going?") + f("ten_bold","[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b][b]e[/b][b]r[/b][b]y[/b][b]o[/b][b]n[/b]e, how's it going?") } func BenchmarkBBCodePluginWithoutCodeTagSerial(b *testing.B) { b.ReportAllocs() - b.Run("empty_post", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeParseWithoutCode("") - } - }) - b.Run("short_post", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeParseWithoutCode("Hey everyone, how's it going?") - } - }) - b.Run("one_smily", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeParseWithoutCode("Hey everyone, how's it going? :)") - } - }) - b.Run("five_smilies", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeParseWithoutCode("Hey everyone, how's it going? :):):):):)") - } - }) - b.Run("ten_smilies", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeParseWithoutCode("Hey everyone, how's it going? :):):):):):):):):):)") - } - }) - b.Run("twenty_smilies", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeParseWithoutCode("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") - } - }) - b.Run("one_bold", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeParseWithoutCode("[b]H[/b]ey everyone, how's it going?") - } - }) - b.Run("five_bold", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeParseWithoutCode("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b]eryone, how's it going?") - } - }) - b.Run("ten_bold", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeParseWithoutCode("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b][b]e[/b][b]r[/b][b]y[/b][b]o[/b][b]n[/b]e, how's it going?") - } - }) + f := func(name string, msg string) { + b.Run(name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = bbcodeParseWithoutCode(msg) + } + }) + } + f("empty_post","") + f("short_post","Hey everyone, how's it going?") + f("one_smily","Hey everyone, how's it going? :)") + f("five_smilies","Hey everyone, how's it going? :):):):):)") + f("ten_smilies","Hey everyone, how's it going? :):):):):):):):):):)") + f("twenty_smilies","Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") + f("one_bold","[b]H[/b]ey everyone, how's it going?") + f("five_bold","[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b]eryone, how's it going?") + f("ten_bold","[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b][b]e[/b][b]r[/b][b]y[/b][b]o[/b][b]n[/b]e, how's it going?") } func BenchmarkBBCodePluginWithFullParserSerial(b *testing.B) { b.ReportAllocs() - b.Run("empty_post", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeFullParse("") - } - }) - b.Run("short_post", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeFullParse("Hey everyone, how's it going?") - } - }) - b.Run("one_smily", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeFullParse("Hey everyone, how's it going? :)") - } - }) - b.Run("five_smilies", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeFullParse("Hey everyone, how's it going? :):):):):)") - } - }) - b.Run("ten_smilies", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeFullParse("Hey everyone, how's it going? :):):):):):):):):):)") - } - }) - b.Run("twenty_smilies", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeFullParse("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") - } - }) - b.Run("one_bold", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeFullParse("[b]H[/b]ey everyone, how's it going?") - } - }) - b.Run("five_bold", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeFullParse("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b]eryone, how's it going?") - } - }) - b.Run("ten_bold", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = bbcodeFullParse("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b][b]e[/b][b]r[/b][b]y[/b][b]o[/b][b]n[/b]e, how's it going?") - } - }) + f := func(name string, msg string) { + b.Run(name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = bbcodeFullParse(msg) + } + }) + } + f("empty_post","") + f("short_post","Hey everyone, how's it going?") + f("one_smily","Hey everyone, how's it going? :)") + f("five_smilies","Hey everyone, how's it going? :):):):):)") + f("ten_smilies","Hey everyone, how's it going? :):):):):):):):):):)") + f("twenty_smilies","Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") + f("one_bold","[b]H[/b]ey everyone, how's it going?") + f("five_bold","[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b]eryone, how's it going?") + f("ten_bold","[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b][b]e[/b][b]r[/b][b]y[/b][b]o[/b][b]n[/b]e, how's it going?") } func TestLevels(t *testing.T) { @@ -1209,19 +1117,19 @@ func TestForumsAdminRoute(t *testing.T) { if !admin.Is_Admin { t.Fatal("UID1 is not an admin") } - admin_uid_cookie := http.Cookie{Name:"uid",Value:"1",Path:"/",MaxAge: year} - admin_session_cookie := http.Cookie{Name:"session",Value: admin.Session,Path:"/",MaxAge: year} + adminUidCookie := http.Cookie{Name:"uid",Value:"1",Path:"/",MaxAge: year} + adminSessionCookie := http.Cookie{Name:"session",Value: admin.Session,Path:"/",MaxAge: year} - forums_w := httptest.NewRecorder() - forums_req := httptest.NewRequest("get","/forums/",bytes.NewReader(nil)) - forums_req_admin := forums_req - forums_req_admin.AddCookie(&admin_uid_cookie) - forums_req_admin.AddCookie(&admin_session_cookie) - forums_handler := http.HandlerFunc(route_forums) + forumsW := httptest.NewRecorder() + forumsReq := httptest.NewRequest("get","/forums/",bytes.NewReader(nil)) + forumsReqAdmin := forums_req + forumsReqAdmin.AddCookie(&adminUidCookie) + forumsReqAdmin.AddCookie(&adminSessionCookie) + forumsHandler := http.HandlerFunc(route_forums) - forums_handler.ServeHTTP(forums_w,forums_req_admin) - if forums_w.Code != 200 { - t.Fatal(forums_w.Body) + forumsHandler.ServeHTTP(forumsW,forumsReqAdmin) + if forumsW.Code != 200 { + t.Fatal(forumsW.Body) } } @@ -1316,7 +1224,7 @@ func TestForumsGuestRoute(t *testing.T) { func TestSplittyThing(t *testing.T) { var extraData string - var path = "/pages/hohoho" + path := "/pages/hohoho" t.Log("Raw Path:", path) if path[len(path)-1] != '/' { extraData = path[strings.LastIndexByte(path, '/')+1:] diff --git a/langs/english.json b/langs/english.json index 2b22406c..e578c6d7 100644 --- a/langs/english.json +++ b/langs/english.json @@ -29,7 +29,8 @@ "ViewIPs": "Can view IP addresses", "UploadFiles": "Can upload files", - "UploadAvatars": "Can upload avatars" + "UploadAvatars": "Can upload avatars", + "UseConvos":"Can use conversations" }, "LocalPerms": { diff --git a/main.go b/main.go index 4bb31425..8b8b0fef 100644 --- a/main.go +++ b/main.go @@ -25,8 +25,8 @@ import ( "time" c "github.com/Azareal/Gosora/common" - "github.com/Azareal/Gosora/common/counters" - "github.com/Azareal/Gosora/common/phrases" + co "github.com/Azareal/Gosora/common/counters" + p "github.com/Azareal/Gosora/common/phrases" "github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/routes" "github.com/fsnotify/fsnotify" @@ -143,40 +143,33 @@ func storeInit() (err error) { return errors.WithStack(err) } - err = phrases.InitPhrases(c.Site.Language) - if err != nil { + if err = p.InitPhrases(c.Site.Language); err != nil { return errors.WithStack(err) } - err = c.InitEmoji() - if err != nil { + if err = c.InitEmoji(); err != nil { return errors.WithStack(err) } log.Print("Loading the static files.") - err = c.Themes.LoadStaticFiles() - if err != nil { + if err = c.Themes.LoadStaticFiles(); err != nil { return errors.WithStack(err) } - err = c.StaticFiles.Init() - if err != nil { + if err = c.StaticFiles.Init(); err != nil { return errors.WithStack(err) } - err = c.StaticFiles.JSTmplInit() - if err != nil { + if err = c.StaticFiles.JSTmplInit(); err != nil { return errors.WithStack(err) } log.Print("Initialising the widgets") c.Widgets = c.NewDefaultWidgetStore() - err = c.InitWidgets() - if err != nil { + if err = c.InitWidgets(); err != nil { return errors.WithStack(err) } log.Print("Initialising the menu item list") c.Menus = c.NewDefaultMenuStore() - err = c.Menus.Load(1) // 1 = the default menu - if err != nil { + if err = c.Menus.Load(1); err != nil { // 1 = the default menu return errors.WithStack(err) } menuHold, err := c.Menus.Get(1) @@ -269,47 +262,47 @@ func storeInit() (err error) { c.Thumbnailer = c.NewCaireThumbnailer() log.Print("Initialising the view counters") - counters.GlobalViewCounter, err = counters.NewGlobalViewCounter(acc) + co.GlobalViewCounter, err = co.NewGlobalViewCounter(acc) if err != nil { return errors.WithStack(err) } - counters.AgentViewCounter, err = counters.NewDefaultAgentViewCounter(acc) + co.AgentViewCounter, err = co.NewDefaultAgentViewCounter(acc) if err != nil { return errors.WithStack(err) } - counters.OSViewCounter, err = counters.NewDefaultOSViewCounter(acc) + co.OSViewCounter, err = co.NewDefaultOSViewCounter(acc) if err != nil { return errors.WithStack(err) } - counters.LangViewCounter, err = counters.NewDefaultLangViewCounter(acc) + co.LangViewCounter, err = co.NewDefaultLangViewCounter(acc) if err != nil { return errors.WithStack(err) } - counters.RouteViewCounter, err = counters.NewDefaultRouteViewCounter(acc) + co.RouteViewCounter, err = co.NewDefaultRouteViewCounter(acc) if err != nil { return errors.WithStack(err) } - counters.PostCounter, err = counters.NewPostCounter() + co.PostCounter, err = co.NewPostCounter() if err != nil { return errors.WithStack(err) } - counters.TopicCounter, err = counters.NewTopicCounter() + co.TopicCounter, err = co.NewTopicCounter() if err != nil { return errors.WithStack(err) } - counters.TopicViewCounter, err = counters.NewDefaultTopicViewCounter() + co.TopicViewCounter, err = co.NewDefaultTopicViewCounter() if err != nil { return errors.WithStack(err) } - counters.ForumViewCounter, err = counters.NewDefaultForumViewCounter() + co.ForumViewCounter, err = co.NewDefaultForumViewCounter() if err != nil { return errors.WithStack(err) } - counters.ReferrerTracker, err = counters.NewDefaultReferrerTracker() + co.ReferrerTracker, err = co.NewDefaultReferrerTracker() if err != nil { return errors.WithStack(err) } - counters.MemoryCounter, err = counters.NewMemoryCounter(acc) + co.MemoryCounter, err = co.NewMemoryCounter(acc) if err != nil { return errors.WithStack(err) } @@ -422,8 +415,8 @@ func main() { defer watcher.Close() go func() { - var modifiedFileEvent = func(path string) error { - var pathBits = strings.Split(path, "\\") + modifiedFileEvent := func(path string) error { + pathBits := strings.Split(path, "\\") if len(pathBits) == 0 { return nil } @@ -503,7 +496,7 @@ func main() { var lastEvictedCount int var couldNotDealloc bool - var secondTicker = time.NewTicker(time.Second) + secondTicker := time.NewTicker(time.Second) for { select { case <-secondTicker.C: @@ -576,7 +569,7 @@ func main() { func startServer() { // We might not need the timeouts, if we're behind a reverse-proxy like Nginx - var newServer = func(addr string, handler http.Handler) *http.Server { + newServer := func(addr string, handler http.Handler) *http.Server { rtime := c.Config.ReadTimeout if rtime == 0 { rtime = 8 diff --git a/misc_test.go b/misc_test.go index 77a46dee..d9eae399 100644 --- a/misc_test.go +++ b/misc_test.go @@ -15,8 +15,7 @@ import ( ) func miscinit(t *testing.T) { - err := gloinit() - if err != nil { + if err := gloinit(); err != nil { t.Fatal(err) } } @@ -85,7 +84,7 @@ func userStoreTest(t *testing.T, newUserID int) { user, err := c.Users.Get(1) recordMustExist(t, err, "Couldn't find UID #1") - var expectW = func(cond bool, expec bool, prefix string, suffix string) { + expectW := func(cond bool, expec bool, prefix string, suffix string) { midfix := "should not be" if expec { midfix = "should be" @@ -94,15 +93,15 @@ func userStoreTest(t *testing.T, newUserID int) { } // TODO: Add email checks too? Do them separately? - var expectUser = func(user *c.User, uid int, name string, group int, super bool, admin bool, mod bool, banned bool) { - expect(t, user.ID == uid, fmt.Sprintf("user.ID should be %d. Got '%d' instead.", uid, user.ID)) - expect(t, user.Name == name, fmt.Sprintf("user.Name should be '%s', not '%s'", name, user.Name)) - expectW(user.Group == group, true, user.Name, "in group"+strconv.Itoa(group)) - expectW(user.IsSuperAdmin == super, super, user.Name, "a super admin") - expectW(user.IsAdmin == admin, admin, user.Name, "an admin") - expectW(user.IsSuperMod == mod, mod, user.Name, "a super mod") - expectW(user.IsMod == mod, mod, user.Name, "a mod") - expectW(user.IsBanned == banned, banned, user.Name, "banned") + expectUser := func(u *c.User, uid int, name string, group int, super bool, admin bool, mod bool, banned bool) { + expect(t, u.ID == uid, fmt.Sprintf("u.ID should be %d. Got '%d' instead.", uid, u.ID)) + expect(t, u.Name == name, fmt.Sprintf("u.Name should be '%s', not '%s'", name, u.Name)) + expectW(u.Group == group, true, u.Name, "in group"+strconv.Itoa(group)) + expectW(u.IsSuperAdmin == super, super, u.Name, "a super admin") + expectW(u.IsAdmin == admin, admin, u.Name, "an admin") + expectW(u.IsSuperMod == mod, mod, u.Name, "a super mod") + expectW(u.IsMod == mod, mod, u.Name, "a mod") + expectW(u.IsBanned == banned, banned, u.Name, "banned") } expectUser(user, 1, "Admin", 1, true, true, true, false) @@ -111,7 +110,6 @@ func userStoreTest(t *testing.T, newUserID int) { if ucache != nil { expectIntToBeX(t, ucache.Length(), 1, "User cache length should be 1, not %d") - _, err = ucache.Get(-1) recordMustNotExist(t, err, "UID #-1 shouldn't exist, even in the cache") _, err = ucache.Get(0) @@ -167,7 +165,7 @@ func userStoreTest(t *testing.T, newUserID int) { expect(t, isCacheLengthZero(ucache), fmt.Sprintf("User cache length should be 0, not %d", cacheLength(ucache))) expectIntToBeX(t, c.Users.Count(), 1, "The number of users should be one, not %d") - var awaitingActivation = 5 + awaitingActivation := 5 // TODO: Write tests for the registration validators uid, err := c.Users.Create("Sam", "ReallyBadPassword", "sam@localhost.loc", awaitingActivation, false) expectNilErr(t, err) @@ -215,7 +213,7 @@ func userStoreTest(t *testing.T, newUserID int) { expectIntToBeX(t, user.Group, 5, "Sam should still be in group 5 in this copy") // ? - What if we change the caching mechanism so it isn't hard purged and reloaded? We'll deal with that when we come to it, but for now, this is a sign of a cache bug - var afterUserFlush = func(uid int) { + afterUserFlush := func(uid int) { if ucache != nil { expectIntToBeX(t, ucache.Length(), 0, "User cache length should be 0, not %d") _, err = ucache.Get(uid) @@ -252,15 +250,15 @@ func userStoreTest(t *testing.T, newUserID int) { recordMustExist(t, err, "Couldn't find UID #%d", newUserID) expectUser(user, newUserID, "Sam", c.Config.DefaultGroup, false, false, false, false) - var reportsForumID = 1 // TODO: Use the constant in common? - var generalForumID = 2 + reportsForumID := 1 // TODO: Use the constant in common? + generalForumID := 2 dummyResponseRecorder := httptest.NewRecorder() bytesBuffer := bytes.NewBuffer([]byte("")) dummyRequest1 := httptest.NewRequest("", "/forum/"+strconv.Itoa(reportsForumID), bytesBuffer) dummyRequest2 := httptest.NewRequest("", "/forum/"+strconv.Itoa(generalForumID), bytesBuffer) var user2 *c.User - var changeGroupTest = func(oldGroup int, newGroup int) { + changeGroupTest := func(oldGroup int, newGroup int) { err = user.ChangeGroup(newGroup) expectNilErr(t, err) // ! I don't think ChangeGroup should be changing the value of user... Investigate this. @@ -272,7 +270,7 @@ func userStoreTest(t *testing.T, newUserID int) { *user2 = *user } - var changeGroupTest2 = func(rank string, firstShouldBe bool, secondShouldBe bool) { + changeGroupTest2 := func(rank string, firstShouldBe bool, secondShouldBe bool) { head, err := c.UserCheck(dummyResponseRecorder, dummyRequest1, user) if err != nil { t.Fatal(err) @@ -490,7 +488,7 @@ func topicStoreTest(t *testing.T, newID int) { count = c.Topics.Count() expect(t, count == 2, fmt.Sprintf("Global count for topics should be 2, not %d", count)) - var iFrag = func(cond bool) string { + iFrag := func(cond bool) string { if !cond { return "n't" } @@ -513,7 +511,7 @@ func topicStoreTest(t *testing.T, newID int) { } tcache := c.Topics.GetCache() - var shouldNotBeIn = func(tid int) { + shouldNotBeIn := func(tid int) { if tcache != nil { _, err = tcache.Get(tid) recordMustNotExist(t, err, "Topic cache should be empty") @@ -581,7 +579,7 @@ func TestForumStore(t *testing.T) { // TODO: Check the preset and forum permissions expect(t, forum.Name == "Reports", fmt.Sprintf("FID #0 is named '%s' and not 'Reports'", forum.Name)) expect(t, !forum.Active, fmt.Sprintf("The reports forum shouldn't be active")) - var expectDesc = "All the reports go here" + expectDesc := "All the reports go here" expect(t, forum.Desc == expectDesc, fmt.Sprintf("The forum description should be '%s' not '%s'", expectDesc, forum.Desc)) forum, err = c.Forums.BypassGet(1) recordMustExist(t, err, "Couldn't find FID #1") @@ -732,48 +730,24 @@ func TestForumPermsStore(t *testing.T) { c.InitPlugins() } - var initialState = func() { - fid := 1 - gid := 1 - fperms, err := c.FPStore.Get(fid,gid) - expectNilErr(t,err) - expect(t,fperms.ViewTopic,"admins should be able to see reports") + f := func(fid int, gid int, msg string, inv ...bool) { + fp, err := c.FPStore.Get(fid,gid) + expectNilErr(t,err) + vt := fp.ViewTopic + if len(inv) > 0 && inv[0] == true { + vt = !vt + } + expect(t,vt,msg) + } - fid = 1 - gid = 2 - fperms, err = c.FPStore.Get(fid,gid) - expectNilErr(t,err) - expect(t,fperms.ViewTopic,"mods should be able to see reports") - - fid = 1 - gid = 3 - fperms, err = c.FPStore.Get(fid,gid) - expectNilErr(t,err) - expect(t,!fperms.ViewTopic,"members should not be able to see reports") - - fid = 1 - gid = 4 - fperms, err = c.FPStore.Get(fid,gid) - expectNilErr(t,err) - expect(t,!fperms.ViewTopic,"banned users should not be able to see reports") - - fid = 2 - gid = 1 - fperms, err = c.FPStore.Get(fid,gid) - expectNilErr(t,err) - expect(t,fperms.ViewTopic,"admins should be able to see general") - - fid = 2 - gid = 3 - fperms, err = c.FPStore.Get(fid,gid) - expectNilErr(t,err) - expect(t,fperms.ViewTopic,"members should be able to see general") - - fid = 2 - gid = 6 - fperms, err = c.FPStore.Get(fid,gid) - expectNilErr(t,err) - expect(t,fperms.ViewTopic,"guests should be able to see general") + initialState := func() { + f(1,1,"admins should be able to see reports") + f(1,2,"mods should be able to see reports") + f(1,3,"members should not be able to see reports",true) + f(1,4,"banned users should not be able to see reports",true) + f(2,1,"admins should be able to see general") + f(2,3,"members should be able to see general") + f(2,6,"guests should be able to see general") } initialState() @@ -811,9 +785,9 @@ func TestGroupStore(t *testing.T) { expect(t, c.Groups.Exists(0), "GID #0 should exist") expect(t, c.Groups.Exists(1), "GID #1 should exist") - var isAdmin = true - var isMod = true - var isBanned = false + isAdmin := true + isMod := true + isBanned := false gid, err := c.Groups.Create("Testing", "Test", isAdmin, isMod, isBanned) expectNilErr(t, err) expect(t, c.Groups.Exists(gid), "The group we just made doesn't exist") @@ -1032,7 +1006,7 @@ func TestProfileReplyStore(t *testing.T) { //err = profileReply.Delete() //expect(t,err != nil,"You shouldn't be able to delete profile replies which don't exist") - var profileID = 1 + profileID := 1 prid, err := c.Prstore.Create(profileID, "Haha", 1, "::1") expectNilErr(t, err) expect(t, prid == 1, "The first profile reply should have an ID of 1") @@ -1265,10 +1239,14 @@ func TestPluginManager(t *testing.T) { } func TestPhrases(t *testing.T) { - expect(t, phrases.GetGlobalPermPhrase("BanUsers") == "Can ban users", "Not the expected phrase") - expect(t, phrases.GetGlobalPermPhrase("NoSuchPerm") == "{lang.perms[NoSuchPerm]}", "Not the expected phrase") - expect(t, phrases.GetLocalPermPhrase("ViewTopic") == "Can view topics", "Not the expected phrase") - expect(t, phrases.GetLocalPermPhrase("NoSuchPerm") == "{lang.perms[NoSuchPerm]}", "Not the expected phrase") + getPhrase := phrases.GetGlobalPermPhrase + tp := func(name string, expects string) { + expect(t, getPhrase(name) == expects, "Not the expected phrase") + } + tp("BanUsers","Can ban users") + tp("NoSuchPerm","{lang.perms[NoSuchPerm]}") + tp("ViewTopic","Can view topics") + tp("NoSuchPerm","{lang.perms[NoSuchPerm]}") // TODO: Cover the other phrase types, also try switching between languages to see if anything strange happens } @@ -1326,34 +1304,33 @@ func TestWordFilters(t *testing.T) { // TODO: Expand upon the valid characters which can go in URLs? func TestSlugs(t *testing.T) { - var res string - var msgList = &MEPairList{nil} + l := &MEPairList{nil} c.Config.BuildSlugs = true // Flip this switch, otherwise all the tests will fail - msgList.Add("Unknown", "unknown") - msgList.Add("Unknown2", "unknown2") - msgList.Add("Unknown ", "unknown") - msgList.Add("Unknown 2", "unknown-2") - msgList.Add("Unknown 2", "unknown-2") - msgList.Add("Admin Alice", "admin-alice") - msgList.Add("Admin_Alice", "adminalice") - msgList.Add("Admin_Alice-", "adminalice") - msgList.Add("-Admin_Alice-", "adminalice") - msgList.Add("-Admin@Alice-", "adminalice") - msgList.Add("-AdminπŸ˜€Alice-", "adminalice") - msgList.Add("u", "u") - msgList.Add("", "untitled") - msgList.Add(" ", "untitled") - msgList.Add("-", "untitled") - msgList.Add("--", "untitled") - msgList.Add("Γ©", "Γ©") - msgList.Add("-Γ©-", "Γ©") - msgList.Add("-δ½ ε₯½-", "untitled") - msgList.Add("-こにけは-", "untitled") + l.Add("Unknown", "unknown") + l.Add("Unknown2", "unknown2") + l.Add("Unknown ", "unknown") + l.Add("Unknown 2", "unknown-2") + l.Add("Unknown 2", "unknown-2") + l.Add("Admin Alice", "admin-alice") + l.Add("Admin_Alice", "adminalice") + l.Add("Admin_Alice-", "adminalice") + l.Add("-Admin_Alice-", "adminalice") + l.Add("-Admin@Alice-", "adminalice") + l.Add("-AdminπŸ˜€Alice-", "adminalice") + l.Add("u", "u") + l.Add("", "untitled") + l.Add(" ", "untitled") + l.Add("-", "untitled") + l.Add("--", "untitled") + l.Add("Γ©", "Γ©") + l.Add("-Γ©-", "Γ©") + l.Add("-δ½ ε₯½-", "untitled") + l.Add("-こにけは-", "untitled") - for _, item := range msgList.Items { + for _, item := range l.Items { t.Log("Testing string '" + item.Msg + "'") - res = c.NameToSlug(item.Msg) + res := c.NameToSlug(item.Msg) if res != item.Expects { t.Error("Bad output:", "'"+res+"'") t.Error("Expected:", item.Expects) @@ -1523,14 +1500,14 @@ type METriList struct { Items []METri } -func (tlist *METriList) Add(args ...string) { +func (l *METriList) Add(args ...string) { if len(args) < 2 { panic("need 2 or more args") } if len(args) > 2 { - tlist.Items = append(tlist.Items, METri{args[0], args[1], args[2]}) + l.Items = append(l.Items, METri{args[0], args[1], args[2]}) } else { - tlist.Items = append(tlist.Items, METri{"", args[0], args[1]}) + l.Items = append(l.Items, METri{"", args[0], args[1]}) } } @@ -1544,37 +1521,36 @@ type CountTestList struct { Items []CountTest } -func (tlist *CountTestList) Add(name string, msg string, expects int) { - tlist.Items = append(tlist.Items, CountTest{name, msg, expects}) +func (l *CountTestList) Add(name string, msg string, expects int) { + l.Items = append(l.Items, CountTest{name, msg, expects}) } func TestWordCount(t *testing.T) { - var msgList = &CountTestList{nil} + l := &CountTestList{nil} + l.Add("blank", "", 0) + l.Add("single-letter", "h", 1) + l.Add("single-kana", "お", 1) + l.Add("single-letter-words", "h h", 2) + l.Add("two-letter", "h", 1) + l.Add("two-kana", "おは", 1) + l.Add("two-letter-words", "hh hh", 2) + l.Add("", "h,h", 2) + l.Add("", "h,,h", 2) + l.Add("", "h, h", 2) + l.Add("", " h, h", 2) + l.Add("", "h, h ", 2) + l.Add("", " h, h ", 2) + l.Add("", "h, h", 2) + l.Add("", "h\nh", 2) + l.Add("", "h\"h", 2) + l.Add("", "h[r]h", 3) + l.Add("", "お,お", 2) + l.Add("", "γŠγ€γŠ", 2) + l.Add("", "お\nお", 2) + l.Add("", "γŠβ€γŠ", 2) + l.Add("", "γŠγ€Œγ‚γ€γŠ", 3) - msgList.Add("blank", "", 0) - msgList.Add("single-letter", "h", 1) - msgList.Add("single-kana", "お", 1) - msgList.Add("single-letter-words", "h h", 2) - msgList.Add("two-letter", "h", 1) - msgList.Add("two-kana", "おは", 1) - msgList.Add("two-letter-words", "hh hh", 2) - msgList.Add("", "h,h", 2) - msgList.Add("", "h,,h", 2) - msgList.Add("", "h, h", 2) - msgList.Add("", " h, h", 2) - msgList.Add("", "h, h ", 2) - msgList.Add("", " h, h ", 2) - msgList.Add("", "h, h", 2) - msgList.Add("", "h\nh", 2) - msgList.Add("", "h\"h", 2) - msgList.Add("", "h[r]h", 3) - msgList.Add("", "お,お", 2) - msgList.Add("", "γŠγ€γŠ", 2) - msgList.Add("", "お\nお", 2) - msgList.Add("", "γŠβ€γŠ", 2) - msgList.Add("", "γŠγ€Œγ‚γ€γŠ", 3) - - for _, item := range msgList.Items { + for _, item := range l.Items { res := c.WordCount(item.Msg) if res != item.Expects { if item.Name != "" { diff --git a/parser_test.go b/parser_test.go index 20b601e3..ed678afd 100644 --- a/parser_test.go +++ b/parser_test.go @@ -13,114 +13,115 @@ func TestPreparser(t *testing.T) { if !c.PluginsInited { c.InitPlugins() } - var msgList = &METriList{nil} + l := &METriList{nil} // Note: The open tag is evaluated without knowledge of the close tag for efficiency and simplicity, so the parser autofills the associated close tag when it finds an open tag without a partner - msgList.Add("", "") - msgList.Add(" ", "") - msgList.Add(" hi", "hi") - msgList.Add("hi ", "hi") - msgList.Add("hi", "hi") - msgList.Add(":grinning:", "πŸ˜€") - msgList.Add("πŸ˜€", "πŸ˜€") - msgList.Add(" ", "") - msgList.Add("

", "") - msgList.Add("

", "") - msgList.Add("

", "") + l.Add("", "") + l.Add(" ", "") + l.Add(" hi", "hi") + l.Add("hi ", "hi") + l.Add("hi", "hi") + l.Add(":grinning:", "πŸ˜€") + l.Add("πŸ˜€", "πŸ˜€") + l.Add(" ", "") + l.Add("

", "") + l.Add("

", "") + l.Add("

", "") - msgList.Add("<", "<") - msgList.Add(">", ">") - msgList.Add("", "<meow>") - msgList.Add("<", "&lt;") - msgList.Add("&", "&") + l.Add("<", "<") + l.Add(">", ">") + l.Add("", "<meow>") + l.Add("<", "&lt;") + l.Add("&", "&") // Note: strings.TrimSpace strips newlines, if there's nothing before or after them - msgList.Add("
", "") - msgList.Add("
", "") - msgList.Add("\\n", "\n", "") - msgList.Add("\\n\\n", "\n\n", "") - msgList.Add("\\n\\n\\n", "\n\n\n", "") - msgList.Add("\\r\\n", "\r\n", "") // Windows style line ending - msgList.Add("\\n\\r", "\n\r", "") + l.Add("
", "") + l.Add("
", "") + l.Add("\\n", "\n", "") + l.Add("\\n\\n", "\n\n", "") + l.Add("\\n\\n\\n", "\n\n\n", "") + l.Add("\\r\\n", "\r\n", "") // Windows style line ending + l.Add("\\n\\r", "\n\r", "") - msgList.Add("ho
ho", "ho\n\nho") - msgList.Add("ho
ho", "ho\n\nho") - msgList.Add("ho\\nho", "ho\nho", "ho\nho") - msgList.Add("ho\\n\\nho", "ho\n\nho", "ho\n\nho") - //msgList.Add("ho\\n\\n\\n\\nho", "ho\n\n\n\nho", "ho\n\n\nho") - msgList.Add("ho\\r\\nho", "ho\r\nho", "ho\nho") // Windows style line ending - msgList.Add("ho\\n\\rho", "ho\n\rho", "ho\nho") + l.Add("ho
ho", "ho\n\nho") + l.Add("ho
ho", "ho\n\nho") + l.Add("ho\\nho", "ho\nho", "ho\nho") + l.Add("ho\\n\\nho", "ho\n\nho", "ho\n\nho") + //l.Add("ho\\n\\n\\n\\nho", "ho\n\n\n\nho", "ho\n\n\nho") + l.Add("ho\\r\\nho", "ho\r\nho", "ho\nho") // Windows style line ending + l.Add("ho\\n\\rho", "ho\n\rho", "ho\nho") - msgList.Add("", "") - msgList.Add("hi", "hi") - msgList.Add("h", "h") - msgList.Add("hi", "hi") - msgList.Add("hi", "hi") - msgList.Add("hi", "hi") - msgList.Add("hi", "hi") - msgList.Add("hi", "hi") - msgList.Add("hi", "hi") - msgList.Add("hi", "hi") - msgList.Add("hi", "hi") - msgList.Add("hi", "hi") - msgList.Add("hi", "hi") - msgList.Add("
hi
", "<div>hi</div>") - msgList.Add("hi", "hi") // This is stripped since the editor (Trumbowyg) likes blasting useless spans - msgList.Add("hi", "hi") - msgList.Add("hi", "hi") - msgList.Add(">hi", ">hi") - msgList.Add("hi", "hi") - msgList.Add("hi", "hi</b>") - msgList.Add("", "</b>") - msgList.Add("", "</del>") - msgList.Add("", "</strong>") - msgList.Add("", "") - msgList.Add("hi", "hi") - msgList.Add("hi", "hi") - msgList.Add("", "") - msgList.Add("", "") - msgList.Add("", "") - msgList.Add("", "") - msgList.Add("", "") - msgList.Add("

t

", "

t

") - msgList.Add("

t

", "

t

") - msgList.Add("

t

", "

t

") - msgList.Add("<>", "<></>") - msgList.Add("<>", "</><>") - msgList.Add("<>", "<>") - msgList.Add("", "</>") - msgList.Add("

hi

", "hi") - msgList.Add("

", "") - msgList.Add("
hi
", "
hi
") - msgList.Add("
hi
", "
hi
") - msgList.Add("
hi
", "
<meow>hi</meow>
") - msgList.Add("\\
hi
", "<blockquote>hi</blockquote>") - //msgList.Add("\\\\
hi
", "\\
<meow>hi</meow>
") // TODO: Double escapes should print a literal backslash - //msgList.Add("<blockquote>hi</blockquote>", "<blockquote>hi</blockquote>") // TODO: Stop double-entitising this - msgList.Add("\\
hi
\\
hi
", "<blockquote>hi</blockquote><blockquote>hi</blockquote>") - msgList.Add("\\Admin", "<a itemprop="author">Admin</a>") - msgList.Add("
\\Admin
", "
<a itemprop="author">Admin</a>
") - msgList.Add("\n
\\Admin
\n", "
<a itemprop="author">Admin</a>
") - msgList.Add("tt\n
\\Admin
\ntt", "tt\n
<a itemprop="author">Admin</a>
\ntt") - msgList.Add("@", "@") - msgList.Add("@Admin", "@1") - msgList.Add("@Bah", "@Bah") - msgList.Add(" @Admin", "@1") - msgList.Add("\n@Admin", "@1") - msgList.Add("@Admin\n", "@1") - msgList.Add("@Admin\ndd", "@1\ndd") - msgList.Add("d@Admin", "d@Admin") - msgList.Add("\\@Admin", "@Admin") - msgList.Add("@ε…ƒζ°—", "@ε…ƒζ°—") + l.Add("", "") + l.Add("hi", "hi") + l.Add("h", "h") + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add("
hi
", "<div>hi</div>") + l.Add("hi", "hi") // This is stripped since the editor (Trumbowyg) likes blasting useless spans + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add(">hi", ">hi") + l.Add("hi", "hi") + l.Add("hi", "hi</b>") + l.Add("
", "</b>") + l.Add("", "</del>") + l.Add("", "</strong>") + l.Add("", "") + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add("hi", "hi") + l.Add("", "") + l.Add("", "") + l.Add("", "") + l.Add("", "") + l.Add("", "") + l.Add("

t

", "

t

") + l.Add("

t

", "

t

") + l.Add("

t

", "

t

") + l.Add("<>", "<></>") + l.Add("<>", "</><>") + l.Add("<>", "<>") + l.Add("", "</>") + l.Add("

hi

", "hi") + l.Add("

", "") + l.Add("
hi
", "
hi
") + l.Add("
hi
", "
hi
") + l.Add("
hi
", "
<meow>hi</meow>
") + l.Add("\\
hi
", "<blockquote>hi</blockquote>") + //l.Add("\\\\
hi
", "\\
<meow>hi</meow>
") // TODO: Double escapes should print a literal backslash + //l.Add("<blockquote>hi</blockquote>", "<blockquote>hi</blockquote>") // TODO: Stop double-entitising this + l.Add("\\
hi
\\
hi
", "<blockquote>hi</blockquote><blockquote>hi</blockquote>") + l.Add("\\Admin", "<a itemprop="author">Admin</a>") + l.Add("
\\Admin
", "
<a itemprop="author">Admin</a>
") + l.Add("\n
\\Admin
\n", "
<a itemprop="author">Admin</a>
") + l.Add("tt\n
\\Admin
\ntt", "tt\n
<a itemprop="author">Admin</a>
\ntt") + l.Add("@", "@") + l.Add("@Admin", "@1") + l.Add("@Bah", "@Bah") + l.Add(" @Admin", "@1") + l.Add("\n@Admin", "@1") + l.Add("@Admin\n", "@1") + l.Add("@Admin\ndd", "@1\ndd") + l.Add("d@Admin", "d@Admin") + l.Add("\\@Admin", "@Admin") + l.Add("@ε…ƒζ°—", "@ε…ƒζ°—") // TODO: More tests for unicode names? - //msgList.Add("\\\\@Admin", "@1") - //msgList.Add("byte 0", string([]byte{0}), "") - msgList.Add("byte 'a'", string([]byte{'a'}), "a") - //msgList.Add("byte 255", string([]byte{255}), "") - //msgList.Add("rune 0", string([]rune{0}), "") + //l.Add("\\\\@Admin", "@1") + //l.Add("byte 0", string([]byte{0}), "") + l.Add("byte 'a'", string([]byte{'a'}), "a") + //l.Add("byte 255", string([]byte{255}), "") + //l.Add("rune 0", string([]rune{0}), "") // TODO: Do a test with invalid UTF-8 input - for _, item := range msgList.Items { + for _, item := range l.Items { res := c.PreparseMessage(item.Msg) if res != item.Expects { if item.Name != "" { @@ -139,145 +140,148 @@ func TestParser(t *testing.T) { if !c.PluginsInited { c.InitPlugins() } - var msgList = &METriList{nil} + l := &METriList{nil} url := "github.com/Azareal/Gosora" - msgList.Add("", "") - msgList.Add("haha", "haha") - msgList.Add("t", "t") - msgList.Add("//", "//") - msgList.Add("http://", "[Invalid URL]") - msgList.Add("https://", "[Invalid URL]") - msgList.Add("ftp://", "[Invalid URL]") - msgList.Add("git://", "[Invalid URL]") - msgList.Add("ssh://", "ssh://") + l.Add("", "") + l.Add("haha", "haha") + l.Add("t", "t") + l.Add("//", "//") + l.Add("http://", "[Invalid URL]") + l.Add("https://", "[Invalid URL]") + l.Add("ftp://", "[Invalid URL]") + l.Add("git://", "[Invalid URL]") + l.Add("ssh://", "ssh://") - msgList.Add("// ", "// ") - msgList.Add("// //", "// //") - msgList.Add("// // //", "// // //") - msgList.Add("http:// ", "[Invalid URL] ") - msgList.Add("https:// ", "[Invalid URL] ") - msgList.Add("ftp:// ", "[Invalid URL] ") - msgList.Add("git:// ", "[Invalid URL] ") - msgList.Add("ssh:// ", "ssh:// ") + l.Add("// ", "// ") + l.Add("// //", "// //") + l.Add("// // //", "// // //") + l.Add("http:// ", "[Invalid URL] ") + l.Add("https:// ", "[Invalid URL] ") + l.Add("ftp:// ", "[Invalid URL] ") + l.Add("git:// ", "[Invalid URL] ") + l.Add("ssh:// ", "ssh:// ") - msgList.Add("// t", "// t") - msgList.Add("http:// t", "[Invalid URL] t") + l.Add("// t", "// t") + l.Add("http:// t", "[Invalid URL] t") - msgList.Add("http:", "http:") - msgList.Add("https:", "https:") - msgList.Add("ftp:", "ftp:") - msgList.Add("git:", "git:") - msgList.Add("ssh:", "ssh:") + l.Add("http:", "http:") + l.Add("https:", "https:") + l.Add("ftp:", "ftp:") + l.Add("git:", "git:") + l.Add("ssh:", "ssh:") - msgList.Add("http", "http") - msgList.Add("https", "https") - msgList.Add("ftp", "ftp") - msgList.Add("git", "git") - msgList.Add("ssh", "ssh") + l.Add("http", "http") + l.Add("https", "https") + l.Add("ftp", "ftp") + l.Add("git", "git") + l.Add("ssh", "ssh") - msgList.Add("ht", "ht") - msgList.Add("htt", "htt") - msgList.Add("ft", "ft") - msgList.Add("gi", "gi") - msgList.Add("ss", "ss") - msgList.Add("haha\nhaha\nhaha", "haha
haha
haha") - msgList.Add("//"+url, "//"+url+"") - msgList.Add("//a", "//a") - msgList.Add(" //a", " //a") - msgList.Add("//a ", "//a ") - msgList.Add(" //a ", " //a ") - msgList.Add("d //a ", "d //a ") - msgList.Add("ddd ddd //a ", "ddd ddd //a ") - msgList.Add("https://"+url, "https://"+url+"") - msgList.Add("https://t", "https://t") - msgList.Add("http://"+url, "http://"+url+"") - msgList.Add("#http://"+url, "#http://"+url) - msgList.Add("@http://"+url, "[Invalid Profile]ttp://"+url) - msgList.Add("//"+url+"\n", "//"+url+"
") - msgList.Add("\n//"+url, "
//"+url+"") - msgList.Add("\n//"+url+"\n", "
//"+url+"
") - msgList.Add("\n//"+url+"\n\n", "
//"+url+"

") - msgList.Add("//"+url+"\n//"+url, "//"+url+"
//"+url+"") - msgList.Add("//"+url+"\n\n//"+url, "//"+url+"

//"+url+"") - msgList.Add("//"+c.Site.URL, "//"+c.Site.URL+"") - msgList.Add("//"+c.Site.URL+"\n", "//"+c.Site.URL+"
") - msgList.Add("//"+c.Site.URL+"\n//"+c.Site.URL, "//"+c.Site.URL+"
//"+c.Site.URL+"") + l.Add("ht", "ht") + l.Add("htt", "htt") + l.Add("ft", "ft") + l.Add("gi", "gi") + l.Add("ss", "ss") + l.Add("haha\nhaha\nhaha", "haha
haha
haha") + l.Add("//"+url, "//"+url+"") + l.Add("//a", "//a") + l.Add(" //a", " //a") + l.Add("//a ", "//a ") + l.Add(" //a ", " //a ") + l.Add("d //a ", "d //a ") + l.Add("ddd ddd //a ", "ddd ddd //a ") + l.Add("https://"+url, "https://"+url+"") + l.Add("https://t", "https://t") + l.Add("http://"+url, "http://"+url+"") + l.Add("#http://"+url, "#http://"+url) + l.Add("@http://"+url, "[Invalid Profile]ttp://"+url) + l.Add("//"+url+"\n", "//"+url+"
") + l.Add("\n//"+url, "
//"+url+"") + l.Add("\n//"+url+"\n", "
//"+url+"
") + l.Add("\n//"+url+"\n\n", "
//"+url+"

") + l.Add("//"+url+"\n//"+url, "//"+url+"
//"+url+"") + l.Add("//"+url+"\n\n//"+url, "//"+url+"

//"+url+"") + l.Add("//"+c.Site.URL, "//"+c.Site.URL+"") + l.Add("//"+c.Site.URL+"\n", "//"+c.Site.URL+"
") + l.Add("//"+c.Site.URL+"\n//"+c.Site.URL, "//"+c.Site.URL+"
//"+c.Site.URL+"") - var local = func(url string) { - msgList.Add("//"+url, "//"+url+"") - msgList.Add("//"+url+"\n", "//"+url+"
") - msgList.Add("//"+url+"\n//"+url, "//"+url+"
//"+url+"") + local := func(url string) { + l.Add("//"+url, "//"+url+"") + l.Add("//"+url+"\n", "//"+url+"
") + l.Add("//"+url+"\n//"+url, "//"+url+"
//"+url+"") } local("localhost") local("127.0.0.1") local("[::1]") - msgList.Add("https://www.youtube.com/watch?v=lalalalala","") - //msgList.Add("https://www.youtube.com/watch?v=;","") - msgList.Add("https://www.youtube.com/watch?v=d;","") - msgList.Add("https://www.youtube.com/watch?v=d;d","") - msgList.Add("https://www.youtube.com/watch?v=alert()","[Invalid URL]()") - msgList.Add("https://www.youtube.com/watch?v=js:alert()","[Invalid URL]()") - msgList.Add("https://www.youtube.com/watch?v='+><+'","[Invalid URL]'+><+'") - msgList.Add("https://www.youtube.com/watch?v='+onready='alert(\"\")'+'","[Invalid URL]'+onready='alert(\"\")'+'") - msgList.Add(" https://www.youtube.com/watch?v=lalalalala"," ") - msgList.Add("https://www.youtube.com/watch?v=lalalalala tt"," tt") - msgList.Add("https://www.youtube.com/watch?v=lalalalala&d=haha","") - msgList.Add("https://gaming.youtube.com/watch?v=lalalalala","") - msgList.Add("https://gaming.youtube.com/watch?v=lalalalala&d=haha","") - msgList.Add("https://m.youtube.com/watch?v=lalalalala","") - msgList.Add("https://m.youtube.com/watch?v=lalalalala&d=haha","") - msgList.Add("http://www.youtube.com/watch?v=lalalalala","") - msgList.Add("//www.youtube.com/watch?v=lalalalala","") - //msgList.Add("www.youtube.com/watch?v=lalalalala","") + l.Add("https://www.youtube.com/watch?v=lalalalala","") + //l.Add("https://www.youtube.com/watch?v=;","") + l.Add("https://www.youtube.com/watch?v=d;","") + l.Add("https://www.youtube.com/watch?v=d;d","") + l.Add("https://www.youtube.com/watch?v=alert()","[Invalid URL]()") + l.Add("https://www.youtube.com/watch?v=alert()()","[Invalid URL]()()") + l.Add("https://www.youtube.com/watch?v=js:alert()","[Invalid URL]()") + l.Add("https://www.youtube.com/watch?v='+><+'","[Invalid URL]'+><+'") + l.Add("https://www.youtube.com/watch?v='+onready='alert(\"\")'+'","[Invalid URL]'+onready='alert(\"\")'+'") + l.Add(" https://www.youtube.com/watch?v=lalalalala"," ") + l.Add("https://www.youtube.com/watch?v=lalalalala tt"," tt") + l.Add("https://www.youtube.com/watch?v=lalalalala&d=haha","") + l.Add("https://gaming.youtube.com/watch?v=lalalalala","") + l.Add("https://gaming.youtube.com/watch?v=lalalalala&d=haha","") + l.Add("https://m.youtube.com/watch?v=lalalalala","") + l.Add("https://m.youtube.com/watch?v=lalalalala&d=haha","") + l.Add("http://www.youtube.com/watch?v=lalalalala","") + l.Add("//www.youtube.com/watch?v=lalalalala","") + //l.Add("www.youtube.com/watch?v=lalalalala","") - msgList.Add("#tid-1", "#tid-1") - msgList.Add("##tid-1", "##tid-1") - msgList.Add("# #tid-1", "# #tid-1") - msgList.Add("@ #tid-1", "[Invalid Profile]#tid-1") - msgList.Add("@#tid-1", "[Invalid Profile]tid-1") - msgList.Add("@ #tid-@", "[Invalid Profile]#tid-@") - msgList.Add("#tid-1 #tid-1", "#tid-1 #tid-1") - msgList.Add("#tid-0", "[Invalid Topic]") - msgList.Add("https://"+url+"/#tid-1", "https://"+url+"/#tid-1") - msgList.Add("https://"+url+"/?hi=2", "https://"+url+"/?hi=2") - msgList.Add("#fid-1", "#fid-1") - msgList.Add(" #fid-1", " #fid-1") - msgList.Add("#fid-0", "[Invalid Forum]") - msgList.Add(" #fid-0", " [Invalid Forum]") - msgList.Add("#", "#") - msgList.Add("# ", "# ") - msgList.Add(" @", " @") - msgList.Add(" #", " #") - msgList.Add("#@", "#@") - msgList.Add("#@ ", "#@ ") - msgList.Add("#@1", "#@1") - msgList.Add("#f", "#f") - msgList.Add("#ff", "#ff") - msgList.Add("#ffffid-0", "#ffffid-0") - //msgList.Add("#ffffid-0", "#ffffid-0") - msgList.Add("#nid-0", "#nid-0") - msgList.Add("#nnid-0", "#nnid-0") - msgList.Add("@@", "[Invalid Profile]") - msgList.Add("@@ @@", "[Invalid Profile] [Invalid Profile]") - msgList.Add("@@1", "[Invalid Profile]1") - msgList.Add("@#1", "[Invalid Profile]1") - msgList.Add("@##1", "[Invalid Profile]#1") - msgList.Add("@2", "[Invalid Profile]") - msgList.Add("@2t", "[Invalid Profile]t") - msgList.Add("@2 t", "[Invalid Profile] t") - msgList.Add("@2 ", "[Invalid Profile] ") - msgList.Add("@2 @2", "[Invalid Profile] [Invalid Profile]") - msgList.Add("@1", "@Admin") - msgList.Add(" @1", " @Admin") - msgList.Add("@1t", "@Admint") - msgList.Add("@1 ", "@Admin ") - msgList.Add("@1 @1", "@Admin @Admin") - msgList.Add("@0", "[Invalid Profile]") - msgList.Add("@-1", "[Invalid Profile]1") + l.Add("#tid-1", "#tid-1") + l.Add("##tid-1", "##tid-1") + l.Add("# #tid-1", "# #tid-1") + l.Add("@ #tid-1", "[Invalid Profile]#tid-1") + l.Add("@#tid-1", "[Invalid Profile]tid-1") + l.Add("@ #tid-@", "[Invalid Profile]#tid-@") + l.Add("#tid-1 #tid-1", "#tid-1 #tid-1") + l.Add("#tid-0", "[Invalid Topic]") + l.Add("https://"+url+"/#tid-1", "https://"+url+"/#tid-1") + l.Add("https://"+url+"/?hi=2", "https://"+url+"/?hi=2") + l.Add("#fid-1", "#fid-1") + l.Add(" #fid-1", " #fid-1") + l.Add("#fid-0", "[Invalid Forum]") + l.Add(" #fid-0", " [Invalid Forum]") + l.Add("#", "#") + l.Add("# ", "# ") + l.Add(" @", " @") + l.Add(" #", " #") + l.Add("#@", "#@") + l.Add("#@ ", "#@ ") + l.Add("#@1", "#@1") + l.Add("#f", "#f") + l.Add("f#f", "f#f") + l.Add("f#", "f#") + l.Add("#ff", "#ff") + l.Add("#ffffid-0", "#ffffid-0") + //l.Add("#ffffid-0", "#ffffid-0") + l.Add("#nid-0", "#nid-0") + l.Add("#nnid-0", "#nnid-0") + l.Add("@@", "[Invalid Profile]") + l.Add("@@ @@", "[Invalid Profile] [Invalid Profile]") + l.Add("@@1", "[Invalid Profile]1") + l.Add("@#1", "[Invalid Profile]1") + l.Add("@##1", "[Invalid Profile]#1") + l.Add("@2", "[Invalid Profile]") + l.Add("@2t", "[Invalid Profile]t") + l.Add("@2 t", "[Invalid Profile] t") + l.Add("@2 ", "[Invalid Profile] ") + l.Add("@2 @2", "[Invalid Profile] [Invalid Profile]") + l.Add("@1", "@Admin") + l.Add(" @1", " @Admin") + l.Add("@1t", "@Admint") + l.Add("@1 ", "@Admin ") + l.Add("@1 @1", "@Admin @Admin") + l.Add("@0", "[Invalid Profile]") + l.Add("@-1", "[Invalid Profile]1") - for _, item := range msgList.Items { + for _, item := range l.Items { res := c.ParseMessage(item.Msg, 1, "forums") if res != item.Expects { if item.Name != "" { diff --git a/plugin_test.go b/plugin_test.go index bb8cdf0f..a2bf52db 100644 --- a/plugin_test.go +++ b/plugin_test.go @@ -4,7 +4,7 @@ import ( "strconv" "testing" - "github.com/Azareal/Gosora/common" + c "github.com/Azareal/Gosora/common" ) // go test -v @@ -20,61 +20,61 @@ type MEPairList struct { Items []MEPair } -func (tlist *MEPairList) Add(msg string, expects string) { - tlist.Items = append(tlist.Items, MEPair{msg, expects}) +func (l *MEPairList) Add(msg string, expects string) { + l.Items = append(l.Items, MEPair{msg, expects}) } func TestBBCodeRender(t *testing.T) { //t.Skip() - err := initBbcode(common.Plugins["bbcode"]) + err := initBbcode(c.Plugins["bbcode"]) if err != nil { t.Fatal(err) } var res string - var msgList = &MEPairList{nil} - msgList.Add("", "") - msgList.Add(" ", " ") - msgList.Add(" ", " ") - msgList.Add(" ", " ") - msgList.Add("[b]", "") - msgList.Add("[b][/b]", "") - msgList.Add("hi", "hi") - msgList.Add("πŸ˜€", "πŸ˜€") - msgList.Add("[b]πŸ˜€[/b]", "πŸ˜€") - msgList.Add("[b]πŸ˜€πŸ˜€πŸ˜€[/b]", "πŸ˜€πŸ˜€πŸ˜€") - msgList.Add("[b]hi[/b]", "hi") - msgList.Add("[u]hi[/u]", "hi") - msgList.Add("[i]hi[/i]", "hi") - msgList.Add("[s]hi[/s]", "hi") - msgList.Add("[c]hi[/c]", "[c]hi[/c]") - msgList.Add("[h1]hi", "[h1]hi") - msgList.Add("[h1]hi[/h1]", "

hi

") + l := &MEPairList{nil} + l.Add("", "") + l.Add(" ", " ") + l.Add(" ", " ") + l.Add(" ", " ") + l.Add("[b]", "") + l.Add("[b][/b]", "") + l.Add("hi", "hi") + l.Add("πŸ˜€", "πŸ˜€") + l.Add("[b]πŸ˜€[/b]", "πŸ˜€") + l.Add("[b]πŸ˜€πŸ˜€πŸ˜€[/b]", "πŸ˜€πŸ˜€πŸ˜€") + l.Add("[b]hi[/b]", "hi") + l.Add("[u]hi[/u]", "hi") + l.Add("[i]hi[/i]", "hi") + l.Add("[s]hi[/s]", "hi") + l.Add("[c]hi[/c]", "[c]hi[/c]") + l.Add("[h1]hi", "[h1]hi") + l.Add("[h1]hi[/h1]", "

hi

") if !testing.Short() { - //msgList.Add("[b]hi[/i]", "[b]hi[/i]") - //msgList.Add("[/b]hi[b]", "[/b]hi[b]") - //msgList.Add("[/b]hi[/b]", "[/b]hi[/b]") - //msgList.Add("[b][b]hi[/b]", "hi") - //msgList.Add("[b][b]hi", "[b][b]hi") - //msgList.Add("[b][b][b]hi", "[b][b][b]hi") - //msgList.Add("[/b]hi", "[/b]hi") + //l.Add("[b]hi[/i]", "[b]hi[/i]") + //l.Add("[/b]hi[b]", "[/b]hi[b]") + //l.Add("[/b]hi[/b]", "[/b]hi[/b]") + //l.Add("[b][b]hi[/b]", "hi") + //l.Add("[b][b]hi", "[b][b]hi") + //l.Add("[b][b][b]hi", "[b][b][b]hi") + //l.Add("[/b]hi", "[/b]hi") } - msgList.Add("[code]hi[/code]", "hi") - msgList.Add("[code][b]hi[/b][/code]", "[b]hi[/b]") - msgList.Add("[code][b]hi[/code][/b]", "[b]hi[/b]") - msgList.Add("[quote]hi[/quote]", "
hi
") - msgList.Add("[quote][b]hi[/b][/quote]", "
hi
") - msgList.Add("[quote][b]h[/b][/quote]", "
h
") - msgList.Add("[quote][b][/b][/quote]", "
") - msgList.Add("[url][/url]", "") - msgList.Add("[url]https://github.com/Azareal/Gosora[/url]", "https://github.com/Azareal/Gosora") - msgList.Add("[url]http://github.com/Azareal/Gosora[/url]", "http://github.com/Azareal/Gosora") - msgList.Add("[url]//github.com/Azareal/Gosora[/url]", "//github.com/Azareal/Gosora") - msgList.Add("-δ½ ε₯½-", "-δ½ ε₯½-") - msgList.Add("[i]-δ½ ε₯½-[/i]", "-δ½ ε₯½-") // TODO: More of these Unicode tests? Emoji, Chinese, etc.? + l.Add("[code]hi[/code]", "hi") + l.Add("[code][b]hi[/b][/code]", "[b]hi[/b]") + l.Add("[code][b]hi[/code][/b]", "[b]hi[/b]") + l.Add("[quote]hi[/quote]", "
hi
") + l.Add("[quote][b]hi[/b][/quote]", "
hi
") + l.Add("[quote][b]h[/b][/quote]", "
h
") + l.Add("[quote][b][/b][/quote]", "
") + l.Add("[url][/url]", "") + l.Add("[url]https://github.com/Azareal/Gosora[/url]", "https://github.com/Azareal/Gosora") + l.Add("[url]http://github.com/Azareal/Gosora[/url]", "http://github.com/Azareal/Gosora") + l.Add("[url]//github.com/Azareal/Gosora[/url]", "//github.com/Azareal/Gosora") + l.Add("-δ½ ε₯½-", "-δ½ ε₯½-") + l.Add("[i]-δ½ ε₯½-[/i]", "-δ½ ε₯½-") // TODO: More of these Unicode tests? Emoji, Chinese, etc.? t.Log("Testing bbcodeFullParse") - for _, item := range msgList.Items { + for _, item := range l.Items { res = bbcodeFullParse(item.Msg) if res != item.Expects { t.Error("Testing string '" + item.Msg + "'") @@ -83,77 +83,26 @@ func TestBBCodeRender(t *testing.T) { } } - var msg string - var expects string - - msg = "[rand][/rand]" - expects = "[Invalid Number][rand][/rand]" - t.Log("Testing string '" + msg + "'") - res = bbcodeFullParse(msg) - if res != expects { - t.Error("Bad output:", "'"+res+"'") - t.Error("Expected:", "'"+expects+"'") + f := func(msg, expects string) { + t.Log("Testing string '" + msg + "'") + res := bbcodeFullParse(msg) + if res != expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", "'"+expects+"'") + } } + f("[rand][/rand]","[Invalid Number][rand][/rand]") + f("[rand]-1[/rand]","[No Negative Numbers][rand]-1[/rand]") + f("[rand]-01[/rand]","[No Negative Numbers][rand]-01[/rand]") + f("[rand]NaN[/rand]","[Invalid Number][rand]NaN[/rand]") + f("[rand]Inf[/rand]","[Invalid Number][rand]Inf[/rand]") + f("[rand]+[/rand]","[Invalid Number][rand]+[/rand]") + f("[rand]1+1[/rand]","[Invalid Number][rand]1+1[/rand]") - msg = "[rand]-1[/rand]" - expects = "[No Negative Numbers][rand]-1[/rand]" + msg := "[rand]1[/rand]" t.Log("Testing string '" + msg + "'") res = bbcodeFullParse(msg) - if res != expects { - t.Error("Bad output:", "'"+res+"'") - t.Error("Expected:", "'"+expects+"'") - } - - msg = "[rand]-01[/rand]" - expects = "[No Negative Numbers][rand]-01[/rand]" - t.Log("Testing string '" + msg + "'") - res = bbcodeFullParse(msg) - if res != expects { - t.Error("Bad output:", "'"+res+"'") - t.Error("Expected:", "'"+expects+"'") - } - - msg = "[rand]NaN[/rand]" - expects = "[Invalid Number][rand]NaN[/rand]" - t.Log("Testing string '" + msg + "'") - res = bbcodeFullParse(msg) - if res != expects { - t.Error("Bad output:", "'"+res+"'") - t.Error("Expected:", "'"+expects+"'") - } - - msg = "[rand]Inf[/rand]" - expects = "[Invalid Number][rand]Inf[/rand]" - t.Log("Testing string '" + msg + "'") - res = bbcodeFullParse(msg) - if res != expects { - t.Error("Bad output:", "'"+res+"'") - t.Error("Expected:", "'"+expects+"'") - } - - msg = "[rand]+[/rand]" - expects = "[Invalid Number][rand]+[/rand]" - t.Log("Testing string '" + msg + "'") - res = bbcodeFullParse(msg) - if res != expects { - t.Error("Bad output:", "'"+res+"'") - t.Error("Expected:", "'"+expects+"'") - } - - msg = "[rand]1+1[/rand]" - expects = "[Invalid Number][rand]1+1[/rand]" - t.Log("Testing string '" + msg + "'") - res = bbcodeFullParse(msg) - if res != expects { - t.Error("Bad output:", "'"+res+"'") - t.Error("Expected:", "'"+expects+"'") - } - - var conv int - msg = "[rand]1[/rand]" - t.Log("Testing string '" + msg + "'") - res = bbcodeFullParse(msg) - conv, err = strconv.Atoi(res) + conv, err := strconv.Atoi(res) if err != nil || (conv > 1 || conv < 0) { t.Error("Bad output:", "'"+res+"'") t.Error("Expected a number in the range 0-1") @@ -205,7 +154,7 @@ func TestBBCodeRender(t *testing.T) { } /*t.Log("Testing bbcode_regex_parse") - for _, item := range msgList { + for _, item := range l.Items { t.Log("Testing string '" + item.Msg + "'") res = bbcodeRegexParse(item.Msg) if res != item.Expects { @@ -217,94 +166,92 @@ func TestBBCodeRender(t *testing.T) { func TestMarkdownRender(t *testing.T) { //t.Skip() - err := initMarkdown(common.Plugins["markdown"]) + err := initMarkdown(c.Plugins["markdown"]) if err != nil { t.Fatal(err) } - var res string - var msgList = &MEPairList{nil} - var msgList2 = &MEPairList{nil} + l := &MEPairList{nil} + l2 := &MEPairList{nil} // TODO: Fix more of these odd cases - msgList.Add("", "") - msgList.Add(" ", " ") - msgList.Add(" ", " ") - msgList.Add(" ", " ") - msgList.Add("\t", "\t") - msgList.Add("\n", "\n") - msgList.Add("*", "*") - msgList.Add("`", "`") - //msgList.Add("**", "") - msgList.Add("h", "h") - msgList.Add("hi", "hi") - msgList.Add("**h**", "h") - msgList.Add("**hi**", "hi") - msgList.Add("_h_", "h") - msgList.Add("_hi_", "hi") - msgList.Add("*h*", "h") - msgList.Add("*hi*", "hi") - msgList.Add("~h~", "h") - msgList.Add("~hi~", "hi") - msgList.Add("`hi`", "
hi
") + l.Add("", "") + l.Add(" ", " ") + l.Add(" ", " ") + l.Add(" ", " ") + l.Add("\t", "\t") + l.Add("\n", "\n") + l.Add("*", "*") + l.Add("`", "`") + //l.Add("**", "") + l.Add("h", "h") + l.Add("hi", "hi") + l.Add("**h**", "h") + l.Add("**hi**", "hi") + l.Add("_h_", "h") + l.Add("_hi_", "hi") + l.Add("*h*", "h") + l.Add("*hi*", "hi") + l.Add("~h~", "h") + l.Add("~hi~", "hi") + l.Add("`hi`", "
hi
") // TODO: Hide the backslash after escaping the item // TODO: Doesn't behave consistently with d in-front of it - msgList2.Add("\\`hi`", "\\`hi`") - msgList2.Add("#", "#") - msgList2.Add("#h", "

h

") - msgList2.Add("#hi", "

hi

") - msgList2.Add("# hi", "

hi

") - msgList2.Add("# hi", "

hi

") - msgList.Add("\n#", "\n#") - msgList.Add("\n#h", "\n

h

") - msgList.Add("\n#hi", "\n

hi

") - msgList.Add("\n#h\n", "\n

h

") - msgList.Add("\n#hi\n", "\n

hi

") - msgList.Add("*hi**", "hi*") - msgList.Add("**hi***", "hi*") - //msgList.Add("**hi*", "*hi") - msgList.Add("***hi***", "hi") - msgList.Add("***h***", "h") - msgList.Add("\\***h**\\*", "*h*") - msgList.Add("\\*\\**h*\\*\\*", "**h**") - msgList.Add("\\*hi\\*", "*hi*") - msgList.Add("d\\*hi\\*", "d*hi*") - msgList.Add("\\*hi\\*d", "*hi*d") - msgList.Add("d\\*hi\\*d", "d*hi*d") - msgList.Add("\\", "\\") - msgList.Add("\\\\", "\\\\") - msgList.Add("\\d", "\\d") - msgList.Add("\\\\d", "\\\\d") - msgList.Add("\\\\\\d", "\\\\\\d") - msgList.Add("d\\", "d\\") - msgList.Add("\\d\\", "\\d\\") - msgList.Add("*_hi_*", "hi") - msgList.Add("*~hi~*", "hi") - //msgList.Add("~*hi*~", "hi") - //msgList.Add("~ *hi* ~", " hi ") - msgList.Add("_~hi~_", "hi") - msgList.Add("***~hi~***", "hi") - msgList.Add("**", "**") - msgList.Add("***", "***") - msgList.Add("****", "****") - msgList.Add("*****", "*****") - msgList.Add("******", "******") - msgList.Add("*******", "*******") - msgList.Add("~~", "~~") - msgList.Add("~~~", "~~~") - msgList.Add("~~~~", "~~~~") - msgList.Add("~~~~~", "~~~~~") - msgList.Add("__", "__") - msgList.Add("___", "___") - msgList.Add("_ _", " ") - msgList.Add("* *", " ") - msgList.Add("** **", " ") - msgList.Add("*** ***", " ") - msgList.Add("-δ½ ε₯½-", "-δ½ ε₯½-") - msgList.Add("*-δ½ ε₯½-*", "-δ½ ε₯½-") // TODO: More of these Unicode tests? Emoji, Chinese, etc.? + l2.Add("\\`hi`", "\\`hi`") + l2.Add("#", "#") + l2.Add("#h", "

h

") + l2.Add("#hi", "

hi

") + l2.Add("# hi", "

hi

") + l2.Add("# hi", "

hi

") + l.Add("\n#", "\n#") + l.Add("\n#h", "\n

h

") + l.Add("\n#hi", "\n

hi

") + l.Add("\n#h\n", "\n

h

") + l.Add("\n#hi\n", "\n

hi

") + l.Add("*hi**", "hi*") + l.Add("**hi***", "hi*") + //l.Add("**hi*", "*hi") + l.Add("***hi***", "hi") + l.Add("***h***", "h") + l.Add("\\***h**\\*", "*h*") + l.Add("\\*\\**h*\\*\\*", "**h**") + l.Add("\\*hi\\*", "*hi*") + l.Add("d\\*hi\\*", "d*hi*") + l.Add("\\*hi\\*d", "*hi*d") + l.Add("d\\*hi\\*d", "d*hi*d") + l.Add("\\", "\\") + l.Add("\\\\", "\\\\") + l.Add("\\d", "\\d") + l.Add("\\\\d", "\\\\d") + l.Add("\\\\\\d", "\\\\\\d") + l.Add("d\\", "d\\") + l.Add("\\d\\", "\\d\\") + l.Add("*_hi_*", "hi") + l.Add("*~hi~*", "hi") + //l.Add("~*hi*~", "hi") + //l.Add("~ *hi* ~", " hi ") + l.Add("_~hi~_", "hi") + l.Add("***~hi~***", "hi") + l.Add("**", "**") + l.Add("***", "***") + l.Add("****", "****") + l.Add("*****", "*****") + l.Add("******", "******") + l.Add("*******", "*******") + l.Add("~~", "~~") + l.Add("~~~", "~~~") + l.Add("~~~~", "~~~~") + l.Add("~~~~~", "~~~~~") + l.Add("__", "__") + l.Add("___", "___") + l.Add("_ _", " ") + l.Add("* *", " ") + l.Add("** **", " ") + l.Add("*** ***", " ") + l.Add("-δ½ ε₯½-", "-δ½ ε₯½-") + l.Add("*-δ½ ε₯½-*", "-δ½ ε₯½-") // TODO: More of these Unicode tests? Emoji, Chinese, etc.? - for _, item := range msgList.Items { - res = markdownParse(item.Msg) - if res != item.Expects { + for _, item := range l.Items { + if res := markdownParse(item.Msg); res != item.Expects { t.Error("Testing string '" + item.Msg + "'") t.Error("Bad output:", "'"+res+"'") //t.Error("Ouput in bytes:", []byte(res)) @@ -312,9 +259,8 @@ func TestMarkdownRender(t *testing.T) { } } - for _, item := range msgList2.Items { - res = markdownParse(item.Msg) - if res != item.Expects { + for _, item := range l2.Items { + if res := markdownParse(item.Msg); res != item.Expects { t.Error("Testing string '" + item.Msg + "'") t.Error("Bad output:", "'"+res+"'") //t.Error("Ouput in bytes:", []byte(res)) @@ -322,9 +268,8 @@ func TestMarkdownRender(t *testing.T) { } } - /*for _, item := range msgList.Items { - res = markdownParse("\n" + item.Msg) - if res != "\n"+item.Expects { + /*for _, item := range l.Items { + if res := markdownParse("\n" + item.Msg); res != "\n"+item.Expects { t.Error("Testing string '\n" + item.Msg + "'") t.Error("Bad output:", "'"+res+"'") //t.Error("Ouput in bytes:", []byte(res)) @@ -332,9 +277,8 @@ func TestMarkdownRender(t *testing.T) { } } - for _, item := range msgList.Items { - res = markdownParse("\t" + item.Msg) - if res != "\t"+item.Expects { + for _, item := range l.Items { + if res := markdownParse("\t" + item.Msg); res != "\t"+item.Expects { t.Error("Testing string '\t" + item.Msg + "'") t.Error("Bad output:", "'"+res+"'") //t.Error("Ouput in bytes:", []byte(res)) @@ -342,9 +286,8 @@ func TestMarkdownRender(t *testing.T) { } }*/ - for _, item := range msgList.Items { - res = markdownParse("d" + item.Msg) - if res != "d"+item.Expects { + for _, item := range l.Items { + if res := markdownParse("d" + item.Msg); res != "d"+item.Expects { t.Error("Testing string 'd" + item.Msg + "'") t.Error("Bad output:", "'"+res+"'") //t.Error("Ouput in bytes:", []byte(res)) diff --git a/routes/account.go b/routes/account.go index 1e9e1648..981c98fe 100644 --- a/routes/account.go +++ b/routes/account.go @@ -13,19 +13,19 @@ import ( "strings" c "github.com/Azareal/Gosora/common" - "github.com/Azareal/Gosora/common/phrases" + p "github.com/Azareal/Gosora/common/phrases" "github.com/Azareal/Gosora/query_gen" ) // 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, header *c.Header) c.RouteError { +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) } - header.Title = phrases.GetTitlePhrase("login") - return renderTemplate("login", w, r, header, c.Page{header, tList, nil}) + h.Title = p.GetTitlePhrase("login") + return renderTemplate("login", w, r, h, c.Page{h, tList, nil}) } // TODO: Log failed attempted logins? @@ -141,11 +141,11 @@ func mfaVerifySession(provSession string, signedSession string, uid int) bool { return subtle.ConstantTimeCompare([]byte(signedSession), []byte(expected)) == 1 } -func AccountLoginMFAVerify(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { +func AccountLoginMFAVerify(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) } - header.Title = phrases.GetTitlePhrase("login_mfa_verify") + h.Title = p.GetTitlePhrase("login_mfa_verify") uid, provSession, signedSession, err := mfaGetCookies(r) if err != nil { @@ -155,7 +155,7 @@ func AccountLoginMFAVerify(w http.ResponseWriter, r *http.Request, user c.User, return c.LocalError("Invalid session", w, r, user) } - return renderTemplate("login_mfa_verify", w, r, header, c.Page{header, tList, nil}) + return renderTemplate("login_mfa_verify", w, r, h, c.Page{h, tList, nil}) } func AccountLoginMFAVerifySubmit(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { @@ -182,13 +182,13 @@ func AccountLogout(w http.ResponseWriter, r *http.Request, user c.User) c.RouteE return nil } -func AccountRegister(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { +func AccountRegister(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) } - header.Title = phrases.GetTitlePhrase("register") - header.AddScriptAsync("register.js") - return renderTemplate("register", w, r, header, c.Page{header, tList, nil}) + h.Title = p.GetTitlePhrase("register") + h.AddScriptAsync("register.js") + return renderTemplate("register", w, r, h, c.Page{h, tList, nil}) } func isNumeric(data string) (numeric bool) { @@ -204,10 +204,10 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user c.User) headerLite, _ := c.SimpleUserCheck(w, r, &user) // TODO: Should we push multiple validation errors to the user instead of just one? - var regSuccess = true - var regErrMsg = "" - var regErrReason = "" - var regError = func(userMsg string, reason string) { + regSuccess := true + regErrMsg := "" + regErrReason := "" + regError := func(userMsg string, reason string) { regSuccess = false if regErrMsg == "" { regErrMsg = userMsg @@ -216,14 +216,14 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user c.User) } if r.PostFormValue("tos") != "0" { - regError(phrases.GetErrorPhrase("register_might_be_machine"), "trap-question") + regError(p.GetErrorPhrase("register_might_be_machine"), "trap-question") } if !c.Config.DisableJSAntispam { h := sha256.New() h.Write([]byte(c.JSTokenBox.Load().(string))) h.Write([]byte(user.LastIP)) if r.PostFormValue("golden-watch") != hex.EncodeToString(h.Sum(nil)) { - regError(phrases.GetErrorPhrase("register_might_be_machine"), "js-antispam") + regError(p.GetErrorPhrase("register_might_be_machine"), "js-antispam") } } @@ -231,21 +231,20 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user c.User) // TODO: Add a dedicated function for validating emails email := c.SanitiseSingleLine(r.PostFormValue("email")) if username == "" { - regError(phrases.GetErrorPhrase("register_need_username"), "no-username") + regError(p.GetErrorPhrase("register_need_username"), "no-username") } if email == "" { - regError(phrases.GetErrorPhrase("register_need_email"), "no-email") + regError(p.GetErrorPhrase("register_need_email"), "no-email") } // This is so a numeric name won't interfere with mentioning a user by ID, there might be a better way of doing this like perhaps !@ to mean IDs and @ to mean usernames in the pre-parser usernameBits := strings.Split(username, " ") if isNumeric(usernameBits[0]) { - regError(phrases.GetErrorPhrase("register_first_word_numeric"), "numeric-name") + regError(p.GetErrorPhrase("register_first_word_numeric"), "numeric-name") } - ok := c.HasSuspiciousEmail(email) - if ok { - regError(phrases.GetErrorPhrase("register_suspicious_email"), "suspicious-email") + if c.HasSuspiciousEmail(email) { + regError(p.GetErrorPhrase("register_suspicious_email"), "suspicious-email") } password := r.PostFormValue("password") @@ -257,7 +256,7 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user c.User) // Do the two inputted passwords match..? confirmPassword := r.PostFormValue("confirm_password") if password != confirmPassword { - regError(phrases.GetErrorPhrase("register_password_mismatch"), "password-mismatch") + regError(p.GetErrorPhrase("register_password_mismatch"), "password-mismatch") } } @@ -290,14 +289,14 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user c.User) if err != nil { return c.InternalError(err, w, r) } - return c.LocalError(phrases.GetErrorPhrase("register_username_unavailable"), w, r, user) + return c.LocalError(p.GetErrorPhrase("register_username_unavailable"), w, r, user) } else if err == c.ErrLongUsername { regLog.FailureReason += "username-too-long" err = regLog.Commit() if err != nil { return c.InternalError(err, w, r) } - return c.LocalError(phrases.GetErrorPhrase("register_username_too_long_prefix")+strconv.Itoa(c.Config.MaxUsernameLength), w, r, user) + return c.LocalError(p.GetErrorPhrase("register_username_too_long_prefix")+strconv.Itoa(c.Config.MaxUsernameLength), w, r, user) } regLog.FailureReason += "internal-error" err2 := regLog.Commit() @@ -328,7 +327,7 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user c.User) err = c.SendValidationEmail(username, email, token) if err != nil { - return c.LocalError(phrases.GetErrorPhrase("register_email_fail"), w, r, user) + return c.LocalError(p.GetErrorPhrase("register_email_fail"), w, r, user) } } @@ -337,11 +336,11 @@ 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, header *c.Header) { - header.Title = phrases.GetTitlePhrase(titlePhrase) - header.Path = "/user/edit/" - header.AddSheet(header.Theme.Name + "/account.css") - header.AddScriptAsync("account.js") +func accountEditHead(titlePhrase string, w http.ResponseWriter, r *http.Request, user *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 { @@ -356,7 +355,7 @@ func AccountEdit(w http.ResponseWriter, r *http.Request, user c.User, header *c. } // TODO: Find a more efficient way of doing this - var mfaSetup = false + mfaSetup := false _, err := c.MFAstore.Get(user.ID) if err != sql.ErrNoRows && err != nil { return c.InternalError(err, w, r) @@ -375,9 +374,9 @@ func AccountEdit(w http.ResponseWriter, r *http.Request, user c.User, header *c. } //edit_password -func AccountEditPassword(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { - accountEditHead("account_password", w, r, &user, header) - return renderTemplate("account_own_edit_password", w, r, header, c.Page{header, tList, nil}) +func AccountEditPassword(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { + accountEditHead("account_password", w, r, &user, h) + return renderTemplate("account_own_edit_password", w, r, h, c.Page{h, tList, nil}) } // TODO: Require re-authentication if the user hasn't logged in in a while @@ -479,8 +478,8 @@ func AccountEditUsernameSubmit(w http.ResponseWriter, r *http.Request, user c.Us return nil } -func AccountEditMFA(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { - accountEditHead("account_mfa", w, r, &user, header) +func AccountEditMFA(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { + accountEditHead("account_mfa", w, r, &user, h) mfaItem, err := c.MFAstore.Get(user.ID) if err != sql.ErrNoRows && err != nil { @@ -489,13 +488,13 @@ func AccountEditMFA(w http.ResponseWriter, r *http.Request, user c.User, header return c.LocalError("Two-factor authentication hasn't been setup on your account", w, r, user) } - pi := c.Page{header, tList, mfaItem.Scratch} - return renderTemplate("account_own_edit_mfa", w, r, header, pi) + pi := c.Page{h, tList, mfaItem.Scratch} + return renderTemplate("account_own_edit_mfa", w, r, h, pi) } // If not setup, generate a string, otherwise give an option to disable mfa given the right code -func AccountEditMFASetup(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { - accountEditHead("account_mfa_setup", w, r, &user, header) +func AccountEditMFASetup(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { + accountEditHead("account_mfa_setup", w, r, &user, h) // Flash an error if mfa is already setup _, err := c.MFAstore.Get(user.ID) @@ -511,8 +510,8 @@ func AccountEditMFASetup(w http.ResponseWriter, r *http.Request, user c.User, he return c.InternalError(err, w, r) } - pi := c.Page{header, tList, c.FriendlyGAuthSecret(code)} - return renderTemplate("account_own_edit_mfa_setup", w, r, header, pi) + pi := c.Page{h, tList, c.FriendlyGAuthSecret(code)} + return renderTemplate("account_own_edit_mfa_setup", w, r, h, pi) } // Form should bounce the random mfa secret back and the otp to be verified server-side to reduce the chances of a bug arising on the JS side which makes every code mismatch @@ -530,8 +529,8 @@ func AccountEditMFASetupSubmit(w http.ResponseWriter, r *http.Request, user c.Us return c.LocalError("You have already setup two-factor authentication", w, r, user) } - var code = r.PostFormValue("code") - var otp = r.PostFormValue("otp") + code := r.PostFormValue("code") + otp := r.PostFormValue("otp") ok, err := c.VerifyGAuthToken(code, otp) if err != nil { //fmt.Println("err: ", err) @@ -576,8 +575,8 @@ func AccountEditMFADisableSubmit(w http.ResponseWriter, r *http.Request, user c. return nil } -func AccountEditEmail(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { - accountEditHead("account_email", w, r, &user, header) +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) if err != nil { return c.InternalError(err, w, r) @@ -586,22 +585,18 @@ func AccountEditEmail(w http.ResponseWriter, r *http.Request, user c.User, heade // 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 { - email := c.Email{UserID: user.ID} - email.Email = user.Email - email.Validated = false - email.Primary = true - emails = append(emails, email) + emails = append(emails, c.Email{UserID: user.ID, Email: user.Email, Validated: false, Primary: true}) } if !c.Site.EnableEmails { - header.AddNotice("account_mail_disabled") + h.AddNotice("account_mail_disabled") } if r.FormValue("verified") == "1" { - header.AddNotice("account_mail_verify_success") + h.AddNotice("account_mail_verify_success") } - pi := c.Account{header, "edit_emails", "account_own_edit_email", c.EmailListPage{header, emails}} - return renderTemplate("account", w, r, header, pi) + pi := c.Account{h, "edit_emails", "account_own_edit_email", c.EmailListPage{h, emails}} + return renderTemplate("account", w, r, h, pi) } // TODO: Should we make this an AnonAction so someone can do this without being logged in? @@ -649,9 +644,8 @@ func AccountEditEmailTokenSubmit(w http.ResponseWriter, r *http.Request, user c. return nil } -func AccountLogins(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { - accountEditHead("account_logins", w, r, &user, header) - +func AccountLogins(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { + accountEditHead("account_logins", w, r, &user, h) logCount := c.LoginLogs.CountUser(user.ID) page, _ := strconv.Atoi(r.FormValue("page")) perPage := 12 @@ -663,15 +657,15 @@ func AccountLogins(w http.ResponseWriter, r *http.Request, user c.User, header * } pageList := c.Paginate(page, lastPage, 5) - pi := c.Account{header, "logins", "account_logins", c.AccountLoginsPage{header, logs, c.Paginator{pageList, page, lastPage}}} - return renderTemplate("account", w, r, header, pi) + pi := c.Account{h, "logins", "account_logins", c.AccountLoginsPage{h, logs, c.Paginator{pageList, page, lastPage}}} + return renderTemplate("account", w, r, h, pi) } -func LevelList(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { - header.Title = phrases.GetTitlePhrase("account_level_list") +func LevelList(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { + h.Title = p.GetTitlePhrase("account_level_list") - var fScores = c.GetLevels(20) - var levels = make([]c.LevelListItem, len(fScores)) + fScores := c.GetLevels(20) + levels := make([]c.LevelListItem, len(fScores)) for i, fScore := range fScores { var status string if user.Level > i { @@ -686,25 +680,25 @@ func LevelList(w http.ResponseWriter, r *http.Request, user c.User, header *c.He levels[i] = c.LevelListItem{i, iScore, status, perc * 2} } - return renderTemplate("level_list", w, r, header, c.LevelListPage{header, levels[1:]}) + return renderTemplate("level_list", w, r, h, c.LevelListPage{h, levels[1:]}) } -func Alerts(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { +func Alerts(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { return nil } -func AccountPasswordReset(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { +func AccountPasswordReset(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) } if !c.Site.EnableEmails { - return c.LocalError(phrases.GetNoticePhrase("account_mail_disabled"), w, r, user) + return c.LocalError(p.GetNoticePhrase("account_mail_disabled"), w, r, user) } if r.FormValue("email_sent") == "1" { - header.AddNotice("password_reset_email_sent") + h.AddNotice("password_reset_email_sent") } - header.Title = phrases.GetTitlePhrase("password_reset") - return renderTemplate("password_reset", w, r, header, c.Page{header, tList, nil}) + h.Title = p.GetTitlePhrase("password_reset") + return renderTemplate("password_reset", w, r, h, c.Page{h, tList, nil}) } // TODO: Ratelimit this @@ -713,7 +707,7 @@ func AccountPasswordResetSubmit(w http.ResponseWriter, r *http.Request, user c.U return c.LocalError("You're already logged in.", w, r, user) } if !c.Site.EnableEmails { - return c.LocalError(phrases.GetNoticePhrase("account_mail_disabled"), w, r, user) + return c.LocalError(p.GetNoticePhrase("account_mail_disabled"), w, r, user) } username := r.PostFormValue("username") @@ -767,9 +761,9 @@ func AccountPasswordResetSubmit(w http.ResponseWriter, r *http.Request, user c.U schema = "s" } - err = c.SendEmail(tuser.Email, phrases.GetTmplPhrase("password_reset_subject"), phrases.GetTmplPhrasef("password_reset_body", tuser.Name, "http"+schema+"://"+c.Site.URL+"/accounts/password-reset/token/?uid="+strconv.Itoa(tuser.ID)+"&token="+token)) + err = c.SendEmail(tuser.Email, p.GetTmplPhrase("password_reset_subject"), p.GetTmplPhrasef("password_reset_body", tuser.Name, "http"+schema+"://"+c.Site.URL+"/accounts/password-reset/token/?uid="+strconv.Itoa(tuser.ID)+"&token="+token)) if err != nil { - return c.LocalError(phrases.GetErrorPhrase("password_reset_email_fail"), w, r, user) + return c.LocalError(p.GetErrorPhrase("password_reset_email_fail"), w, r, user) } http.Redirect(w, r, "/accounts/password-reset/?email_sent=1", http.StatusSeeOther) @@ -804,7 +798,7 @@ func AccountPasswordResetToken(w http.ResponseWriter, r *http.Request, user c.Us } mfa := err != sql.ErrNoRows - header.Title = phrases.GetTitlePhrase("password_reset_token") + header.Title = p.GetTitlePhrase("password_reset_token") return renderTemplate("password_reset_token", w, r, header, c.ResetPage{header, uid, html.EscapeString(token), mfa}) } @@ -812,8 +806,6 @@ func AccountPasswordResetTokenSubmit(w http.ResponseWriter, r *http.Request, use if user.Loggedin { return c.LocalError("You're already logged in.", w, r, user) } - - token := r.FormValue("token") uid, err := strconv.Atoi(r.FormValue("uid")) if err != nil { return c.LocalError("Invalid uid", w, r, user) @@ -822,6 +814,7 @@ func AccountPasswordResetTokenSubmit(w http.ResponseWriter, r *http.Request, use return c.LocalError("This reset token has expired.", w, r, user) } + token := r.FormValue("token") err = c.PasswordResetter.ValidateToken(uid, token) if err == sql.ErrNoRows || err == c.ErrBadResetToken { return c.LocalError("This reset token has expired.", w, r, user) diff --git a/routes/convos.go b/routes/convos.go index 42428f8c..97f09b9c 100644 --- a/routes/convos.go +++ b/routes/convos.go @@ -6,17 +6,18 @@ import ( "net/http" "strconv" "strings" + //"log" c "github.com/Azareal/Gosora/common" p "github.com/Azareal/Gosora/common/phrases" ) -func Convos(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { - accountEditHead("convos", w, r, &user, header) - header.AddScript("convo.js") - header.AddSheet(header.Theme.Name + "/convo.css") - header.AddNotice("convo_dev") +func Convos(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { + accountEditHead("convos", w, r, &user, h) + h.AddScript("convo.js") + h.AddSheet(h.Theme.Name + "/convo.css") + h.AddNotice("convo_dev") ccount := c.Convos.GetUserCount(user.ID) page, _ := strconv.Atoi(r.FormValue("page")) offset, page, lastPage := c.PageOffset(ccount, page, c.Config.ItemsPerPage) @@ -25,13 +26,13 @@ func Convos(w http.ResponseWriter, r *http.Request, user c.User, header *c.Heade convos, err := c.Convos.GetUserExtra(user.ID, offset) //log.Printf("convos: %+v\n", convos) if err == sql.ErrNoRows { - return c.NotFound(w, r, header) + return c.NotFound(w, r, h) } else if err != nil { return c.InternalError(err, w, r) } - pi := c.Account{header, "dashboard", "convos", c.ConvoListPage{header, convos, c.Paginator{pageList, page, lastPage}}} - return renderTemplate("account", w, r, header, pi) + pi := c.Account{h, "dashboard", "convos", c.ConvoListPage{h, convos, c.Paginator{pageList, page, lastPage}}} + return renderTemplate("account", w, r, h, pi) } func Convo(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header, scid string) c.RouteError { @@ -99,12 +100,12 @@ func Convo(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header return renderTemplate("account", w, r, header, pi) } -func ConvosCreate(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { - accountEditHead("create_convo", w, r, &user, header) - header.AddNotice("convo_dev") +func ConvosCreate(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { + accountEditHead("create_convo", w, r, &user, h) + h.AddNotice("convo_dev") recpName := "" - pi := c.Account{header, "dashboard", "create_convo", c.ConvoCreatePage{header, recpName}} - return renderTemplate("account", w, r, header, pi) + pi := c.Account{h, "dashboard", "create_convo", c.ConvoCreatePage{h, recpName}} + return renderTemplate("account", w, r, h, pi) } func ConvosCreateSubmit(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { @@ -112,7 +113,7 @@ func ConvosCreateSubmit(w http.ResponseWriter, r *http.Request, user c.User) c.R if ferr != nil { return ferr } - if user.IsBanned { + if !user.Perms.UseConvos { return c.NoPermissions(w, r, user) } @@ -131,6 +132,10 @@ func ConvosCreateSubmit(w http.ResponseWriter, r *http.Request, user c.User) c.R } else if err != nil { return c.InternalError(err, w, r) } + // TODO: Should we kick them out of existing conversations if they're moved into a group without permission or the permission is revoked from their group? We might want to give them a chance to delete their messages though to avoid privacy headaches here and it may only be temporarily to tackle a specific incident. + if !u.Perms.UseConvos { + return c.LocalError("One of the recipients doesn't have permission to use the conversations system", w, r, user) + } rlist = append(rlist, u.ID) } @@ -168,7 +173,7 @@ func ConvosCreateReplySubmit(w http.ResponseWriter, r *http.Request, user c.User if ferr != nil { return ferr } - if user.IsBanned { + if !user.Perms.UseConvos { return c.NoPermissions(w, r, user) } cid, err := strconv.Atoi(scid) @@ -263,6 +268,9 @@ func ConvosEditReplySubmit(w http.ResponseWriter, r *http.Request, user c.User, if err != nil { return c.LocalError(p.GetErrorPhrase("id_must_be_integer"), w, r, user) } + if !user.Perms.UseConvos { + return c.NoPermissions(w, r, user) + } js := (r.PostFormValue("js") == "1") post := &c.ConversationPost{ID: cpid} diff --git a/routes/forum_list.go b/routes/forum_list.go index 2f241d68..e4e0e4e7 100644 --- a/routes/forum_list.go +++ b/routes/forum_list.go @@ -38,15 +38,15 @@ func ForumList(w http.ResponseWriter, r *http.Request, user c.User, header *c.He var forumList []c.Forum for _, fid := range canSee { // Avoid data races by copying the struct into something we can freely mold without worrying about breaking something somewhere else - var forum = c.Forums.DirtyGet(fid).Copy() - if forum.ParentID == 0 && forum.Name != "" && forum.Active { - if forum.LastTopicID != 0 { - if forum.LastTopic.ID != 0 && forum.LastReplyer.ID != 0 { - forum.LastTopicTime = c.RelativeTime(forum.LastTopic.LastReplyAt) + f := c.Forums.DirtyGet(fid).Copy() + if f.ParentID == 0 && f.Name != "" && f.Active { + if f.LastTopicID != 0 { + if f.LastTopic.ID != 0 && f.LastReplyer.ID != 0 { + f.LastTopicTime = c.RelativeTime(f.LastTopic.LastReplyAt) } } - header.Hooks.Hook("forums_frow_assign", &forum) - forumList = append(forumList, forum) + header.Hooks.Hook("forums_frow_assign", &f) + forumList = append(forumList, f) } } diff --git a/routes/misc.go b/routes/misc.go index 8cdac1e8..143282b7 100644 --- a/routes/misc.go +++ b/routes/misc.go @@ -52,28 +52,28 @@ func StaticFile(w http.ResponseWriter, r *http.Request) { // Other options instead of io.Copy: io.CopyN(), w.Write(), http.ServeContent() } -func Overview(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { - header.Title = phrases.GetTitlePhrase("overview") - header.Zone = "overview" - return renderTemplate("overview", w, r, header, c.Page{header, tList, nil}) +func Overview(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { + h.Title = phrases.GetTitlePhrase("overview") + h.Zone = "overview" + return renderTemplate("overview", w, r, h, c.Page{h, tList, nil}) } -func CustomPage(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header, name string) c.RouteError { - header.Zone = "custom_page" +func CustomPage(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header, name string) c.RouteError { + h.Zone = "custom_page" name = c.SanitiseSingleLine(name) page, err := c.Pages.GetByName(name) if err == nil { - header.Title = page.Title - return renderTemplate("custom_page", w, r, header, c.CustomPagePage{header, page}) + h.Title = page.Title + return renderTemplate("custom_page", w, r, h, c.CustomPagePage{h, page}) } else if err != sql.ErrNoRows { return c.InternalError(err, w, r) } - header.Title = phrases.GetTitlePhrase("page") + h.Title = phrases.GetTitlePhrase("page") // TODO: Pass the page name to the pre-render hook? - err = renderTemplate3("page_"+name, "tmpl_page", w, r, header, c.Page{header, tList, nil}) + err = renderTemplate3("page_"+name, "tmpl_page", w, r, h, c.Page{h, tList, nil}) if err == c.ErrBadDefaultTemplate { - return c.NotFound(w, r, header) + return c.NotFound(w, r, h) } else if err != nil { return c.InternalError(err, w, r) } @@ -84,7 +84,7 @@ func CustomPage(w http.ResponseWriter, r *http.Request, user c.User, header *c.H func ChangeTheme(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { //headerLite, _ := SimpleUserCheck(w, r, &user) // TODO: Rename js to something else, just in case we rewrite the JS side in WebAssembly? - js := (r.PostFormValue("js") == "1") + js := r.PostFormValue("js") == "1" newTheme := c.SanitiseSingleLine(r.PostFormValue("newTheme")) theme, ok := c.Themes[newTheme] diff --git a/routes/panel/groups.go b/routes/panel/groups.go index 09e33cc1..78158d23 100644 --- a/routes/panel/groups.go +++ b/routes/panel/groups.go @@ -80,7 +80,7 @@ func GroupsEdit(w http.ResponseWriter, r *http.Request, user c.User, sgid string //log.Print("aaaaa monsters") return c.NotFound(w, r, basePage.Header) } - ferr = groupCheck(w,r,user,g,err) + ferr = groupCheck(w, r, user, g, err) if ferr != nil { return ferr } @@ -122,7 +122,7 @@ func GroupsEditPromotions(w http.ResponseWriter, r *http.Request, user c.User, s //log.Print("aaaaa monsters") return c.NotFound(w, r, basePage.Header) } - ferr = groupCheck(w,r,user,g,err) + ferr = groupCheck(w, r, user, g, err) if ferr != nil { return ferr } @@ -343,6 +343,7 @@ func GroupsEditPerms(w http.ResponseWriter, r *http.Request, user c.User, sgid s addGlobalPerm("ViewIPs", g.Perms.ViewIPs) addGlobalPerm("UploadFiles", g.Perms.UploadFiles) addGlobalPerm("UploadAvatars", g.Perms.UploadAvatars) + addGlobalPerm("UseConvos", g.Perms.UseConvos) pi := c.PanelEditGroupPermsPage{basePage, g.ID, g.Name, localPerms, globalPerms} return renderTemplate("panel_group_edit_perms", w, r, basePage.Header, pi) diff --git a/routes/panel/settings.go b/routes/panel/settings.go index fc90a635..3cb81ff4 100644 --- a/routes/panel/settings.go +++ b/routes/panel/settings.go @@ -7,7 +7,7 @@ import ( "strings" c "github.com/Azareal/Gosora/common" - "github.com/Azareal/Gosora/common/phrases" + p "github.com/Azareal/Gosora/common/phrases" ) func Settings(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { @@ -24,33 +24,34 @@ func Settings(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError if err != nil { return c.InternalError(err, w, r) } - settingPhrases := phrases.GetAllSettingPhrases() + settingPhrases := p.GetAllSettingPhrases() var settingList []*c.PanelSetting for _, settingPtr := range settings { - setting := settingPtr.Copy() - if setting.Type == "list" { - llist := settingPhrases[setting.Name+"_label"] + s := settingPtr.Copy() + if s.Type == "list" { + llist := settingPhrases[s.Name+"_label"] labels := strings.Split(llist, ",") - conv, err := strconv.Atoi(setting.Content) + conv, err := strconv.Atoi(s.Content) if err != nil { - return c.LocalError("The setting '"+setting.Name+"' can't be converted to an integer", w, r, user) + return c.LocalError("The setting '"+s.Name+"' can't be converted to an integer", w, r, user) } - setting.Content = labels[conv-1] - } else if setting.Type == "bool" { - if setting.Content == "1" { - setting.Content = "Yes" + s.Content = labels[conv-1] + // TODO: Localise this + } else if s.Type == "bool" { + if s.Content == "1" { + s.Content = "Yes" } else { - setting.Content = "No" + s.Content = "No" } - } else if setting.Type == "html-attribute" { - setting.Type = "textarea" + } else if s.Type == "html-attribute" { + s.Type = "textarea" } - settingList = append(settingList, &c.PanelSetting{setting, phrases.GetSettingPhrase(setting.Name)}) + settingList = append(settingList, &c.PanelSetting{s, p.GetSettingPhrase(s.Name)}) } pi := c.PanelPage{basePage, tList, settingList} - return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_settings",&pi}) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_settings", &pi}) } func SettingEdit(w http.ResponseWriter, r *http.Request, user c.User, sname string) c.RouteError { @@ -71,7 +72,7 @@ func SettingEdit(w http.ResponseWriter, r *http.Request, user c.User, sname stri var itemList []c.OptionLabel if setting.Type == "list" { - llist := phrases.GetSettingPhrase(setting.Name + "_label") + llist := p.GetSettingPhrase(setting.Name + "_label") conv, err := strconv.Atoi(setting.Content) if err != nil { return c.LocalError("The value of this setting couldn't be converted to an integer", w, r, user) @@ -88,9 +89,9 @@ func SettingEdit(w http.ResponseWriter, r *http.Request, user c.User, sname stri setting.Type = "textarea" } - pSetting := &c.PanelSetting{setting, phrases.GetSettingPhrase(setting.Name)} + pSetting := &c.PanelSetting{setting, p.GetSettingPhrase(setting.Name)} pi := c.PanelSettingPage{basePage, itemList, pSetting} - return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_setting",&pi}) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_setting", &pi}) } func SettingEditSubmit(w http.ResponseWriter, r *http.Request, user c.User, sname string) c.RouteError { diff --git a/routes/panel/themes.go b/routes/panel/themes.go index 7d339dfe..de1a2327 100644 --- a/routes/panel/themes.go +++ b/routes/panel/themes.go @@ -34,7 +34,7 @@ func Themes(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { } pi := c.PanelThemesPage{basePage, pThemeList, vThemeList} - return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"panel_themes","","panel_themes",&pi}) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "panel_themes", "", "panel_themes", &pi}) } func ThemesSetDefault(w http.ResponseWriter, r *http.Request, user c.User, uname string) c.RouteError { @@ -74,7 +74,7 @@ func ThemesMenus(w http.ResponseWriter, r *http.Request, user c.User) c.RouteErr var menuList []c.PanelMenuListItem for mid, list := range c.Menus.GetAllMap() { - var name = "" + name := "" if mid == 1 { name = p.GetTmplPhrase("panel_themes_menus_main") } @@ -85,7 +85,7 @@ func ThemesMenus(w http.ResponseWriter, r *http.Request, user c.User) c.RouteErr }) } - return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_themes_menus", &c.PanelMenuListPage{basePage, menuList}}) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_themes_menus", &c.PanelMenuListPage{basePage, menuList}}) } func ThemesMenusEdit(w http.ResponseWriter, r *http.Request, user c.User, smid string) c.RouteError { @@ -132,7 +132,7 @@ func ThemesMenusEdit(w http.ResponseWriter, r *http.Request, user c.User, smid s menuList = append(menuList, item) } - return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_themes_menus_items", &c.PanelMenuPage{basePage, mid, menuList}}) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_themes_menus_items", &c.PanelMenuPage{basePage, mid, menuList}}) } func ThemesMenuItemEdit(w http.ResponseWriter, r *http.Request, user c.User, sitemID string) c.RouteError { @@ -157,53 +157,53 @@ func ThemesMenuItemEdit(w http.ResponseWriter, r *http.Request, user c.User, sit return c.InternalError(err, w, r) } - return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_themes_menus_item_edit", &c.PanelMenuItemPage{basePage, menuItem}}) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_themes_menus_item_edit", &c.PanelMenuItemPage{basePage, menuItem}}) } -func themesMenuItemSetters(r *http.Request, mItem c.MenuItem) c.MenuItem { +func themesMenuItemSetters(r *http.Request, i c.MenuItem) c.MenuItem { getItem := func(name string) string { return c.SanitiseSingleLine(r.PostFormValue("item-" + name)) } - mItem.Name = getItem("name") - mItem.HTMLID = getItem("htmlid") - mItem.CSSClass = getItem("cssclass") - mItem.Position = getItem("position") - if mItem.Position != "left" && mItem.Position != "right" { - mItem.Position = "left" + i.Name = getItem("name") + i.HTMLID = getItem("htmlid") + i.CSSClass = getItem("cssclass") + i.Position = getItem("position") + if i.Position != "left" && i.Position != "right" { + i.Position = "left" } - mItem.Path = getItem("path") - mItem.Aria = getItem("aria") - mItem.Tooltip = getItem("tooltip") - mItem.TmplName = getItem("tmplname") + i.Path = getItem("path") + i.Aria = getItem("aria") + i.Tooltip = getItem("tooltip") + i.TmplName = getItem("tmplname") switch getItem("permissions") { case "everyone": - mItem.GuestOnly = false - mItem.MemberOnly = false - mItem.SuperModOnly = false - mItem.AdminOnly = false + i.GuestOnly = false + i.MemberOnly = false + i.SuperModOnly = false + i.AdminOnly = false case "guest-only": - mItem.GuestOnly = true - mItem.MemberOnly = false - mItem.SuperModOnly = false - mItem.AdminOnly = false + i.GuestOnly = true + i.MemberOnly = false + i.SuperModOnly = false + i.AdminOnly = false case "member-only": - mItem.GuestOnly = false - mItem.MemberOnly = true - mItem.SuperModOnly = false - mItem.AdminOnly = false + i.GuestOnly = false + i.MemberOnly = true + i.SuperModOnly = false + i.AdminOnly = false case "supermod-only": - mItem.GuestOnly = false - mItem.MemberOnly = true - mItem.SuperModOnly = true - mItem.AdminOnly = false + i.GuestOnly = false + i.MemberOnly = true + i.SuperModOnly = true + i.AdminOnly = false case "admin-only": - mItem.GuestOnly = false - mItem.MemberOnly = true - mItem.SuperModOnly = true - mItem.AdminOnly = true + i.GuestOnly = false + i.MemberOnly = true + i.SuperModOnly = true + i.AdminOnly = true } - return mItem + return i } func ThemesMenuItemEditSubmit(w http.ResponseWriter, r *http.Request, user c.User, sitemID string) c.RouteError { @@ -211,7 +211,7 @@ func ThemesMenuItemEditSubmit(w http.ResponseWriter, r *http.Request, user c.Use if ferr != nil { return ferr } - js := (r.PostFormValue("js") == "1") + js := r.PostFormValue("js") == "1" if !user.Perms.ManageThemes { return c.NoPermissionsJSQ(w, r, user, js) } @@ -243,7 +243,7 @@ func ThemesMenuItemCreateSubmit(w http.ResponseWriter, r *http.Request, user c.U return ferr } - js := (r.PostFormValue("js") == "1") + js := r.PostFormValue("js") == "1" if !user.Perms.ManageThemes { return c.NoPermissionsJSQ(w, r, user, js) } @@ -270,7 +270,7 @@ func ThemesMenuItemDeleteSubmit(w http.ResponseWriter, r *http.Request, user c.U if ferr != nil { return ferr } - js := (r.PostFormValue("js") == "1") + js := r.PostFormValue("js") == "1" if !user.Perms.ManageThemes { return c.NoPermissionsJSQ(w, r, user, js) } @@ -299,7 +299,7 @@ func ThemesMenuItemOrderSubmit(w http.ResponseWriter, r *http.Request, user c.Us if ferr != nil { return ferr } - js := (r.PostFormValue("js") == "1") + js := r.PostFormValue("js") == "1" if !user.Perms.ManageThemes { return c.NoPermissionsJSQ(w, r, user, js) } @@ -341,14 +341,14 @@ func ThemesWidgets(w http.ResponseWriter, r *http.Request, user c.User) c.RouteE } basePage.Header.AddScript("widgets.js") - var docks = make(map[string][]c.WidgetEdit) + docks := make(map[string][]c.WidgetEdit) for _, name := range c.GetDockList() { if name == "leftOfNav" || name == "rightOfNav" { continue } var widgets []c.WidgetEdit for _, widget := range c.GetDock(name) { - var data = make(map[string]string) + data := make(map[string]string) err := json.Unmarshal([]byte(widget.RawBody), &data) if err != nil { return c.InternalError(err, w, r) @@ -359,12 +359,12 @@ func ThemesWidgets(w http.ResponseWriter, r *http.Request, user c.User) c.RouteE } pi := c.PanelWidgetListPage{basePage, docks, c.WidgetEdit{&c.Widget{ID: 0, Type: "simple"}, make(map[string]string)}} - return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_themes_widgets", pi}) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_themes_widgets", pi}) } func widgetsParseInputs(r *http.Request, widget *c.Widget) (*c.WidgetEdit, error) { - var data = make(map[string]string) - widget.Enabled = (r.FormValue("wenabled") == "1") + data := make(map[string]string) + widget.Enabled = r.FormValue("wenabled") == "1" widget.Location = r.FormValue("wlocation") if widget.Location == "" { return nil, errors.New("You need to specify a location for this widget.") @@ -374,7 +374,7 @@ func widgetsParseInputs(r *http.Request, widget *c.Widget) (*c.WidgetEdit, error return nil, errors.New("The widget dock you specified doesn't exist.") } - var wtype = r.FormValue("wtype") + wtype := r.FormValue("wtype") switch wtype { case "simple", "about": data["Name"] = r.FormValue("wname") @@ -402,7 +402,7 @@ func ThemesWidgetsEditSubmit(w http.ResponseWriter, r *http.Request, user c.User if ferr != nil { return ferr } - js := (r.PostFormValue("js") == "1") + js := r.PostFormValue("js") == "1" if !user.Perms.ManageThemes { return c.NoPermissionsJSQ(w, r, user, js) } @@ -435,7 +435,7 @@ func ThemesWidgetsEditSubmit(w http.ResponseWriter, r *http.Request, user c.User // ThemesWidgetsCreateSubmit is an action which is triggered when someone sends a create request for a widget func ThemesWidgetsCreateSubmit(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { //fmt.Println("in ThemesWidgetsCreateSubmit") - js := (r.PostFormValue("js") == "1") + js := r.PostFormValue("js") == "1" _, ferr := c.SimplePanelUserCheck(w, r, &user) if ferr != nil { return ferr @@ -462,7 +462,7 @@ func ThemesWidgetsDeleteSubmit(w http.ResponseWriter, r *http.Request, user c.Us if ferr != nil { return ferr } - js := (r.PostFormValue("js") == "1") + js := r.PostFormValue("js") == "1" if !user.Perms.ManageThemes { return c.NoPermissionsJSQ(w, r, user, js) } diff --git a/routes/poll.go b/routes/poll.go index ab6abcc0..60385ad3 100644 --- a/routes/poll.go +++ b/routes/poll.go @@ -7,7 +7,7 @@ import ( "strconv" c "github.com/Azareal/Gosora/common" - "github.com/Azareal/Gosora/query_gen" + qgen "github.com/Azareal/Gosora/query_gen" ) func PollVote(w http.ResponseWriter, r *http.Request, user c.User, sPollID string) c.RouteError { @@ -57,7 +57,6 @@ func PollVote(w http.ResponseWriter, r *http.Request, user c.User, sPollID strin if err != nil { return c.LocalError("Malformed input", w, r, user) } - err = poll.CastVote(optionIndex, user.ID, user.LastIP) if err != nil { return c.InternalError(err, w, r) @@ -88,7 +87,7 @@ func PollResults(w http.ResponseWriter, r *http.Request, user c.User, sPollID st } defer rows.Close() - var optionList = "" + optionList := "" for rows.Next() { var votes int err := rows.Scan(&votes) diff --git a/routes/topic_list.go b/routes/topic_list.go index 12e85966..3b879d2a 100644 --- a/routes/topic_list.go +++ b/routes/topic_list.go @@ -19,16 +19,16 @@ func wsTopicList(topicList []*c.TopicsRow, lastPage int) *c.WsTopicList { return &c.WsTopicList{wsTopicList, lastPage, 0} } -func TopicList(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { - skip, rerr := header.Hooks.VhookSkippable("route_topic_list_start", w, r, &user, header) +func TopicList(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { + skip, rerr := h.Hooks.VhookSkippable("route_topic_list_start", w, r, &user, h) if skip || rerr != nil { return rerr } - return TopicListCommon(w, r, user, header, "lastupdated", "") + return TopicListCommon(w, r, user, h, "lastupdated", "") } -func TopicListMostViewed(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError { - return TopicListCommon(w, r, user, header, "mostviewed", "most-viewed") +func TopicListMostViewed(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { + return TopicListCommon(w, r, user, h, "mostviewed", "most-viewed") } // TODO: Implement search @@ -85,7 +85,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, header var cfids []int if len(fids) > 0 { - var inSlice = func(haystack []int, needle int) bool { + inSlice := func(haystack []int, needle int) bool { for _, item := range haystack { if needle == item { return true @@ -117,7 +117,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, header if err != nil { return c.InternalError(err, w, r) } - var reqUserList = make(map[int]bool) + reqUserList := make(map[int]bool) for _, topic := range tMap { reqUserList[topic.CreatedBy] = true reqUserList[topic.LastReplyBy] = true @@ -126,7 +126,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, header //fmt.Printf("reqUserList %+v\n", reqUserList) // Convert the user ID map to a slice, then bulk load the users - var idSlice = make([]int, len(reqUserList)) + idSlice := make([]int, len(reqUserList)) var i int for userID := range reqUserList { idSlice[i] = userID diff --git a/schema/mssql/inserts.sql b/schema/mssql/inserts.sql index b0dd2453..ef7bc8b2 100644 --- a/schema/mssql/inserts.sql +++ b/schema/mssql/inserts.sql @@ -7,9 +7,9 @@ INSERT INTO [settings] ([name],[content],[type]) VALUES ('rapid_loading','1','bo INSERT INTO [settings] ([name],[content],[type]) VALUES ('google_site_verify','','html-attribute'); INSERT INTO [themes] ([uname],[default]) VALUES ('cosora',1); INSERT INTO [emails] ([email],[uid],[validated]) VALUES ('admin@localhost',1,1); -INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[tag]) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,'Admin'); -INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[tag]) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,'Mod'); -INSERT INTO [users_groups] ([name],[permissions],[plugin_perms]) VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'); +INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[tag]) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,'Admin'); +INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[tag]) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,'Mod'); +INSERT INTO [users_groups] ([name],[permissions],[plugin_perms]) VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'); INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_banned]) VALUES ('Banned','{"ViewTopic":true}','{}',1); INSERT INTO [users_groups] ([name],[permissions],[plugin_perms]) VALUES ('Awaiting Activation','{"ViewTopic":true}','{}'); INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[tag]) VALUES ('Not Loggedin','{"ViewTopic":true}','{}','Guest'); @@ -36,6 +36,6 @@ INSERT INTO [menu_items] ([mid],[htmlID],[cssClass],[position],[tmplName],[order INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[order]) VALUES (1,'{lang.menu_account}','menu_account','left','/user/edit/','{lang.menu_account_aria}','{lang.menu_account_tooltip}',1,3); INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[order]) VALUES (1,'{lang.menu_profile}','menu_profile','left','{me.Link}','{lang.menu_profile_aria}','{lang.menu_profile_tooltip}',1,4); INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[staffOnly],[order]) VALUES (1,'{lang.menu_panel}','menu_panel menu_account','left','/panel/','{lang.menu_panel_aria}','{lang.menu_panel_tooltip}',1,1,5); -INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[order]) VALUES (1,'{lang.menu_logout}','menu_logout','left','/accounts/logout/?session={me.Session}','{lang.menu_logout_aria}','{lang.menu_logout_tooltip}',1,6); +INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[order]) VALUES (1,'{lang.menu_logout}','menu_logout','left','/accounts/logout/?s={me.Session}','{lang.menu_logout_aria}','{lang.menu_logout_tooltip}',1,6); INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[guestOnly],[order]) VALUES (1,'{lang.menu_register}','menu_register','left','/accounts/create/','{lang.menu_register_aria}','{lang.menu_register_tooltip}',1,7); INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[guestOnly],[order]) VALUES (1,'{lang.menu_login}','menu_login','left','/accounts/login/','{lang.menu_login_aria}','{lang.menu_login_tooltip}',1,8); diff --git a/schema/mysql/inserts.sql b/schema/mysql/inserts.sql index 83f07bce..913b315c 100644 --- a/schema/mysql/inserts.sql +++ b/schema/mysql/inserts.sql @@ -15,9 +15,9 @@ INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('rapid_loading','1','boo INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('google_site_verify','','html-attribute'); INSERT INTO `themes`(`uname`,`default`) VALUES ('cosora',1); INSERT INTO `emails`(`email`,`uid`,`validated`) VALUES ('admin@localhost',1,1); -INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,'Admin'); -INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,'Mod'); -INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`) VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'); +INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,'Admin'); +INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,'Mod'); +INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`) VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'); INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_banned`) VALUES ('Banned','{"ViewTopic":true}','{}',1); INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`) VALUES ('Awaiting Activation','{"ViewTopic":true}','{}'); INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`tag`) VALUES ('Not Loggedin','{"ViewTopic":true}','{}','Guest'); @@ -44,6 +44,6 @@ INSERT INTO `menu_items`(`mid`,`htmlID`,`cssClass`,`position`,`tmplName`,`order` INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`order`) VALUES (1,'{lang.menu_account}','menu_account','left','/user/edit/','{lang.menu_account_aria}','{lang.menu_account_tooltip}',1,3); INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`order`) VALUES (1,'{lang.menu_profile}','menu_profile','left','{me.Link}','{lang.menu_profile_aria}','{lang.menu_profile_tooltip}',1,4); INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`staffOnly`,`order`) VALUES (1,'{lang.menu_panel}','menu_panel menu_account','left','/panel/','{lang.menu_panel_aria}','{lang.menu_panel_tooltip}',1,1,5); -INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`order`) VALUES (1,'{lang.menu_logout}','menu_logout','left','/accounts/logout/?session={me.Session}','{lang.menu_logout_aria}','{lang.menu_logout_tooltip}',1,6); +INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`order`) VALUES (1,'{lang.menu_logout}','menu_logout','left','/accounts/logout/?s={me.Session}','{lang.menu_logout_aria}','{lang.menu_logout_tooltip}',1,6); INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`guestOnly`,`order`) VALUES (1,'{lang.menu_register}','menu_register','left','/accounts/create/','{lang.menu_register_aria}','{lang.menu_register_tooltip}',1,7); INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`guestOnly`,`order`) VALUES (1,'{lang.menu_login}','menu_login','left','/accounts/login/','{lang.menu_login_aria}','{lang.menu_login_tooltip}',1,8); diff --git a/schema/pgsql/inserts.sql b/schema/pgsql/inserts.sql index c374ae08..ed218269 100644 --- a/schema/pgsql/inserts.sql +++ b/schema/pgsql/inserts.sql @@ -7,9 +7,9 @@ INSERT INTO "settings"("name","content","type") VALUES ('rapid_loading','1','boo INSERT INTO "settings"("name","content","type") VALUES ('google_site_verify','','html-attribute'); INSERT INTO "themes"("uname","default") VALUES ('cosora',1); INSERT INTO "emails"("email","uid","validated") VALUES ('admin@localhost',1,1); -INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","tag") VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,'Admin'); -INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","tag") VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,'Mod'); -INSERT INTO "users_groups"("name","permissions","plugin_perms") VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'); +INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","tag") VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,'Admin'); +INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","tag") VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,'Mod'); +INSERT INTO "users_groups"("name","permissions","plugin_perms") VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}'); INSERT INTO "users_groups"("name","permissions","plugin_perms","is_banned") VALUES ('Banned','{"ViewTopic":true}','{}',1); INSERT INTO "users_groups"("name","permissions","plugin_perms") VALUES ('Awaiting Activation','{"ViewTopic":true}','{}'); INSERT INTO "users_groups"("name","permissions","plugin_perms","tag") VALUES ('Not Loggedin','{"ViewTopic":true}','{}','Guest'); @@ -36,6 +36,6 @@ INSERT INTO "menu_items"("mid","htmlID","cssClass","position","tmplName","order" INSERT INTO "menu_items"("mid","name","cssClass","position","path","aria","tooltip","memberOnly","order") VALUES (1,'{lang.menu_account}','menu_account','left','/user/edit/','{lang.menu_account_aria}','{lang.menu_account_tooltip}',1,3); INSERT INTO "menu_items"("mid","name","cssClass","position","path","aria","tooltip","memberOnly","order") VALUES (1,'{lang.menu_profile}','menu_profile','left','{me.Link}','{lang.menu_profile_aria}','{lang.menu_profile_tooltip}',1,4); INSERT INTO "menu_items"("mid","name","cssClass","position","path","aria","tooltip","memberOnly","staffOnly","order") VALUES (1,'{lang.menu_panel}','menu_panel menu_account','left','/panel/','{lang.menu_panel_aria}','{lang.menu_panel_tooltip}',1,1,5); -INSERT INTO "menu_items"("mid","name","cssClass","position","path","aria","tooltip","memberOnly","order") VALUES (1,'{lang.menu_logout}','menu_logout','left','/accounts/logout/?session={me.Session}','{lang.menu_logout_aria}','{lang.menu_logout_tooltip}',1,6); +INSERT INTO "menu_items"("mid","name","cssClass","position","path","aria","tooltip","memberOnly","order") VALUES (1,'{lang.menu_logout}','menu_logout','left','/accounts/logout/?s={me.Session}','{lang.menu_logout_aria}','{lang.menu_logout_tooltip}',1,6); INSERT INTO "menu_items"("mid","name","cssClass","position","path","aria","tooltip","guestOnly","order") VALUES (1,'{lang.menu_register}','menu_register','left','/accounts/create/','{lang.menu_register_aria}','{lang.menu_register_tooltip}',1,7); INSERT INTO "menu_items"("mid","name","cssClass","position","path","aria","tooltip","guestOnly","order") VALUES (1,'{lang.menu_login}','menu_login','left','/accounts/login/','{lang.menu_login_aria}','{lang.menu_login_tooltip}',1,8); diff --git a/templates/footer.html b/templates/footer.html index 6be90a71..3868a5f3 100644 --- a/templates/footer.html +++ b/templates/footer.html @@ -9,12 +9,12 @@
{{lang "footer_powered_by"}} - {{lang "footer_made_with_love"}}
- {{/**{{if .CurrentUser.IsAdmin}}**/}}
{{.Header.Elapsed1}}
{{elapsed .Header.StartedAt}}
{{/**{{end}}**/}} + {{if .CurrentUser.IsAdmin}}
{{.Header.Elapsed1}}
{{elapsed .Header.StartedAt}}
{{end}}
- +
diff --git a/templates/panel_menu.html b/templates/panel_menu.html index dd39062a..16a84bee 100644 --- a/templates/panel_menu.html +++ b/templates/panel_menu.html @@ -1 +1 @@ - + \ No newline at end of file diff --git a/tickloop.go b/tickloop.go index 955f47f2..40e987a4 100644 --- a/tickloop.go +++ b/tickloop.go @@ -15,8 +15,7 @@ import ( // TODO: Name the tasks so we can figure out which one it was when something goes wrong? Or maybe toss it up WithStack down there? func runTasks(tasks []func() error) { for _, task := range tasks { - err := task() - if err != nil { + if err := task(); err != nil { c.LogError(err) } } @@ -24,8 +23,7 @@ func runTasks(tasks []func() error) { func startTick() (abort bool) { isDBDown := atomic.LoadInt32(&c.IsDBDown) - err := db.Ping() - if err != nil { + if err := db.Ping(); err != nil { // TODO: There's a bit of a race here, but it doesn't matter if this error appears multiple times in the logs as it's capped at three times, we just want to cut it down 99% of the time if isDBDown == 0 { db.SetConnMaxLifetime(time.Second) // Drop all the connections and start over @@ -45,8 +43,7 @@ func startTick() (abort bool) { } func runHook(name string) { - err := c.RunTaskHook(name) - if err != nil { + if err := c.RunTaskHook(name); err != nil { c.LogError(err, "Failed at task '"+name+"'") } } @@ -88,16 +85,14 @@ func tickLoop(thumbChan chan bool) { runTasks(c.ScheduledSecondTasks) // TODO: Stop hard-coding this - err := c.HandleExpiredScheduledGroups() - if err != nil { + if err := c.HandleExpiredScheduledGroups(); err != nil { c.LogError(err) } // TODO: Handle delayed moderation tasks // Sync with the database, if there are any changes - err = c.HandleServerSync() - if err != nil { + if err = c.HandleServerSync(); err != nil { c.LogError(err) } @@ -164,35 +159,30 @@ func dailies() { } if c.Config.LogPruneCutoff > -1 { - _, err := qgen.NewAcc().Delete("login_logs").DateOlderThan("doneAt",c.Config.LogPruneCutoff,"day").Run() - if err != nil { - c.LogError(err) - } - _, err = qgen.NewAcc().Delete("registration_logs").DateOlderThan("doneAt",c.Config.LogPruneCutoff,"day").Run() - if err != nil { - c.LogError(err) + f := func(tbl string) { + _, err := qgen.NewAcc().Delete(tbl).DateOlderThan("doneAt",c.Config.LogPruneCutoff,"day").Run() + if err != nil { + c.LogError(err) + } } + f("login_logs") + f("registration_logs") } if c.Config.PostIPCutoff > -1 { // TODO: Use unixtime to remove this MySQLesque logic? - _, err := qgen.NewAcc().Update("topics").Set("ipaddress = '0'").DateOlderThan("createdAt",c.Config.PostIPCutoff,"day").Where("ipaddress != '0'").Exec() - if err != nil { - c.LogError(err) + f := func(tbl string) { + _, err := qgen.NewAcc().Update(tbl).Set("ipaddress = '0'").DateOlderThan("createdAt",c.Config.PostIPCutoff,"day").Where("ipaddress != '0'").Exec() + if err != nil { + c.LogError(err) + } } + f("topics") + f("replies") + f("users_replies") - _, err = qgen.NewAcc().Update("replies").Set("ipaddress = '0'").DateOlderThan("createdAt",c.Config.PostIPCutoff,"day").Where("ipaddress != '0'").Exec() - if err != nil { - c.LogError(err) - } - // TODO: Find some way of purging the ip data in polls_votes without breaking any anti-cheat measures which might be running... maybe hash it instead? - _, err = qgen.NewAcc().Update("users_replies").Set("ipaddress = '0'").DateOlderThan("createdAt",c.Config.PostIPCutoff,"day").Where("ipaddress != '0'").Exec() - if err != nil { - c.LogError(err) - } - // TODO: lastActiveAt isn't currently set, so we can't rely on this to purge last_ips of users who haven't been on in a while /*_, err = qgen.NewAcc().Update("users").Set("last_ip = '0'").DateOlderThan("lastActiveAt",c.Config.PostIPCutoff,"day").Where("last_ip != '0'").Exec() if err != nil {