feat: add handlers - WIP
This commit is contained in:
@@ -19,42 +19,39 @@ Clean Architecture sample
|
||||
|
||||
## API requests
|
||||
|
||||
### Add a bookmark
|
||||
### Add a book
|
||||
|
||||
```
|
||||
curl -X "POST" "http://localhost:8080/v1/bookmark" \
|
||||
curl -X "POST" "http://localhost:8080/v1/book" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json' \
|
||||
-d $'{
|
||||
"tags": [
|
||||
"git",
|
||||
"social"
|
||||
],
|
||||
"name": "Github",
|
||||
"description": "Github site",
|
||||
"link": "http://github.com"
|
||||
"title": "I Am Ozzy",
|
||||
"author": "Ozzy Osbourne",
|
||||
"pages": 294,
|
||||
"quantity":1
|
||||
}'
|
||||
```
|
||||
### Search a bookmark
|
||||
### Search a book
|
||||
|
||||
```
|
||||
curl "http://localhost:8080/v1/bookmark?name=github" \
|
||||
curl "http://localhost:8080/v1/book?title=ozzy" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json'
|
||||
```
|
||||
|
||||
### Show all bookmarks
|
||||
### Show all books
|
||||
|
||||
```
|
||||
curl "http://localhost:8080/v1/bookmark" \
|
||||
curl "http://localhost:8080/v1/book" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json'
|
||||
```
|
||||
|
||||
## CMD
|
||||
|
||||
### Search for a bookmark
|
||||
### Search for a book
|
||||
|
||||
```
|
||||
./bin/search github
|
||||
./bin/search ozzy
|
||||
```
|
||||
@@ -0,0 +1,183 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/api/presenter"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity"
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity/book"
|
||||
|
||||
"github.com/codegangsta/negroni"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func listBooks(service book.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error reading books"
|
||||
var data []*book.Book
|
||||
var err error
|
||||
title := r.URL.Query().Get("title")
|
||||
switch {
|
||||
case title == "":
|
||||
data, err = service.List()
|
||||
default:
|
||||
data, err = service.Search(title)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err != nil && err != domain.ErrNotFound {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
var toJ []*presenter.Book
|
||||
for _, d := range data {
|
||||
toJ = append(toJ, &presenter.Book{
|
||||
ID: d.ID,
|
||||
Title: d.Title,
|
||||
Author: d.Author,
|
||||
Pages: d.Pages,
|
||||
Quantity: d.Quantity,
|
||||
})
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode(toJ); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func createBook(service book.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error adding book"
|
||||
var input struct {
|
||||
Title string `json:"title"`
|
||||
Author string `json:"author"`
|
||||
Pages int `json:"pages"`
|
||||
Quantity int `json:"quantity"`
|
||||
}
|
||||
err := json.NewDecoder(r.Body).Decode(&input)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
b := &book.Book{
|
||||
ID: entity.NewID(),
|
||||
Title: input.Title,
|
||||
Author: input.Author,
|
||||
Pages: input.Pages,
|
||||
Quantity: input.Quantity,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
b.ID, err = service.Create(b)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
toJ := &presenter.Book{
|
||||
ID: b.ID,
|
||||
Title: b.Title,
|
||||
Author: b.Author,
|
||||
Pages: b.Pages,
|
||||
Quantity: b.Quantity,
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
if err := json.NewEncoder(w).Encode(toJ); err != nil {
|
||||
log.Println(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func getBook(service book.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error reading book"
|
||||
vars := mux.Vars(r)
|
||||
id, err := entity.StringToID(vars["id"])
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
data, err := service.Get(id)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err != nil && err != domain.ErrNotFound {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
toJ := &presenter.Book{
|
||||
ID: data.ID,
|
||||
Title: data.Title,
|
||||
Author: data.Author,
|
||||
Pages: data.Pages,
|
||||
Quantity: data.Quantity,
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode(toJ); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func deleteBook(service book.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error removing bookmark"
|
||||
vars := mux.Vars(r)
|
||||
id, err := entity.StringToID(vars["id"])
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
err = service.Delete(id)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//MakeBookHandlers make url handlers
|
||||
func MakeBookHandlers(r *mux.Router, n negroni.Negroni, service book.UseCase) {
|
||||
r.Handle("/v1/book", n.With(
|
||||
negroni.Wrap(listBooks(service)),
|
||||
)).Methods("GET", "OPTIONS").Name("listBooks")
|
||||
|
||||
r.Handle("/v1/book", n.With(
|
||||
negroni.Wrap(createBook(service)),
|
||||
)).Methods("POST", "OPTIONS").Name("createBook")
|
||||
|
||||
r.Handle("/v1/book/{id}", n.With(
|
||||
negroni.Wrap(getBook(service)),
|
||||
)).Methods("GET", "OPTIONS").Name("getBook")
|
||||
|
||||
r.Handle("/v1/book/{id}", n.With(
|
||||
negroni.Wrap(deleteBook(service)),
|
||||
)).Methods("DELETE", "OPTIONS").Name("deleteBook")
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain"
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity/book"
|
||||
|
||||
"github.com/codegangsta/negroni"
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity/book/mock"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_BookIndex(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
r := mux.NewRouter()
|
||||
n := negroni.New()
|
||||
MakeBookHandlers(r, *n, service)
|
||||
path, err := r.GetRoute("bookIndex").GetPathTemplate()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/v1/book", path)
|
||||
b := book.NewFixtureBook()
|
||||
service.EXPECT().
|
||||
List().
|
||||
Return([]*book.Book{b}, nil)
|
||||
ts := httptest.NewServer(listBooks(service))
|
||||
defer ts.Close()
|
||||
res, err := http.Get(ts.URL)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
}
|
||||
|
||||
func Test_BookIndexNotFound(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
ts := httptest.NewServer(listBooks(service))
|
||||
defer ts.Close()
|
||||
service.EXPECT().
|
||||
Search("book of books").
|
||||
Return(nil, domain.ErrNotFound)
|
||||
res, err := http.Get(ts.URL + "?title=book+of+books")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusNotFound, res.StatusCode)
|
||||
}
|
||||
|
||||
func Test_BookSearch(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
b := book.NewFixtureBook()
|
||||
service.EXPECT().
|
||||
Search("ozzy").
|
||||
Return([]*book.Book{b}, nil)
|
||||
ts := httptest.NewServer(listBooks(service))
|
||||
defer ts.Close()
|
||||
res, err := http.Get(ts.URL + "?title=ozzy")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
}
|
||||
|
||||
func Test_BookAdd(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
r := mux.NewRouter()
|
||||
n := negroni.New()
|
||||
MakeBookHandlers(r, *n, service)
|
||||
path, err := r.GetRoute("bookAdd").GetPathTemplate()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/v1/book", path)
|
||||
|
||||
service.EXPECT().
|
||||
Create(gomock.Any()).
|
||||
Return(entity.NewID(), nil)
|
||||
h := createBook(service)
|
||||
|
||||
ts := httptest.NewServer(h)
|
||||
defer ts.Close()
|
||||
payload := fmt.Sprintf(`{
|
||||
"title": "I Am Ozzy",
|
||||
"author": "Ozzy Osbourne",
|
||||
"pages": 294,
|
||||
"quantity":1
|
||||
}`)
|
||||
resp, _ := http.Post(ts.URL+"/v1/book", "application/json", strings.NewReader(payload))
|
||||
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
||||
|
||||
var b *book.Book
|
||||
json.NewDecoder(resp.Body).Decode(&b)
|
||||
assert.Equal(t, "Ozzy Osbourne", b.Author)
|
||||
}
|
||||
|
||||
func Test_BookFind(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
r := mux.NewRouter()
|
||||
n := negroni.New()
|
||||
MakeBookHandlers(r, *n, service)
|
||||
path, err := r.GetRoute("bookFind").GetPathTemplate()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/v1/book/{id}", path)
|
||||
b := book.NewFixtureBook()
|
||||
service.EXPECT().
|
||||
Get(b.ID).
|
||||
Return(b, nil)
|
||||
handler := getBook(service)
|
||||
r.Handle("/v1/book/{id}", handler)
|
||||
ts := httptest.NewServer(r)
|
||||
defer ts.Close()
|
||||
res, err := http.Get(ts.URL + "/v1/book/" + b.ID.String())
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
var d *book.Book
|
||||
json.NewDecoder(res.Body).Decode(&d)
|
||||
assert.NotNil(t, d)
|
||||
assert.Equal(t, b.ID, d.ID)
|
||||
}
|
||||
|
||||
func TestBookRemove(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
r := mux.NewRouter()
|
||||
n := negroni.New()
|
||||
MakeBookHandlers(r, *n, service)
|
||||
path, err := r.GetRoute("bookDelete").GetPathTemplate()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/v1/book/{id}", path)
|
||||
b := book.NewFixtureBook()
|
||||
service.EXPECT().Delete(b.ID).Return(nil)
|
||||
handler := deleteBook(service)
|
||||
req, _ := http.NewRequest("DELETE", "/v1/bookmark/"+b.ID.String(), nil)
|
||||
r.Handle("/v1/bookmark/{id}", handler).Methods("DELETE", "OPTIONS")
|
||||
rr := httptest.NewRecorder()
|
||||
r.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusOK, rr.Code)
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/eminetto/clean-architecture-go/pkg/middleware"
|
||||
"log"
|
||||
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/codegangsta/negroni"
|
||||
"github.com/eminetto/clean-architecture-go/pkg/bookmark"
|
||||
"github.com/eminetto/clean-architecture-go/pkg/entity"
|
||||
"github.com/gorilla/mux"
|
||||
valid "github.com/asaskevich/govalidator"
|
||||
)
|
||||
|
||||
|
||||
//BookmarkInput data
|
||||
type BookmarkInput struct {
|
||||
ID entity.ID `json:"id" valid:"type(entity.ID)"`
|
||||
Name string `json:"name" valid:"stringlength(1|50),required"`
|
||||
Description string `json:"description" valid:"stringlength(1|150),required"`
|
||||
Link string `json:"link" valid:"url,required"`
|
||||
Tags []string `json:"tags" valid:"-"`
|
||||
Favorite bool `json:"favorite" valid:"required"`
|
||||
CreatedAt time.Time `json:"created_at" valid:"-"`
|
||||
}
|
||||
|
||||
func (v *BookmarkInput) Validate() error {
|
||||
_, err := valid.ValidateStruct(*v)
|
||||
return err
|
||||
}
|
||||
|
||||
func bookmarkIndex(service bookmark.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error reading bookmarks"
|
||||
var data []*entity.Bookmark
|
||||
var err error
|
||||
name := r.URL.Query().Get("name")
|
||||
switch {
|
||||
case name == "":
|
||||
data, err = service.FindAll()
|
||||
default:
|
||||
data, err = service.Search(name)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err != nil && err != entity.ErrNotFound {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode(data); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func bookmarkAdd(service bookmark.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error adding bookmark"
|
||||
i := r.Context().Value("InputParam").(*BookmarkInput)
|
||||
b := &entity.Bookmark{
|
||||
Name: i.Name,
|
||||
Description: i.Description,
|
||||
Link: i.Link,
|
||||
Tags: i.Tags,
|
||||
Favorite: i.Favorite,
|
||||
}
|
||||
_, err := service.Store(b)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
if err := json.NewEncoder(w).Encode(b); err != nil {
|
||||
log.Println(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func bookmarkFind(service bookmark.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error reading bookmark"
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
data, err := service.Find(entity.StringToID(id))
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err != nil && err != entity.ErrNotFound {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode(data); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func bookmarkDelete(service bookmark.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error removing bookmark"
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
err := service.Delete(entity.StringToID(id))
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//MakeBookmarkHandlers make url handlers
|
||||
func MakeBookmarkHandlers(r *mux.Router, n negroni.Negroni, service bookmark.UseCase) {
|
||||
r.Handle("/v1/bookmark", n.With(
|
||||
negroni.Wrap(bookmarkIndex(service)),
|
||||
)).Methods("GET", "OPTIONS").Name("bookmarkIndex")
|
||||
|
||||
r.Handle("/v1/bookmark", n.With(
|
||||
negroni.HandlerFunc(middleware.Validate(&BookmarkInput{})),
|
||||
negroni.Wrap(bookmarkAdd(service)),
|
||||
)).Methods("POST", "OPTIONS").Name("bookmarkAdd")
|
||||
|
||||
r.Handle("/v1/bookmark/{id}", n.With(
|
||||
negroni.Wrap(bookmarkFind(service)),
|
||||
)).Methods("GET", "OPTIONS").Name("bookmarkFind")
|
||||
|
||||
r.Handle("/v1/bookmark/{id}", n.With(
|
||||
negroni.Wrap(bookmarkDelete(service)),
|
||||
)).Methods("DELETE", "OPTIONS").Name("bookmarkDelete")
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/codegangsta/negroni"
|
||||
"github.com/eminetto/clean-architecture-go/pkg/bookmark/mock"
|
||||
"github.com/eminetto/clean-architecture-go/pkg/entity"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBookmarkIndex(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
r := mux.NewRouter()
|
||||
n := negroni.New()
|
||||
MakeBookmarkHandlers(r, *n, service)
|
||||
path, err := r.GetRoute("bookmarkIndex").GetPathTemplate()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/v1/bookmark", path)
|
||||
b := &entity.Bookmark{
|
||||
Name: "Elton Minetto",
|
||||
Description: "Minetto's page",
|
||||
Link: "http://www.eltonminetto.net",
|
||||
Tags: []string{"golang", "php", "linux", "mac"},
|
||||
Favorite: true,
|
||||
}
|
||||
service.EXPECT().
|
||||
FindAll().
|
||||
Return([]*entity.Bookmark{b}, nil)
|
||||
ts := httptest.NewServer(bookmarkIndex(service))
|
||||
defer ts.Close()
|
||||
res, err := http.Get(ts.URL)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
}
|
||||
|
||||
func TestBookmarkIndexNotFound(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
ts := httptest.NewServer(bookmarkIndex(service))
|
||||
defer ts.Close()
|
||||
service.EXPECT().
|
||||
Search("github").
|
||||
Return(nil, entity.ErrNotFound)
|
||||
res, err := http.Get(ts.URL + "?name=github")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusNotFound, res.StatusCode)
|
||||
}
|
||||
|
||||
func TestBookmarkSearch(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
b := &entity.Bookmark{
|
||||
Name: "Elton Minetto",
|
||||
Description: "Minetto's page",
|
||||
Link: "http://www.eltonminetto.net",
|
||||
Tags: []string{"golang", "php", "linux", "mac"},
|
||||
Favorite: true,
|
||||
}
|
||||
service.EXPECT().
|
||||
Search("minetto").
|
||||
Return([]*entity.Bookmark{b}, nil)
|
||||
ts := httptest.NewServer(bookmarkIndex(service))
|
||||
defer ts.Close()
|
||||
res, err := http.Get(ts.URL + "?name=minetto")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
}
|
||||
|
||||
func TestBookmarkAdd(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
r := mux.NewRouter()
|
||||
n := negroni.New()
|
||||
MakeBookmarkHandlers(r, *n, service)
|
||||
path, err := r.GetRoute("bookmarkAdd").GetPathTemplate()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/v1/bookmark", path)
|
||||
|
||||
service.EXPECT().
|
||||
Store(gomock.Any()).
|
||||
Return(entity.NewID(), nil)
|
||||
ts := httptest.NewServer(r)
|
||||
defer ts.Close()
|
||||
payload := fmt.Sprintf(`{
|
||||
"name": "Github",
|
||||
"description": "Github site",
|
||||
"link": "http://github.com",
|
||||
"tags": [
|
||||
"git",
|
||||
"social"
|
||||
]
|
||||
}`)
|
||||
resp, _ := http.Post(ts.URL+"/v1/bookmark", "application/json", strings.NewReader(payload))
|
||||
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
||||
|
||||
var b *entity.Bookmark
|
||||
json.NewDecoder(resp.Body).Decode(&b)
|
||||
assert.Equal(t, "http://github.com", b.Link)
|
||||
}
|
||||
|
||||
func TestBookmarkFind(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
r := mux.NewRouter()
|
||||
n := negroni.New()
|
||||
MakeBookmarkHandlers(r, *n, service)
|
||||
path, err := r.GetRoute("bookmarkFind").GetPathTemplate()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/v1/bookmark/{id}", path)
|
||||
b := &entity.Bookmark{
|
||||
ID: entity.NewID(),
|
||||
Name: "Elton Minetto",
|
||||
Description: "Minetto's page",
|
||||
Link: "http://www.eltonminetto.net",
|
||||
Tags: []string{"golang", "php", "linux", "mac"},
|
||||
Favorite: true,
|
||||
}
|
||||
service.EXPECT().
|
||||
Find(b.ID).
|
||||
Return(b, nil)
|
||||
handler := bookmarkFind(service)
|
||||
r.Handle("/v1/bookmark/{id}", handler)
|
||||
ts := httptest.NewServer(r)
|
||||
defer ts.Close()
|
||||
res, err := http.Get(ts.URL + "/v1/bookmark/" + b.ID.String())
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
var d *entity.Bookmark
|
||||
json.NewDecoder(res.Body).Decode(&d)
|
||||
assert.NotNil(t, d)
|
||||
assert.Equal(t, b.ID, d.ID)
|
||||
}
|
||||
|
||||
func TestBookmarkRemove(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
r := mux.NewRouter()
|
||||
n := negroni.New()
|
||||
MakeBookmarkHandlers(r, *n, service)
|
||||
path, err := r.GetRoute("bookmarkDelete").GetPathTemplate()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/v1/bookmark/{id}", path)
|
||||
b := &entity.Bookmark{
|
||||
ID: entity.NewID(),
|
||||
Name: "Elton Minetto",
|
||||
Description: "Minetto's page",
|
||||
Link: "http://www.eltonminetto.net",
|
||||
Tags: []string{"golang", "php", "linux", "mac"},
|
||||
Favorite: false,
|
||||
}
|
||||
service.EXPECT().Delete(b.ID).Return(nil)
|
||||
handler := bookmarkDelete(service)
|
||||
req, _ := http.NewRequest("DELETE", "/v1/bookmark/"+b.ID.String(), nil)
|
||||
r.Handle("/v1/bookmark/{id}", handler).Methods("DELETE", "OPTIONS")
|
||||
rr := httptest.NewRecorder()
|
||||
r.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusOK, rr.Code)
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity/user"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/api/presenter"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity"
|
||||
|
||||
"github.com/codegangsta/negroni"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func listUsers(service user.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error reading users"
|
||||
var data []*user.User
|
||||
var err error
|
||||
name := r.URL.Query().Get("name")
|
||||
switch {
|
||||
case name == "":
|
||||
data, err = service.List()
|
||||
default:
|
||||
data, err = service.Search(name)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err != nil && err != domain.ErrNotFound {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
var toJ []*presenter.User
|
||||
for _, d := range data {
|
||||
toJ = append(toJ, &presenter.User{
|
||||
ID: d.ID,
|
||||
Email: d.Email,
|
||||
FirstName: d.FirstName,
|
||||
LastName: d.LastName,
|
||||
})
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode(toJ); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func createUser(service user.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error adding user"
|
||||
var input struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
}
|
||||
err := json.NewDecoder(r.Body).Decode(&input)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
//TODO: validate data ;)
|
||||
u := &user.User{
|
||||
ID: entity.NewID(),
|
||||
Email: input.Email,
|
||||
Password: input.Password,
|
||||
FirstName: input.FirstName,
|
||||
LastName: input.LastName,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
u.ID, err = service.Create(u)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
toJ := &presenter.User{
|
||||
ID: u.ID,
|
||||
Email: u.Email,
|
||||
FirstName: u.FirstName,
|
||||
LastName: u.LastName,
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
if err := json.NewEncoder(w).Encode(toJ); err != nil {
|
||||
log.Println(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func getUser(service user.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error reading user"
|
||||
vars := mux.Vars(r)
|
||||
id, err := entity.StringToID(vars["id"])
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
data, err := service.Get(id)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err != nil && err != domain.ErrNotFound {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
toJ := &presenter.User{
|
||||
ID: data.ID,
|
||||
Email: data.Email,
|
||||
FirstName: data.FirstName,
|
||||
LastName: data.LastName,
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode(toJ); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func deleteUser(service user.UseCase) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
errorMessage := "Error removing user"
|
||||
vars := mux.Vars(r)
|
||||
id, err := entity.StringToID(vars["id"])
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
err = service.Delete(id)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(errorMessage))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//MakeUserHandlers make url handlers
|
||||
func MakeUserHandlers(r *mux.Router, n negroni.Negroni, service user.UseCase) {
|
||||
r.Handle("/v1/user", n.With(
|
||||
negroni.Wrap(listUsers(service)),
|
||||
)).Methods("GET", "OPTIONS").Name("listUsers")
|
||||
|
||||
r.Handle("/v1/user", n.With(
|
||||
negroni.Wrap(createUser(service)),
|
||||
)).Methods("POST", "OPTIONS").Name("createUser")
|
||||
|
||||
r.Handle("/v1/user/{id}", n.With(
|
||||
negroni.Wrap(getUser(service)),
|
||||
)).Methods("GET", "OPTIONS").Name("getUser")
|
||||
|
||||
r.Handle("/v1/user/{id}", n.With(
|
||||
negroni.Wrap(deleteUser(service)),
|
||||
)).Methods("DELETE", "OPTIONS").Name("deleteUser")
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/api/presenter"
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain"
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity"
|
||||
|
||||
"github.com/codegangsta/negroni"
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity/user"
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity/user/mock"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_UserIndex(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
r := mux.NewRouter()
|
||||
n := negroni.New()
|
||||
MakeUserHandlers(r, *n, service)
|
||||
path, err := r.GetRoute("userIndex").GetPathTemplate()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/v1/user", path)
|
||||
u := user.NewFixtureUser()
|
||||
service.EXPECT().
|
||||
List().
|
||||
Return([]*user.User{u}, nil)
|
||||
ts := httptest.NewServer(userIndex(service))
|
||||
defer ts.Close()
|
||||
res, err := http.Get(ts.URL)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
}
|
||||
|
||||
func Test_UserIndexNotFound(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
ts := httptest.NewServer(userIndex(service))
|
||||
defer ts.Close()
|
||||
service.EXPECT().
|
||||
Search("dio").
|
||||
Return(nil, domain.ErrNotFound)
|
||||
res, err := http.Get(ts.URL + "?name=dio")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusNotFound, res.StatusCode)
|
||||
}
|
||||
|
||||
func Test_UserSearch(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
u := user.NewFixtureUser()
|
||||
service.EXPECT().
|
||||
Search("ozzy").
|
||||
Return([]*user.User{u}, nil)
|
||||
ts := httptest.NewServer(userIndex(service))
|
||||
defer ts.Close()
|
||||
res, err := http.Get(ts.URL + "?name=ozzy")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
}
|
||||
|
||||
func Test_UserAdd(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
r := mux.NewRouter()
|
||||
n := negroni.New()
|
||||
MakeUserHandlers(r, *n, service)
|
||||
path, err := r.GetRoute("userAdd").GetPathTemplate()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/v1/user", path)
|
||||
|
||||
service.EXPECT().
|
||||
Create(gomock.Any()).
|
||||
Return(entity.NewID(), nil)
|
||||
h := userAdd(service)
|
||||
|
||||
ts := httptest.NewServer(h)
|
||||
defer ts.Close()
|
||||
payload := fmt.Sprintf(`{
|
||||
"name": "ozzy",
|
||||
"email": "ozzy@hell.com",
|
||||
"password": "asasa",
|
||||
"first_name":"Ozzy",
|
||||
"last_name":"Osbourne"
|
||||
}`)
|
||||
resp, _ := http.Post(ts.URL+"/v1/user", "application/json", strings.NewReader(payload))
|
||||
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
||||
|
||||
var u *presenter.User
|
||||
json.NewDecoder(resp.Body).Decode(&u)
|
||||
assert.Equal(t, "Ozzy Osbourne", fmt.Sprintf("%s %s", u.FirstName, u.LastName))
|
||||
}
|
||||
|
||||
func Test_UserFind(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
service := mock.NewMockUseCase(controller)
|
||||
r := mux.NewRouter()
|
||||
n := negroni.New()
|
||||
MakeUserHandlers(r, *n, service)
|
||||
path, err := r.GetRoute("userFind").GetPathTemplate()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "/v1/user/{id}", path)
|
||||
u := user.NewFixtureUser()
|
||||
service.EXPECT().
|
||||
Get(u.ID).
|
||||
Return(u, nil)
|
||||
handler := userFind(service)
|
||||
r.Handle("/v1/bookmark/{id}", handler)
|
||||
ts := httptest.NewServer(r)
|
||||
defer ts.Close()
|
||||
res, err := http.Get(ts.URL + "/v1/bookmark/" + b.ID.String())
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
var d *entity.Bookmark
|
||||
json.NewDecoder(res.Body).Decode(&d)
|
||||
assert.NotNil(t, d)
|
||||
assert.Equal(t, b.ID, d.ID)
|
||||
}
|
||||
|
||||
//
|
||||
//func TestBookmarkRemove(t *testing.T) {
|
||||
// controller := gomock.NewController(t)
|
||||
// defer controller.Finish()
|
||||
// service := mock.NewMockUseCase(controller)
|
||||
// r := mux.NewRouter()
|
||||
// n := negroni.New()
|
||||
// MakeBookmarkHandlers(r, *n, service)
|
||||
// path, err := r.GetRoute("bookmarkDelete").GetPathTemplate()
|
||||
// assert.Nil(t, err)
|
||||
// assert.Equal(t, "/v1/bookmark/{id}", path)
|
||||
// b := &entity.Bookmark{
|
||||
// ID: entity.NewID(),
|
||||
// Name: "Elton Minetto",
|
||||
// Description: "Minetto's page",
|
||||
// Link: "http://www.eltonminetto.net",
|
||||
// Tags: []string{"golang", "php", "linux", "mac"},
|
||||
// Favorite: false,
|
||||
// }
|
||||
// service.EXPECT().Delete(b.ID).Return(nil)
|
||||
// handler := bookmarkDelete(service)
|
||||
// req, _ := http.NewRequest("DELETE", "/v1/bookmark/"+b.ID.String(), nil)
|
||||
// r.Handle("/v1/bookmark/{id}", handler).Methods("DELETE", "OPTIONS")
|
||||
// rr := httptest.NewRecorder()
|
||||
// r.ServeHTTP(rr, req)
|
||||
// assert.Equal(t, http.StatusOK, rr.Code)
|
||||
//}
|
||||
+27
-18
@@ -1,53 +1,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity/user"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity/book"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
|
||||
"github.com/codegangsta/negroni"
|
||||
"github.com/eminetto/clean-architecture-go/api/handler"
|
||||
"github.com/eminetto/clean-architecture-go/config"
|
||||
"github.com/eminetto/clean-architecture-go/pkg/bookmark"
|
||||
"github.com/eminetto/clean-architecture-go/pkg/middleware"
|
||||
"github.com/eminetto/clean-architecture-go/pkg/metric"
|
||||
"github.com/eminetto/clean-architecture-go-v2/api/handler"
|
||||
"github.com/eminetto/clean-architecture-go-v2/api/middleware"
|
||||
"github.com/eminetto/clean-architecture-go-v2/config"
|
||||
"github.com/eminetto/clean-architecture-go-v2/pkg/metric"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/gorilla/context"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/juju/mgosession"
|
||||
mgo "gopkg.in/mgo.v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
session, err := mgo.Dial(config.MONGODB_HOST)
|
||||
|
||||
dataSourceName := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?parseTime=true", config.DB_USER, config.DB_PASSWORD, config.DB_HOST, config.DB_DATABASE)
|
||||
db, err := sql.Open("mysql", dataSourceName)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
defer session.Close()
|
||||
defer db.Close()
|
||||
|
||||
r := mux.NewRouter()
|
||||
bookRepo := book.NewMySQLRepoRepository(db)
|
||||
bookService := book.NewService(bookRepo)
|
||||
|
||||
mPool := mgosession.NewPool(nil, session, config.MONGODB_CONNECTION_POOL)
|
||||
defer mPool.Close()
|
||||
userRepo := user.NewMySQLRepoRepository(db)
|
||||
userService := user.NewService(userRepo)
|
||||
|
||||
bookmarkRepo := bookmark.NewMongoRepository(mPool, config.MONGODB_DATABASE)
|
||||
bookmarkService := bookmark.NewService(bookmarkRepo)
|
||||
//loanService := loan.NewService(userService, bookService)
|
||||
|
||||
metricService, err := metric.NewPrometheusService()
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
r := mux.NewRouter()
|
||||
//handlers
|
||||
n := negroni.New(
|
||||
negroni.HandlerFunc(middleware.Cors),
|
||||
negroni.HandlerFunc(middleware.Metrics(metricService)),
|
||||
negroni.NewLogger(),
|
||||
)
|
||||
//bookmark
|
||||
handler.MakeBookmarkHandlers(r, *n, bookmarkService)
|
||||
//book
|
||||
handler.MakeBookHandlers(r, *n, bookService)
|
||||
|
||||
//user
|
||||
handler.MakeUserHandlers(r, *n, userService)
|
||||
|
||||
http.Handle("/", r)
|
||||
http.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/eminetto/clean-architecture-go/pkg/metric"
|
||||
"github.com/eminetto/clean-architecture-go-v2/pkg/metric"
|
||||
|
||||
"github.com/codegangsta/negroni"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package presenter
|
||||
|
||||
import (
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity"
|
||||
)
|
||||
|
||||
//Book data
|
||||
type Book struct {
|
||||
ID entity.ID `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Author string `json:"author"`
|
||||
Pages int `json:"pages"`
|
||||
Quantity int `json:"quantity"`
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package presenter
|
||||
|
||||
import (
|
||||
"github.com/eminetto/clean-architecture-go-v2/domain/entity"
|
||||
)
|
||||
|
||||
//User data
|
||||
type User struct {
|
||||
ID entity.ID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
}
|
||||
@@ -84,7 +84,27 @@ func (r *MySQLRepo) Search(query string) ([]*Book, error) {
|
||||
|
||||
//List users
|
||||
func (r *MySQLRepo) List() ([]*Book, error) {
|
||||
return nil, nil
|
||||
stmt, err := r.db.Prepare(`select id, title, author, pages, quantity, created_at from book`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var books []*Book
|
||||
rows, err := stmt.Query()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var b Book
|
||||
err = rows.Scan(&b.ID, &b.Title, &b.Author, &b.Pages, &b.Quantity, &b.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
books = append(books, &b)
|
||||
}
|
||||
if len(books) == 0 {
|
||||
return nil, domain.ErrNotFound
|
||||
}
|
||||
return books, nil
|
||||
}
|
||||
|
||||
//Delete an user
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package metric
|
||||
|
||||
import (
|
||||
"github.com/eminetto/clean-architecture-go-v2/config"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/push"
|
||||
"github.com/eminetto/clean-architecture-go/config"
|
||||
)
|
||||
|
||||
//Service implements UseCase interface
|
||||
|
||||
Reference in New Issue
Block a user