From b20e295375a22322ae76779c53277fbcb0a381c5 Mon Sep 17 00:00:00 2001 From: Azareal Date: Sat, 17 Mar 2018 08:16:43 +0000 Subject: [PATCH] Changed the defaultest default theme to Cosora... For now. You need the ViewIPs permission to view IPs on logs now. Added the leftOfNav and rightOfNav docks, more on this soon. Added a max length for topic titles. Added a max length for usernames. Added none as a possible language for the language view counter. We began adding the notice phrases. Fixed a misnamed phrase which was spitting out placeholder text. Localised unknown for the human language phrases. Moved routeForums to routes.ForumList. Moved routeRobotsTxt to routes.RobotsTxt. Started tracking the views for routes.RobotsTxt. Moved routeSitemapXml to routes.SitemapXml. Started tracking the views for routes.SitemapXml. Changed the fallback theme to Cosora. Fixed changing the default theme to Cosora or Tempra Conflux. Removed some redundant type definitions in template init. Return ErrNoTitle instead of ErrNoBody when trying to create a topic with no title. Moved some in-progress routes and helper functions for handling search engine crawlers to routes/api.go --- common/counters/langs.go | 1 + common/phrases.go | 9 ++++ common/routes_common.go | 4 +- common/site.go | 21 ++++++++- common/template_init.go | 22 ++++----- common/themes.go | 74 +++++++++++++++++-------------- common/topic.go | 11 +++++ common/topic_store.go | 7 ++- common/user_store.go | 8 ++++ common/widgets.go | 37 +++++++++++++--- gen_router.go | 28 ++++++++---- langs/english.json | 9 +++- query_gen/main.go | 2 +- query_gen/tables.go | 2 +- router_gen/main.go | 10 ++++- router_gen/routes.go | 2 +- routes.go | 55 ----------------------- routes/account.go | 3 ++ bot_routes.go => routes/api.go | 22 ++++----- routes/forum_list.go | 62 ++++++++++++++++++++++++++ routes/topic.go | 11 +++++ schema/mssql/inserts.sql | 2 +- schema/mysql/inserts.sql | 2 +- template_error.go | 56 ++++++++++++----------- template_forum.go | 56 ++++++++++++----------- template_forums.go | 54 ++++++++++++----------- template_guilds_guild_list.go | 56 ++++++++++++----------- template_ip_search.go | 54 ++++++++++++----------- template_list.go | 81 ++++++++++++++++++---------------- template_login.go | 54 ++++++++++++----------- template_profile.go | 54 ++++++++++++----------- template_register.go | 54 ++++++++++++----------- template_topic.go | 56 ++++++++++++----------- template_topic_alt.go | 54 ++++++++++++----------- template_topics.go | 54 ++++++++++++----------- templates/menu.html | 2 + templates/panel_adminlogs.html | 4 +- templates/panel_modlogs.html | 4 +- 38 files changed, 637 insertions(+), 460 deletions(-) rename bot_routes.go => routes/api.go (90%) create mode 100644 routes/forum_list.go diff --git a/common/counters/langs.go b/common/counters/langs.go index a5312b39..4b07a0bb 100644 --- a/common/counters/langs.go +++ b/common/counters/langs.go @@ -8,6 +8,7 @@ var LangViewCounter *DefaultLangViewCounter var langCodes = []string{ "unknown", + "none", "af", "ar", "az", diff --git a/common/phrases.go b/common/phrases.go index a8530801..ebb73770 100644 --- a/common/phrases.go +++ b/common/phrases.go @@ -46,6 +46,7 @@ type LanguagePack struct { OperatingSystems map[string]string HumanLanguages map[string]string Errors map[string]map[string]string // map[category]map[name]value + NoticePhrases map[string]string PageTitles map[string]string TmplPhrases map[string]string CSSPhrases map[string]string @@ -206,6 +207,14 @@ func GetErrorPhrase(category string, name string) string { return res } +func GetNoticePhrase(name string) string { + res, ok := currentLangPack.Load().(*LanguagePack).NoticePhrases[name] + if !ok { + return getPhrasePlaceholder("notices", name) + } + return res +} + func GetTitlePhrase(name string) string { res, ok := currentLangPack.Load().(*LanguagePack).PageTitles[name] if !ok { diff --git a/common/routes_common.go b/common/routes_common.go index ab1e93f8..50a300cb 100644 --- a/common/routes_common.go +++ b/common/routes_common.go @@ -215,10 +215,10 @@ func userCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars * } if user.IsBanned { - headerVars.NoticeList = append(headerVars.NoticeList, "Your account has been suspended. Some of your permissions may have been revoked.") + headerVars.NoticeList = append(headerVars.NoticeList, GetNoticePhrase("account_banned")) } if user.Loggedin && !user.Active { - headerVars.NoticeList = append(headerVars.NoticeList, "Your account hasn't been activated yet. Some features may remain unavailable until it is.") + headerVars.NoticeList = append(headerVars.NoticeList, GetNoticePhrase("account_inactive")) } if len(theme.Resources) > 0 { diff --git a/common/site.go b/common/site.go index 04f14b0c..a0c91ca2 100644 --- a/common/site.go +++ b/common/site.go @@ -69,8 +69,10 @@ type config struct { MinifyTemplates bool ServerCount int - Noavatar string // ? - Move this into the settings table? - ItemsPerPage int // ? - Move this into the settings table? + Noavatar string // ? - Move this into the settings table? + ItemsPerPage int // ? - Move this into the settings table? + MaxTopicTitleLength int + MaxUsernameLength int } type devConfig struct { @@ -90,6 +92,15 @@ func ProcessConfig() error { Site.URL = strings.TrimSuffix(Site.URL, ":") Site.URL = Site.URL + ":" + Site.Port } + + // ? Find a way of making these unlimited if zero? It might rule out some optimisations, waste memory, and break layouts + if Config.MaxTopicTitleLength == 0 { + Config.MaxTopicTitleLength = 100 + } + if Config.MaxUsernameLength == 0 { + Config.MaxUsernameLength = 100 + } + // We need this in here rather than verifyConfig as switchToTestDB() currently overwrites the values it verifies if DbConfig.TestDbname == DbConfig.Dbname { return errors.New("Your test database can't have the same name as your production database") @@ -107,6 +118,12 @@ func VerifyConfig() error { if Config.ServerCount < 1 { return errors.New("You can't have less than one server") } + if Config.MaxTopicTitleLength > 100 { + return errors.New("The max topic title length cannot be over 100 as that's unable to fit in the database row") + } + if Config.MaxUsernameLength > 100 { + return errors.New("The max username length cannot be over 100 as that's unable to fit in the database row") + } return nil } diff --git a/common/template_init.go b/common/template_init.go index f68f1a9e..e2e59dfa 100644 --- a/common/template_init.go +++ b/common/template_init.go @@ -34,11 +34,11 @@ func interpreted_topic_template(pi TopicPage, w http.ResponseWriter) error { } // nolint -var Template_topic_handle func(TopicPage, http.ResponseWriter) error = interpreted_topic_template -var Template_topic_alt_handle func(TopicPage, http.ResponseWriter) error = interpreted_topic_template +var Template_topic_handle = interpreted_topic_template +var Template_topic_alt_handle = interpreted_topic_template // nolint -var Template_topics_handle func(TopicsPage, http.ResponseWriter) error = func(pi TopicsPage, w http.ResponseWriter) error { +var Template_topics_handle = func(pi TopicsPage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["topics"] if !ok { mapping = "topics" @@ -47,7 +47,7 @@ var Template_topics_handle func(TopicsPage, http.ResponseWriter) error = func(pi } // nolint -var Template_forum_handle func(ForumPage, http.ResponseWriter) error = func(pi ForumPage, w http.ResponseWriter) error { +var Template_forum_handle = func(pi ForumPage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["forum"] if !ok { mapping = "forum" @@ -56,7 +56,7 @@ var Template_forum_handle func(ForumPage, http.ResponseWriter) error = func(pi F } // nolint -var Template_forums_handle func(ForumsPage, http.ResponseWriter) error = func(pi ForumsPage, w http.ResponseWriter) error { +var Template_forums_handle = func(pi ForumsPage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["forums"] if !ok { mapping = "forums" @@ -65,7 +65,7 @@ var Template_forums_handle func(ForumsPage, http.ResponseWriter) error = func(pi } // nolint -var Template_profile_handle func(ProfilePage, http.ResponseWriter) error = func(pi ProfilePage, w http.ResponseWriter) error { +var Template_profile_handle = func(pi ProfilePage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["profile"] if !ok { mapping = "profile" @@ -74,7 +74,7 @@ var Template_profile_handle func(ProfilePage, http.ResponseWriter) error = func( } // nolint -var Template_create_topic_handle func(CreateTopicPage, http.ResponseWriter) error = func(pi CreateTopicPage, w http.ResponseWriter) error { +var Template_create_topic_handle = func(pi CreateTopicPage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["create_topic"] if !ok { mapping = "create_topic" @@ -83,7 +83,7 @@ var Template_create_topic_handle func(CreateTopicPage, http.ResponseWriter) erro } // nolint -var Template_login_handle func(Page, http.ResponseWriter) error = func(pi Page, w http.ResponseWriter) error { +var Template_login_handle = func(pi Page, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["login"] if !ok { mapping = "login" @@ -92,7 +92,7 @@ var Template_login_handle func(Page, http.ResponseWriter) error = func(pi Page, } // nolint -var Template_register_handle func(Page, http.ResponseWriter) error = func(pi Page, w http.ResponseWriter) error { +var Template_register_handle = func(pi Page, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["register"] if !ok { mapping = "register" @@ -101,7 +101,7 @@ var Template_register_handle func(Page, http.ResponseWriter) error = func(pi Pag } // nolint -var Template_error_handle func(Page, http.ResponseWriter) error = func(pi Page, w http.ResponseWriter) error { +var Template_error_handle = func(pi Page, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["error"] if !ok { mapping = "error" @@ -110,7 +110,7 @@ var Template_error_handle func(Page, http.ResponseWriter) error = func(pi Page, } // nolint -var Template_ip_search_handle func(IPSearchPage, http.ResponseWriter) error = func(pi IPSearchPage, w http.ResponseWriter) error { +var Template_ip_search_handle = func(pi IPSearchPage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["ip_search"] if !ok { mapping = "ip_search" diff --git a/common/themes.go b/common/themes.go index 4cf34d83..dfb715a1 100644 --- a/common/themes.go +++ b/common/themes.go @@ -29,7 +29,7 @@ var DefaultThemeBox atomic.Value var ChangeDefaultThemeMutex sync.Mutex // TODO: Use this when the default theme doesn't exist -var fallbackTheme = "shadow" +var fallbackTheme = "cosora" var overridenTemplates = make(map[string]bool) type Theme struct { @@ -270,72 +270,72 @@ func (theme *Theme) MapTemplates() { } switch dTmplPtr := destTmplPtr.(type) { - case *func(TopicPage, http.ResponseWriter): + case *func(TopicPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(TopicPage, http.ResponseWriter): + case *func(TopicPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(TopicsPage, http.ResponseWriter): + case *func(TopicsPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(TopicsPage, http.ResponseWriter): + case *func(TopicsPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(ForumPage, http.ResponseWriter): + case *func(ForumPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(ForumPage, http.ResponseWriter): + case *func(ForumPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(ForumsPage, http.ResponseWriter): + case *func(ForumsPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(ForumsPage, http.ResponseWriter): + case *func(ForumsPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(ProfilePage, http.ResponseWriter): + case *func(ProfilePage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(ProfilePage, http.ResponseWriter): + case *func(ProfilePage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(CreateTopicPage, http.ResponseWriter): + case *func(CreateTopicPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(CreateTopicPage, http.ResponseWriter): + case *func(CreateTopicPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(IPSearchPage, http.ResponseWriter): + case *func(IPSearchPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(IPSearchPage, http.ResponseWriter): + case *func(IPSearchPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(Page, http.ResponseWriter): + case *func(Page, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(Page, http.ResponseWriter): + case *func(Page, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr @@ -343,6 +343,8 @@ func (theme *Theme) MapTemplates() { LogError(errors.New("The source and destination templates are incompatible")) } default: + log.Print("themeTmpl.Name: ", themeTmpl.Name) + log.Print("themeTmpl.Source: ", themeTmpl.Source) LogError(errors.New("Unknown destination template type!")) } } @@ -369,63 +371,64 @@ func ResetTemplateOverrides() { // Not really a pointer, more of a function handle, an artifact from one of the earlier versions of themes.go switch oPtr := originPointer.(type) { - case func(TopicPage, http.ResponseWriter): + case func(TopicPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(TopicPage, http.ResponseWriter): + case *func(TopicPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(TopicsPage, http.ResponseWriter): + case func(TopicsPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(TopicsPage, http.ResponseWriter): + case *func(TopicsPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(ForumPage, http.ResponseWriter): + case func(ForumPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(ForumPage, http.ResponseWriter): + case *func(ForumPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(ForumsPage, http.ResponseWriter): + case func(ForumsPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(ForumsPage, http.ResponseWriter): + case *func(ForumsPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(ProfilePage, http.ResponseWriter): + case func(ProfilePage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(ProfilePage, http.ResponseWriter): + case *func(ProfilePage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(CreateTopicPage, http.ResponseWriter): + case func(CreateTopicPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(CreateTopicPage, http.ResponseWriter): + case *func(CreateTopicPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(IPSearchPage, http.ResponseWriter): + case func(IPSearchPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(IPSearchPage, http.ResponseWriter): + case *func(IPSearchPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(Page, http.ResponseWriter): + case func(Page, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(Page, http.ResponseWriter): + case *func(Page, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } default: + log.Print("name: ", name) LogError(errors.New("Unknown destination template type!")) } log.Print("The template override was reset") @@ -546,3 +549,8 @@ func (theme Theme) HasDock(name string) bool { } return false } + +// TODO: Implement this +func (theme Theme) BuildDock(dock string) (sbody string) { + return "" +} diff --git a/common/topic.go b/common/topic.go index 0c2cc14f..d2c7bf97 100644 --- a/common/topic.go +++ b/common/topic.go @@ -254,6 +254,17 @@ func (topic *Topic) Delete() error { // TODO: Write tests for this func (topic *Topic) Update(name string, content string) error { name = html.EscapeString(strings.Replace(html.UnescapeString(name), "\n", "", -1)) + + // TODO: Stop duplicating this logic? + name = strings.TrimSpace(name) + if name == "" { + return ErrNoTitle + } + // ? This number might be a little screwy with Unicode, but it's the only consistent thing we have, as Unicode characters can be any number of bytes in theory? + if len(name) > Config.MaxTopicTitleLength { + return ErrLongTitle + } + content = PreparseMessage(html.UnescapeString(content)) parsedContent := ParseMessage(content, topic.ParentID, "forums") _, err := topicStmts.edit.Exec(name, content, parsedContent, topic.ID) diff --git a/common/topic_store.go b/common/topic_store.go index 128f5101..b1bbf5e4 100644 --- a/common/topic_store.go +++ b/common/topic_store.go @@ -20,6 +20,7 @@ import ( // ? - Should we add stick, lock, unstick, and unlock methods? These might be better on the Topics not the TopicStore var Topics TopicStore var ErrNoTitle = errors.New("This message is missing a title") +var ErrLongTitle = errors.New("The title is too long") var ErrNoBody = errors.New("This message is missing a body") type TopicStore interface { @@ -122,7 +123,11 @@ func (mts *DefaultTopicStore) Exists(id int) bool { func (mts *DefaultTopicStore) Create(fid int, topicName string, content string, uid int, ipaddress string) (tid int, err error) { topicName = strings.TrimSpace(topicName) if topicName == "" { - return 0, ErrNoBody + return 0, ErrNoTitle + } + // ? This number might be a little screwy with Unicode, but it's the only consistent thing we have, as Unicode characters can be any number of bytes in theory? + if len(topicName) > Config.MaxTopicTitleLength { + return 0, ErrLongTitle } content = strings.TrimSpace(content) diff --git a/common/user_store.go b/common/user_store.go index da6c8ddf..e8bd6667 100644 --- a/common/user_store.go +++ b/common/user_store.go @@ -14,6 +14,7 @@ import ( // TODO: Add some sort of update method var Users UserStore var ErrAccountExists = errors.New("this username is already in use") +var ErrLongUsername = errors.New("this username is too long") type UserStore interface { DirtyGet(id int) *User @@ -203,6 +204,13 @@ func (mus *DefaultUserStore) Exists(id int) bool { // TODO: Change active to a bool? func (mus *DefaultUserStore) Create(username string, password string, email string, group int, active bool) (int, error) { + // TODO: Strip spaces? + + // ? This number might be a little screwy with Unicode, but it's the only consistent thing we have, as Unicode characters can be any number of bytes in theory? + if len(username) > Config.MaxUsernameLength { + return 0, ErrLongUsername + } + // Is this username already taken..? err := mus.usernameExists.QueryRow(username).Scan(&username) if err != ErrNoRows { diff --git a/common/widgets.go b/common/widgets.go index 8e547d6a..c3ab3d79 100644 --- a/common/widgets.go +++ b/common/widgets.go @@ -16,6 +16,8 @@ var Docks WidgetDocks var widgetUpdateMutex sync.RWMutex type WidgetDocks struct { + LeftOfNav []*Widget + RightOfNav []*Widget LeftSidebar []*Widget RightSidebar []*Widget //PanelLeft []Menus @@ -120,7 +122,18 @@ func BuildWidget(dock string, headerVars *HeaderVars) (sbody string) { if !headerVars.Theme.HasDock(dock) { return "" } + + // Let themes forcibly override this slot + sbody = headerVars.Theme.BuildDock(dock) + if sbody != "" { + return sbody + } + switch dock { + case "leftOfNav": + widgets = Docks.LeftOfNav + case "rightOfNav": + widgets = Docks.RightOfNav case "rightSidebar": widgets = Docks.RightSidebar case "footer": @@ -178,8 +191,10 @@ func InitWidgets() error { defer rows.Close() var data string - var leftWidgets []*Widget - var rightWidgets []*Widget + var leftOfNavWidgets []*Widget + var rightOfNavWidgets []*Widget + var leftSidebarWidgets []*Widget + var rightSidebarWidgets []*Widget var footerWidgets []*Widget for rows.Next() { @@ -195,10 +210,14 @@ func InitWidgets() error { } switch widget.Side { + case "leftOfNav": + leftOfNavWidgets = append(leftOfNavWidgets, widget) + case "rightOfNav": + rightOfNavWidgets = append(rightOfNavWidgets, widget) case "left": - leftWidgets = append(leftWidgets, widget) + leftSidebarWidgets = append(leftSidebarWidgets, widget) case "right": - rightWidgets = append(rightWidgets, widget) + rightSidebarWidgets = append(rightSidebarWidgets, widget) case "footer": footerWidgets = append(footerWidgets, widget) } @@ -208,12 +227,18 @@ func InitWidgets() error { return err } + // TODO: Let themes set default values for widget docks, and let them lock in particular places with their stuff, e.g. leftOfNav and rightOfNav + widgetUpdateMutex.Lock() - Docks.LeftSidebar = leftWidgets - Docks.RightSidebar = rightWidgets + Docks.LeftOfNav = leftOfNavWidgets + Docks.RightOfNav = rightOfNavWidgets + Docks.LeftSidebar = leftSidebarWidgets + Docks.RightSidebar = rightSidebarWidgets Docks.Footer = footerWidgets widgetUpdateMutex.Unlock() + DebugLog("Docks.LeftOfNav", Docks.LeftOfNav) + DebugLog("Docks.RightOfNav", Docks.RightOfNav) DebugLog("Docks.LeftSidebar", Docks.LeftSidebar) DebugLog("Docks.RightSidebar", Docks.RightSidebar) DebugLog("Docks.Footer", Docks.Footer) diff --git a/gen_router.go b/gen_router.go index 255ec9f5..2c55e642 100644 --- a/gen_router.go +++ b/gen_router.go @@ -21,7 +21,7 @@ var RouteMap = map[string]interface{}{ "routeAPI": routeAPI, "routes.Overview": routes.Overview, "routes.CustomPage": routes.CustomPage, - "routeForums": routeForums, + "routes.ForumList": routes.ForumList, "routes.ViewForum": routes.ViewForum, "routeChangeTheme": routeChangeTheme, "routeShowAttachment": routeShowAttachment, @@ -120,6 +120,8 @@ var RouteMap = map[string]interface{}{ "routeDynamic": routeDynamic, "routeUploads": routeUploads, "routes.StaticFile": routes.StaticFile, + "routes.RobotsTxt": routes.RobotsTxt, + "routes.SitemapXml": routes.SitemapXml, "BadRoute": BadRoute, } @@ -128,7 +130,7 @@ var routeMapEnum = map[string]int{ "routeAPI": 0, "routes.Overview": 1, "routes.CustomPage": 2, - "routeForums": 3, + "routes.ForumList": 3, "routes.ViewForum": 4, "routeChangeTheme": 5, "routeShowAttachment": 6, @@ -227,13 +229,15 @@ var routeMapEnum = map[string]int{ "routeDynamic": 99, "routeUploads": 100, "routes.StaticFile": 101, - "BadRoute": 102, + "routes.RobotsTxt": 102, + "routes.SitemapXml": 103, + "BadRoute": 104, } var reverseRouteMapEnum = map[int]string{ 0: "routeAPI", 1: "routes.Overview", 2: "routes.CustomPage", - 3: "routeForums", + 3: "routes.ForumList", 4: "routes.ViewForum", 5: "routeChangeTheme", 6: "routeShowAttachment", @@ -332,7 +336,9 @@ var reverseRouteMapEnum = map[int]string{ 99: "routeDynamic", 100: "routeUploads", 101: "routes.StaticFile", - 102: "BadRoute", + 102: "routes.RobotsTxt", + 103: "routes.SitemapXml", + 104: "BadRoute", } var osMapEnum = map[string]int{ "unknown": 0, @@ -723,6 +729,8 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { lLang := strings.Split(lang,"-") common.DebugDetail("lLang:", lLang) counters.LangViewCounter.Bump(lLang[0]) + } else { + counters.LangViewCounter.Bump("none") } referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P @@ -768,7 +776,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { } case "/forums": counters.RouteViewCounter.Bump(3) - err = routeForums(w,req,user) + err = routes.ForumList(w,req,user) if err != nil { router.handleError(err,w,req,user) } @@ -1726,13 +1734,15 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { // TODO: Add support for favicons and robots.txt files switch(extraData) { case "robots.txt": - err = routeRobotsTxt(w,req) // TODO: Count these views + counters.RouteViewCounter.Bump(102) + err = routes.RobotsTxt(w,req) if err != nil { router.handleError(err,w,req,user) } return /*case "sitemap.xml": - err = routeSitemapXml(w,req) // TODO: Count these views + counters.RouteViewCounter.Bump(103) + err = routes.SitemapXml(w,req) if err != nil { router.handleError(err,w,req,user) } @@ -1774,7 +1784,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { if strings.Contains(lowerPath,"admin") || strings.Contains(lowerPath,"sql") || strings.Contains(lowerPath,"manage") || strings.Contains(lowerPath,"//") || strings.Contains(lowerPath,"\\\\") || strings.Contains(lowerPath,"wp") || strings.Contains(lowerPath,"wordpress") || strings.Contains(lowerPath,"config") || strings.Contains(lowerPath,"setup") || strings.Contains(lowerPath,"install") || strings.Contains(lowerPath,"update") || strings.Contains(lowerPath,"php") { router.SuspiciousRequest(req) } - counters.RouteViewCounter.Bump(102) + counters.RouteViewCounter.Bump(104) common.NotFound(w,req,nil) } } diff --git a/langs/english.json b/langs/english.json index 587b5660..500a15f9 100644 --- a/langs/english.json +++ b/langs/english.json @@ -143,6 +143,8 @@ }, "HumanLanguages": { + "unknown":"Unknown", + "none":"None", "af":"Afrikaans", "ar":"Arabic", "az":"Azeri (Latin)", @@ -227,6 +229,11 @@ "zu":"Zulu" }, + "NoticePhrases": { + "account_banned":"Your account has been suspended. Some of your permissions may have been revoked.", + "account_inactive":"Your account hasn't been activated yet. Some features may remain unavailable until it is." + }, + "TmplPhrases": { "menu_forums_tooltip":"Forum List", "menu_forums_aria":"The Forum list", @@ -304,7 +311,7 @@ "quick_topic_avatar_tooltip":"Your Avatar", "quick_topic_avatar_alt":"Your Avatar", "quick_topic_whatsup":"What's up?", - "quick_topic_placeholder":"Insert post here", + "quick_topic_content_placeholder":"Insert post here", "quick_topic_add_poll_option":"Add new poll option", "quick_topic_create_topic_button":"Create Topic", "quick_topic_add_poll_button":"Add Poll", diff --git a/query_gen/main.go b/query_gen/main.go index 2bcd3dab..aa61a1f5 100644 --- a/query_gen/main.go +++ b/query_gen/main.go @@ -116,7 +116,7 @@ func seedTables(adapter qgen.Adapter) error { qgen.Install.SimpleInsert("settings", "name, content, type", "'bigpost_min_words','250','int'") qgen.Install.SimpleInsert("settings", "name, content, type", "'megapost_min_words','1000','int'") qgen.Install.SimpleInsert("settings", "name, content, type", "'meta_desc','','html-attribute'") - qgen.Install.SimpleInsert("themes", "uname, default", "'tempra-simple',1") + qgen.Install.SimpleInsert("themes", "uname, default", "'cosora',1") qgen.Install.SimpleInsert("emails", "email, uid, validated", "'admin@localhost',1,1") // ? - Use a different default email or let the admin input it during installation? /* diff --git a/query_gen/tables.go b/query_gen/tables.go index 756377f7..03c56411 100644 --- a/query_gen/tables.go +++ b/query_gen/tables.go @@ -147,7 +147,7 @@ func createTables(adapter qgen.Adapter) error { qgen.Install.CreateTable("topics", "utf8mb4", "utf8mb4_general_ci", []qgen.DBTableColumn{ qgen.DBTableColumn{"tid", "int", 0, false, true, ""}, - qgen.DBTableColumn{"title", "varchar", 100, false, false, ""}, + qgen.DBTableColumn{"title", "varchar", 100, false, false, ""}, // TODO: Increase the max length to 200? qgen.DBTableColumn{"content", "text", 0, false, false, ""}, qgen.DBTableColumn{"parsed_content", "text", 0, false, false, ""}, qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""}, diff --git a/router_gen/main.go b/router_gen/main.go index 8653c52b..90bdf001 100644 --- a/router_gen/main.go +++ b/router_gen/main.go @@ -158,6 +158,8 @@ func main() { mapIt("routeDynamic") mapIt("routeUploads") mapIt("routes.StaticFile") + mapIt("routes.RobotsTxt") + mapIt("routes.SitemapXml") mapIt("BadRoute") tmplVars.AllRouteNames = allRouteNames tmplVars.AllRouteMap = allRouteMap @@ -567,6 +569,8 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { lLang := strings.Split(lang,"-") common.DebugDetail("lLang:", lLang) counters.LangViewCounter.Bump(lLang[0]) + } else { + counters.LangViewCounter.Bump("none") } referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P @@ -612,13 +616,15 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { // TODO: Add support for favicons and robots.txt files switch(extraData) { case "robots.txt": - err = routeRobotsTxt(w,req) // TODO: Count these views + counters.RouteViewCounter.Bump({{index .AllRouteMap "routes.RobotsTxt"}}) + err = routes.RobotsTxt(w,req) if err != nil { router.handleError(err,w,req,user) } return /*case "sitemap.xml": - err = routeSitemapXml(w,req) // TODO: Count these views + counters.RouteViewCounter.Bump({{index .AllRouteMap "routes.SitemapXml"}}) + err = routes.SitemapXml(w,req) if err != nil { router.handleError(err,w,req,user) } diff --git a/router_gen/routes.go b/router_gen/routes.go index d53b8c40..f33021ff 100644 --- a/router_gen/routes.go +++ b/router_gen/routes.go @@ -5,7 +5,7 @@ func routes() { addRoute(View("routeAPI", "/api/")) addRoute(View("routes.Overview", "/overview/")) addRoute(View("routes.CustomPage", "/pages/", "extraData")) - addRoute(View("routeForums", "/forums/" /*,"&forums"*/)) + addRoute(View("routes.ForumList", "/forums/" /*,"&forums"*/)) addRoute(View("routes.ViewForum", "/forum/", "extraData")) addRoute(AnonAction("routeChangeTheme", "/theme/")) addRoute( diff --git a/routes.go b/routes.go index 4befe734..d3b7a0d6 100644 --- a/routes.go +++ b/routes.go @@ -8,7 +8,6 @@ package main import ( "html" - "log" "net/http" "strconv" @@ -42,60 +41,6 @@ func routeUploads() { func BadRoute() { } -func routeForums(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { - headerVars, ferr := common.UserCheck(w, r, &user) - if ferr != nil { - return ferr - } - headerVars.Zone = "forums" - headerVars.MetaDesc = headerVars.Settings["meta_desc"].(string) - - var err error - var forumList []common.Forum - var canSee []int - if user.IsSuperAdmin { - canSee, err = common.Forums.GetAllVisibleIDs() - if err != nil { - return common.InternalError(err, w, r) - } - } else { - group, err := common.Groups.Get(user.Group) - if err != nil { - log.Printf("Group #%d doesn't exist despite being used by common.User #%d", user.Group, user.ID) - return common.LocalError("Something weird happened", w, r, user) - } - canSee = group.CanSee - } - - 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 = common.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 = common.RelativeTime(forum.LastTopic.LastReplyAt) - } else { - forum.LastTopicTime = "" - } - } else { - forum.LastTopicTime = "" - } - common.RunHook("forums_frow_assign", &forum) - forumList = append(forumList, forum) - } - } - - pi := common.ForumsPage{common.GetTitlePhrase("forums"), user, headerVars, forumList} - if common.RunPreRenderHook("pre_render_forum_list", w, r, &user, &pi) { - return nil - } - err = common.RunThemeTemplate(headerVars.Theme.Name, "forums", pi, w) - if err != nil { - return common.InternalError(err, w, r) - } - return nil -} - // TODO: Set the cookie domain func routeChangeTheme(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { //headerLite, _ := SimpleUserCheck(w, r, &user) diff --git a/routes/account.go b/routes/account.go index db4504b6..79f649f1 100644 --- a/routes/account.go +++ b/routes/account.go @@ -4,6 +4,7 @@ import ( "html" "log" "net/http" + "strconv" "strings" "../common" @@ -140,6 +141,8 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.U uid, err := common.Users.Create(username, password, email, group, active) if err == common.ErrAccountExists { return common.LocalError("This username isn't available. Try another.", w, r, user) + } else if err == common.ErrLongUsername { + return common.LocalError("The username is too long, max: "+strconv.Itoa(common.Config.MaxUsernameLength), w, r, user) } else if err != nil { return common.InternalError(err, w, r) } diff --git a/bot_routes.go b/routes/api.go similarity index 90% rename from bot_routes.go rename to routes/api.go index c747fe90..7f8f4dd8 100644 --- a/bot_routes.go +++ b/routes/api.go @@ -1,4 +1,4 @@ -package main +package routes import ( "errors" @@ -6,12 +6,12 @@ import ( "strconv" "strings" - "./common" + "../common" ) // TODO: Make this a static file somehow? Is it possible for us to put this file somewhere else? // TODO: Add an API so that plugins can register disallowed areas. E.g. /guilds/join for plugin_guilds -func routeRobotsTxt(w http.ResponseWriter, r *http.Request) common.RouteError { +func RobotsTxt(w http.ResponseWriter, r *http.Request) common.RouteError { // TODO: Do we have to put * or something at the end of the paths? _, _ = w.Write([]byte(`User-agent: * Disallow: /panel/* @@ -31,7 +31,7 @@ func writeXMLHeader(w http.ResponseWriter, r *http.Request) { } // TODO: Keep track of when a sitemap was last modifed and add a lastmod element for it -func routeSitemapXml(w http.ResponseWriter, r *http.Request) common.RouteError { +func SitemapXml(w http.ResponseWriter, r *http.Request) common.RouteError { var sslBit string if common.Site.EnableSsl { sslBit = "s" @@ -61,13 +61,13 @@ type FuzzyRoute struct { // TODO: ^-- Make sure that the API is concurrent // TODO: Add a social group sitemap var sitemapRoutes = map[string]func(http.ResponseWriter, *http.Request) common.RouteError{ - "forums.xml": routeSitemapForums, - "topics.xml": routeSitemapTopics, + "forums.xml": SitemapForums, + "topics.xml": SitemapTopics, } // TODO: Use a router capable of parsing this rather than hard-coding the logic in var fuzzySitemapRoutes = map[string]FuzzyRoute{ - "topics_page_": FuzzyRoute{"topics_page_(%d).xml", routeSitemapTopic}, + "topics_page_": FuzzyRoute{"topics_page_(%d).xml", SitemapTopic}, } func sitemapSwitch(w http.ResponseWriter, r *http.Request) common.RouteError { @@ -93,7 +93,7 @@ func sitemapSwitch(w http.ResponseWriter, r *http.Request) common.RouteError { return route(w, r) } -func routeSitemapForums(w http.ResponseWriter, r *http.Request) common.RouteError { +func SitemapForums(w http.ResponseWriter, r *http.Request) common.RouteError { var sslBit string if common.Site.EnableSsl { sslBit = "s" @@ -127,7 +127,7 @@ func routeSitemapForums(w http.ResponseWriter, r *http.Request) common.RouteErro // TODO: Add a global ratelimit. 10 50MB files (smaller if compressed better) per minute? // ? We might have problems with banned users, if they have fewer ViewTopic permissions than guests as they'll be able to see this list. Then again, a banned user could just logout to see it -func routeSitemapTopics(w http.ResponseWriter, r *http.Request) common.RouteError { +func SitemapTopics(w http.ResponseWriter, r *http.Request) common.RouteError { var sslBit string if common.Site.EnableSsl { sslBit = "s" @@ -169,7 +169,7 @@ func routeSitemapTopics(w http.ResponseWriter, r *http.Request) common.RouteErro return nil } -func routeSitemapTopic(w http.ResponseWriter, r *http.Request, page int) common.RouteError { +func SitemapTopic(w http.ResponseWriter, r *http.Request, page int) common.RouteError { /*var sslBit string if common.Site.EnableSsl { sslBit = "s" @@ -215,7 +215,7 @@ func routeSitemapTopic(w http.ResponseWriter, r *http.Request, page int) common. return nil } -func routeSitemapUsers(w http.ResponseWriter, r *http.Request) common.RouteError { +func SitemapUsers(w http.ResponseWriter, r *http.Request) common.RouteError { writeXMLHeader(w, r) w.Write([]byte("\n")) return nil diff --git a/routes/forum_list.go b/routes/forum_list.go new file mode 100644 index 00000000..000fc10a --- /dev/null +++ b/routes/forum_list.go @@ -0,0 +1,62 @@ +package routes + +import ( + "log" + "net/http" + + "../common" +) + +func ForumList(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { + headerVars, ferr := common.UserCheck(w, r, &user) + if ferr != nil { + return ferr + } + headerVars.Zone = "forums" + headerVars.MetaDesc = headerVars.Settings["meta_desc"].(string) + + var err error + var forumList []common.Forum + var canSee []int + if user.IsSuperAdmin { + canSee, err = common.Forums.GetAllVisibleIDs() + if err != nil { + return common.InternalError(err, w, r) + } + } else { + group, err := common.Groups.Get(user.Group) + if err != nil { + log.Printf("Group #%d doesn't exist despite being used by common.User #%d", user.Group, user.ID) + return common.LocalError("Something weird happened", w, r, user) + } + canSee = group.CanSee + } + + 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 = common.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 = common.RelativeTime(forum.LastTopic.LastReplyAt) + } else { + forum.LastTopicTime = "" + } + } else { + forum.LastTopicTime = "" + } + common.RunHook("forums_frow_assign", &forum) + forumList = append(forumList, forum) + } + } + + pi := common.ForumsPage{common.GetTitlePhrase("forums"), user, headerVars, forumList} + if common.RunPreRenderHook("pre_render_forum_list", w, r, &user, &pi) { + return nil + } + err = common.RunThemeTemplate(headerVars.Theme.Name, "forums", pi, w) + if err != nil { + return common.InternalError(err, w, r) + } + return nil +} diff --git a/routes/topic.go b/routes/topic.go index 73ab9701..767eb610 100644 --- a/routes/topic.go +++ b/routes/topic.go @@ -304,6 +304,8 @@ func CreateTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User) return common.LocalError("Something went wrong, perhaps the forum got deleted?", w, r, user) case common.ErrNoTitle: return common.LocalError("This topic doesn't have a title", w, r, user) + case common.ErrLongTitle: + return common.LocalError("The length of the title is too long, max: "+strconv.Itoa(common.Config.MaxTopicTitleLength), w, r, user) case common.ErrNoBody: return common.LocalError("This topic doesn't have a body", w, r, user) } @@ -469,7 +471,16 @@ func EditTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, s } err = topic.Update(r.PostFormValue("topic_name"), r.PostFormValue("topic_content")) + // TODO: Avoid duplicating this across this route and the topic creation route if err != nil { + switch err { + case common.ErrNoTitle: + return common.LocalErrorJSQ("This topic doesn't have a title", w, r, user, isJs) + case common.ErrLongTitle: + return common.LocalErrorJSQ("The length of the title is too long, max: "+strconv.Itoa(common.Config.MaxTopicTitleLength), w, r, user, isJs) + case common.ErrNoBody: + return common.LocalErrorJSQ("This topic doesn't have a body", w, r, user, isJs) + } return common.InternalErrorJSQ(err, w, r, isJs) } diff --git a/schema/mssql/inserts.sql b/schema/mssql/inserts.sql index 9810fde0..f35b8ee8 100644 --- a/schema/mssql/inserts.sql +++ b/schema/mssql/inserts.sql @@ -4,7 +4,7 @@ INSERT INTO [settings] ([name],[content],[type],[constraints]) VALUES ('activati INSERT INTO [settings] ([name],[content],[type]) VALUES ('bigpost_min_words','250','int'); INSERT INTO [settings] ([name],[content],[type]) VALUES ('megapost_min_words','1000','int'); INSERT INTO [settings] ([name],[content],[type]) VALUES ('meta_desc','','html-attribute'); -INSERT INTO [themes] ([uname],[default]) VALUES ('tempra-simple',1); +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,"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,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,'Mod'); diff --git a/schema/mysql/inserts.sql b/schema/mysql/inserts.sql index c3c0cb5d..6c1e0467 100644 --- a/schema/mysql/inserts.sql +++ b/schema/mysql/inserts.sql @@ -4,7 +4,7 @@ INSERT INTO `settings`(`name`,`content`,`type`,`constraints`) VALUES ('activatio INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('bigpost_min_words','250','int'); INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('megapost_min_words','1000','int'); INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('meta_desc','','html-attribute'); -INSERT INTO `themes`(`uname`,`default`) VALUES ('tempra-simple',1); +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,"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,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,'Mod'); diff --git a/template_error.go b/template_error.go index a8520f38..25f1be35 100644 --- a/template_error.go +++ b/template_error.go @@ -3,8 +3,8 @@ // Code generated by Gosora. More below: /* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ package main -import "./common" import "net/http" +import "./common" var error_tmpl_phrase_id int @@ -82,57 +82,61 @@ w.Write(header_frags[15]) } w.Write(header_frags[16]) w.Write(menu_frags[0]) +w.Write([]byte(common.BuildWidget("leftOfNav",tmpl_error_vars.Header))) w.Write(menu_frags[1]) -w.Write([]byte(tmpl_error_vars.Header.Site.ShortName)) w.Write(menu_frags[2]) -w.Write(phrases[0]) +w.Write([]byte(tmpl_error_vars.Header.Site.ShortName)) w.Write(menu_frags[3]) -w.Write(phrases[1]) +w.Write(phrases[0]) w.Write(menu_frags[4]) -w.Write(phrases[2]) +w.Write(phrases[1]) w.Write(menu_frags[5]) -w.Write(phrases[3]) +w.Write(phrases[2]) w.Write(menu_frags[6]) -w.Write(phrases[4]) +w.Write(phrases[3]) w.Write(menu_frags[7]) -w.Write(phrases[5]) +w.Write(phrases[4]) w.Write(menu_frags[8]) -if tmpl_error_vars.CurrentUser.Loggedin { +w.Write(phrases[5]) w.Write(menu_frags[9]) -w.Write(phrases[6]) +if tmpl_error_vars.CurrentUser.Loggedin { w.Write(menu_frags[10]) -w.Write(phrases[7]) +w.Write(phrases[6]) w.Write(menu_frags[11]) -w.Write([]byte(tmpl_error_vars.CurrentUser.Link)) +w.Write(phrases[7]) w.Write(menu_frags[12]) -w.Write(phrases[8]) +w.Write([]byte(tmpl_error_vars.CurrentUser.Link)) w.Write(menu_frags[13]) -w.Write(phrases[9]) +w.Write(phrases[8]) w.Write(menu_frags[14]) -w.Write(phrases[10]) +w.Write(phrases[9]) w.Write(menu_frags[15]) -w.Write(phrases[11]) +w.Write(phrases[10]) w.Write(menu_frags[16]) -w.Write([]byte(tmpl_error_vars.CurrentUser.Session)) +w.Write(phrases[11]) w.Write(menu_frags[17]) -w.Write(phrases[12]) +w.Write([]byte(tmpl_error_vars.CurrentUser.Session)) w.Write(menu_frags[18]) -w.Write(phrases[13]) +w.Write(phrases[12]) w.Write(menu_frags[19]) -} else { +w.Write(phrases[13]) w.Write(menu_frags[20]) -w.Write(phrases[14]) +} else { w.Write(menu_frags[21]) -w.Write(phrases[15]) +w.Write(phrases[14]) w.Write(menu_frags[22]) -w.Write(phrases[16]) +w.Write(phrases[15]) w.Write(menu_frags[23]) -w.Write(phrases[17]) +w.Write(phrases[16]) w.Write(menu_frags[24]) -} +w.Write(phrases[17]) w.Write(menu_frags[25]) -w.Write(phrases[18]) +} w.Write(menu_frags[26]) +w.Write(phrases[18]) +w.Write(menu_frags[27]) +w.Write([]byte(common.BuildWidget("rightOfNav",tmpl_error_vars.Header))) +w.Write(menu_frags[28]) w.Write(header_frags[17]) if tmpl_error_vars.Header.Widgets.RightSidebar != "" { w.Write(header_frags[18]) diff --git a/template_forum.go b/template_forum.go index 47979f69..8f0dee22 100644 --- a/template_forum.go +++ b/template_forum.go @@ -3,9 +3,9 @@ // Code generated by Gosora. More below: /* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ package main +import "strconv" import "net/http" import "./common" -import "strconv" var forum_tmpl_phrase_id int @@ -115,57 +115,61 @@ w.Write(header_frags[15]) } w.Write(header_frags[16]) w.Write(menu_frags[0]) +w.Write([]byte(common.BuildWidget("leftOfNav",tmpl_forum_vars.Header))) w.Write(menu_frags[1]) -w.Write([]byte(tmpl_forum_vars.Header.Site.ShortName)) w.Write(menu_frags[2]) -w.Write(phrases[0]) +w.Write([]byte(tmpl_forum_vars.Header.Site.ShortName)) w.Write(menu_frags[3]) -w.Write(phrases[1]) +w.Write(phrases[0]) w.Write(menu_frags[4]) -w.Write(phrases[2]) +w.Write(phrases[1]) w.Write(menu_frags[5]) -w.Write(phrases[3]) +w.Write(phrases[2]) w.Write(menu_frags[6]) -w.Write(phrases[4]) +w.Write(phrases[3]) w.Write(menu_frags[7]) -w.Write(phrases[5]) +w.Write(phrases[4]) w.Write(menu_frags[8]) -if tmpl_forum_vars.CurrentUser.Loggedin { +w.Write(phrases[5]) w.Write(menu_frags[9]) -w.Write(phrases[6]) +if tmpl_forum_vars.CurrentUser.Loggedin { w.Write(menu_frags[10]) -w.Write(phrases[7]) +w.Write(phrases[6]) w.Write(menu_frags[11]) -w.Write([]byte(tmpl_forum_vars.CurrentUser.Link)) +w.Write(phrases[7]) w.Write(menu_frags[12]) -w.Write(phrases[8]) +w.Write([]byte(tmpl_forum_vars.CurrentUser.Link)) w.Write(menu_frags[13]) -w.Write(phrases[9]) +w.Write(phrases[8]) w.Write(menu_frags[14]) -w.Write(phrases[10]) +w.Write(phrases[9]) w.Write(menu_frags[15]) -w.Write(phrases[11]) +w.Write(phrases[10]) w.Write(menu_frags[16]) -w.Write([]byte(tmpl_forum_vars.CurrentUser.Session)) +w.Write(phrases[11]) w.Write(menu_frags[17]) -w.Write(phrases[12]) +w.Write([]byte(tmpl_forum_vars.CurrentUser.Session)) w.Write(menu_frags[18]) -w.Write(phrases[13]) +w.Write(phrases[12]) w.Write(menu_frags[19]) -} else { +w.Write(phrases[13]) w.Write(menu_frags[20]) -w.Write(phrases[14]) +} else { w.Write(menu_frags[21]) -w.Write(phrases[15]) +w.Write(phrases[14]) w.Write(menu_frags[22]) -w.Write(phrases[16]) +w.Write(phrases[15]) w.Write(menu_frags[23]) -w.Write(phrases[17]) +w.Write(phrases[16]) w.Write(menu_frags[24]) -} +w.Write(phrases[17]) w.Write(menu_frags[25]) -w.Write(phrases[18]) +} w.Write(menu_frags[26]) +w.Write(phrases[18]) +w.Write(menu_frags[27]) +w.Write([]byte(common.BuildWidget("rightOfNav",tmpl_forum_vars.Header))) +w.Write(menu_frags[28]) w.Write(header_frags[17]) if tmpl_forum_vars.Header.Widgets.RightSidebar != "" { w.Write(header_frags[18]) diff --git a/template_forums.go b/template_forums.go index e7ee7611..929636d6 100644 --- a/template_forums.go +++ b/template_forums.go @@ -85,57 +85,61 @@ w.Write(header_frags[15]) } w.Write(header_frags[16]) w.Write(menu_frags[0]) +w.Write([]byte(common.BuildWidget("leftOfNav",tmpl_forums_vars.Header))) w.Write(menu_frags[1]) -w.Write([]byte(tmpl_forums_vars.Header.Site.ShortName)) w.Write(menu_frags[2]) -w.Write(phrases[0]) +w.Write([]byte(tmpl_forums_vars.Header.Site.ShortName)) w.Write(menu_frags[3]) -w.Write(phrases[1]) +w.Write(phrases[0]) w.Write(menu_frags[4]) -w.Write(phrases[2]) +w.Write(phrases[1]) w.Write(menu_frags[5]) -w.Write(phrases[3]) +w.Write(phrases[2]) w.Write(menu_frags[6]) -w.Write(phrases[4]) +w.Write(phrases[3]) w.Write(menu_frags[7]) -w.Write(phrases[5]) +w.Write(phrases[4]) w.Write(menu_frags[8]) -if tmpl_forums_vars.CurrentUser.Loggedin { +w.Write(phrases[5]) w.Write(menu_frags[9]) -w.Write(phrases[6]) +if tmpl_forums_vars.CurrentUser.Loggedin { w.Write(menu_frags[10]) -w.Write(phrases[7]) +w.Write(phrases[6]) w.Write(menu_frags[11]) -w.Write([]byte(tmpl_forums_vars.CurrentUser.Link)) +w.Write(phrases[7]) w.Write(menu_frags[12]) -w.Write(phrases[8]) +w.Write([]byte(tmpl_forums_vars.CurrentUser.Link)) w.Write(menu_frags[13]) -w.Write(phrases[9]) +w.Write(phrases[8]) w.Write(menu_frags[14]) -w.Write(phrases[10]) +w.Write(phrases[9]) w.Write(menu_frags[15]) -w.Write(phrases[11]) +w.Write(phrases[10]) w.Write(menu_frags[16]) -w.Write([]byte(tmpl_forums_vars.CurrentUser.Session)) +w.Write(phrases[11]) w.Write(menu_frags[17]) -w.Write(phrases[12]) +w.Write([]byte(tmpl_forums_vars.CurrentUser.Session)) w.Write(menu_frags[18]) -w.Write(phrases[13]) +w.Write(phrases[12]) w.Write(menu_frags[19]) -} else { +w.Write(phrases[13]) w.Write(menu_frags[20]) -w.Write(phrases[14]) +} else { w.Write(menu_frags[21]) -w.Write(phrases[15]) +w.Write(phrases[14]) w.Write(menu_frags[22]) -w.Write(phrases[16]) +w.Write(phrases[15]) w.Write(menu_frags[23]) -w.Write(phrases[17]) +w.Write(phrases[16]) w.Write(menu_frags[24]) -} +w.Write(phrases[17]) w.Write(menu_frags[25]) -w.Write(phrases[18]) +} w.Write(menu_frags[26]) +w.Write(phrases[18]) +w.Write(menu_frags[27]) +w.Write([]byte(common.BuildWidget("rightOfNav",tmpl_forums_vars.Header))) +w.Write(menu_frags[28]) w.Write(header_frags[17]) if tmpl_forums_vars.Header.Widgets.RightSidebar != "" { w.Write(header_frags[18]) diff --git a/template_guilds_guild_list.go b/template_guilds_guild_list.go index d943e0a8..826aa01d 100644 --- a/template_guilds_guild_list.go +++ b/template_guilds_guild_list.go @@ -3,10 +3,10 @@ // Code generated by Gosora. More below: /* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ package main +import "strconv" import "net/http" import "./common" import "./extend/guilds/lib" -import "strconv" var guilds_guild_list_tmpl_phrase_id int @@ -80,57 +80,61 @@ w.Write(header_frags[15]) } w.Write(header_frags[16]) w.Write(menu_frags[0]) +w.Write([]byte(common.BuildWidget("leftOfNav",tmpl_guilds_guild_list_vars.Header))) w.Write(menu_frags[1]) -w.Write([]byte(tmpl_guilds_guild_list_vars.Header.Site.ShortName)) w.Write(menu_frags[2]) -w.Write(phrases[0]) +w.Write([]byte(tmpl_guilds_guild_list_vars.Header.Site.ShortName)) w.Write(menu_frags[3]) -w.Write(phrases[1]) +w.Write(phrases[0]) w.Write(menu_frags[4]) -w.Write(phrases[2]) +w.Write(phrases[1]) w.Write(menu_frags[5]) -w.Write(phrases[3]) +w.Write(phrases[2]) w.Write(menu_frags[6]) -w.Write(phrases[4]) +w.Write(phrases[3]) w.Write(menu_frags[7]) -w.Write(phrases[5]) +w.Write(phrases[4]) w.Write(menu_frags[8]) -if tmpl_guilds_guild_list_vars.CurrentUser.Loggedin { +w.Write(phrases[5]) w.Write(menu_frags[9]) -w.Write(phrases[6]) +if tmpl_guilds_guild_list_vars.CurrentUser.Loggedin { w.Write(menu_frags[10]) -w.Write(phrases[7]) +w.Write(phrases[6]) w.Write(menu_frags[11]) -w.Write([]byte(tmpl_guilds_guild_list_vars.CurrentUser.Link)) +w.Write(phrases[7]) w.Write(menu_frags[12]) -w.Write(phrases[8]) +w.Write([]byte(tmpl_guilds_guild_list_vars.CurrentUser.Link)) w.Write(menu_frags[13]) -w.Write(phrases[9]) +w.Write(phrases[8]) w.Write(menu_frags[14]) -w.Write(phrases[10]) +w.Write(phrases[9]) w.Write(menu_frags[15]) -w.Write(phrases[11]) +w.Write(phrases[10]) w.Write(menu_frags[16]) -w.Write([]byte(tmpl_guilds_guild_list_vars.CurrentUser.Session)) +w.Write(phrases[11]) w.Write(menu_frags[17]) -w.Write(phrases[12]) +w.Write([]byte(tmpl_guilds_guild_list_vars.CurrentUser.Session)) w.Write(menu_frags[18]) -w.Write(phrases[13]) +w.Write(phrases[12]) w.Write(menu_frags[19]) -} else { +w.Write(phrases[13]) w.Write(menu_frags[20]) -w.Write(phrases[14]) +} else { w.Write(menu_frags[21]) -w.Write(phrases[15]) +w.Write(phrases[14]) w.Write(menu_frags[22]) -w.Write(phrases[16]) +w.Write(phrases[15]) w.Write(menu_frags[23]) -w.Write(phrases[17]) +w.Write(phrases[16]) w.Write(menu_frags[24]) -} +w.Write(phrases[17]) w.Write(menu_frags[25]) -w.Write(phrases[18]) +} w.Write(menu_frags[26]) +w.Write(phrases[18]) +w.Write(menu_frags[27]) +w.Write([]byte(common.BuildWidget("rightOfNav",tmpl_guilds_guild_list_vars.Header))) +w.Write(menu_frags[28]) w.Write(header_frags[17]) if tmpl_guilds_guild_list_vars.Header.Widgets.RightSidebar != "" { w.Write(header_frags[18]) diff --git a/template_ip_search.go b/template_ip_search.go index c96baad1..09421c71 100644 --- a/template_ip_search.go +++ b/template_ip_search.go @@ -84,57 +84,61 @@ w.Write(header_frags[15]) } w.Write(header_frags[16]) w.Write(menu_frags[0]) +w.Write([]byte(common.BuildWidget("leftOfNav",tmpl_ip_search_vars.Header))) w.Write(menu_frags[1]) -w.Write([]byte(tmpl_ip_search_vars.Header.Site.ShortName)) w.Write(menu_frags[2]) -w.Write(phrases[0]) +w.Write([]byte(tmpl_ip_search_vars.Header.Site.ShortName)) w.Write(menu_frags[3]) -w.Write(phrases[1]) +w.Write(phrases[0]) w.Write(menu_frags[4]) -w.Write(phrases[2]) +w.Write(phrases[1]) w.Write(menu_frags[5]) -w.Write(phrases[3]) +w.Write(phrases[2]) w.Write(menu_frags[6]) -w.Write(phrases[4]) +w.Write(phrases[3]) w.Write(menu_frags[7]) -w.Write(phrases[5]) +w.Write(phrases[4]) w.Write(menu_frags[8]) -if tmpl_ip_search_vars.CurrentUser.Loggedin { +w.Write(phrases[5]) w.Write(menu_frags[9]) -w.Write(phrases[6]) +if tmpl_ip_search_vars.CurrentUser.Loggedin { w.Write(menu_frags[10]) -w.Write(phrases[7]) +w.Write(phrases[6]) w.Write(menu_frags[11]) -w.Write([]byte(tmpl_ip_search_vars.CurrentUser.Link)) +w.Write(phrases[7]) w.Write(menu_frags[12]) -w.Write(phrases[8]) +w.Write([]byte(tmpl_ip_search_vars.CurrentUser.Link)) w.Write(menu_frags[13]) -w.Write(phrases[9]) +w.Write(phrases[8]) w.Write(menu_frags[14]) -w.Write(phrases[10]) +w.Write(phrases[9]) w.Write(menu_frags[15]) -w.Write(phrases[11]) +w.Write(phrases[10]) w.Write(menu_frags[16]) -w.Write([]byte(tmpl_ip_search_vars.CurrentUser.Session)) +w.Write(phrases[11]) w.Write(menu_frags[17]) -w.Write(phrases[12]) +w.Write([]byte(tmpl_ip_search_vars.CurrentUser.Session)) w.Write(menu_frags[18]) -w.Write(phrases[13]) +w.Write(phrases[12]) w.Write(menu_frags[19]) -} else { +w.Write(phrases[13]) w.Write(menu_frags[20]) -w.Write(phrases[14]) +} else { w.Write(menu_frags[21]) -w.Write(phrases[15]) +w.Write(phrases[14]) w.Write(menu_frags[22]) -w.Write(phrases[16]) +w.Write(phrases[15]) w.Write(menu_frags[23]) -w.Write(phrases[17]) +w.Write(phrases[16]) w.Write(menu_frags[24]) -} +w.Write(phrases[17]) w.Write(menu_frags[25]) -w.Write(phrases[18]) +} w.Write(menu_frags[26]) +w.Write(phrases[18]) +w.Write(menu_frags[27]) +w.Write([]byte(common.BuildWidget("rightOfNav",tmpl_ip_search_vars.Header))) +w.Write(menu_frags[28]) w.Write(header_frags[17]) if tmpl_ip_search_vars.Header.Widgets.RightSidebar != "" { w.Write(header_frags[18]) diff --git a/template_list.go b/template_list.go index 20ad4a5c..677c4b6b 100644 --- a/template_list.go +++ b/template_list.go @@ -1,21 +1,21 @@ package main +var ip_search_frags = make([][]byte,18) var header_frags = make([][]byte,24) +var paginator_frags = make([][]byte,16) +var footer_frags = make([][]byte,13) +var register_frags = make([][]byte,9) +var forums_frags = make([][]byte,26) +var topics_frags = make([][]byte,94) +var forum_frags = make([][]byte,87) +var login_frags = make([][]byte,8) +var guilds_guild_list_frags = make([][]byte,10) var topic_alt_frags = make([][]byte,194) var profile_comments_row_frags = make([][]byte,51) var profile_frags = make([][]byte,48) -var forums_frags = make([][]byte,26) -var forum_frags = make([][]byte,87) -var register_frags = make([][]byte,9) -var menu_frags = make([][]byte,28) -var footer_frags = make([][]byte,13) -var paginator_frags = make([][]byte,16) -var topic_frags = make([][]byte,192) -var topics_frags = make([][]byte,94) var error_frags = make([][]byte,4) -var guilds_guild_list_frags = make([][]byte,10) -var login_frags = make([][]byte,8) -var ip_search_frags = make([][]byte,18) +var menu_frags = make([][]byte,30) +var topic_frags = make([][]byte,192) // nolint func init() { @@ -60,61 +60,64 @@ header_frags[15] = []byte(`.supermod_only { display: none !important; }`) header_frags[16] = []byte(`
`) -menu_frags[0] = []byte(`
-`) +
`) +menu_frags[28] = []byte(`
`) header_frags[17] = []byte(`
{{dock "leftOfNav" .Header }}
+
{{dock "rightOfNav" .Header }}
\ No newline at end of file diff --git a/templates/panel_adminlogs.html b/templates/panel_adminlogs.html index 3df32dc8..55c5c220 100644 --- a/templates/panel_adminlogs.html +++ b/templates/panel_adminlogs.html @@ -18,8 +18,8 @@ {{range .Logs}}
- {{.Action}}
- {{.IPAddress}} + {{.Action}} + {{if $.CurrentUser.Perms.ViewIPs}}
{{.IPAddress}}{{end}}
{{.DoneAt}} diff --git a/templates/panel_modlogs.html b/templates/panel_modlogs.html index edfd707f..c67a9433 100644 --- a/templates/panel_modlogs.html +++ b/templates/panel_modlogs.html @@ -18,8 +18,8 @@ {{range .Logs}}
- {{.Action}}
- {{.IPAddress}} + {{.Action}} + {{if $.CurrentUser.Perms.ViewIPs}}
{{.IPAddress}}{{end}}
{{.DoneAt}}