Skip to content

Commit

Permalink
🐛 Return and Updates Tickers for Users
Browse files Browse the repository at this point in the history
  • Loading branch information
0x46616c6b committed Oct 24, 2023
1 parent 4592ab5 commit c0ded21
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 92 deletions.
2 changes: 1 addition & 1 deletion internal/api/middleware/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func PrefetchUser(s storage.Storage) gin.HandlerFunc {
return
}

user, err := s.FindUserByID(userID)
user, err := s.FindUserByID(userID, storage.WithTickers())
if err != nil {
c.JSON(http.StatusNotFound, response.ErrorResponse(response.CodeNotFound, response.UserNotFound))
return
Expand Down
4 changes: 2 additions & 2 deletions internal/api/middleware/user/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestPrefetchUserStorageError(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.AddParam("userID", "1")
s := &storage.MockStorage{}
s.On("FindUserByID", mock.Anything).Return(storage.User{}, errors.New("storage error"))
s.On("FindUserByID", mock.Anything, mock.Anything).Return(storage.User{}, errors.New("storage error"))
mw := PrefetchUser(s)

mw(c)
Expand All @@ -46,7 +46,7 @@ func TestPrefetchUser(t *testing.T) {
c.AddParam("userID", "1")
s := &storage.MockStorage{}
user := storage.User{ID: 1}
s.On("FindUserByID", mock.Anything).Return(user, nil)
s.On("FindUserByID", mock.Anything, mock.Anything).Return(user, nil)
mw := PrefetchUser(s)

mw(c)
Expand Down
35 changes: 30 additions & 5 deletions internal/api/response/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@ import (
)

type User struct {
ID int `json:"id"`
CreatedAt time.Time `json:"createdAt"`
Email string `json:"email"`
Role string `json:"role"`
IsSuperAdmin bool `json:"isSuperAdmin"`
ID int `json:"id"`
CreatedAt time.Time `json:"createdAt"`
Email string `json:"email"`
Role string `json:"role"`
Tickers []UserTicker `json:"tickers"`
IsSuperAdmin bool `json:"isSuperAdmin"`
}

type UserTicker struct {
ID int `json:"id"`
Domain string `json:"domain"`
Title string `json:"title"`
}

func UserResponse(user storage.User) User {
Expand All @@ -20,6 +27,7 @@ func UserResponse(user storage.User) User {
CreatedAt: user.CreatedAt,
Email: user.Email,
IsSuperAdmin: user.IsSuperAdmin,
Tickers: UserTickersResponse(user.Tickers),
}
}

Expand All @@ -31,3 +39,20 @@ func UsersResponse(users []storage.User) []User {

return u
}

func UserTickersResponse(tickers []storage.Ticker) []UserTicker {
t := make([]UserTicker, 0)
for _, ticker := range tickers {
t = append(t, UserTickerResponse(ticker))
}

return t
}

func UserTickerResponse(ticker storage.Ticker) UserTicker {
return UserTicker{
ID: ticker.ID,
Domain: ticker.Domain,
Title: ticker.Title,
}
}
11 changes: 11 additions & 0 deletions internal/api/response/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ func TestUsersResponse(t *testing.T) {
CreatedAt: time.Now(),
Email: "user@systemli.org",
IsSuperAdmin: true,
Tickers: []storage.Ticker{
{
ID: 1,
Domain: "example.com",
Title: "Example",
},
},
},
}

Expand All @@ -24,4 +31,8 @@ func TestUsersResponse(t *testing.T) {
assert.Equal(t, users[0].CreatedAt, usersResponse[0].CreatedAt)
assert.Equal(t, users[0].Email, usersResponse[0].Email)
assert.Equal(t, users[0].IsSuperAdmin, usersResponse[0].IsSuperAdmin)
assert.Equal(t, 1, len(usersResponse[0].Tickers))
assert.Equal(t, users[0].Tickers[0].ID, usersResponse[0].Tickers[0].ID)
assert.Equal(t, users[0].Tickers[0].Domain, usersResponse[0].Tickers[0].Domain)
assert.Equal(t, users[0].Tickers[0].Title, usersResponse[0].Tickers[0].Title)
}
23 changes: 8 additions & 15 deletions internal/api/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

func (h *handler) GetUsers(c *gin.Context) {
//TODO: Discuss need of Pagination
users, err := h.storage.FindUsers()
users, err := h.storage.FindUsers(storage.WithTickers())
if err != nil {
c.JSON(http.StatusNotFound, response.ErrorResponse(response.CodeDefault, response.UserNotFound))
return
Expand Down Expand Up @@ -86,10 +86,10 @@ func (h *handler) PutUser(c *gin.Context) {
}

var body struct {
Email string `json:"email,omitempty" validate:"email"`
Password string `json:"password,omitempty" validate:"min=10"`
IsSuperAdmin bool `json:"isSuperAdmin,omitempty"`
Tickers []int `json:"tickers,omitempty"`
Email string `json:"email,omitempty" validate:"email"`
Password string `json:"password,omitempty" validate:"min=10"`
IsSuperAdmin bool `json:"isSuperAdmin,omitempty"`
Tickers []storage.Ticker `json:"tickers,omitempty"`
}

err = c.Bind(&body)
Expand All @@ -104,22 +104,15 @@ func (h *handler) PutUser(c *gin.Context) {
if body.Password != "" {
user.UpdatePassword(body.Password)
}
if len(body.Tickers) > 0 {
user.Tickers = body.Tickers
}

// You only can set/unset other users SuperAdmin property
if me.ID != user.ID {
user.IsSuperAdmin = body.IsSuperAdmin
}

if body.Tickers != nil {
tickers, err := h.storage.FindTickersByIDs(body.Tickers)
if err != nil {
c.JSON(http.StatusBadRequest, response.ErrorResponse(response.CodeDefault, response.StorageError))
return
}

user.Tickers = tickers
}

err = h.storage.SaveUser(&user)
if err != nil {
c.JSON(http.StatusBadRequest, response.ErrorResponse(response.CodeDefault, response.StorageError))
Expand Down
12 changes: 6 additions & 6 deletions internal/api/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestGetUsersStorageError(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.Set("me", storage.User{IsSuperAdmin: true})
s := &storage.MockStorage{}
s.On("FindUsers").Return([]storage.User{}, errors.New("storage error"))
s.On("FindUsers", mock.Anything).Return([]storage.User{}, errors.New("storage error"))
h := handler{
storage: s,
config: config.NewConfig(),
Expand All @@ -39,7 +39,7 @@ func TestGetUsers(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.Set("me", storage.User{IsSuperAdmin: true})
s := &storage.MockStorage{}
s.On("FindUsers").Return([]storage.User{}, nil)
s.On("FindUsers", mock.Anything).Return([]storage.User{}, nil)

h := handler{
storage: s,
Expand Down Expand Up @@ -89,7 +89,7 @@ func TestGetUserStorageError(t *testing.T) {
c.Set("me", storage.User{ID: 1, IsSuperAdmin: true})

s := &storage.MockStorage{}
s.On("FindUserByID", mock.Anything).Return(storage.User{}, errors.New("storage error"))
s.On("FindUserByID", mock.Anything, mock.Anything).Return(storage.User{}, errors.New("storage error"))
h := handler{
storage: s,
config: config.NewConfig(),
Expand Down Expand Up @@ -267,7 +267,7 @@ func TestPutUserStorageError(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.Set("me", storage.User{ID: 1, IsSuperAdmin: true})
c.Set("user", storage.User{})
json := `{"email":"louis@systemli.org","password":"password1234","isSuperAdmin":true,"tickers":[1]}`
json := `{"email":"louis@systemli.org","password":"password1234","isSuperAdmin":true,"tickers":[{"id":1}]}`
c.Request = httptest.NewRequest(http.MethodPost, "/v1/admin/users", strings.NewReader(json))
c.Request.Header.Add("Content-Type", "application/json")
s := &storage.MockStorage{}
Expand All @@ -288,7 +288,7 @@ func TestPutUserStorageError2(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.Set("me", storage.User{ID: 1, IsSuperAdmin: true})
c.Set("user", storage.User{})
json := `{"email":"louis@systemli.org","password":"password1234","isSuperAdmin":true,"tickers":[1]}`
json := `{"email":"louis@systemli.org","password":"password1234","isSuperAdmin":true,"tickers":[{"id":1}]}`
c.Request = httptest.NewRequest(http.MethodPost, "/v1/admin/users", strings.NewReader(json))
c.Request.Header.Add("Content-Type", "application/json")
s := &storage.MockStorage{}
Expand All @@ -309,7 +309,7 @@ func TestPutUser(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.Set("me", storage.User{ID: 1, IsSuperAdmin: true})
c.Set("user", storage.User{})
json := `{"email":"louis@systemli.org","password":"password1234","isSuperAdmin":true,"tickers":[1]}`
json := `{"email":"louis@systemli.org","password":"password1234","isSuperAdmin":true,"tickers":[{"id":1}]}`
c.Request = httptest.NewRequest(http.MethodPost, "/v1/admin/users", strings.NewReader(json))
c.Request.Header.Add("Content-Type", "application/json")
s := &storage.MockStorage{}
Expand Down
Loading

0 comments on commit c0ded21

Please sign in to comment.