From 85bf3a73db99ecc1b5469606b5dfff21b7efb9b9 Mon Sep 17 00:00:00 2001 From: Gisle Aune Date: Sat, 14 Oct 2017 13:57:17 +0200 Subject: [PATCH] Changed tags to allow same-name taggs with different categories, added tag list --- controllers/listcontroller.go | 46 ++++++++++++++++++++++++++++-- controllers/tagcontroller.go | 34 ++++++++++++++++++++++ main.go | 1 + model/tag.go | 45 +++++++++++++++++++++++++----- view/renderer.go | 1 + view/templates/base/default.tmpl | 2 +- view/templates/index.tmpl | 6 +++- view/templates/page/view.tmpl | 4 +-- view/templates/tags/list.tmpl | 48 ++++++++++++++++++++++++++++++++ viewmodel/taglist.go | 46 ++++++++++++++++++++++++++++++ 10 files changed, 220 insertions(+), 13 deletions(-) create mode 100644 controllers/tagcontroller.go create mode 100644 view/templates/tags/list.tmpl create mode 100644 viewmodel/taglist.go diff --git a/controllers/listcontroller.go b/controllers/listcontroller.go index cc67b94..ad59367 100644 --- a/controllers/listcontroller.go +++ b/controllers/listcontroller.go @@ -52,7 +52,7 @@ func listFiltered(category model.PageCategory) wrouter.FunctionHandlerFunc { vm := viewmodel.PageList{} if tagName != "" { - tag, err := model.FindTag("name", tagName) + tag, err := model.FindTag("name", tagName, "") if err != nil { response.Text(w, 404, err.Error()) return true @@ -79,11 +79,53 @@ func listFiltered(category model.PageCategory) wrouter.FunctionHandlerFunc { } } +func listTagged(tagType string) wrouter.FunctionHandlerFunc { + return func(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool { + var err error + + if req.Method != "GET" || strings.LastIndex(req.URL.Path, "/") >= len(path) { + return false + } + + tagName := strings.Replace(req.URL.Path[len(path):], "_", " ", -1) + + vm := viewmodel.PageList{} + + if tagName == "" { + return false + } + + tag, err := model.FindTag("name", tagName, tagType) + if err != nil { + response.Text(w, 404, err.Error()) + return true + } + + vm.ActiveTag = *tag + vm.Headers, err = model.ListHeadersByTag("", tag) + + vm.Categories = model.PageCategories + vm.Setup(user) + + if err != nil { + response.Text(w, 500, err.Error()) + return true + } + + view.Render(w, "index", 200, vm) + + return true + } +} + func init() { ListController.Function("/", listIndex) - ListController.Function("/", listFiltered(model.PageCategory{Key: ""})) for _, category := range model.PageCategories { ListController.Function(fmt.Sprintf("/%s/", strings.ToLower(category.Plural)), listFiltered(category)) } + + for _, tagType := range model.TagTypes { + ListController.Function(fmt.Sprintf("/%s/", strings.ToLower(tagType)), listTagged(tagType)) + } } diff --git a/controllers/tagcontroller.go b/controllers/tagcontroller.go new file mode 100644 index 0000000..3c68132 --- /dev/null +++ b/controllers/tagcontroller.go @@ -0,0 +1,34 @@ +package controllers + +import ( + "net/http" + + "git.aiterp.net/AiteRP/aitestory/view" + "git.aiterp.net/AiteRP/aitestory/viewmodel" + + "git.aiterp.net/AiteRP/aitestory/model" + "git.aiterp.net/gisle/wrouter" + "git.aiterp.net/gisle/wrouter/auth" +) + +// TagController serves and handles the tag managment pages +var TagController = wrouter.Router{} + +func tagList(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool { + //var err error + if (req.Method != "GET" && req.Method != "POST") || len(req.URL.Path) > len(path) { + return false + } + + tl := viewmodel.TagList{} + tl.Tags, _ = model.ListTags() + tl.Setup(user) + + view.Render(w, "tags/list", 200, tl) + + return true +} + +func init() { + TagController.Function("/", tagList) +} diff --git a/main.go b/main.go index bee08d7..597d0f7 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ func main() { auth.Register(&controllers.WikiAthenticator{}) router.Mount("/user", &controllers.UserController) router.Mount("/page", &controllers.PageController) + router.Mount("/tags", &controllers.TagController) router.Mount("/", &controllers.ListController) router.Static("/ui/", server.Main.Config.Directories.UI) diff --git a/model/tag.go b/model/tag.go index a95dc41..e4e959d 100644 --- a/model/tag.go +++ b/model/tag.go @@ -129,8 +129,9 @@ func (tag Tag) Hook() string { return strings.Replace(tag.Name, " ", "_", -1) } -// FindTag finds a tag by ID -func FindTag(key string, id string) (*Tag, error) { +// FindTag finds a tag by ID. Leave tagtype blank to ignore it. Both key and +// id are checked against their respective lists to prevent SQL injection attacks. +func FindTag(key string, id string, tagType string) (*Tag, error) { db := server.Main.DB // Make damn sure that – should this take user data as key – it @@ -139,7 +140,24 @@ func FindTag(key string, id string) (*Tag, error) { return nil, errors.New("invalid key") } - rows, err := db.Query("SELECT id,type,name FROM `tag` WHERE "+key+"=? AND disabled=false", id) + query := "SELECT id,type,name FROM `tag` WHERE " + key + "=? AND disabled=false" + if tagType != "" { + // Prevent more shenanigans + found := false + for _, existing := range TagTypes { + if existing == tagType { + found = true + break + } + } + if !found { + return nil, errors.New("invalid tag type") + } + + query += fmt.Sprintf(` AND type="%s"`, tagType) + } + + rows, err := db.Query(query, id) if err != nil { return nil, err } @@ -156,7 +174,7 @@ func FindTag(key string, id string) (*Tag, error) { // EnsureTag finds or creates a tag. func EnsureTag(tagType, tagName string) (*Tag, error) { // Try to find it first - tag, err := FindTag("name", tagName) + tag, err := FindTag("name", tagName, tagType) if err != nil && err.Error() != "not found" { // You saw nothing return nil, err } @@ -179,7 +197,15 @@ func EnsureTag(tagType, tagName string) (*Tag, error) { func ListTags() ([]Tag, error) { db := server.Main.DB - rows, err := db.Query("SELECT id,type,name FROM `tag` WHERE disabled=false") + query := ` + SELECT id,type,name,count(pt.page_id) FROM tag + LEFT JOIN page_tag AS pt ON (pt.tag_id = tag.id) + WHERE disabled=false + GROUP BY pt.tag_id + ORDER BY type,name + ` + + rows, err := db.Query(query) if err != nil { return nil, err } @@ -187,9 +213,14 @@ func ListTags() ([]Tag, error) { results := make([]Tag, 0, 64) for rows.Next() { + count := 0 tag := Tag{} - rows.Scan(&tag.ID, &tag.Type, &tag.Name) - results = append(results, tag) + rows.Scan(&tag.ID, &tag.Type, &tag.Name, &count) + + // Let's pretend unused tags don't exist. >_> + if count > 0 { + results = append(results, tag) + } } return results, nil diff --git a/view/renderer.go b/view/renderer.go index 558002a..a0f14cd 100644 --- a/view/renderer.go +++ b/view/renderer.go @@ -83,4 +83,5 @@ func init() { Register("page/edit", "base/default") Register("page/view", "base/default") Register("page/delete", "base/default") + Register("tags/list", "base/default") } diff --git a/view/templates/base/default.tmpl b/view/templates/base/default.tmpl index b585202..10027cb 100644 --- a/view/templates/base/default.tmpl +++ b/view/templates/base/default.tmpl @@ -17,7 +17,7 @@ - + diff --git a/view/templates/index.tmpl b/view/templates/index.tmpl index d3f7b23..f6bfe3e 100644 --- a/view/templates/index.tmpl +++ b/view/templates/index.tmpl @@ -30,7 +30,7 @@ @@ -40,6 +40,10 @@ {{ end }} + + {{ if $.User.LoggedIn }}