Added completed user. Some fixes and more more more...

This commit is contained in:
KamilM1205 2026-01-02 22:56:25 +04:00
parent b96dd39795
commit ea8ab7c0ed
33 changed files with 576 additions and 212 deletions

View file

@ -23,6 +23,7 @@ import (
"58team_blog/internal/utils"
"log"
"github.com/gin-contrib/cors"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
@ -37,12 +38,29 @@ const secret = "58secret"
func main() {
router := gin.Default()
// Setup CORS
// IMPORTANT: Must be setup before all another middlewares.
//cors_config := cors.DefaultConfig()
//cors_config.AllowOrigins = []string{"http://localhost:8080", "http://localhost:5173"}
//cors_config.AllowAllOrigins = true
//cors_config.AllowHeaders = []string{"Origin", "Content-Type", "Accept", "Authorization", "X-Requested-With"}
//router.Use(cors.New(cors_config))
router.Use(cors.New(cors.Config{
AllowOrigins: []string{"http://localhost:5173"},
AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
AllowHeaders: []string{"*"}, // Пробуем разрешить все заголовки
ExposeHeaders: []string{},
AllowCredentials: true,
MaxAge: 12 * 60 * 60,
}))
// Setup cookie container
router.Use(sessions.Sessions("session", cookie.NewStore([]byte(secret))))
// Register custom validators
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("password", utils.PasswordValidator)
v.RegisterValidation("inlineList", utils.InlineListValidator)
}
// Swagger setup
@ -78,6 +96,7 @@ func main() {
imagesService := services.CreateImagesService(&imagesRepository)
interfaces.BindPostAdmin(&postService, &userService, g)
interfaces.BindPost(&postService, &userService, g)
interfaces.BindUser(config.AdminName, config.AdminPassword, &userService, g)
interfaces.BindImages(config.ImagesPath, &imagesService, g)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -29,16 +29,57 @@ definitions:
type: object
requests.CreateUserRequest:
properties:
avatar:
type: string
description:
maxLength: 500
minLength: 10
type: string
joinDate:
type: string
motto:
maxLength: 200
minLength: 2
type: string
name:
maxLength: 100
minLength: 2
type: string
password:
maxLength: 32
minLength: 6
type: string
projects:
items:
type: string
minItems: 1
type: array
role:
type: string
skills:
items:
type: string
minItems: 1
type: array
speciality:
maxLength: 100
minLength: 2
type: string
username:
maxLength: 32
minLength: 3
type: string
required:
- avatar
- description
- joinDate
- motto
- name
- password
- projects
- role
- skills
- speciality
- username
type: object
requests.LoginUserRequest:
@ -66,16 +107,54 @@ definitions:
type: object
requests.PutUserRequest:
properties:
avatar:
type: string
description:
maxLength: 500
minLength: 10
type: string
motto:
maxLength: 200
minLength: 2
type: string
name:
maxLength: 100
minLength: 2
type: string
password:
maxLength: 32
minLength: 6
type: string
projects:
items:
type: string
minItems: 1
type: array
role:
type: string
skills:
items:
type: string
minItems: 1
type: array
speciality:
maxLength: 100
minLength: 2
type: string
username:
maxLength: 32
minLength: 3
type: string
required:
- avatar
- description
- motto
- name
- password
- projects
- role
- skills
- speciality
- username
type: object
responses.ErrorResponse:
@ -85,6 +164,8 @@ definitions:
message:
type: string
type: object
responses.GetAllImagesList:
type: object
responses.GetListPostResponseItem:
properties:
category:
@ -140,8 +221,30 @@ definitions:
type: object
responses.UserResponse:
properties:
avatar:
type: string
description:
type: string
id:
type: string
joinDate:
type: string
motto:
type: string
name:
type: string
projects:
items:
type: string
type: array
role:
type: string
skills:
items:
type: string
type: array
speciality:
type: string
username:
type: string
type: object
@ -159,6 +262,38 @@ info:
title: 58team blog backend
version: "1.0"
paths:
/images:
get:
description: Delete image from server by given path
parameters:
- description: Path to image
in: path
name: filename
required: true
type: string
produces:
- image/png
- image/jpeg
responses:
"200":
description: OK
schema:
$ref: '#/definitions/responses.GetAllImagesList'
"400":
description: Bad Request
schema:
$ref: '#/definitions/responses.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/responses.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
summary: Delete image by path
tags:
- images
/images/:
post:
description: Upload new image and returns uploaded image json object
@ -179,6 +314,8 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
security:
- BasicAuth: []
summary: Upload new image
tags:
- images
@ -209,6 +346,8 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
security:
- BasicAuth: []
summary: Delete image by path
tags:
- images
@ -291,9 +430,34 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
security:
- BasicAuth: []
summary: Create new user
tags:
- user
/members/:
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'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
summary: Get all users
tags:
- user
/post:
get:
description: Return first 5 posts
@ -339,6 +503,8 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
security:
- BasicAuth: []
summary: Create new post
tags:
- post
@ -368,6 +534,8 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
security:
- BasicAuth: []
summary: Delete post
tags:
- post
@ -436,6 +604,8 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
security:
- BasicAuth: []
summary: Update post content
tags:
- post
@ -468,29 +638,7 @@ paths:
summary: Get posts after offset
tags:
- 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'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
summary: Get all users
tags:
- user
/team/:
post:
consumes:
- application/json
@ -521,10 +669,12 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
security:
- BasicAuth: []
summary: Create new user
tags:
- user
/user/{id}:
/team/{id}:
delete:
description: Delete user
parameters:
@ -550,6 +700,8 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
security:
- BasicAuth: []
summary: Delete user
tags:
- user
@ -620,10 +772,12 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/responses.ErrorResponse'
security:
- BasicAuth: []
summary: Change user
tags:
- user
/user/name/{name}:
/team/name/{name}:
get:
consumes:
- application/json

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 60 KiB

1
go.mod
View file

@ -14,6 +14,7 @@ require (
github.com/creasty/defaults v1.8.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
github.com/gin-contrib/cors v1.7.6 // indirect
github.com/gin-contrib/sessions v1.0.4 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect
github.com/gin-gonic/gin v1.10.1 // indirect

2
go.sum
View file

@ -26,6 +26,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gin-contrib/cors v1.7.6 h1:3gQ8GMzs1Ylpf70y8bMw4fVpycXIeX1ZemuSQIsnQQY=
github.com/gin-contrib/cors v1.7.6/go.mod h1:Ulcl+xN4jel9t1Ry8vqph23a60FwH9xVLd+3ykmTjOk=
github.com/gin-contrib/sessions v1.0.4 h1:ha6CNdpYiTOK/hTp05miJLbpTSNfOnFg5Jm2kbcqy8U=
github.com/gin-contrib/sessions v1.0.4/go.mod h1:ccmkrb2z6iU2osiAHZG3x3J4suJK+OU27oqzlWOqQgs=
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=

View file

@ -1,6 +1,17 @@
package commands
import "time"
type CreateUserCommand struct {
Username string
Password string
Username string
Password string
Name string
Role string
Speciality string
Description string
Skills string
Avatar string
JoinDate time.Time
Projects string
Motto string
}

View file

@ -3,7 +3,15 @@ package commands
import "github.com/google/uuid"
type UpdateUserCommand struct {
Id uuid.UUID
Username string
Password string
Id uuid.UUID
Username string
Password string
Name string
Role string
Speciality string
Description string
Skills string
Avatar string
Projects string
Motto string
}

View file

@ -1,11 +1,24 @@
package common
import "github.com/google/uuid"
import (
"time"
"github.com/google/uuid"
)
type UserResult struct {
Id uuid.UUID
UserName string
Password string
Id uuid.UUID
UserName string
Password string
Name string
Role string
Speciality string
Description string
Skills string
Avatar string
JoinDate time.Time
Projects string
Motto string
}
type UserResultList struct {

View file

@ -8,9 +8,18 @@ import (
func CreateUserResultFromEntity(entity *entities.User) *common.UserResult {
return &common.UserResult{
Id: entity.Id,
UserName: entity.UserName,
Password: entity.Password,
Id: entity.Id,
UserName: entity.UserName,
Password: entity.Password,
Name: entity.Name,
Role: entity.Role,
Speciality: entity.Speciality,
Description: entity.Description,
Skills: entity.Skills,
Avatar: entity.Avatar,
JoinDate: entity.JoinDate,
Projects: entity.Projects,
Motto: entity.Motto,
}
}

View file

@ -8,6 +8,7 @@ import (
"58team_blog/internal/application/queries"
"58team_blog/internal/domain/entities"
"58team_blog/internal/domain/repository"
"fmt"
)
type UserService struct {
@ -29,12 +30,15 @@ func (s *UserService) Create(cmd commands.CreateUserCommand) (*common.UserResult
}
if user != nil {
return nil, errors.NewAlreadyExistsError("user: " + cmd.Username)
fmt.Println(user)
return nil, errors.NewAlreadyExistsError("user: " + user.UserName)
}
}
// Create new user
user, err := entities.CreateUser(cmd.Username, cmd.Password)
user, err := entities.CreateUser(cmd.Username, cmd.Password,
cmd.Name, cmd.Role, cmd.Speciality, cmd.Description,
cmd.Skills, cmd.Avatar, cmd.JoinDate, cmd.Projects, cmd.Motto)
if err != nil {
return nil, errors.NewValidationError(err.Error())
}
@ -70,6 +74,10 @@ func (s *UserService) FindByName(query queries.UserFindByNameQuery) (*queries.Us
return nil, errors.NewDBError(err.Error())
}
if entity == nil {
return nil, errors.NewNotFoundError("User not found.")
}
if err := entity.Validate(); err != nil {
return nil, errors.NewValidationError(err.Error())
}
@ -109,6 +117,14 @@ func (s *UserService) Update(cmd commands.UpdateUserCommand) (*common.UserResult
}
entity.Password = cmd.Password
entity.Name = cmd.Name
entity.Role = cmd.Role
entity.Speciality = cmd.Speciality
entity.Description = cmd.Description
entity.Skills = cmd.Skills
entity.Avatar = cmd.Avatar
entity.Projects = cmd.Projects
entity.Motto = cmd.Motto
if err := entity.Validate(); err != nil {
return nil, errors.NewValidationError(err.Error())

View file

@ -2,6 +2,7 @@ package entities
import (
"errors"
"time"
"github.com/google/uuid"
)
@ -9,16 +10,47 @@ import (
const UserTable = "users"
type User struct {
Id uuid.UUID `db:"id"`
UserName string `db:"username"`
Password string `db:"password"`
Id uuid.UUID `db:"id"`
UserName string `db:"username"`
Password string `db:"password"`
Name string `db:"name"`
Role string `db:"role"`
Speciality string `db:"speciality"`
Description string `db:"description"`
Skills string `db:"skills"`
Avatar string `db:"avatar"`
JoinDate time.Time `db:"joindate"`
Projects string `db:"projects"`
Motto string `db:"motto"`
}
func CreateUser(userName string, password string) (user User, err error) {
func CreateUser(
userName string,
password string,
name string,
role string,
speciality string,
description string,
skills string,
avatar string,
joinDate time.Time,
projects string,
motto string,
) (user User, err error) {
user = User{
Id: uuid.New(),
UserName: userName,
Password: password,
Id: uuid.New(),
UserName: userName,
Password: password,
Name: name,
Role: role,
Speciality: speciality,
Description: description,
Skills: skills,
Avatar: avatar,
JoinDate: joinDate,
Projects: projects,
Motto: motto,
}
err = user.Validate()
@ -28,14 +60,51 @@ func CreateUser(userName string, password string) (user User, err error) {
func (u *User) Validate() error {
if err := uuid.Validate(u.Id.String()); err != nil {
return errors.New("Invalid user.id")
return errors.New("invalid user.id")
}
if u.UserName == "" {
return errors.New("Empty user.name")
return errors.New("empty user.username")
}
if u.Password == "" {
return errors.New("Empty user.password")
return errors.New("empty user.password")
}
if u.Role == "" {
return errors.New("empty user.role")
}
if u.Name == "" {
return errors.New("empty user.name")
}
if u.Speciality == "" {
return errors.New("empty user.speciality")
}
if u.Description == "" {
return errors.New("empty user.description")
}
if u.Skills == "" {
return errors.New("empty user.skills")
}
if u.Avatar == "" {
return errors.New("empty user.avatar")
}
if u.Projects == "" {
return errors.New("empty user.projects")
}
if u.Motto == "" {
return errors.New("empty user.motto")
}
if u.JoinDate.IsZero() {
return errors.New("empty user.joinDate")
}
return nil

View file

@ -20,7 +20,9 @@ func CreateUserRepository(conn *db.Database) UserRepository {
}
func (r *UserRepository) Create(entity *entities.User) (*entities.User, error) {
query := "INSERT INTO " + entities.UserTable + "(id, username, password) VALUES (:id, :username, :password)"
query := "INSERT INTO " + entities.UserTable +
"(id, username, password, name, role, speciality, description, skills, avatar, joindate, projects, motto) " +
"VALUES (:id, :username, :password, :name, :role, :speciality, :description, :skills, :avatar, :joindate, :projects, :motto)"
_, err := r.conn.Conn.NamedExec(query, entity)
if err != nil {

View file

@ -36,6 +36,7 @@ func CreateImagesController(images_path string, service *services.ImagesService)
// @Success 200 {object} responses.ImageResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /images/ [post]
// @Security BasicAuth
func (r *ImagesController) PostImage(c *gin.Context) {
file, err := c.FormFile("file")
if err != nil {
@ -139,6 +140,21 @@ func (r *ImagesController) GetImage(c *gin.Context) {
c.File(filePath)
}
// @Summary Delete image by path
// @Description Delete image from server by given path
// @Tags images
// @Param filename path string true "Path to image"
// @Produce image/png
// @Produce image/jpeg
// @Success 200 {object} responses.GetAllImagesList
// @Failure 400 {object} responses.ErrorResponse
// @Failure 404 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /images [get]
func (r *ImagesController) GetAllImage(c *gin.Context) {
panic("Not implemented")
}
// @Summary Delete image by path
// @Description Delete image from server by given path
// @Tags images
@ -150,6 +166,7 @@ func (r *ImagesController) GetImage(c *gin.Context) {
// @Failure 404 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /images/{path} [delete]
// @Security BasicAuth
func (r *ImagesController) DeleteImage(c *gin.Context) {
panic("Not implemented")
}

View file

@ -40,6 +40,8 @@ func CreatePostController(service *services.PostService, userService *services.U
// @Failure 400 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /post [post]
//
// @Security BasicAuth
func (r *PostController) Post(c *gin.Context) {
var request requests.CreatePostRequest
@ -227,6 +229,8 @@ func (r *PostController) GetById(c *gin.Context) {
// @Failure 404 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /post/{id} [put]
//
// @Security BasicAuth
func (r *PostController) Put(c *gin.Context) {
var request requests.PutPostRequest
@ -276,6 +280,8 @@ func (r *PostController) Put(c *gin.Context) {
// @Failure 404 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /post/{id} [delete]
//
// @Security BasicAuth
func (r *PostController) Delete(c *gin.Context) {
id := c.Param("id")
id_valid, err := uuid.Parse(id)

View file

@ -10,6 +10,7 @@ import (
"58team_blog/internal/utils"
"log"
"net/http"
"strings"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
@ -107,6 +108,7 @@ func (r *UserController) Login(c *gin.Context) {
// @Failure 400 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /logout [get]
// @Security BasicAuth
func (r *UserController) Logout(c *gin.Context) {
session := sessions.Default(c)
user := session.Get("user")
@ -132,7 +134,8 @@ func (r *UserController) Logout(c *gin.Context) {
// @Failure 400 {object} responses.ErrorResponse
// @Failure 409 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /user/ [post]
// @Router /team/ [post]
// @Security BasicAuth
func (r *UserController) Post(c *gin.Context) {
var request requests.CreateUserRequest
if err := c.BindJSON(&request); err != nil {
@ -151,8 +154,17 @@ func (r *UserController) Post(c *gin.Context) {
}
cmd := commands.CreateUserCommand{
Username: request.Username,
Password: encrypted_password,
Username: request.Username,
Password: encrypted_password,
Role: request.Role,
Name: request.Name,
Speciality: request.Speciality,
Description: request.Description,
Skills: strings.Join(request.Skills, ";"),
Avatar: request.Avatar,
JoinDate: request.JoinDate,
Projects: strings.Join(request.Projects, ";"),
Motto: request.Motto,
}
user, err := r.service.Create(cmd)
@ -177,7 +189,7 @@ func (r *UserController) Post(c *gin.Context) {
// @Failure 400 {object} responses.ErrorResponse
// @Failure 404 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /user/{id} [get]
// @Router /team/{id} [get]
func (r *UserController) FindById(c *gin.Context) {
id_path := c.Param("id")
@ -214,7 +226,7 @@ func (r *UserController) FindById(c *gin.Context) {
// @Failure 400 {object} responses.ErrorResponse
// @Failure 404 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /user/name/{name} [get]
// @Router /team/name/{name} [get]
func (r *UserController) FindByName(c *gin.Context) {
name := c.Param("name")
@ -230,6 +242,7 @@ func (r *UserController) FindByName(c *gin.Context) {
}
response := mapper.ResponseFromUserFindByNameResult(user)
c.JSON(http.StatusOK, response)
}
@ -240,7 +253,7 @@ func (r *UserController) FindByName(c *gin.Context) {
// @Success 200 {object} responses.UserResponseList
// @Failure 400 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /user/ [get]
// @Router /members/ [get]
func (r *UserController) GetAll(c *gin.Context) {
users, err := r.service.GetAll()
if err != nil {
@ -249,8 +262,9 @@ func (r *UserController) GetAll(c *gin.Context) {
return
}
responses := mapper.ResponseFromUserGetAllResult(users)
c.JSON(http.StatusOK, responses)
resp := mapper.ResponseFromUserGetAllResult(users)
c.JSON(http.StatusOK, resp)
}
// @Summary Change user
@ -264,7 +278,8 @@ func (r *UserController) GetAll(c *gin.Context) {
// @Failure 400 {object} responses.ErrorResponse
// @Failure 404 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /user/{id} [put]
// @Router /team/{id} [put]
// @Security BasicAuth
func (r *UserController) Put(c *gin.Context) {
var request requests.PutUserRequest
id_path := c.Param("id")
@ -292,10 +307,21 @@ func (r *UserController) Put(c *gin.Context) {
return
}
skills := strings.Join(request.Skills, ";")
projects := strings.Join(request.Projects, ";")
cmd := commands.UpdateUserCommand{
Id: id,
Username: request.Username,
Password: password,
Id: id,
Username: request.Username,
Name: request.Name,
Password: password,
Role: request.Role,
Speciality: request.Speciality,
Description: request.Description,
Skills: skills,
Avatar: request.Avatar,
Projects: projects,
Motto: request.Motto,
}
user, err := r.service.Update(cmd)
@ -318,7 +344,8 @@ func (r *UserController) Put(c *gin.Context) {
// @Failure 400 {object} responses.ErrorResponse
// @Failure 404 {object} responses.ErrorResponse
// @Failure 500 {object} responses.ErrorResponse
// @Router /user/{id} [delete]
// @Router /team/{id} [delete]
// @Security BasicAuth
func (r *UserController) Delete(c *gin.Context) {
id_path := c.Param("id")

View file

@ -12,14 +12,14 @@ func itemFromResult(item *common.PostResult) responses.GetListPostResponseItem {
UserId: item.UserId.String(),
Title: item.Title,
Description: item.Description,
UpdatedAt: item.UpdatedAt.String(),
UpdatedAt: item.UpdatedAt,
Tags: item.Tags,
Category: item.Category,
}
}
func ResponseFromPostGetAllResult(result *queries.PostGetAllResult) responses.GetListPostResponse {
var resp []responses.GetListPostResponseItem
resp := responses.GetListPostResponse{}
for _, r := range result.Result.Result {
resp = append(resp, itemFromResult(r))

View file

@ -3,11 +3,25 @@ package mapper
import (
"58team_blog/internal/application/queries"
"58team_blog/internal/interfaces/api/responses"
"strings"
)
func ResponseFromUserFindByIdResult(user *queries.UserFindByIdResult) responses.UserResponse {
res := user.Result
skills := strings.Split(res.Skills, ";")
projects := strings.Split(res.Projects, ";")
return responses.UserResponse{
Id: user.Result.Id.String(),
UserName: user.Result.UserName,
Id: res.Id.String(),
UserName: res.UserName,
Name: res.Name,
Role: res.Role,
Speciality: res.Speciality,
Description: res.Description,
Skills: skills,
Avatar: res.Avatar,
JoinDate: res.JoinDate,
Projects: projects,
Motto: res.Motto,
}
}

View file

@ -3,11 +3,25 @@ package mapper
import (
"58team_blog/internal/application/queries"
"58team_blog/internal/interfaces/api/responses"
"strings"
)
func ResponseFromUserFindByNameResult(result *queries.UserFindByNameResult) responses.UserResponse {
res := result.Result
skills := strings.Split(res.Skills, ";")
projects := strings.Split(res.Projects, ";")
return responses.UserResponse{
Id: result.Result.Id.String(),
UserName: result.Result.UserName,
Id: res.Id.String(),
UserName: res.UserName,
Name: res.Name,
Role: res.Role,
Speciality: res.Speciality,
Description: res.Description,
Skills: skills,
Avatar: res.Avatar,
JoinDate: res.JoinDate,
Projects: projects,
Motto: res.Motto,
}
}

View file

@ -6,7 +6,7 @@ import (
)
func ResponseFromUserGetAllResult(result *queries.UserGetAllResult) responses.UserResponseList {
var list responses.UserResponseList
list := responses.UserResponseList{}
for _, i := range result.Result.Result {
list = append(list, ResponseFromUserResult(i))

View file

@ -3,11 +3,24 @@ package mapper
import (
"58team_blog/internal/application/common"
"58team_blog/internal/interfaces/api/responses"
"strings"
)
func ResponseFromUserResult(result *common.UserResult) responses.UserResponse {
skills := strings.Split(result.Skills, ";")
projects := strings.Split(result.Projects, ";")
return responses.UserResponse{
Id: result.Id.String(),
UserName: result.UserName,
Id: result.Id.String(),
UserName: result.UserName,
Name: result.Name,
Role: result.Role,
Speciality: result.Speciality,
Description: result.Description,
Skills: skills,
Avatar: result.Avatar,
JoinDate: result.JoinDate,
Projects: projects,
Motto: result.Motto,
}
}

View file

@ -1,10 +1,10 @@
package requests
type CreatePostRequest struct {
Title string `json:"title" validate:"required,min=8,max=255"`
Description string `json:"description" validate:"required,min=8,max=255"`
Content string `json:"content" validate:"required,min=36"`
UserId string `json:"userId" validate:"required,uuid5"`
Title string `json:"title" binding:"required,min=8,max=255"`
Description string `json:"description" binding:"required,min=8,max=255"`
Content string `json:"content" binding:"required,min=36"`
UserId string `json:"userId" binding:"required,uuid5"`
Category string `json:"category"`
Tags []string `json:"tags"`
}

View file

@ -1,6 +1,17 @@
package requests
import "time"
type CreateUserRequest struct {
Username string `json:"username" validate:"required,min=3,max=32"`
Password string `json:"password" validate:"required,min=6,max=32,password"`
Username string `json:"username" binding:"required,min=3,max=32"`
Password string `json:"password" binding:"required,min=6,max=32,password"`
Name string `json:"name" binding:"required,min=2,max=100"`
Role string `json:"role" binding:"required"`
Speciality string `json:"speciality" binding:"required,min=2,max=100"`
Description string `json:"description" binding:"required,min=10,max=500"`
Skills []string `json:"skills" binding:"required,min=1,inlineList"`
Avatar string `json:"avatar" binding:"required"`
JoinDate time.Time `json:"joinDate" binding:"required"`
Projects []string `json:"projects" binding:"required,min=1,inlineList"`
Motto string `json:"motto" binding:"required,min=2,max=200"`
}

View file

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

View file

@ -1,6 +1,14 @@
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"`
Username string `json:"username" binding:"required,min=3,max=32"`
Password string `json:"password" binding:"required,min=6,max=32,password"`
Name string `json:"name" binding:"required,min=2,max=100"`
Role string `json:"role" binding:"required"`
Speciality string `json:"speciality" binding:"required,min=2,max=100"`
Description string `json:"description" binding:"required,min=10,max=500"`
Skills []string `json:"skills" binding:"required,min=1,inlineList"`
Avatar string `json:"avatar" binding:"required"`
Projects []string `json:"projects" binding:"required,min=1,inlineList"`
Motto string `json:"motto" binding:"required,min=2,max=200"`
}

View file

@ -1,14 +1,16 @@
package responses
import "time"
type GetListPostResponseItem struct {
Id string `json:"id"`
UserId string `json:"userId"`
Title string `json:"title"`
Description string `json:"description"`
UpdatedAt string `json:"updatedAt"`
Tags []string `json:"tags"`
Category string `json:"category"`
Username string `json:"username"`
Id string `json:"id"`
UserId string `json:"userId"`
Title string `json:"title"`
Description string `json:"description"`
UpdatedAt time.Time `json:"updatedAt"`
Tags []string `json:"tags"`
Category string `json:"category"`
Username string `json:"username"`
}
type GetListPostResponse []GetListPostResponseItem

View file

@ -0,0 +1,4 @@
package responses
type GetAllImagesList struct {
}

View file

@ -1,8 +1,18 @@
package responses
type UserResponse struct {
Id string `json:"id"`
UserName string `json:"username"`
}
import "time"
type UserResponse struct {
Id string `json:"id"`
UserName string `json:"username"`
Name string `json:"name"`
Role string `json:"role"`
Speciality string `json:"speciality"`
Description string `json:"description"`
Skills []string `json:"skills"`
Avatar string `json:"avatar"`
JoinDate time.Time `json:"joinDate"`
Projects []string `json:"projects"`
Motto string `json:"motto"`
}
type UserResponseList []UserResponse

View file

@ -34,13 +34,15 @@ func BindUser(adminName string, adminPass string, service *services.UserService,
group.POST("/login", user.Login)
group.GET("/logout", user.Logout)
g := group.Group("/user/")
g_all := group.Group("/members")
g_all.GET("/", user.GetAll)
g_all.GET("/:id", user.FindById)
g_all.GET("/name/:name", user.FindByName)
g := group.Group("/team/")
g.Use(infrastructure.AuthRequired)
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

@ -14,17 +14,24 @@ func HandleError(err error) responses.ErrorResponse {
log.Println(err)
if errors.Is(&ie.ValidationError{}, err) {
var validationErr *ie.ValidationError
var readFileErr *ie.ReadFileError
var notFoundErr *ie.NotFoundError
var alreadyExistsErr *ie.AlreadyExistsError
var dbErr *ie.DBError
switch {
case errors.As(err, &validationErr):
errorCode = http.StatusBadRequest
} else if errors.Is(&ie.ReadFileError{}, err) {
case errors.As(err, &readFileErr):
errorCode = http.StatusInternalServerError
} else if errors.Is(&ie.NotFoundError{}, err) {
case errors.As(err, &notFoundErr):
errorCode = http.StatusNotFound
} else if errors.Is(&ie.AlreadyExistsError{}, err) {
case errors.As(err, &alreadyExistsErr):
errorCode = http.StatusConflict
} else if errors.Is(&ie.DBError{}, err) {
case errors.As(err, &dbErr):
errorCode = http.StatusInternalServerError
} else {
default:
errorCode = http.StatusInternalServerError
}

View file

@ -0,0 +1,21 @@
package utils
import (
"strings"
"github.com/go-playground/validator/v10"
)
func InlineListValidator(fl validator.FieldLevel) bool {
str, ok := fl.Field().Interface().(string)
if ok {
for _, char := range str {
if strings.ContainsRune(";", char) {
return false
}
}
}
return true
}

View file

@ -0,0 +1,10 @@
ALTER TABLE users
ADD COLUMN name TEXT NOT NULL DEFAULT '',
ADD COLUMN role TEXT NOT NULL DEFAULT '',
ADD COLUMN speciality TEXT NOT NULL DEFAULT '',
ADD COLUMN description TEXT NOT NULL DEFAULT '',
ADD COLUMN skills TEXT NOT NULL DEFAULT '',
ADD COLUMN avatar TEXT NOT NULL DEFAULT '',
ADD COLUMN joinDate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN projects TEXT NOT NULL DEFAULT '',
ADD COLUMN motto TEXT NOT NULL DEFAULT '';