Skip to content

Commit

Permalink
feat: add user api
Browse files Browse the repository at this point in the history
  • Loading branch information
xbmlz committed Jun 22, 2024
1 parent b0e5af9 commit a5ecf93
Show file tree
Hide file tree
Showing 15 changed files with 349 additions and 59 deletions.
12 changes: 4 additions & 8 deletions api/handler/auth_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@ func NewAuthHandler(authService service.AuthService, userService service.UserSer
}
}

// LoginHandler handles login requests
// @Tags Auth
// @Summary Login user
// @Description Login user with username and password
// @Tags auth
// @Accept json
// @Produce json
// @Param request body model.LoginRequest true "Login request"
// @Success 200 {object} model.LoginResponse
// @Success 200 {object} Response{data=model.LoginResponse}
// @Router /login [post]
func (a *AuthHandler) HandleLogin(ctx *gin.Context) {
var req model.LoginRequest
Expand All @@ -52,14 +50,12 @@ func (a *AuthHandler) HandleLogin(ctx *gin.Context) {
})
}

// RegisterHandler handles registration requests
// @Tags Auth
// @Summary Register user
// @Description Register user with username and password
// @Tags auth
// @Accept json
// @Produce json
// @Param request body model.RegisterRequest true "Register request"
// @Success 200 {object} model.RegisterResponse
// @Success 200 {object} Response{data=model.RegisterResponse}
// @Router /register [post]
func (a *AuthHandler) HandleRegister(ctx *gin.Context) {
req := &model.RegisterRequest{}
Expand Down
10 changes: 8 additions & 2 deletions api/handler/user_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@ func NewUserHandler(userService service.UserService) UserHandler {
return UserHandler{userService}
}

func (h UserHandler) HandleGet(ctx *gin.Context) {
// @Tags User
// @Summary User Get By ID
// @Produce application/json
// @Param id path int true "user id"
// @Success 200 {object} model.User
// @router /users/{id} [get]
func (h UserHandler) Get(ctx *gin.Context) {
id := ctx.Param("id")

userId, _ := strconv.Atoi(id)

user, err := h.userService.GetByID(uint(userId))
user, err := h.userService.Get(uint(userId))
if err != nil {
newResponse(ctx).Error(err.Error())
}
Expand Down
7 changes: 7 additions & 0 deletions api/model/base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package model

type BaseModel struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt Datetime `json:"created_at"`
UpdatedAt Datetime `json:"updated_at"`
}
62 changes: 62 additions & 0 deletions api/model/datetime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package model

import (
"database/sql"
"database/sql/driver"
"encoding/json"
"fmt"
"strings"
"time"
)

var DefaultTimeFormat = "2006-01-02 15:04:05"

type Datetime sql.NullTime

// Scan implements the Scanner interface.
func (a *Datetime) Scan(value interface{}) error {
return (*sql.NullTime)(a).Scan(value)
}

// Value implements the driver Valuer interface.
func (a Datetime) Value() (driver.Value, error) {
if !a.Valid {
return nil, nil
}

return a.Time.Format(DefaultTimeFormat), nil
}

func (a Datetime) MarshalJSON() ([]byte, error) {
if a.Valid {
return []byte(fmt.Sprintf("\"%s\"", a.Time.Format(DefaultTimeFormat))), nil
}

return json.Marshal(nil)
}

func (a *Datetime) UnmarshalJSON(b []byte) error {
s := strings.Trim(string(b), "\"")

if s == "null" || s == "" {
a.Valid = false
a.Time = time.Time{}
return nil
}

cst, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
return fmt.Errorf("time.LoadLocation error: %s", err.Error())
}

a.Time, err = time.ParseInLocation(DefaultTimeFormat, s, cst)
if err != nil {
// When time cannot be resolved using the default format, try RFC3339Nano
if a.Time, err = time.ParseInLocation(time.RFC3339Nano, s, cst); err == nil {
a.Time = a.Time.In(cst)
}
}

a.Valid = true
return err
}
6 changes: 2 additions & 4 deletions api/model/user.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package model

import "gorm.io/gorm"

type User struct {
*gorm.Model
BaseModel
Username string `json:"username"`
Password string `json:"password"`
Password string `json:"-"`
}
8 changes: 4 additions & 4 deletions api/repo/user_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package repo

import (
"github.com/nglab-dev/nglab/api/model"
"github.com/nglab-dev/nglab/internal/storage"
"github.com/nglab-dev/nglab/internal/database"
)

type UserRepo struct {
db storage.Storage
db database.Database
}

func NewUserRepo(db storage.Storage) UserRepo {
func NewUserRepo(db database.Database) UserRepo {
return UserRepo{db}
}

Expand All @@ -27,7 +27,7 @@ func (r UserRepo) Create(user *model.User) (err error) {
return
}

func (r UserRepo) GetByID(id uint) (user *model.User, err error) {
func (r UserRepo) Get(id uint) (user *model.User, err error) {
if err = r.db.DB.Where("id = ?", id).First(&user).Error; err != nil {
return nil, err
}
Expand Down
4 changes: 3 additions & 1 deletion api/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "go.uber.org/fx"

var Module = fx.Options(
fx.Provide(NewAuthRouter),
fx.Provide(NewUserRouter),
fx.Provide(NewRouter),
)

Expand All @@ -16,9 +17,10 @@ type IRoute interface {
type Routes []IRoute

// New returns a new router.
func NewRouter(authRouter AuthRouter) Routes {
func NewRouter(authRouter AuthRouter, userRouter UserRouter) Routes {
return Routes{
authRouter,
userRouter,
}
}

Expand Down
6 changes: 3 additions & 3 deletions api/router/user_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ func NewUserRouter(srv server.Server, userHandler handler.UserHandler) UserRoute
}

func (r UserRouter) Setup() {
api := r.srv.Router.Use()
api := r.srv.Router
{
api.POST("/users/{id}", r.userHandler.HandleGet)
api.GET("/users/:id", r.userHandler.Get)
}
slog.Info("Auth router is setup")
slog.Info("User router is setup")
}
7 changes: 2 additions & 5 deletions api/service/user_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,16 @@ import (
"golang.org/x/crypto/bcrypt"
)

// UserService user service layer
type UserService struct {
userRepo repo.UserRepo
}

// NewUserService create new user service
func NewUserService(userRepo repo.UserRepo) UserService {
return UserService{
userRepo,
}
}

// Create user
func (s UserService) Create(user *model.User) error {
if u, err := s.userRepo.GetByUsername(user.Username); err == nil && u != nil {
return errors.New("username already exists")
Expand Down Expand Up @@ -54,6 +51,6 @@ func (s UserService) Verify(username, password string) (*model.User, error) {
return user, nil
}

func (s UserService) GetByID(id uint) (*model.User, error) {
return s.userRepo.GetByID(id)
func (s UserService) Get(id uint) (*model.User, error) {
return s.userRepo.Get(id)
}
8 changes: 4 additions & 4 deletions cmd/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cmd

import (
"github.com/nglab-dev/nglab/internal/config"
"github.com/nglab-dev/nglab/internal/storage"
"github.com/nglab-dev/nglab/internal/database"
"github.com/spf13/cobra"
)

Expand All @@ -19,14 +19,14 @@ var migrateCmd = &cobra.Command{
func runMigrateCmd() {
cfg := config.New()

storage := storage.New(cfg)
sqlDB, err := storage.DB.DB()
db := database.New(cfg)
sqlDB, err := db.DB.DB()
if err != nil {
panic(err)
}
defer sqlDB.Close()

if err = storage.AutoMigrate(); err != nil {
if err = db.AutoMigrate(); err != nil {
panic(err)
}
}
Loading

0 comments on commit a5ecf93

Please sign in to comment.