Go, Gin, MySQL 및 Docker를 사용한 블로그 프로젝트 - 3부
38385 단어 dockermysqlgoarchitecture
Part 2 및 Part 1을 통과했는지 확인하십시오.
참고: 이 시리즈의 모든 코드는 여기repo에서 찾을 수 있습니다. 이 문서의 코드를 얻으려면
part-3
를 통해 분기git checkout part-3
를 확인하십시오.내용물
사용자 API 및 인증 생성
사용자 구조체 설계
models
폴더 안에 아래 내용이 있는 user.go
파일을 추가합니다.package models
import "time"
//User -> User struct to save user on database
type User struct {
ID int64 `gorm:primary_key;auto_increment;json:id`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
Password string `json:"password"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at", omitempty`
UpdatedAt time.Time `json:"updated_at", omitempty`
}
//TableName -> returns the table name of User Model
func (user *User) TableName() string {
return "user"
}
//UserLogin -> Request Binding for User Login
type UserLogin struct {
Email string `form:"email" binding:"required"`
Password string `form:"password" binding:"required"`
}
//UserRegister -> Request Binding for User Register
type UserRegister struct {
Email string `form:"email" json:"email" binding:"required"`
Password string `form:"password" json:"password" binding:"required"`
FirstName string `form:"first_name"`
LastName string `form:"last_name"`
}
//ResponseMap -> response map method of User
func (user *User) ResponseMap() map[string]interface{} {
resp := make(map[string]interface{})
resp["id"] = user.ID
resp["email"] = user.Email
resp["first_name"] = user.FirstName
resp["last_name"] = user.LastName
resp["is_active"] = user.IsActive
resp["created_at"] = user.CreatedAt
resp["updated_at"] = user.UpdatedAt
return resp
}
해시된 비밀번호 해시 및 비교
보안을 위해 데이터베이스에서 해시된 암호를 암호화합니다. 명령줄에서
go get golang.org/x/crypto/bcrypt
를 실행하여 bcrypt
패키지를 설치합니다. util/password.go
파일을 생성하고 다음 코드를 추가합니다.Note : A project directory structure is shown down below
package util
import "golang.org/x/crypto/bcrypt"
func HashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
return string(bytes), err
}
func CheckPasswordHash(password string, hash string) error {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err
}
사용자 등록 및 로그인 저장소
api/repository/user.go
파일을 추가하고 다음 코드를 추가합니다.package repository
import (
"blog/infrastructure"
"blog/models"
"blog/util"
)
//UserRepository -> UserRepository resposible for accessing database
type UserRepository struct {
db infrastructure.Database
}
//NewUserRepository -> creates a instance on UserRepository
func NewUserRepository(db infrastructure.Database) UserRepository {
return UserRepository{
db: db,
}
}
//CreateUser -> method for saving user to database
func (u UserRepository) CreateUser(user models.UserRegister) error {
var dbUser models.User
dbUser.Email = user.Email
dbUser.FirstName = user.FirstName
dbUser.LastName = user.LastName
dbUser.Password = user.Password
dbUser.IsActive = true
return u.db.DB.Create(&dbUser).Error
}
//LoginUser -> method for returning user
func (u UserRepository) LoginUser(user models.UserLogin) (*models.User, error) {
var dbUser models.User
email := user.Email
password := user.Password
err := u.db.DB.Where("email = ?", email).First(&dbUser).Error
if err != nil {
return nil, err
}
hashErr := util.CheckPasswordHash(password, dbUser.Password)
if hashErr != nil {
return nil, hashErr
}
return &dbUser, nil
}
여기
dbUser.IsActive = true
이것은 약간 잘못된 것 같습니까? 아니요, 일부러 지금입니다. 나중에 다가오는 부분에서 우리는 이메일을 통해 사용자 확인을 구현할 것입니다.사용자 등록 및 로그인 서비스
api/service/user.go
파일을 추가하고 다음 코드를 추가합니다.package service
import (
"blog/api/repository"
"blog/models"
)
//UserService UserService struct
type UserService struct {
repo repository.UserRepository
}
//NewUserService : get injected user repo
func NewUserService(repo repository.UserRepository) UserService {
return UserService{
repo: repo,
}
}
//Save -> saves users entity
func (u UserService) CreateUser(user models.UserRegister) error {
return u.repo.CreateUser(user)
}
//Login -> Gets validated user
func (u UserService) LoginUser(user models.UserLogin) (*models.User, error) {
return u.repo.LoginUser(user)
}
사용자 등록 및 로그인 컨트롤러
jwt
패키지 설치go get github.com/golang-jwt/jwt
이 패키지는 JWT 토큰을 발행하는 데 사용됩니다. api/controller/user.go
파일을 추가하고 다음을 추가합니다.package controller
import (
"blog/api/service"
"blog/models"
"blog/util"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt"
)
//UserController struct
type UserController struct {
service service.UserService
}
//NewUserController : NewUserController
func NewUserController(s service.UserService) UserController {
return UserController{
service: s,
}
}
//CreateUser -> calls CreateUser services for validated user
func (u *UserController) CreateUser(c *gin.Context) {
var user models.UserRegister
if err := c.ShouldBind(&user); err != nil {
util.ErrorJSON(c, http.StatusBadRequest, "Inavlid Json Provided")
return
}
hashPassword, _ := util.HashPassword(user.Password)
user.Password = hashPassword
err := u.service.CreateUser(user)
if err != nil {
util.ErrorJSON(c, http.StatusBadRequest, "Failed to create user")
return
}
util.SuccessJSON(c, http.StatusOK, "Successfully Created user")
}
//LoginUser : Generates JWT Token for validated user
func (u *UserController) Login(c *gin.Context) {
var user models.UserLogin
var hmacSampleSecret []byte
if err := c.ShouldBindJSON(&user); err != nil {
util.ErrorJSON(c, http.StatusBadRequest, "Inavlid Json Provided")
return
}
dbUser, err := u.service.LoginUser(user)
if err != nil {
util.ErrorJSON(c, http.StatusBadRequest, "Invalid Login Credentials")
return
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"user": dbUser,
"exp": time.Now().Add(time.Minute * 15).Unix(),
})
tokenString, err := token.SignedString(hmacSampleSecret)
if err != nil {
util.ErrorJSON(c, http.StatusBadRequest, "Failed to get token")
return
}
response := &util.Response{
Success: true,
Message: "Token generated sucessfully",
Data: tokenString,
}
c.JSON(http.StatusOK, response)
}
사용자 등록 및 로그인 경로
마지막으로 등록 및 로그인 api를 노출할 수 있는 부분에 도달했습니다.
api/routes/user.go
에 다음 코드를 추가합니다.package routes
import (
"blog/api/controller"
"blog/infrastructure"
)
//UserRoute -> Route for user module
type UserRoute struct {
Handler infrastructure.GinRouter
Controller controller.UserController
}
//NewUserRoute -> initializes new instance of UserRoute
func NewUserRoute(
controller controller.UserController,
handler infrastructure.GinRouter,
) UserRoute {
return UserRoute{
Handler: handler,
Controller: controller,
}
}
//Setup -> setups user routes
func (u UserRoute) Setup() {
user := u.Handler.Gin.Group("/auth")
{
user.POST("/register", u.Controller.CreateUser)
user.POST("/login", u.Controller.LoginUser)
}
}
위의 코드는 사용자 인증 경로
register
및 login
를 구성합니다.main.go 구성
이제 마지막 코드는
main.go
파일을 업데이트하여 모든 것을 하나로 묶는 것입니다.package main
import (
"blog/api/controller"
"blog/api/repository"
"blog/api/routes"
"blog/api/service"
"blog/infrastructure"
"blog/models"
)
func init() {
infrastructure.LoadEnv()
}
func main() {
router := infrastructure.NewGinRouter()
db := infrastructure.NewDatabase()
postRepository := repository.NewPostRepository(db)
postService := service.NewPostService(postRepository)
postController := controller.NewPostController(postService)
postRoute := routes.NewPostRoute(postController, router)
postRoute.Setup()
// add up these
userRepository := repository.NewUserRepository(db)
userService := service.NewUserService(userRepository)
userController := controller.NewUserController(userService)
userRoute := routes.NewUserRoute(userController, router)
userRoute.Setup()
db.DB.AutoMigrate(&models.Post{}, &models.User{})
router.Gin.Run(":8000")
}
API 데모
이제 서버를 가동하고
register
및 login
api를 테스트할 시간입니다.docker-compose up --build
이제 좋아하는 API 테스터 애플리케이션을 불러옵니다. 나는 사용할 것이다 postman
등록 엔드포인트 테스트 -> /auth/register
로그인 끝점 테스트 -> /auth/login
jwt.io에서 토큰 확인
마무리
다음으로 예정된 파트 4에서는 다음 내용을 다룹니다.
중요 링크:
정말 감사합니다! 피드백은 정말 감사합니다. 나는 . 연결합시다.
즐거운 독서!!!
Reference
이 문제에 관하여(Go, Gin, MySQL 및 Docker를 사용한 블로그 프로젝트 - 3부), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/umschaudhary/blog-project-with-go-gin-mysql-and-docker-part-3-1na4텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)