diff --git a/model/tag.go b/model/tag.go index dba4b05..a5425f4 100644 --- a/model/tag.go +++ b/model/tag.go @@ -2,7 +2,6 @@ package model import ( "errors" - "fmt" "git.aiterp.net/AiteRP/aitestory/server" "git.aiterp.net/gisle/wrouter/generate" @@ -29,6 +28,67 @@ func (tag *Tag) Insert() error { db := server.Main.DB // Validate tag type + if err := tag.Validate(); err != nil { + return err + } + + // Generate an ID if none exists + if tag.ID == "" { + tag.ID = generate.ID() + } + + // Do the thing + _, err := db.Exec("INSERT INTO `tag` (id,type,name,disabled) VALUES (?,?,?,false)", tag.ID, tag.Type, tag.Name) + if err != nil { + return err + } + + return nil +} + +// Update saves the entry for the tag in the database +func (tag *Tag) Update() error { + db := server.Main.DB + + // Validate tag type + if err := tag.Validate(); err != nil { + return err + } + + // Do the thing + _, err := db.Exec("UPDATE `tag` SET type=?,name=? WHERE id=?", tag.Type, tag.Name, tag.ID) + if err != nil { + return err + } + + return nil +} + +// Delete removes a tag from the database +func (tag *Tag) Delete() error { + db := server.Main.DB + + // Do the thing + results, err := db.Exec("DELETE FROM `tag` WHERE id=? LIMIT 1", tag.ID) + if err != nil { + return err + } + + // Count the stuffs that were done things to + affected, err := results.RowsAffected() + if err != nil { + return err + } + if affected == 0 { + return errors.New("tag not found") + } + + return nil +} + +// Validate checks the name and type, and returns an error if they're not valid. It's +// ran by Update and Insert before doing anything +func (tag *Tag) Validate() error { validType := false for _, tagType := range TagTypes { if tagType == tag.Type { @@ -37,26 +97,39 @@ func (tag *Tag) Insert() error { } } if !validType { - return fmt.Errorf("\"%s\" is not a valid tag type", tag.Type) + return errors.New("invalid tag type") } // Validate tag name - if len(tag.Name) == 0 { - return errors.New("Tag name is empty") + if len(tag.Name) == 0 || len(tag.Name) > 64 { + return errors.New("invalid length") } - // Generate an ID if none exists - if tag.ID == "" { - tag.ID = generate.ID() + return nil +} + +// FindTag finds a tag by ID +func FindTag(key string, id string) (*Tag, error) { + db := server.Main.DB + + // Make damn sure that – should this take user data as key – it + // does not open up for a SQL injection attack + if key != "name" && key != "id" { + return nil, errors.New("invalid key") } - // Do the thing - _, err := db.Exec("INSERT INTO `tag` (id,type,name,disabled) VALUES (?,?,?,false)", tag.ID, tag.Type, tag.Name) + rows, err := db.Query("SELECT id,type,name FROM `tag` WHERE "+key+"=? AND disabled=false", id) if err != nil { - return err + return nil, err + } + defer rows.Close() + if !rows.Next() { + return nil, errors.New("not found") } - return nil + tag := new(Tag) + rows.Scan(&tag.ID, &tag.Type, &tag.Name) + return tag, nil } // ListTags finds all the tags, without filter. If it hits @@ -64,12 +137,12 @@ func (tag *Tag) Insert() error { func ListTags() ([]Tag, error) { db := server.Main.DB - // Read from the database rows, err := db.Query("SELECT id,type,name FROM `tag` WHERE disabled=false") if err != nil { return nil, err } defer rows.Close() + results := make([]Tag, 0, 64) for rows.Next() { tag := Tag{} diff --git a/model/tag_test.go b/model/tag_test.go index 8af7966..8a96646 100644 --- a/model/tag_test.go +++ b/model/tag_test.go @@ -12,9 +12,13 @@ func TestTag(t *testing.T) { return } + var testTag *Tag + name := "Te'Eryvi" + id := "" + t.Run("Insert", func(t *testing.T) { tag := Tag{} - tag.Name = "Te'Eryvi" + tag.Name = name tag.Type = "Organization" err := tag.Insert() @@ -22,6 +26,8 @@ func TestTag(t *testing.T) { t.Log("Failed to insert:", err) t.Fail() } + + id = tag.ID }) t.Run("Insert_BadType", func(t *testing.T) { @@ -36,7 +42,7 @@ func TestTag(t *testing.T) { return } - if err.Error() != `"Karakter" is not a valid tag type` { + if err.Error() != `invalid tag type` { t.Log("Wrong error:", err) t.Fail() } @@ -54,7 +60,7 @@ func TestTag(t *testing.T) { return } - if err.Error() != `Tag name is empty` { + if err.Error() != `invalid length` { t.Log("Wrong error:", err) t.Fail() } @@ -75,7 +81,7 @@ func TestTag(t *testing.T) { found := false for _, tag := range tags { - if tag.Name == "Te'Eryvi" { + if tag.Name == name && tag.ID == id { t.Logf("Tag found: %+v", tag) found = true break @@ -86,4 +92,60 @@ func TestTag(t *testing.T) { t.Fail() } }) + + t.Run("FindByID", func(t *testing.T) { + tag, err := FindTag("id", id) + if err != nil { + t.Log("Failed to get tags:", err) + t.Fail() + } + if tag == nil { + t.Log("No tag found") + t.Fail() + return + } + + t.Logf("Tag found: %+v", tag) + + if tag.Name != name || tag.ID != id { + t.Error("Incorrect tag") + t.Fail() + } + + testTag = tag + }) + + t.Run("FindByName", func(t *testing.T) { + tag, err := FindTag("name", name) + if err != nil { + t.Log("Failed to get tags:", err) + t.Fail() + } + if tag == nil { + t.Log("No tag found") + t.Fail() + return + } + + t.Logf("Tag found: %+v", tag) + + if tag.Name != name || tag.ID != id { + t.Error("Incorrect tag") + t.Fail() + } + }) + + t.Run("Delete", func(t *testing.T) { + if testTag == nil { + t.Error("No tag to delete") + t.Fail() + return + } + + err := testTag.Delete() + if err != nil { + t.Error("Delete failed:", err) + t.Fail() + } + }) }