Skip to content
This repository has been archived by the owner on Mar 12, 2023. It is now read-only.

Commit

Permalink
Add comment api (#1)
Browse files Browse the repository at this point in the history
* added Comment proto

* added extra fields to the makefile

* added docker set-up

* added comment methods to Backender interface

* added Comment model with auto migration extension

* added controllers for Comment, added two new helper func to work with time&model

* style fix

* fix typo

* added missing field for the Comment entity and implemented crud functionality

* fixed docker flow, added air.toml for hot-reloading, makefile add-ons, removed godotenv

* removed godotenv and refactored

* refactor

* implemented Comment functionalities
  • Loading branch information
ikadgzl authored Jan 26, 2023
1 parent 889c384 commit 6f85d0b
Show file tree
Hide file tree
Showing 25 changed files with 3,257 additions and 445 deletions.
36 changes: 36 additions & 0 deletions .air.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ./cmd/pano-api"
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
kill_delay = "0s"
log = "build-errors.log"
send_interrupt = false
stop_on_error = true

[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"

[log]
time = false

[misc]
clean_on_exit = false

[screen]
clear_on_rebuild = false
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Building the binary of the App
FROM golang:latest AS builder
RUN mkdir -p /app
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /bin/pano-api /app/cmd/pano-api/main.go

# Moving the binary to the 'final Image' to make it smaller
FROM alpine
RUN mkdir -p /app
WORKDIR /app
RUN apk add --no-cache nano git curl
# COPY --from=builder /feedback-api/internal/configs/dev.env .env
COPY --from=builder bin/pano-api pano-api

CMD ["./pano-api"]

EXPOSE 80
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
gen:
@echo "Generating proto files..."
protoc --twirp_out=. --go_out=. rpc/pano-api/service.proto

upgrade:
@echo "Upgrading dependencies..."
go get -u

build_up:
@echo "Building pano-api..."
sudo docker compose up --build --remove-orphans

up:
@echo "Starting docker-compose..."
sudo docker compose up

down:
@echo "Stopping docker-compose..."
sudo docker compose down --remove-orphans
29 changes: 17 additions & 12 deletions cmd/pano-api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"net/http"
"os"

"github.com/joho/godotenv"
"github.com/kamp-us/pano-api/internal/backend/postgresql"
"github.com/kamp-us/pano-api/internal/db"
"github.com/kamp-us/pano-api/internal/models"
Expand All @@ -15,27 +14,33 @@ import (
)

func main() {
envError := godotenv.Load()
if envError != nil {
log.Fatalf("An error occurred while loading env file. Error: %s", envError)
}

pgConfigData := db.PostgreSQLConfig{Host: os.Getenv("POSTGRES_HOST"), Port: 5432, Username: os.Getenv("POSTGRES_USERNAME"), Password: os.Getenv("POSTGRES_PASSWORD"), DbName: os.Getenv("POSTGRES_DBNAME")}

dbClient, dbError := db.NewPostgreSQLConnect(pgConfigData)
if dbError != nil {
log.Fatalf("An error occurred while establishing db connection. Error: %s", dbError)
dbClient, err := db.NewPostgreSQLConnect(db.PostgreSQLConfig{
Host: os.Getenv("POSTGRES_HOST"),
Port: 5432,
Username: os.Getenv("POSTGRES_USER"),
Password: os.Getenv("POSTGRES_PASSWORD"),
DbName: os.Getenv("POSTGRES_DB"),
})

if err != nil {
log.Fatalf("An error occurred while establishing db connection. Error: %s", err)
}

if err := models.AutoMigrate(dbClient); err != nil {
log.Fatalf("An error occurred while auto migrate. Error: %s", err)
}

s := server.NewPanoAPIServer(postgresql.NewPostgreSQLBackend(dbClient))
postgreSQLBackend := postgresql.NewPostgreSQLBackend(dbClient)

s := server.NewPanoAPIServer(postgreSQLBackend)
twirpHander := api.NewPanoAPIServer(s)

mux := http.NewServeMux()
mux.Handle(twirpHander.PathPrefix(), twirpHander)
mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
w.WriteHeader(http.StatusOK)
}))

fmt.Println("Listening to :8080")
http.ListenAndServe(":8080", mux)
Expand Down
67 changes: 67 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
version: "3.9"

services:
api-with-air:
image: cosmtrek/air
working_dir: /app
environment:
- POSTGRES_USER=pgtest
- POSTGRES_DB=pgtest
- POSTGRES_PASSWORD=pgtest
- POSTGRES_HOST=postgres
ports:
- "8080:80"
volumes:
- ./.:/app
links:
- postgres
depends_on:
- postgres

postgres:
image: postgres:13.3-alpine
environment:
- POSTGRES_USER=pgtest
- POSTGRES_DB=pgtest
- POSTGRES_PASSWORD=pgtest
ports:
- "15432:5432"
healthcheck:
test: pg_isready -U pgtest -d pgtest
interval: 10s
timeout: 3s
retries: 5

pgadmin:
image: dpage/pgadmin4
restart: always
environment:
- PGADMIN_DEFAULT_EMAIL=admin@kamp.us
- PGADMIN_DEFAULT_PASSWORD=secret
- PGADMIN_LISTEN_PORT=80
- PGADMIN_LOG_LEVEL=50
ports:
- "8090:80"
links:
- postgres
logging:
driver: "none"
volumes:
- ./scripts/servers.json:/pgadmin4/servers.json

db-migrator:
image: migrate/migrate
command:
- -path
- /migrations/
- -database
- postgres://pgtest:pgtest@postgres:5432/pgtest?sslmode=disable
- up
links:
- postgres
depends_on:
- postgres
volumes:
- ./db/migrations:/migrations
profiles:
- tools
17 changes: 10 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ module github.com/kamp-us/pano-api
go 1.19

require (
github.com/google/uuid v1.3.0 // indirect
github.com/gosimple/slug v1.13.1 // indirect
github.com/golang/protobuf v1.5.2
github.com/google/uuid v1.3.0
github.com/gosimple/slug v1.13.1
github.com/twitchtv/twirp v8.1.3+incompatible
google.golang.org/protobuf v1.28.1
gorm.io/driver/postgres v1.4.6
gorm.io/gorm v1.24.3
)

require (
github.com/gosimple/unidecode v1.0.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.2.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/joho/godotenv v1.4.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/twitchtv/twirp v8.1.3+incompatible // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/text v0.6.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gorm.io/driver/postgres v1.4.6 // indirect
gorm.io/gorm v1.24.3 // indirect
)
11 changes: 9 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
Expand All @@ -22,8 +26,6 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
Expand All @@ -32,6 +34,7 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand All @@ -40,6 +43,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/twitchtv/twirp v8.1.3+incompatible h1:+F4TdErPgSUbMZMwp13Q/KgDVuI7HJXP61mNV3/7iuU=
github.com/twitchtv/twirp v8.1.3+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
Expand Down Expand Up @@ -82,8 +86,10 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand All @@ -92,6 +98,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.4.6 h1:1FPESNXqIKG5JmraaH2bfCVlMQ7paLoCreFxDtqzwdc=
gorm.io/driver/postgres v1.4.6/go.mod h1:UJChCNLFKeBqQRE+HrkFUbKbq9idPXmTOk2u4Wok8S4=
Expand Down
8 changes: 8 additions & 0 deletions internal/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package backend

import (
"context"
"time"

"github.com/kamp-us/pano-api/internal/models"
)
Expand All @@ -13,4 +14,11 @@ type Backender interface {
CreatePost(ctx context.Context, title string, url string, content string, userId string) (*models.Post, error)
UpdatePost(ctx context.Context, id string, title *string, url *string, content *string) error
DeletePost(ctx context.Context, id string) error

// Comment
GetBatchComments(ctx context.Context, ids []string) ([]*models.Comment, error)
GetComments(ctx context.Context) ([]*models.Comment, error)
CreateComment(ctx context.Context, content string, postId string, userId string, parentId *string, deletedAt *time.Time) (*models.Comment, error)
UpdateComment(ctx context.Context, id string, content string) error
DeleteComment(ctx context.Context, id string) error
}
32 changes: 32 additions & 0 deletions internal/backend/postgresql/create_comment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package postgresql

import (
"context"
"time"

"github.com/kamp-us/pano-api/internal/models"
)

func (b *PostgreSQLBackend) CreateComment(ctx context.Context, content string, postId string, userId string, parentId *string, deletedAt *time.Time) (*models.Comment, error) {
comment := models.Comment{
Content: content,
PostID: postId,
UserID: userId,
}

// TODO: is this the way?
if parentId != nil {
comment.ParentID = *parentId
}

if deletedAt != nil {
comment.DeletedAt = *deletedAt
}

result := b.DB.Create(&comment)
if result.Error != nil {
return nil, result.Error
}

return &comment, nil
}
23 changes: 23 additions & 0 deletions internal/backend/postgresql/delete_comment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package postgresql

import (
"context"

"github.com/kamp-us/pano-api/internal/models"
)

func (b *PostgreSQLBackend) DeleteComment(ctx context.Context, id string) error {
comment := models.Comment{}

result := b.DB.First(&comment, "id = ?", id)
if result.Error != nil {
return result.Error
}

result = b.DB.Delete(&comment)
if result.Error != nil {
return result.Error
}

return nil
}
19 changes: 19 additions & 0 deletions internal/backend/postgresql/get_batch_comments.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package postgresql

import (
"context"

"github.com/kamp-us/pano-api/internal/models"
)

// TODO: why do we return array of pointers?
func (b *PostgreSQLBackend) GetBatchComments(ctx context.Context, ids []string) ([]*models.Comment, error) {
var comments []*models.Comment
result := b.DB.Find(comments, ids)

if result.Error != nil {
return nil, result.Error
}

return comments, nil
}
Loading

0 comments on commit 6f85d0b

Please sign in to comment.