package api import ( "database/sql" "net/http" "time" db "git.nochill.in/nochill/naice_pos/db/sqlc" "git.nochill.in/nochill/naice_pos/util" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/lib/pq" ) type createUserMerchantRequest struct { Email string `json:"email" binding:"required,email"` Fullname string `json:"fullname" binding:"required,alphanum"` Password string `json:"password" binding:"required"` OutletName string `json:"outlet_name" binding:"required,alphanum"` } type userMerchantResponse struct { ID uuid.UUID `json:"id"` IndexID int64 `json:"index_id"` Email string `json:"email"` Fullname string `json:"fullname"` CreatedAt sql.NullTime `json:"created_at"` UpdatedAt sql.NullTime `json:"updated_at"` Outlet db.Merchant `json:"outlet"` } func newUserMerchantResponse(user db.GetUserByEmailRow, merchant db.Merchant) userMerchantResponse { return userMerchantResponse{ ID: user.ID, IndexID: user.IndexID, Email: user.Email, Fullname: user.Fullname, CreatedAt: sql.NullTime{Valid: true, Time: user.CreatedAt.Time}, UpdatedAt: sql.NullTime{Valid: true, Time: user.UpdatedAt.Time}, Outlet: merchant, } } func (server *Server) createUserMerchant(ctx *gin.Context) { var req createUserMerchantRequest if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err)) return } hashedPassword, err := util.HashPassword(req.Password) if err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } arg := db.UserMerchantTxParams{ Email: req.Email, Fullname: req.Fullname, Password: hashedPassword, OutletName: req.OutletName, } user, err := server.store.CreateUserMerchantTx(ctx, arg) if err != nil { if pqErr, ok := err.(*pq.Error); ok { switch pqErr.Code.Name() { case "foreign_key_violation", "unique_violation": ctx.JSON(http.StatusConflict, errorResponse(err)) return } } ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } res := userMerchantResponse{ ID: user.OwnerProfile.ID, IndexID: user.OwnerProfile.IndexID, Email: user.OwnerProfile.Email, Fullname: user.OwnerProfile.Fullname, CreatedAt: sql.NullTime{Valid: true, Time: user.OwnerProfile.CreatedAt.Time}, UpdatedAt: sql.NullTime{Valid: true, Time: user.OwnerProfile.UpdatedAt.Time}, Outlet: user.OutletProfile, } ctx.JSON(http.StatusOK, res) } type userLoginRequest struct { Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required"` } type userLoginResponse struct { SessionID uuid.UUID `json:"session_id"` AccesToken string `json:"access_token"` AccessTokenExpiresAt time.Time `json:"access_token_expires_at"` RefreshToken string `json:"refresh_token"` RefreshTokenExpiresAt time.Time `json:"refresh_token_expires_at"` UserMerchantResponse userMerchantResponse } func (server *Server) loginUser(ctx *gin.Context) { var req userLoginRequest if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err)) return } user, err := server.store.GetUserByEmail(ctx, req.Email) if err != nil { if err == sql.ErrNoRows { ctx.JSON(http.StatusNotFound, errorResponse(err)) return } ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } outlet, err := server.store.GetMerchantByUserId(ctx, user.ID) if err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } err = util.CheckPassword(req.Password, user.Password) if err != nil { ctx.JSON(http.StatusUnauthorized, errorResponse(err)) return } accessToken, accessPayload, err := server.tokenMaker.CreateToken( user.Email, outlet.ID.String(), server.config.TokenDuration, ) if err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } refreshToken, refreshTokenPayload, err := server.tokenMaker.CreateToken( user.Email, outlet.ID.String(), server.config.RefreshTokenDuration, ) session, err := server.store.CreateSession(ctx, db.CreateSessionParams{ ID: refreshTokenPayload.ID, Email: user.Email, RefreshToken: refreshToken, UserAgent: ctx.Request.UserAgent(), ClientIp: ctx.ClientIP(), IsBlocked: false, ExpiresAt: refreshTokenPayload.ExpiredAt, }) if err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err)) return } res := userLoginResponse{ SessionID: session.ID, AccesToken: accessToken, AccessTokenExpiresAt: accessPayload.ExpiredAt, RefreshToken: refreshToken, RefreshTokenExpiresAt: refreshTokenPayload.ExpiredAt, UserMerchantResponse: newUserMerchantResponse(user, outlet), } ctx.JSON(http.StatusOK, res) }