fix: make user signup work for the minimum
A lot of work is still to be done ...
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -25,3 +25,4 @@ go.work.sum
 | 
				
			|||||||
# Custom
 | 
					# Custom
 | 
				
			||||||
/_output
 | 
					/_output
 | 
				
			||||||
/deployment/db_data
 | 
					/deployment/db_data
 | 
				
			||||||
 | 
					/tmp/**
 | 
				
			||||||
 | 
				
			|||||||
@ -39,7 +39,7 @@ tags:
 | 
				
			|||||||
  - name: user
 | 
					  - name: user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
paths:
 | 
					paths:
 | 
				
			||||||
  /signup:
 | 
					  /user/signup:
 | 
				
			||||||
    post:
 | 
					    post:
 | 
				
			||||||
      tags:
 | 
					      tags:
 | 
				
			||||||
        - user
 | 
					        - user
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										7
									
								
								docs/error_code.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								docs/error_code.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					# Platform level error code design
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- InternalError
 | 
				
			||||||
 | 
					- InvalidParameter
 | 
				
			||||||
 | 
					- AuthFailure
 | 
				
			||||||
 | 
					- ResourceNotFound
 | 
				
			||||||
 | 
					- FailedOperation
 | 
				
			||||||
@ -25,33 +25,66 @@ package controller
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.vinchent.xyz/vinchent/howmuch/internal/howmuch/model"
 | 
				
			||||||
 | 
						"git.vinchent.xyz/vinchent/howmuch/internal/howmuch/usecase/usecase"
 | 
				
			||||||
	"git.vinchent.xyz/vinchent/howmuch/internal/pkg/core"
 | 
						"git.vinchent.xyz/vinchent/howmuch/internal/pkg/core"
 | 
				
			||||||
 | 
						"git.vinchent.xyz/vinchent/howmuch/internal/pkg/errno"
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// User is the user controller interface, it describes all the handlers
 | 
					// User is the user controller interface, it describes all the handlers
 | 
				
			||||||
// that need to be implemented for the /user endpoint
 | 
					// that need to be implemented for the /user endpoint
 | 
				
			||||||
type User interface {
 | 
					type User interface {
 | 
				
			||||||
	Signup(core.Context)
 | 
						Signup(core.Context)
 | 
				
			||||||
	UpdateInfo(core.Context)
 | 
						UpdateInfo(*gin.Context)
 | 
				
			||||||
	Login(core.Context)
 | 
						Login(*gin.Context)
 | 
				
			||||||
	Logout(core.Context)
 | 
						Logout(*gin.Context)
 | 
				
			||||||
	ChangePassword(core.Context)
 | 
						ChangePassword(*gin.Context)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type UserController struct{}
 | 
					type UserController struct {
 | 
				
			||||||
 | 
						userUsecase usecase.User
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var UserParamsErr = &errno.Errno{
 | 
				
			||||||
 | 
						HTTP:    http.StatusBadRequest,
 | 
				
			||||||
 | 
						Code:    errno.ErrorCode(errno.InvalidParameterCode, "UserParamsErr"),
 | 
				
			||||||
 | 
						Message: "user info is not correct",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewUserController(us usecase.User) User {
 | 
				
			||||||
 | 
						return &UserController{
 | 
				
			||||||
 | 
							userUsecase: us,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (uc *UserController) Signup(ctx core.Context) {
 | 
					func (uc *UserController) Signup(ctx core.Context) {
 | 
				
			||||||
	ctx.JSON(http.StatusOK, "hello")
 | 
						var params model.User
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := ctx.Bind(¶ms); err != nil {
 | 
				
			||||||
 | 
							core.WriteResponse(ctx, UserParamsErr, nil)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: check params validity (govalidator)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := uc.userUsecase.Create(ctx, ¶ms)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							core.WriteResponse(ctx, err, nil)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						core.WriteResponse(ctx, errno.OK, nil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (uc *UserController) UpdateInfo(ctx core.Context) {
 | 
					func (uc *UserController) UpdateInfo(ctx *gin.Context) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (uc *UserController) Login(ctx core.Context) {
 | 
					func (uc *UserController) Login(ctx *gin.Context) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (uc *UserController) Logout(ctx core.Context) {
 | 
					func (uc *UserController) Logout(ctx *gin.Context) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (uc *UserController) ChangePassword(ctx core.Context) {
 | 
					func (uc *UserController) ChangePassword(ctx *gin.Context) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -34,9 +34,6 @@ import (
 | 
				
			|||||||
	"github.com/jackc/pgx/v5/pgtype"
 | 
						"github.com/jackc/pgx/v5/pgtype"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get business service model, convert to the DB model (generated by sqlc)
 | 
					 | 
				
			||||||
// To test repo's methods, I have to mock a pgx.Conn
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type userRepository struct {
 | 
					type userRepository struct {
 | 
				
			||||||
	db *pgx.Conn
 | 
						db *pgx.Conn
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -67,9 +64,9 @@ func (ur *userRepository) Create(
 | 
				
			|||||||
		UpdatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true},
 | 
							UpdatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tx, ok := transaction.(*pgx.Conn)
 | 
						tx, ok := transaction.(pgx.Tx)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return nil, errors.New("transaction is not a *pgx.Conn")
 | 
							return nil, errors.New("transaction is not a pgx.Tx")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	queries := sqlc.New(tx)
 | 
						queries := sqlc.New(tx)
 | 
				
			||||||
 | 
				
			|||||||
@ -48,7 +48,13 @@ func Routes(engine *gin.Engine, c controller.AppController) *gin.Engine {
 | 
				
			|||||||
		core.WriteResponse(ctx, errno.PageNotFoundErr, nil)
 | 
							core.WriteResponse(ctx, errno.PageNotFoundErr, nil)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	engine.POST("/signup", func(ctx *gin.Context) { c.User.Signup(ctx) })
 | 
						v1 := engine.Group("/v1")
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							userV1 := v1.Group("/user")
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								userV1.POST("/signup", func(ctx *gin.Context) { c.User.Signup(ctx) })
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return engine
 | 
						return engine
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -22,9 +22,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package registry
 | 
					package registry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "git.vinchent.xyz/vinchent/howmuch/internal/howmuch/adapter/controller"
 | 
					import (
 | 
				
			||||||
 | 
						"git.vinchent.xyz/vinchent/howmuch/internal/howmuch/adapter/controller"
 | 
				
			||||||
 | 
						"git.vinchent.xyz/vinchent/howmuch/internal/howmuch/adapter/repo"
 | 
				
			||||||
 | 
						"git.vinchent.xyz/vinchent/howmuch/internal/howmuch/usecase/usecase"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewUserController returns a user controller's implementation
 | 
					// NewUserController returns a user controller's implementation
 | 
				
			||||||
func (r *registry) NewUserController() controller.User {
 | 
					func (r *registry) NewUserController() controller.User {
 | 
				
			||||||
	return &controller.UserController{}
 | 
						u := usecase.NewUserUsecase(repo.NewUserRepository(r.db), repo.NewDBRepository(r.db))
 | 
				
			||||||
 | 
						return controller.NewUserController(u)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -68,11 +68,11 @@ func (uuc *userUsecase) Create(ctx context.Context, u *model.User) (*model.User,
 | 
				
			|||||||
			return u, err
 | 
								return u, err
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	user := data.(*model.User)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						user := data.(*model.User)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return user, nil
 | 
						return user, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,18 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package core
 | 
					package core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Context interface {
 | 
					type Context interface {
 | 
				
			||||||
 | 
						// Context
 | 
				
			||||||
 | 
						Deadline() (deadline time.Time, ok bool)
 | 
				
			||||||
 | 
						Done() <-chan struct{}
 | 
				
			||||||
 | 
						Err() error
 | 
				
			||||||
 | 
						Value(key any) any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Request
 | 
				
			||||||
 | 
						Bind(obj any) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Response
 | 
				
			||||||
	JSON(code int, obj any)
 | 
						JSON(code int, obj any)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -24,18 +24,28 @@ package errno
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import "net/http"
 | 
					import "net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PlatformLevelErrCode string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						InternalErrorCode    = "InternalError"
 | 
				
			||||||
 | 
						InvalidParameterCode = "InvalidParameter"
 | 
				
			||||||
 | 
						AuthFailureCode      = "AuthFailure"
 | 
				
			||||||
 | 
						ResourceNotFoundCode = "ResourceNotFound"
 | 
				
			||||||
 | 
						FailedOperationCode  = "FailedOperation"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	OK = &Errno{HTTP: http.StatusOK, Code: "", Message: ""}
 | 
						OK = &Errno{HTTP: http.StatusOK, Code: "", Message: ""}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	InternalServerErr = &Errno{
 | 
						InternalServerErr = &Errno{
 | 
				
			||||||
		HTTP:    http.StatusInternalServerError,
 | 
							HTTP:    http.StatusInternalServerError,
 | 
				
			||||||
		Code:    "InternalError",
 | 
							Code:    InternalErrorCode,
 | 
				
			||||||
		Message: "Internal server error",
 | 
							Message: "Internal server error",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PageNotFoundErr = &Errno{
 | 
						PageNotFoundErr = &Errno{
 | 
				
			||||||
		HTTP:    http.StatusNotFound,
 | 
							HTTP:    http.StatusNotFound,
 | 
				
			||||||
		Code:    "ResourceNotFound.PageNotFound",
 | 
							Code:    ErrorCode(ResourceNotFoundCode, "PageNotFound"),
 | 
				
			||||||
		Message: "Page not found",
 | 
							Message: "Page not found",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,10 @@ type Errno struct {
 | 
				
			|||||||
	Message string
 | 
						Message string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ErrorCode(platformErrCode string, resourceErrCode string) string {
 | 
				
			||||||
 | 
						return platformErrCode + "." + resourceErrCode
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Error implements Error() method in error interface
 | 
					// Error implements Error() method in error interface
 | 
				
			||||||
func (err *Errno) Error() string {
 | 
					func (err *Errno) Error() string {
 | 
				
			||||||
	return err.Message
 | 
						return err.Message
 | 
				
			||||||
 | 
				
			|||||||
@ -1 +0,0 @@
 | 
				
			|||||||
exit status 2exit status 2exit status 2exit status 2exit status 2
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user