diff --git a/migrations/1579998283_create_comments_table.down.sql b/migrations/1579998283_create_comments_table.down.sql new file mode 100644 index 0000000..a528f50 --- /dev/null +++ b/migrations/1579998283_create_comments_table.down.sql @@ -0,0 +1,3 @@ +BEGIN; +DROP TABLE IF EXISTS comments; +COMMIT; diff --git a/migrations/1579998283_create_comments_table.up.sql b/migrations/1579998283_create_comments_table.up.sql new file mode 100644 index 0000000..c81031c --- /dev/null +++ b/migrations/1579998283_create_comments_table.up.sql @@ -0,0 +1,11 @@ +BEGIN; +CREATE TABLE IF NOT EXISTS comments ( + id SERIAL PRIMARY KEY, + parent INTEGER REFERENCES posts (id), + author text REFERENCES users (username), + content text, + time_published timestamp, + modified bool, + last_modified timestamp +); +COMMIT; diff --git a/packages/blog/base.go b/packages/blog/base.go new file mode 100644 index 0000000..e7f6461 --- /dev/null +++ b/packages/blog/base.go @@ -0,0 +1,16 @@ +package blog + +import ( + "database/sql" + "github.com/go-chi/jwtauth" +) + +type ReturnMessage struct { + Message string `json:"msg"` + Error bool `json:"error"` +} + +var ( + DB *sql.DB + TokenAuth *jwtauth.JWTAuth +) diff --git a/packages/blog/comments.go b/packages/blog/comments.go new file mode 100644 index 0000000..f86a78c --- /dev/null +++ b/packages/blog/comments.go @@ -0,0 +1,101 @@ +package blog + +import ( + "database/sql" + "encoding/json" + "fmt" + "github.com/go-chi/chi" + "github.com/go-chi/jwtauth" + "github.com/go-chi/render" + "net/http" + "time" +) + +type Comment struct { + ID int `json:"id",db:"id"` + Parent string `json:"post_id",db:"parent"` + Author string `json:"author",db:"author"` + Content string `json:"content",db:"content"` + TimePublished time.Time `json:"time_published", db:"time_published"` + Modified bool `json:"modified", db:"modified"` + TimeModified time.Time `json:"last_modified", db:"last_modified"` +} + +type Comments []Comments + +func getCommentById(w http.ResponseWriter, r *http.Request) { + returnMessage := ReturnMessage{} + returnMessage.Error = false + id := chi.URLParam(r, "id") + result := DB.QueryRow("SELECT id, parent, author, content, time_published, modified, last_modified FROM comments WHERE id=$1", id) + comment := Comment{} + err := result.Scan(&comment.ID, &comment.Parent, &comment.Author, &comment.Content, &comment.TimePublished, &comment.Modified, &comment.TimeModified) + if err != nil { + returnMessage.Message = "comment not found" + returnMessage.Error = true + w.WriteHeader(http.StatusBadRequest) + render.JSON(w, r, returnMessage) + return + } + w.WriteHeader(http.StatusOK) + render.JSON(w, r, comment) + return +} + +func postComment(w http.ResponseWriter, r *http.Request) { + returnMessage := ReturnMessage{} + returnMessage.Error = false + newComment := &Comment{} + // basic checks + _, claims, _ := jwtauth.FromContext(r.Context()) + + username := claims["username"].(string) + post_id := chi.URLParam(r, "id") + err := json.NewDecoder(r.Body).Decode(newComment) + if err != nil { + returnMessage.Message = "unknown error, try again later" + returnMessage.Error = true + w.WriteHeader(http.StatusBadRequest) + render.JSON(w, r, returnMessage) + return + } + if newComment.Parent == "" { + returnMessage.Message = "title is required" + returnMessage.Error = true + w.WriteHeader(http.StatusBadRequest) + render.JSON(w, r, returnMessage) + return + } + if newComment.Content == "" { + returnMessage.Message = "content is required" + returnMessage.Error = true + w.WriteHeader(http.StatusBadRequest) + render.JSON(w, r, returnMessage) + return + } + c := `INSERT INTO comments (parent, author, content, time_published, modified, last_modified) + VALUES ($1, $2, $3, $4, $5, $6) + RETURNING id` + comment_id := 0 + err = DB.QueryRow(c, post_id, username, newComment.Content, time.Now().UTC(), false, time.Now().UTC()).Scan(&comment_id) + if err != nil { + if err == sql.ErrNoRows { + returnMessage.Message = "something is super broken..." + returnMessage.Error = true + w.WriteHeader(http.StatusInternalServerError) + render.JSON(w, r, returnMessage) + fmt.Println(err) + return + } + returnMessage.Message = "something is super broken..." + returnMessage.Error = true + w.WriteHeader(http.StatusInternalServerError) + render.JSON(w, r, returnMessage) + fmt.Println(err) + return + } + returnMessage.Message = "comment added" + w.WriteHeader(http.StatusCreated) + render.JSON(w, r, returnMessage) + return +} diff --git a/packages/blog/blog.go b/packages/blog/posts.go similarity index 94% rename from packages/blog/blog.go rename to packages/blog/posts.go index 2c6d2bc..7edb9ae 100644 --- a/packages/blog/blog.go +++ b/packages/blog/posts.go @@ -4,7 +4,6 @@ import ( "database/sql" "encoding/json" "fmt" - "git.minhas.io/asara/sudoscientist-go-backend/packages/middleware" "github.com/go-chi/chi" "github.com/go-chi/jwtauth" "github.com/go-chi/render" @@ -14,11 +13,6 @@ import ( "time" ) -var ( - DB *sql.DB - TokenAuth *jwtauth.JWTAuth -) - type BlogPost struct { ID int `json:"id",db:"id"` Title string `json:"title",db:"title"` @@ -43,11 +37,6 @@ type NewBlogPost struct { Author string `json:"author",db:"author"` } -type ReturnMessage struct { - Message string `json:"msg"` - Error bool `json:"error"` -} - type ReturnSuccess struct { Message string `json:"success"` ID int `json:"id"` @@ -58,22 +47,6 @@ type ReferenceID struct { LastID int `json:"last_id"` } -func Routes() *chi.Mux { - r := chi.NewRouter() - r.Group(func(r chi.Router) { - r.Use(jwtauth.Verify(TokenAuth, auth_middleware.TokenFromSplitCookie)) - r.Use(jwtauth.Authenticator) - r.Post("/", createBlogPost) - r.Patch("/by-id/{id}", updateBlogPostById) - }) - r.Get("/", getBlogPosts) - r.Get("/by-id/{id}", getBlogPostById) - r.Get("/by-tag/{tag}", getBlogPostsByTag) - r.Get("/by-author/{author}", getBlogPostsByAuthor) - r.Get("/by-slug/{slug}", getBlogPostBySlug) - return r -} - func createBlogPost(w http.ResponseWriter, r *http.Request) { returnMessage := ReturnMessage{} returnMessage.Error = false diff --git a/packages/blog/routes.go b/packages/blog/routes.go new file mode 100644 index 0000000..cf73a05 --- /dev/null +++ b/packages/blog/routes.go @@ -0,0 +1,32 @@ +package blog + +import ( + "git.minhas.io/asara/sudoscientist-go-backend/packages/middleware" + "github.com/go-chi/chi" + "github.com/go-chi/jwtauth" +) + +func Routes() *chi.Mux { + r := chi.NewRouter() + r.Group(func(r chi.Router) { + r.Use(jwtauth.Verify(TokenAuth, auth_middleware.TokenFromSplitCookie)) + r.Use(jwtauth.Authenticator) + r.Post("/posts", createBlogPost) + r.Patch("/posts/by-id/{id}", updateBlogPostById) + r.Post("/comments/{post_id}", postComment) + /* + r.Patch("/comments/{id}", updateComment) + */ + }) + r.Get("/posts", getBlogPosts) + r.Get("/posts/by-id/{id}", getBlogPostById) + r.Get("/posts/by-tag/{tag}", getBlogPostsByTag) + r.Get("/posts/by-author/{author}", getBlogPostsByAuthor) + r.Get("/posts/by-slug/{slug}", getBlogPostBySlug) + r.Get("/comments/{id}", getCommentById) + /* + r.Get("/by-author/{author}", getCommentsByAuthor) + r.Get("/by-parent/{post_id}", getCommentsByPost) + */ + return r +}