changes...

This commit is contained in:
KamilM1205 2025-09-22 22:12:49 +04:00
parent 41944884b4
commit ab4b53fd40
26 changed files with 600 additions and 51 deletions

View file

@ -20,9 +20,12 @@ import (
"58team_blog/internal/infrastructure/db" "58team_blog/internal/infrastructure/db"
"58team_blog/internal/infrastructure/db/repo" "58team_blog/internal/infrastructure/db/repo"
"58team_blog/internal/interfaces" "58team_blog/internal/interfaces"
"58team_blog/internal/utils"
"log" "log"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
swaggerFiles "github.com/swaggo/files" swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger" ginSwagger "github.com/swaggo/gin-swagger"
) )
@ -30,6 +33,11 @@ import (
func main() { func main() {
router := gin.Default() router := gin.Default()
// Register custom validators
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("password", utils.PasswordValidator)
}
// Swagger setup // Swagger setup
docs.SwaggerInfo.Title = "58team blog" docs.SwaggerInfo.Title = "58team blog"
docs.SwaggerInfo.Description = "This is blog 58team" docs.SwaggerInfo.Description = "This is blog 58team"
@ -38,14 +46,6 @@ func main() {
docs.SwaggerInfo.BasePath = "/api/v1/" docs.SwaggerInfo.BasePath = "/api/v1/"
docs.SwaggerInfo.Schemes = []string{"http", "https"} docs.SwaggerInfo.Schemes = []string{"http", "https"}
// router.GET("/swagger/*any", func(c *gin.Context) {
// path := c.Param("any")
// if strings.HasPrefix(path, "/doc.json") {
// c.File("docs/swagger.json")
// } else {
//
// }
// })
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.URL("http://localhost:8080/swag/doc/doc.json"))) router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.URL("http://localhost:8080/swag/doc/doc.json")))
router.StaticFile("/swag/doc/doc.json", "docs/swagger.json") router.StaticFile("/swag/doc/doc.json", "docs/swagger.json")
@ -61,10 +61,15 @@ func main() {
if err != nil { if err != nil {
log.Fatal("Database error: ", err) log.Fatal("Database error: ", err)
} }
postRepository := repo.CreatePostRepository(d) postRepository := repo.CreatePostRepository(d)
userRepository := repo.CreateUserRepository(d)
postService := services.CreatePostService(&postRepository) postService := services.CreatePostService(&postRepository)
userService := services.CreateUserService(&userRepository)
interfaces.BindPostAdmin(&postService, g) interfaces.BindPostAdmin(&postService, g)
interfaces.BindUser(&userService, g)
router.Run(":8080") router.Run(":8080")
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -21,6 +21,20 @@ definitions:
- title - title
- userId - userId
type: object type: object
requests.CreateUserRequest:
properties:
password:
maxLength: 32
minLength: 6
type: string
username:
maxLength: 32
minLength: 3
type: string
required:
- password
- username
type: object
requests.PutPostRequest: requests.PutPostRequest:
properties: properties:
content: content:
@ -30,6 +44,20 @@ definitions:
title: title:
type: string type: string
type: object type: object
requests.PutUserRequest:
properties:
password:
maxLength: 32
minLength: 6
type: string
username:
maxLength: 32
minLength: 3
type: string
required:
- password
- username
type: object
responses.ErrorResponse: responses.ErrorResponse:
properties: properties:
error_code: error_code:
@ -63,6 +91,13 @@ definitions:
userId: userId:
type: string type: string
type: object type: object
responses.UserResponse:
properties:
id:
type: string
username:
type: string
type: object
host: localhost:8080 host: localhost:8080
info: info:
contact: contact:
@ -79,7 +114,7 @@ info:
paths: paths:
/images/{path}: /images/{path}:
get: get:
description: Creates new user in system description: get image by path
parameters: parameters:
- description: Path to image - description: Path to image
in: query in: query
@ -87,11 +122,12 @@ paths:
required: true required: true
type: string type: string
produces: produces:
- application/json - image/png
- image/jpeg
responses: responses:
"200": "200":
description: OK description: OK
summary: Create new user summary: Get an image by path
/post: /post:
get: get:
description: Return first 5 posts description: Return first 5 posts
@ -125,8 +161,8 @@ paths:
produces: produces:
- application/json - application/json
responses: responses:
"200": "201":
description: OK description: Created
schema: schema:
$ref: '#/definitions/responses.PostResponse' $ref: '#/definitions/responses.PostResponse'
"400": "400":
@ -238,6 +274,150 @@ paths:
summary: Get posts after offset summary: Get posts after offset
tags: tags:
- post - post
/user/:
get:
description: Return all registered users
produces:
- application/json
responses:
"200":
description: OK
schema:
items:
$ref: '#/definitions/responses.UserResponse'
type: array
"400":
description: Bad Request
schema:
$ref: '#/definitions/responses.ErrorResponse'
summary: Get all users
tags:
- user
post:
consumes:
- application/json
description: Creates new user in system
parameters:
- description: User data
in: body
name: request
required: true
schema:
$ref: '#/definitions/requests.CreateUserRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/responses.UserResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/responses.ErrorResponse'
summary: Create new user
tags:
- user
/user/{id}:
delete:
description: Delete user
parameters:
- description: User id
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
"400":
description: Bad Request
schema:
$ref: '#/definitions/responses.ErrorResponse'
summary: Delete user
tags:
- user
get:
consumes:
- application/json
description: Find user by id
parameters:
- description: user id
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/responses.UserResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/responses.ErrorResponse'
summary: Find user by id
tags:
- user
put:
consumes:
- application/json
description: Change the user's name and password
parameters:
- description: User id
in: path
name: id
required: true
type: string
- description: User data
in: body
name: request
required: true
schema:
$ref: '#/definitions/requests.PutUserRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/responses.UserResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/responses.ErrorResponse'
summary: Change user
tags:
- user
/user/name/{name}:
get:
consumes:
- application/json
description: Find user by username
parameters:
- description: User name
in: path
name: name
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/responses.UserResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/responses.ErrorResponse'
summary: Find user by username
tags:
- user
securityDefinitions: securityDefinitions:
BasicAuth: BasicAuth:
type: basic type: basic

View file

@ -0,0 +1,15 @@
package errors
type DBError struct {
msg string
}
func NewDBError(msg string) DBError {
return DBError{
msg: msg,
}
}
func (e *DBError) Error() string {
return e.msg
}

View file

@ -0,0 +1,15 @@
package errors
type NotFoundError struct {
msg string
}
func NewNotFoundError(msg string) *NotFoundError {
return &NotFoundError{
msg: msg,
}
}
func (e *NotFoundError) Error() string {
return e.msg
}

View file

@ -3,6 +3,7 @@ package services
import ( import (
"58team_blog/internal/application/commands" "58team_blog/internal/application/commands"
"58team_blog/internal/application/common" "58team_blog/internal/application/common"
ie "58team_blog/internal/application/errors"
"58team_blog/internal/application/mapper" "58team_blog/internal/application/mapper"
"58team_blog/internal/application/queries" "58team_blog/internal/application/queries"
"58team_blog/internal/domain/entities" "58team_blog/internal/domain/entities"
@ -44,6 +45,10 @@ func (s *PostService) FindById(query queries.PostFindByIdQuery) (*queries.PostFi
return nil, err return nil, err
} }
if post == nil {
return nil, ie.NewNotFoundError("Post")
}
if err := post.Validate(); err != nil { if err := post.Validate(); err != nil {
return nil, err return nil, err
} }

View file

@ -15,7 +15,7 @@ type UserService struct {
repo repository.UsersRepository repo repository.UsersRepository
} }
func NewUserService(repo repository.UsersRepository) UserService { func CreateUserService(repo repository.UsersRepository) UserService {
return UserService{ return UserService{
repo: repo, repo: repo,
} }
@ -26,7 +26,7 @@ func (s *UserService) Create(cmd commands.CreateUserCommand) (*common.UserResult
{ {
user, err := s.repo.FindByName(cmd.Username) user, err := s.repo.FindByName(cmd.Username)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("User.create findByName error: %s", err)
} }
if user != nil { if user != nil {

View file

@ -3,6 +3,7 @@ package repo
import ( import (
"58team_blog/internal/domain/entities" "58team_blog/internal/domain/entities"
"58team_blog/internal/infrastructure/db" "58team_blog/internal/infrastructure/db"
"database/sql"
"strconv" "strconv"
"github.com/google/uuid" "github.com/google/uuid"
@ -28,7 +29,7 @@ func (r *PostRepository) Create(entity *entities.Post) (*entities.Post, error) {
} }
func (r *PostRepository) FindById(id uuid.UUID) (*entities.Post, error) { func (r *PostRepository) FindById(id uuid.UUID) (*entities.Post, error) {
var entity *entities.Post var entity entities.Post
query := "SELECT * FROM " + entities.PostTable + " WHERE id=?" query := "SELECT * FROM " + entities.PostTable + " WHERE id=?"
query, args, err := sqlx.In(query, id) query, args, err := sqlx.In(query, id)
@ -37,9 +38,13 @@ func (r *PostRepository) FindById(id uuid.UUID) (*entities.Post, error) {
} }
query = r.conn.Conn.Rebind(query) query = r.conn.Conn.Rebind(query)
err = r.conn.Conn.Get(entity, query, args) err = r.conn.Conn.Get(&entity, query, args...)
return entity, err if err == sql.ErrNoRows {
return nil, nil
}
return &entity, err
} }
func (r *PostRepository) FindAllByUserName(userName string) ([]*entities.Post, error) { func (r *PostRepository) FindAllByUserName(userName string) ([]*entities.Post, error) {

View file

@ -3,6 +3,7 @@ package repo
import ( import (
"58team_blog/internal/domain/entities" "58team_blog/internal/domain/entities"
"58team_blog/internal/infrastructure/db" "58team_blog/internal/infrastructure/db"
"database/sql"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
@ -39,31 +40,29 @@ func (r *UserRepository) FindById(id uuid.UUID) (*entities.User, error) {
} }
query = r.conn.Conn.Rebind(query) query = r.conn.Conn.Rebind(query)
err = r.conn.Conn.Get(entity, query, arg...) err = r.conn.Conn.Select(entity, query, arg...)
return entity, err return entity, err
} }
func (r *UserRepository) FindByName(username string) (*entities.User, error) { func (r *UserRepository) FindByName(username string) (*entities.User, error) {
var entity *entities.User var entity entities.User
query := "SELECT * FROM " + entities.UserTable + " WHERE username=?" query := "SELECT * FROM " + entities.UserTable + " WHERE username=$1"
query, arg, err := sqlx.In(query, username)
if err != nil { err := r.conn.Conn.Get(&entity, query, username)
return nil, err if err == sql.ErrNoRows {
return nil, nil
} }
query = r.conn.Conn.Rebind(query) return &entity, nil
err = r.conn.Conn.Get(entity, query, arg...)
return entity, err
} }
func (r *UserRepository) GetAll() ([]*entities.User, error) { func (r *UserRepository) GetAll() ([]*entities.User, error) {
var entity_list []*entities.User var entity_list []*entities.User
query := "SELECT * FROM " + entities.UserTable query := "SELECT * FROM " + entities.UserTable
err := r.conn.Conn.Select(entity_list, query) err := r.conn.Conn.Select(&entity_list, query)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -4,7 +4,7 @@ import (
"58team_blog/internal/application/commands" "58team_blog/internal/application/commands"
"58team_blog/internal/application/queries" "58team_blog/internal/application/queries"
"58team_blog/internal/application/services" "58team_blog/internal/application/services"
"58team_blog/internal/interfaces/api/dto" "58team_blog/internal/interfaces/api/mapper"
"58team_blog/internal/interfaces/api/requests" "58team_blog/internal/interfaces/api/requests"
"58team_blog/internal/interfaces/api/responses" "58team_blog/internal/interfaces/api/responses"
"log" "log"
@ -33,7 +33,7 @@ func CreatePostController(service *services.PostService) PostController {
// @Accept json // @Accept json
// @Produce json // @Produce json
// @Param request body requests.CreatePostRequest true "Post data" // @Param request body requests.CreatePostRequest true "Post data"
// @Success 200 {object} responses.PostResponse // @Success 201 {object} responses.PostResponse
// @Failure 400 {object} responses.ErrorResponse // @Failure 400 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse // @Failure 500 {object} responses.ErrorResponse
// @Router /post [post] // @Router /post [post]
@ -70,9 +70,9 @@ func (r *PostController) Post(c *gin.Context) {
return return
} }
response := dto.ResponseFromPostResult(res) response := mapper.ResponseFromPostResult(res)
c.JSON(http.StatusOK, response) c.JSON(http.StatusCreated, response)
} }
// GetAllPost godoc // GetAllPost godoc
@ -93,7 +93,7 @@ func (r *PostController) GetAll(c *gin.Context) {
return return
} }
res := dto.ResponseFromPostGetAllResult(result) res := mapper.ResponseFromPostGetAllResult(result)
c.JSON(http.StatusOK, res) c.JSON(http.StatusOK, res)
} }
@ -126,7 +126,7 @@ func (r *PostController) GetAllWithOffset(c *gin.Context) {
return return
} }
res := dto.ResponseFromPostGetAllResult(result) res := mapper.ResponseFromPostGetAllResult(result)
c.JSON(http.StatusOK, res) c.JSON(http.StatusOK, res)
} }
@ -164,7 +164,7 @@ func (r *PostController) GetById(c *gin.Context) {
return return
} }
result := dto.ResponseFormPostFindByIdResult(posts) result := mapper.ResponseFormPostFindByIdResult(posts)
c.JSON(http.StatusOK, result) c.JSON(http.StatusOK, result)
} }
@ -216,7 +216,7 @@ func (r *PostController) Put(c *gin.Context) {
return return
} }
response := dto.ResponseFromPostResult(post) response := mapper.ResponseFromPostResult(post)
c.JSON(http.StatusOK, response) c.JSON(http.StatusOK, response)
} }

View file

@ -1,9 +1,18 @@
package controllers package controllers
import ( import (
"58team_blog/internal/application/commands"
"58team_blog/internal/application/queries"
"58team_blog/internal/application/services" "58team_blog/internal/application/services"
"58team_blog/internal/interfaces/api/mapper"
"58team_blog/internal/interfaces/api/requests"
"58team_blog/internal/interfaces/api/responses"
"58team_blog/internal/utils"
"log"
"net/http"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/google/uuid"
) )
type UserController struct { type UserController struct {
@ -18,33 +27,216 @@ func CreateUserController(service *services.UserService) UserController {
// @Summary Create new user // @Summary Create new user
// @Description Creates new user in system // @Description Creates new user in system
// @Param path query string true "Path to image" // @Tags user
// @Accept json
// @Produce json // @Produce json
// @Success 200 // @Param request body requests.CreateUserRequest true "User data"
// @Router /images/{path} [get] // @Success 201 {object} responses.UserResponse
// @Failure 400 {object} responses.ErrorResponse
// @Router /user/ [post]
func (r *UserController) Post(c *gin.Context) { func (r *UserController) Post(c *gin.Context) {
// TODO: return image var request requests.CreateUserRequest
panic("Not implemented") if err := c.BindJSON(&request); err != nil {
log.Println("User invalid request: ", err)
resp := responses.CreateErrorResponse(http.StatusBadRequest, "Bad request")
c.JSON(resp.ErrorCode, resp)
return
} }
encrypted_password, err := utils.EncryptPassword(request.Password)
if err != nil {
log.Println("User encrupt password error: ", err)
resp := responses.CreateErrorResponse(http.StatusInternalServerError, "Internal server error")
c.JSON(resp.ErrorCode, resp)
return
}
cmd := commands.CreateUserCommand{
Username: request.Username,
Password: encrypted_password,
}
user, err := r.service.Create(cmd)
if err != nil {
log.Println("User service error: ", err)
resp := responses.CreateErrorResponse(http.StatusBadRequest, "Bad request")
c.JSON(resp.ErrorCode, resp)
return
}
response := mapper.ResponseFromUserResult(user)
c.JSON(http.StatusCreated, response)
}
// @Summary Find user by id
// @Description Find user by id
// @Tags user
// @Accept json
// @Produce json
// @Param id path string true "user id"
// @Success 200 {object} responses.UserResponse
// @Failure 400 {object} responses.ErrorResponse
// @Router /user/{id} [get]
func (r *UserController) FindById(c *gin.Context) { func (r *UserController) FindById(c *gin.Context) {
id_path := c.Param("id")
id, err := uuid.Parse(id_path)
if err != nil {
log.Println("User id error: ", err)
resp := responses.CreateErrorResponse(http.StatusBadRequest, "Bad request")
c.JSON(resp.ErrorCode, resp)
return
} }
query := queries.UserFindByIdQuery{
Id: id,
}
user, err := r.service.FindById(query)
if err != nil {
log.Println("User service error: ", err)
resp := responses.CreateErrorResponse(http.StatusNotFound, "Not found")
c.JSON(resp.ErrorCode, resp)
return
}
response := mapper.ResponseFromUserFindByIdResult(user)
c.JSON(http.StatusOK, response)
}
// @Summary Find user by username
// @Description Find user by username
// @Tags user
// @Accept json
// @Produce json
// @Param name path string true "User name"
// @Success 200 {object} responses.UserResponse
// @Failure 400 {object} responses.ErrorResponse
// @Router /user/name/{name} [get]
func (r *UserController) FindByName(c *gin.Context) { func (r *UserController) FindByName(c *gin.Context) {
name := c.Param("name")
query := queries.UserFindByNameQuery{
Name: name,
} }
user, err := r.service.FindByName(query)
if err != nil {
log.Println("User service error: ", err)
resp := responses.CreateErrorResponse(http.StatusNotFound, "Not found")
c.JSON(resp.ErrorCode, resp)
return
}
response := mapper.ResponseFromUserFindByNameResult(user)
c.JSON(http.StatusOK, response)
}
// @Summary Get all users
// @Description Return all registered users
// @Tags user
// @Produce json
// @Success 200 {object} responses.UserResponseList
// @Failure 400 {object} responses.ErrorResponse
// @Router /user/ [get]
func (r *UserController) GetAll(c *gin.Context) { func (r *UserController) GetAll(c *gin.Context) {
// TODO: return image users, err := r.service.GetAll()
panic("Not implemented") if err != nil {
log.Println("User service error: ", err)
resp := responses.CreateErrorResponse(http.StatusInternalServerError, "Internal server error")
c.JSON(resp.ErrorCode, resp)
return
} }
responses := mapper.ResponseFromUserGetAllResult(users)
c.JSON(http.StatusOK, responses)
}
// @Summary Change user
// @Description Change the user's name and password
// @Tags user
// @Accept json
// @Produce json
// @Param id path string true "User id"
// @Param request body requests.PutUserRequest true "User data"
// @Success 200 {object} responses.UserResponse
// @Failure 400 {object} responses.ErrorResponse
// @Router /user/{id} [put]
func (r *UserController) Put(c *gin.Context) { func (r *UserController) Put(c *gin.Context) {
var request requests.PutUserRequest
id_path := c.Param("id")
id, err := uuid.Parse(id_path)
if err != nil {
log.Println("User id error: ", err)
resp := responses.CreateErrorResponse(http.StatusBadRequest, "Bad request")
c.JSON(resp.ErrorCode, resp)
return
} }
if err := c.BindJSON(&request); err != nil {
log.Println("User request error: ", err)
resp := responses.CreateErrorResponse(http.StatusBadRequest, "Bad request")
c.JSON(resp.ErrorCode, resp)
return
}
password, err := utils.EncryptPassword(request.Password)
if err != nil {
log.Println("User password encrypt error: ", err)
resp := responses.CreateErrorResponse(http.StatusInternalServerError, "Internal server error")
c.JSON(resp.ErrorCode, resp)
return
}
cmd := commands.UpdateUserCommand{
Id: id,
Username: request.Username,
Password: password,
}
user, err := r.service.Update(cmd)
if err != nil {
log.Println("User service error: ", err)
resp := responses.CreateErrorResponse(http.StatusInternalServerError, "Internal server error")
c.JSON(resp.ErrorCode, resp)
return
}
response := mapper.ResponseFromUserResult(user)
c.JSON(http.StatusOK, response)
}
// @Summary Delete user
// @Description Delete user
// @Tags user
// @Produce json
// @Param id path string true "User id"
// @Success 200
// @Failure 400 {object} responses.ErrorResponse
// @Router /user/{id} [delete]
func (r *UserController) Delete(c *gin.Context) { func (r *UserController) Delete(c *gin.Context) {
// TODO: return image id_path := c.Param("id")
panic("Not implemented")
id, err := uuid.Parse(id_path)
if err != nil {
log.Println("User id error: ", err)
resp := responses.CreateErrorResponse(http.StatusBadRequest, "Bad request")
c.JSON(resp.ErrorCode, resp)
return
}
cmd := commands.DeleteUserCommand{
Id: id,
}
if err := r.service.Delete(cmd); err != nil {
log.Println("User service error: ", err)
resp := responses.CreateErrorResponse(http.StatusNotFound, "User not found")
c.JSON(resp.ErrorCode, resp)
return
}
c.Status(http.StatusOK)
} }

View file

@ -1,4 +1,4 @@
package dto package mapper
import ( import (
"58team_blog/internal/application/queries" "58team_blog/internal/application/queries"

View file

@ -1,4 +1,4 @@
package dto package mapper
import ( import (
"58team_blog/internal/application/common" "58team_blog/internal/application/common"

View file

@ -1,4 +1,4 @@
package dto package mapper
import ( import (
"58team_blog/internal/application/common" "58team_blog/internal/application/common"

View file

@ -0,0 +1,13 @@
package mapper
import (
"58team_blog/internal/application/queries"
"58team_blog/internal/interfaces/api/responses"
)
func ResponseFromUserFindByIdResult(user *queries.UserFindByIdResult) responses.UserResponse {
return responses.UserResponse{
Id: user.Result.Id.String(),
UserName: user.Result.UserName,
}
}

View file

@ -0,0 +1,13 @@
package mapper
import (
"58team_blog/internal/application/queries"
"58team_blog/internal/interfaces/api/responses"
)
func ResponseFromUserFindByNameResult(result *queries.UserFindByNameResult) responses.UserResponse {
return responses.UserResponse{
Id: result.Result.Id.String(),
UserName: result.Result.UserName,
}
}

View file

@ -0,0 +1,16 @@
package mapper
import (
"58team_blog/internal/application/queries"
"58team_blog/internal/interfaces/api/responses"
)
func ResponseFromUserGetAllResult(result *queries.UserGetAllResult) responses.UserResponseList {
var list responses.UserResponseList
for _, i := range result.Result.Result {
list = append(list, ResponseFromUserResult(i))
}
return list
}

View file

@ -0,0 +1,13 @@
package mapper
import (
"58team_blog/internal/application/common"
"58team_blog/internal/interfaces/api/responses"
)
func ResponseFromUserResult(result *common.UserResult) responses.UserResponse {
return responses.UserResponse{
Id: result.Id.String(),
UserName: result.UserName,
}
}

View file

@ -0,0 +1,6 @@
package requests
type CreateUserRequest struct {
Username string `json:"username" validate:"required,min=3,max=32"`
Password string `json:"password" validate:"required,min=6,max=32,password"`
}

View file

@ -0,0 +1,6 @@
package requests
type PutUserRequest struct {
Username string `json:"username" validate:"required,min=3,max=32"`
Password string `json:"password" validate:"required,min=6,max=32,password"`
}

View file

@ -0,0 +1,8 @@
package responses
type UserResponse struct {
Id string `json:"id"`
UserName string `json:"username"`
}
type UserResponseList []UserResponse

View file

@ -18,3 +18,15 @@ func BindPostAdmin(service *services.PostService, group *gin.RouterGroup) {
g.PUT("/:id", post.Put) g.PUT("/:id", post.Put)
g.DELETE("/:id", post.Delete) g.DELETE("/:id", post.Delete)
} }
func BindUser(service *services.UserService, group *gin.RouterGroup) {
user := controllers.CreateUserController(service)
g := group.Group("/user/")
g.POST("/", user.Post)
g.GET("/", user.GetAll)
g.GET("/:id", user.FindById)
g.GET("/name/:name", user.FindByName)
g.PUT("/:id", user.Put)
g.DELETE("/:id", user.Delete)
}

View file

@ -0,0 +1,21 @@
package utils
import (
"fmt"
"golang.org/x/crypto/bcrypt"
)
func EncryptPassword(pass string) (string, error) {
var salted string
salt := "58_team:%s:1205secret"
salted = fmt.Sprintf(salt, pass)
hashed, err := bcrypt.GenerateFromPassword([]byte(salted), 12)
if err != nil {
return "", err
}
return string(hashed), nil
}

View file

@ -0,0 +1,25 @@
package utils
import (
"unicode"
"github.com/go-playground/validator/v10"
)
func PasswordValidator(fl validator.FieldLevel) bool {
password := fl.Field().Interface().(string)
var hasUpper, hasNumber, hasLower = false, false, false
for _, c := range password {
if unicode.IsUpper(c) {
hasUpper = true
} else if unicode.IsLower(c) {
hasLower = true
} else if unicode.IsDigit(c) {
hasNumber = true
}
}
return hasUpper && hasNumber && hasLower
}