Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor user handlers' code #5

Merged
merged 2 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion internal/handlers/user/create_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package user
import (
"encoding/json"
"errors"
"hash"
"net/http"
"questspace/internal/validate"
aerrors "questspace/pkg/application/errors"
Expand All @@ -18,15 +19,20 @@ const defaultAvatarURL = "https://api.dicebear.com/7.x/thumbs/svg"
type CreateHandler struct {
storage storage.UserStorage
fetcher http.Client
hasher hash.Hash
}

func NewCreateHandler(s storage.UserStorage, f http.Client) CreateHandler {
func NewCreateHandler(s storage.UserStorage, f http.Client, h hash.Hash) CreateHandler {
return CreateHandler{
storage: s,
fetcher: f,
hasher: h,
}
}

// @Param request body storage.CreateUserRequest true "query params"
// @Success 200 {object} storage.User
// @Router /user [post]
func (h CreateHandler) Handle(c *gin.Context) error {
data, err := c.GetRawData()
if err != nil {
Expand All @@ -42,6 +48,7 @@ func (h CreateHandler) Handle(c *gin.Context) error {
if req.AvatarURL == "" {
req.AvatarURL = defaultAvatarURL
}
req.Password = string(h.hasher.Sum([]byte(req.Password)))
user, err := h.storage.CreateUser(c, &req)
if err != nil {
if errors.Is(err, storage.ErrExists) {
Expand Down
16 changes: 12 additions & 4 deletions internal/handlers/user/create_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package user

import (
"bytes"
"crypto/sha256"
"encoding/json"
"net/http"
"net/http/httptest"
Expand Down Expand Up @@ -86,7 +87,8 @@ func TestCreateHandler_CommonCases(t *testing.T) {
ctrl := gomock.NewController(t)
userStorage := mocks.NewMockUserStorage(ctrl)
router := gin.Default()
handler := NewCreateHandler(userStorage, http.Client{})
hasher := sha256.New()
handler := NewCreateHandler(userStorage, http.Client{}, hasher)
router.POST("/test", application.AsGinHandler(handler.Handle))

for _, tc := range testCases {
Expand All @@ -105,9 +107,14 @@ func TestCreateHandler_CommonCases(t *testing.T) {
require.NoError(t, err)
request, err := http.NewRequest(http.MethodPost, "/test", bytes.NewReader(raw))
require.NoError(t, err)
actualReq := &storage.CreateUserRequest{
Username: tc.req.Username,
Password: string(hasher.Sum([]byte(tc.req.Password))),
AvatarURL: tc.req.AvatarURL,
}

if tc.wantStore {
userStorage.EXPECT().CreateUser(gomock.Any(), tc.req).Return(nil, tc.storeErr)
userStorage.EXPECT().CreateUser(gomock.Any(), actualReq).Return(nil, tc.storeErr)
}

router.ServeHTTP(rr, request)
Expand All @@ -120,9 +127,10 @@ func TestCreateHandler_SetsDefaultURL(t *testing.T) {
gin.SetMode(gin.TestMode)
ctrl := gomock.NewController(t)
userStorage := mocks.NewMockUserStorage(ctrl)
hasher := sha256.New()
rr := httptest.NewRecorder()
router := gin.Default()
handler := NewCreateHandler(userStorage, http.Client{})
handler := NewCreateHandler(userStorage, http.Client{}, hasher)
router.POST("/test", application.AsGinHandler(handler.Handle))

req := &storage.CreateUserRequest{
Expand All @@ -131,7 +139,7 @@ func TestCreateHandler_SetsDefaultURL(t *testing.T) {
}
storageReq := &storage.CreateUserRequest{
Username: "user",
Password: "password",
Password: string(hasher.Sum([]byte("password"))),
AvatarURL: defaultAvatarURL,
}

Expand Down
11 changes: 6 additions & 5 deletions internal/pgdb/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ func (c *Client) CreateUser(ctx context.Context, req *storage.CreateUserRequest)
Columns("username", "password").
Suffix("RETURNING id").
PlaceholderFormat(sq.Dollar)
if req.FirstName != "" && req.LastName != "" {
query = query.Columns("first_name", "last_name")
values = append(values, req.FirstName, req.LastName)
}
if req.AvatarURL != "" {
query = query.Columns("avatar_url")
values = append(values, req.AvatarURL)
Expand All @@ -64,7 +60,12 @@ func (c *Client) CreateUser(ctx context.Context, req *storage.CreateUserRequest)
if err := row.Scan(&id); err != nil {
return nil, xerrors.Errorf("failed to scan row: %w", err)
}
user := storage.User(*req)
user := storage.User{
Id: id,
Username: req.Username,
Password: req.Password,
AvatarURL: req.AvatarURL,
}
user.Id = id
return &user, nil
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE "user" DROP COLUMN first_name, DROP COLUMN last_name;
4 changes: 3 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"crypto/sha256"
"fmt"
"net/http"
user "questspace/internal/handlers/user"
Expand Down Expand Up @@ -70,10 +71,11 @@ func Init(app application.App) error {
}
sqlStorage := pgdb.NewClient(conn)
client := http.Client{}
hasher := sha256.New()

userGroup := app.Router().Group("/user")

createHandler := user.NewCreateHandler(sqlStorage, client)
createHandler := user.NewCreateHandler(sqlStorage, client, hasher)
userGroup.POST("", application.AsGinHandler(createHandler.Handle))

getHandler := user.NewGetHandler(sqlStorage)
Expand Down
28 changes: 0 additions & 28 deletions pkg/storage/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,6 @@ type Quest struct {
MaxTeamCap *int
}

type CreateQuestRequest Quest

type GetQuestRequest struct {
Id string
}

type UpdateQuestRequest Quest

type DeleteQuestRequest GetQuestRequest

type Team struct {
Id string
Name string
Expand All @@ -58,25 +48,7 @@ type Team struct {
InviteLink string
}

type CreateTeamRequest Team

type User struct {
Id string `json:"id"`
Username string `json:"username"`
Password string `json:"password,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
}

type CreateUserRequest User

type GetUserRequest struct {
Id string
Username string
}

type UpdateUserRequest struct {
Id string `json:"id"`
Username string `json:"username"`
Password string `json:"password,omitempty"`
Expand Down
56 changes: 56 additions & 0 deletions pkg/storage/requests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package storage

import "time"

type CreateUserRequest struct {
Username string `json:"username"`
Password string `json:"password,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
}

type GetUserRequest struct {
Id string
Username string
}

type UpdateUserRequest struct {
Id string `json:"id"`
Username string `json:"username"`
Password string `json:"password,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
}

type CreateQuestRequest struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Access AccessType `json:"access"`
CreatorName string `json:"creator_name"`
Creator *User `json:"-"`
RegistrationDeadline *time.Time `json:"registration_deadline"`
StartTime *time.Time `json:"start_time"`
FinishTime *time.Time `json:"finish_time"`
MediaLink string `json:"media_link"`
MaxTeamCap *int `json:"max_team_cap"`
}

type GetQuestRequest struct {
Id string
}

type UpdateQuestRequest struct {
Id string `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Access AccessType `json:"access"`
CreatorName string `json:"creator_name"`
Creator *User `json:"-"`
RegistrationDeadline *time.Time `json:"registration_deadline"`
StartTime *time.Time `json:"start_time"`
FinishTime *time.Time `json:"finish_time"`
MediaLink string `json:"media_link"`
MaxTeamCap *int `json:"max_team_cap"`
}

type DeleteQuestRequest struct {
Id string
}