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 {