diff --git a/cmd/main.go b/cmd/main.go index 50d49a6..8b2afa2 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -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) diff --git a/docs/docs.go b/docs/docs.go index f56b2b3..9c53d57 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -5,7 +5,7 @@ package docs import "github.com/swaggo/swag/v2" const docTemplate = `{ - "schemes": {{ marshal .Schemes }},"swagger":"2.0","info":{"description":"{{escape .Description}}","title":"{{.Title}}","termsOfService":"http://swagger.io/terms/","contact":{"name":"API Support","url":"http://www.swagger.io/support","email":"support@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"},"version":"{{.Version}}"},"host":"{{.Host}}","basePath":"{{.BasePath}}","paths":{"/images/":{"post":{"description":"Upload new image and returns uploaded image json object","produces":["application/json"],"tags":["images"],"summary":"Upload new image","parameters":[{"type":"file","description":"image file","name":"file","in":"formData","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.ImageResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/images/{path}":{"get":{"description":"get image by path","produces":["application/octet-stream","application/json"],"tags":["images"],"summary":"Get an image by path","parameters":[{"type":"string","description":"Path to image","name":"path","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"file"}},"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"}}}},"delete":{"description":"Delete image from server by given path","produces":["image/png","image/jpeg"],"tags":["images"],"summary":"Delete image by path","parameters":[{"type":"string","description":"Path to image","name":"filename","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}},"/login":{"post":{"description":"Login user into system","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Login","parameters":[{"description":"User login data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.LoginUserRequest"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/logout":{"get":{"description":"Creates new user in system","produces":["application/json"],"tags":["user"],"summary":"Create new user","responses":{"200":{"description":"OK"},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post":{"get":{"description":"Return first 5 posts","produces":["application/json"],"tags":["post"],"summary":"Get all posts","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}},"post":{"description":"Create new post in blog","consumes":["application/json"],"produces":["application/json"],"tags":["post"],"summary":"Create new post","parameters":[{"description":"Post data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.CreatePostRequest"}}],"responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/responses.PostResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post/offset/{offset}":{"get":{"description":"return 5 posts after first offset posts","produces":["application/json"],"tags":["post"],"summary":"Get posts after offset","parameters":[{"type":"integer","description":"Offset of posts","name":"offset","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post/{id}":{"get":{"description":"get post by id","produces":["application/json"],"tags":["post"],"summary":"Get post by id","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.PostResponse"}}},"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"}}}},"put":{"description":"update post content","produces":["application/json"],"tags":["post"],"summary":"Update post content","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true},{"description":"Post data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.PutPostRequest"}}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.PostResponse"}},"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"}}}},"delete":{"description":"Delete post by id","produces":["application/json"],"tags":["post"],"summary":"Delete post","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}},"/user/":{"get":{"description":"Return all registered users","produces":["application/json"],"tags":["user"],"summary":"Get all users","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.UserResponse"}}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}},"post":{"description":"Creates new user in system","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Create new user","parameters":[{"description":"User data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.CreateUserRequest"}}],"responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/responses.UserResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"409":{"description":"Conflict","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/user/name/{name}":{"get":{"description":"Find user by username","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Find user by username","parameters":[{"type":"string","description":"User name","name":"name","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}}},"/user/{id}":{"get":{"description":"Find user by id","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Find user by id","parameters":[{"type":"string","description":"user id","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}},"put":{"description":"Change the user's name and password","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Change user","parameters":[{"type":"string","description":"User id","name":"id","in":"path","required":true},{"description":"User data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.PutUserRequest"}}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}},"delete":{"description":"Delete user","produces":["application/json"],"tags":["user"],"summary":"Delete user","parameters":[{"type":"string","description":"User id","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}}},"definitions":{"requests.CreatePostRequest":{"type":"object","required":["content","description","title","userId"],"properties":{"category":{"type":"string"},"content":{"type":"string","minLength":36},"description":{"type":"string","maxLength":255,"minLength":8},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string","maxLength":255,"minLength":8},"userId":{"type":"string"}}},"requests.CreateUserRequest":{"type":"object","required":["password","username"],"properties":{"password":{"type":"string","maxLength":32,"minLength":6},"username":{"type":"string","maxLength":32,"minLength":3}}},"requests.LoginUserRequest":{"type":"object","required":["password","username"],"properties":{"password":{"type":"string","maxLength":32,"minLength":6},"username":{"type":"string","maxLength":32,"minLength":3}}},"requests.PutPostRequest":{"type":"object","properties":{"content":{"type":"string"},"description":{"type":"string"},"title":{"type":"string"}}},"requests.PutUserRequest":{"type":"object","required":["password","username"],"properties":{"password":{"type":"string","maxLength":32,"minLength":6},"username":{"type":"string","maxLength":32,"minLength":3}}},"responses.ErrorResponse":{"type":"object","properties":{"error_code":{"type":"integer"},"message":{"type":"string"}}},"responses.GetListPostResponseItem":{"type":"object","properties":{"category":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string"},"updatedAt":{"type":"string"},"userId":{"type":"string"},"username":{"type":"string"}}},"responses.ImageResponse":{"type":"object","properties":{"id":{"type":"string"},"path":{"type":"string"}}},"responses.PostResponse":{"type":"object","properties":{"category":{"type":"string"},"content":{"type":"string"},"createdAt":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string"},"updatedAt":{"type":"string"},"userId":{"type":"string"},"username":{"type":"string"}}},"responses.UserResponse":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"}}}},"securityDefinitions":{"BasicAuth":{"type":"basic"}}}` + "schemes": {{ marshal .Schemes }},"swagger":"2.0","info":{"description":"{{escape .Description}}","title":"{{.Title}}","termsOfService":"http://swagger.io/terms/","contact":{"name":"API Support","url":"http://www.swagger.io/support","email":"support@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"},"version":"{{.Version}}"},"host":"{{.Host}}","basePath":"{{.BasePath}}","paths":{"/images":{"get":{"description":"Delete image from server by given path","produces":["image/png","image/jpeg"],"tags":["images"],"summary":"Delete image by path","parameters":[{"type":"string","description":"Path to image","name":"filename","in":"path","required":true}],"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"}}}}},"/images/":{"post":{"security":[{"BasicAuth":[]}],"description":"Upload new image and returns uploaded image json object","produces":["application/json"],"tags":["images"],"summary":"Upload new image","parameters":[{"type":"file","description":"image file","name":"file","in":"formData","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.ImageResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/images/{path}":{"get":{"description":"get image by path","produces":["application/octet-stream","application/json"],"tags":["images"],"summary":"Get an image by path","parameters":[{"type":"string","description":"Path to image","name":"path","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"file"}},"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"}}}},"delete":{"security":[{"BasicAuth":[]}],"description":"Delete image from server by given path","produces":["image/png","image/jpeg"],"tags":["images"],"summary":"Delete image by path","parameters":[{"type":"string","description":"Path to image","name":"filename","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}},"/login":{"post":{"description":"Login user into system","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Login","parameters":[{"description":"User login data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.LoginUserRequest"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/logout":{"get":{"security":[{"BasicAuth":[]}],"description":"Creates new user in system","produces":["application/json"],"tags":["user"],"summary":"Create new user","responses":{"200":{"description":"OK"},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/members/":{"get":{"description":"Return all registered users","produces":["application/json"],"tags":["user"],"summary":"Get all users","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.UserResponse"}}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post":{"get":{"description":"Return first 5 posts","produces":["application/json"],"tags":["post"],"summary":"Get all posts","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}},"post":{"security":[{"BasicAuth":[]}],"description":"Create new post in blog","consumes":["application/json"],"produces":["application/json"],"tags":["post"],"summary":"Create new post","parameters":[{"description":"Post data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.CreatePostRequest"}}],"responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/responses.PostResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post/offset/{offset}":{"get":{"description":"return 5 posts after first offset posts","produces":["application/json"],"tags":["post"],"summary":"Get posts after offset","parameters":[{"type":"integer","description":"Offset of posts","name":"offset","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post/{id}":{"get":{"description":"get post by id","produces":["application/json"],"tags":["post"],"summary":"Get post by id","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.PostResponse"}}},"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"}}}},"put":{"security":[{"BasicAuth":[]}],"description":"update post content","produces":["application/json"],"tags":["post"],"summary":"Update post content","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true},{"description":"Post data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.PutPostRequest"}}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.PostResponse"}},"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"}}}},"delete":{"security":[{"BasicAuth":[]}],"description":"Delete post by id","produces":["application/json"],"tags":["post"],"summary":"Delete post","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}},"/team/":{"post":{"security":[{"BasicAuth":[]}],"description":"Creates new user in system","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Create new user","parameters":[{"description":"User data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.CreateUserRequest"}}],"responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/responses.UserResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"409":{"description":"Conflict","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/team/name/{name}":{"get":{"description":"Find user by username","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Find user by username","parameters":[{"type":"string","description":"User name","name":"name","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}}},"/team/{id}":{"get":{"description":"Find user by id","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Find user by id","parameters":[{"type":"string","description":"user id","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}},"put":{"security":[{"BasicAuth":[]}],"description":"Change the user's name and password","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Change user","parameters":[{"type":"string","description":"User id","name":"id","in":"path","required":true},{"description":"User data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.PutUserRequest"}}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}},"delete":{"security":[{"BasicAuth":[]}],"description":"Delete user","produces":["application/json"],"tags":["user"],"summary":"Delete user","parameters":[{"type":"string","description":"User id","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}}},"definitions":{"requests.CreatePostRequest":{"type":"object","required":["content","description","title","userId"],"properties":{"category":{"type":"string"},"content":{"type":"string","minLength":36},"description":{"type":"string","maxLength":255,"minLength":8},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string","maxLength":255,"minLength":8},"userId":{"type":"string"}}},"requests.CreateUserRequest":{"type":"object","required":["avatar","description","joinDate","motto","name","password","projects","role","skills","speciality","username"],"properties":{"avatar":{"type":"string"},"description":{"type":"string","maxLength":500,"minLength":10},"joinDate":{"type":"string"},"motto":{"type":"string","maxLength":200,"minLength":2},"name":{"type":"string","maxLength":100,"minLength":2},"password":{"type":"string","maxLength":32,"minLength":6},"projects":{"type":"array","minItems":1,"items":{"type":"string"}},"role":{"type":"string"},"skills":{"type":"array","minItems":1,"items":{"type":"string"}},"speciality":{"type":"string","maxLength":100,"minLength":2},"username":{"type":"string","maxLength":32,"minLength":3}}},"requests.LoginUserRequest":{"type":"object","required":["password","username"],"properties":{"password":{"type":"string","maxLength":32,"minLength":6},"username":{"type":"string","maxLength":32,"minLength":3}}},"requests.PutPostRequest":{"type":"object","properties":{"content":{"type":"string"},"description":{"type":"string"},"title":{"type":"string"}}},"requests.PutUserRequest":{"type":"object","required":["avatar","description","motto","name","password","projects","role","skills","speciality","username"],"properties":{"avatar":{"type":"string"},"description":{"type":"string","maxLength":500,"minLength":10},"motto":{"type":"string","maxLength":200,"minLength":2},"name":{"type":"string","maxLength":100,"minLength":2},"password":{"type":"string","maxLength":32,"minLength":6},"projects":{"type":"array","minItems":1,"items":{"type":"string"}},"role":{"type":"string"},"skills":{"type":"array","minItems":1,"items":{"type":"string"}},"speciality":{"type":"string","maxLength":100,"minLength":2},"username":{"type":"string","maxLength":32,"minLength":3}}},"responses.ErrorResponse":{"type":"object","properties":{"error_code":{"type":"integer"},"message":{"type":"string"}}},"responses.GetAllImagesList":{"type":"object"},"responses.GetListPostResponseItem":{"type":"object","properties":{"category":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string"},"updatedAt":{"type":"string"},"userId":{"type":"string"},"username":{"type":"string"}}},"responses.ImageResponse":{"type":"object","properties":{"id":{"type":"string"},"path":{"type":"string"}}},"responses.PostResponse":{"type":"object","properties":{"category":{"type":"string"},"content":{"type":"string"},"createdAt":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string"},"updatedAt":{"type":"string"},"userId":{"type":"string"},"username":{"type":"string"}}},"responses.UserResponse":{"type":"object","properties":{"avatar":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"joinDate":{"type":"string"},"motto":{"type":"string"},"name":{"type":"string"},"projects":{"type":"array","items":{"type":"string"}},"role":{"type":"string"},"skills":{"type":"array","items":{"type":"string"}},"speciality":{"type":"string"},"username":{"type":"string"}}}},"securityDefinitions":{"BasicAuth":{"type":"basic"}}}` // SwaggerInfo holds exported Swagger Info so clients can modify it var SwaggerInfo = &swag.Spec{ diff --git a/docs/swagger.json b/docs/swagger.json index 30a04f4..c1bd86b 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -1 +1 @@ -{"swagger":"2.0","info":{"description":"58team blog's backend","title":"58team blog backend","termsOfService":"http://swagger.io/terms/","contact":{"name":"API Support","url":"http://www.swagger.io/support","email":"support@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"},"version":"1.0"},"host":"localhost:8080","basePath":"/api/v1","paths":{"/images/":{"post":{"description":"Upload new image and returns uploaded image json object","produces":["application/json"],"tags":["images"],"summary":"Upload new image","parameters":[{"type":"file","description":"image file","name":"file","in":"formData","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.ImageResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/images/{path}":{"get":{"description":"get image by path","produces":["application/octet-stream","application/json"],"tags":["images"],"summary":"Get an image by path","parameters":[{"type":"string","description":"Path to image","name":"path","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"file"}},"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"}}}},"delete":{"description":"Delete image from server by given path","produces":["image/png","image/jpeg"],"tags":["images"],"summary":"Delete image by path","parameters":[{"type":"string","description":"Path to image","name":"filename","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}},"/login":{"post":{"description":"Login user into system","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Login","parameters":[{"description":"User login data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.LoginUserRequest"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/logout":{"get":{"description":"Creates new user in system","produces":["application/json"],"tags":["user"],"summary":"Create new user","responses":{"200":{"description":"OK"},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post":{"get":{"description":"Return first 5 posts","produces":["application/json"],"tags":["post"],"summary":"Get all posts","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}},"post":{"description":"Create new post in blog","consumes":["application/json"],"produces":["application/json"],"tags":["post"],"summary":"Create new post","parameters":[{"description":"Post data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.CreatePostRequest"}}],"responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/responses.PostResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post/offset/{offset}":{"get":{"description":"return 5 posts after first offset posts","produces":["application/json"],"tags":["post"],"summary":"Get posts after offset","parameters":[{"type":"integer","description":"Offset of posts","name":"offset","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post/{id}":{"get":{"description":"get post by id","produces":["application/json"],"tags":["post"],"summary":"Get post by id","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.PostResponse"}}},"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"}}}},"put":{"description":"update post content","produces":["application/json"],"tags":["post"],"summary":"Update post content","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true},{"description":"Post data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.PutPostRequest"}}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.PostResponse"}},"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"}}}},"delete":{"description":"Delete post by id","produces":["application/json"],"tags":["post"],"summary":"Delete post","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}},"/user/":{"get":{"description":"Return all registered users","produces":["application/json"],"tags":["user"],"summary":"Get all users","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.UserResponse"}}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}},"post":{"description":"Creates new user in system","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Create new user","parameters":[{"description":"User data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.CreateUserRequest"}}],"responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/responses.UserResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"409":{"description":"Conflict","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/user/name/{name}":{"get":{"description":"Find user by username","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Find user by username","parameters":[{"type":"string","description":"User name","name":"name","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}}},"/user/{id}":{"get":{"description":"Find user by id","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Find user by id","parameters":[{"type":"string","description":"user id","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}},"put":{"description":"Change the user's name and password","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Change user","parameters":[{"type":"string","description":"User id","name":"id","in":"path","required":true},{"description":"User data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.PutUserRequest"}}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}},"delete":{"description":"Delete user","produces":["application/json"],"tags":["user"],"summary":"Delete user","parameters":[{"type":"string","description":"User id","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}}},"definitions":{"requests.CreatePostRequest":{"type":"object","required":["content","description","title","userId"],"properties":{"category":{"type":"string"},"content":{"type":"string","minLength":36},"description":{"type":"string","maxLength":255,"minLength":8},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string","maxLength":255,"minLength":8},"userId":{"type":"string"}}},"requests.CreateUserRequest":{"type":"object","required":["password","username"],"properties":{"password":{"type":"string","maxLength":32,"minLength":6},"username":{"type":"string","maxLength":32,"minLength":3}}},"requests.LoginUserRequest":{"type":"object","required":["password","username"],"properties":{"password":{"type":"string","maxLength":32,"minLength":6},"username":{"type":"string","maxLength":32,"minLength":3}}},"requests.PutPostRequest":{"type":"object","properties":{"content":{"type":"string"},"description":{"type":"string"},"title":{"type":"string"}}},"requests.PutUserRequest":{"type":"object","required":["password","username"],"properties":{"password":{"type":"string","maxLength":32,"minLength":6},"username":{"type":"string","maxLength":32,"minLength":3}}},"responses.ErrorResponse":{"type":"object","properties":{"error_code":{"type":"integer"},"message":{"type":"string"}}},"responses.GetListPostResponseItem":{"type":"object","properties":{"category":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string"},"updatedAt":{"type":"string"},"userId":{"type":"string"},"username":{"type":"string"}}},"responses.ImageResponse":{"type":"object","properties":{"id":{"type":"string"},"path":{"type":"string"}}},"responses.PostResponse":{"type":"object","properties":{"category":{"type":"string"},"content":{"type":"string"},"createdAt":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string"},"updatedAt":{"type":"string"},"userId":{"type":"string"},"username":{"type":"string"}}},"responses.UserResponse":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"}}}},"securityDefinitions":{"BasicAuth":{"type":"basic"}}} \ No newline at end of file +{"swagger":"2.0","info":{"description":"58team blog's backend","title":"58team blog backend","termsOfService":"http://swagger.io/terms/","contact":{"name":"API Support","url":"http://www.swagger.io/support","email":"support@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"},"version":"1.0"},"host":"localhost:8080","basePath":"/api/v1","paths":{"/images":{"get":{"description":"Delete image from server by given path","produces":["image/png","image/jpeg"],"tags":["images"],"summary":"Delete image by path","parameters":[{"type":"string","description":"Path to image","name":"filename","in":"path","required":true}],"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"}}}}},"/images/":{"post":{"security":[{"BasicAuth":[]}],"description":"Upload new image and returns uploaded image json object","produces":["application/json"],"tags":["images"],"summary":"Upload new image","parameters":[{"type":"file","description":"image file","name":"file","in":"formData","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.ImageResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/images/{path}":{"get":{"description":"get image by path","produces":["application/octet-stream","application/json"],"tags":["images"],"summary":"Get an image by path","parameters":[{"type":"string","description":"Path to image","name":"path","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"file"}},"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"}}}},"delete":{"security":[{"BasicAuth":[]}],"description":"Delete image from server by given path","produces":["image/png","image/jpeg"],"tags":["images"],"summary":"Delete image by path","parameters":[{"type":"string","description":"Path to image","name":"filename","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}},"/login":{"post":{"description":"Login user into system","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Login","parameters":[{"description":"User login data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.LoginUserRequest"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/logout":{"get":{"security":[{"BasicAuth":[]}],"description":"Creates new user in system","produces":["application/json"],"tags":["user"],"summary":"Create new user","responses":{"200":{"description":"OK"},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/members/":{"get":{"description":"Return all registered users","produces":["application/json"],"tags":["user"],"summary":"Get all users","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.UserResponse"}}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post":{"get":{"description":"Return first 5 posts","produces":["application/json"],"tags":["post"],"summary":"Get all posts","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}},"post":{"security":[{"BasicAuth":[]}],"description":"Create new post in blog","consumes":["application/json"],"produces":["application/json"],"tags":["post"],"summary":"Create new post","parameters":[{"description":"Post data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.CreatePostRequest"}}],"responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/responses.PostResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post/offset/{offset}":{"get":{"description":"return 5 posts after first offset posts","produces":["application/json"],"tags":["post"],"summary":"Get posts after offset","parameters":[{"type":"integer","description":"Offset of posts","name":"offset","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post/{id}":{"get":{"description":"get post by id","produces":["application/json"],"tags":["post"],"summary":"Get post by id","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.PostResponse"}}},"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"}}}},"put":{"security":[{"BasicAuth":[]}],"description":"update post content","produces":["application/json"],"tags":["post"],"summary":"Update post content","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true},{"description":"Post data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.PutPostRequest"}}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.PostResponse"}},"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"}}}},"delete":{"security":[{"BasicAuth":[]}],"description":"Delete post by id","produces":["application/json"],"tags":["post"],"summary":"Delete post","parameters":[{"type":"string","description":"Id of post","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}},"/team/":{"post":{"security":[{"BasicAuth":[]}],"description":"Creates new user in system","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Create new user","parameters":[{"description":"User data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.CreateUserRequest"}}],"responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/responses.UserResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"409":{"description":"Conflict","schema":{"$ref":"#/definitions/responses.ErrorResponse"}},"500":{"description":"Internal Server Error","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/team/name/{name}":{"get":{"description":"Find user by username","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Find user by username","parameters":[{"type":"string","description":"User name","name":"name","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}}},"/team/{id}":{"get":{"description":"Find user by id","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Find user by id","parameters":[{"type":"string","description":"user id","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}},"put":{"security":[{"BasicAuth":[]}],"description":"Change the user's name and password","consumes":["application/json"],"produces":["application/json"],"tags":["user"],"summary":"Change user","parameters":[{"type":"string","description":"User id","name":"id","in":"path","required":true},{"description":"User data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.PutUserRequest"}}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.UserResponse"}},"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"}}}},"delete":{"security":[{"BasicAuth":[]}],"description":"Delete user","produces":["application/json"],"tags":["user"],"summary":"Delete user","parameters":[{"type":"string","description":"User id","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK"},"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"}}}}}},"definitions":{"requests.CreatePostRequest":{"type":"object","required":["content","description","title","userId"],"properties":{"category":{"type":"string"},"content":{"type":"string","minLength":36},"description":{"type":"string","maxLength":255,"minLength":8},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string","maxLength":255,"minLength":8},"userId":{"type":"string"}}},"requests.CreateUserRequest":{"type":"object","required":["avatar","description","joinDate","motto","name","password","projects","role","skills","speciality","username"],"properties":{"avatar":{"type":"string"},"description":{"type":"string","maxLength":500,"minLength":10},"joinDate":{"type":"string"},"motto":{"type":"string","maxLength":200,"minLength":2},"name":{"type":"string","maxLength":100,"minLength":2},"password":{"type":"string","maxLength":32,"minLength":6},"projects":{"type":"array","minItems":1,"items":{"type":"string"}},"role":{"type":"string"},"skills":{"type":"array","minItems":1,"items":{"type":"string"}},"speciality":{"type":"string","maxLength":100,"minLength":2},"username":{"type":"string","maxLength":32,"minLength":3}}},"requests.LoginUserRequest":{"type":"object","required":["password","username"],"properties":{"password":{"type":"string","maxLength":32,"minLength":6},"username":{"type":"string","maxLength":32,"minLength":3}}},"requests.PutPostRequest":{"type":"object","properties":{"content":{"type":"string"},"description":{"type":"string"},"title":{"type":"string"}}},"requests.PutUserRequest":{"type":"object","required":["avatar","description","motto","name","password","projects","role","skills","speciality","username"],"properties":{"avatar":{"type":"string"},"description":{"type":"string","maxLength":500,"minLength":10},"motto":{"type":"string","maxLength":200,"minLength":2},"name":{"type":"string","maxLength":100,"minLength":2},"password":{"type":"string","maxLength":32,"minLength":6},"projects":{"type":"array","minItems":1,"items":{"type":"string"}},"role":{"type":"string"},"skills":{"type":"array","minItems":1,"items":{"type":"string"}},"speciality":{"type":"string","maxLength":100,"minLength":2},"username":{"type":"string","maxLength":32,"minLength":3}}},"responses.ErrorResponse":{"type":"object","properties":{"error_code":{"type":"integer"},"message":{"type":"string"}}},"responses.GetAllImagesList":{"type":"object"},"responses.GetListPostResponseItem":{"type":"object","properties":{"category":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string"},"updatedAt":{"type":"string"},"userId":{"type":"string"},"username":{"type":"string"}}},"responses.ImageResponse":{"type":"object","properties":{"id":{"type":"string"},"path":{"type":"string"}}},"responses.PostResponse":{"type":"object","properties":{"category":{"type":"string"},"content":{"type":"string"},"createdAt":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"title":{"type":"string"},"updatedAt":{"type":"string"},"userId":{"type":"string"},"username":{"type":"string"}}},"responses.UserResponse":{"type":"object","properties":{"avatar":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"joinDate":{"type":"string"},"motto":{"type":"string"},"name":{"type":"string"},"projects":{"type":"array","items":{"type":"string"}},"role":{"type":"string"},"skills":{"type":"array","items":{"type":"string"}},"speciality":{"type":"string"},"username":{"type":"string"}}}},"securityDefinitions":{"BasicAuth":{"type":"basic"}}} \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 405e89e..af69c5a 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -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 diff --git a/go-arch-lint-graph.svg b/go-arch-lint-graph.svg deleted file mode 100755 index 855288a..0000000 --- a/go-arch-lint-graph.svg +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - -cmdapplicationinfrastructureinterface - - - - - - \ No newline at end of file diff --git a/go.mod b/go.mod index 26f2ed0..5ce1ba6 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 8a8360b..bf12c4b 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/internal/application/commands/create_user_command.go b/internal/application/commands/create_user_command.go index 454829d..2ebfaed 100644 --- a/internal/application/commands/create_user_command.go +++ b/internal/application/commands/create_user_command.go @@ -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 } diff --git a/internal/application/commands/update_user_command.go b/internal/application/commands/update_user_command.go index 5c083bc..4897a8f 100644 --- a/internal/application/commands/update_user_command.go +++ b/internal/application/commands/update_user_command.go @@ -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 } diff --git a/internal/application/common/user_result.go b/internal/application/common/user_result.go index 9a04b9b..0c79b8c 100644 --- a/internal/application/common/user_result.go +++ b/internal/application/common/user_result.go @@ -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 { diff --git a/internal/application/mapper/user_result.go b/internal/application/mapper/user_result.go index ee287a8..fa5d755 100644 --- a/internal/application/mapper/user_result.go +++ b/internal/application/mapper/user_result.go @@ -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, } } diff --git a/internal/application/services/user_service.go b/internal/application/services/user_service.go index 3b5de27..f97d077 100644 --- a/internal/application/services/user_service.go +++ b/internal/application/services/user_service.go @@ -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()) diff --git a/internal/domain/entities/user.go b/internal/domain/entities/user.go index 2286edf..c765738 100644 --- a/internal/domain/entities/user.go +++ b/internal/domain/entities/user.go @@ -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 diff --git a/internal/infrastructure/db/repo/user_repo.go b/internal/infrastructure/db/repo/user_repo.go index c1a968c..5cec8cd 100644 --- a/internal/infrastructure/db/repo/user_repo.go +++ b/internal/infrastructure/db/repo/user_repo.go @@ -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 { diff --git a/internal/interfaces/api/controllers/images_controller.go b/internal/interfaces/api/controllers/images_controller.go index 801b51a..0cb4147 100644 --- a/internal/interfaces/api/controllers/images_controller.go +++ b/internal/interfaces/api/controllers/images_controller.go @@ -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") } diff --git a/internal/interfaces/api/controllers/post_controller.go b/internal/interfaces/api/controllers/post_controller.go index 069b3f9..6f22f18 100644 --- a/internal/interfaces/api/controllers/post_controller.go +++ b/internal/interfaces/api/controllers/post_controller.go @@ -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) diff --git a/internal/interfaces/api/controllers/user_controller.go b/internal/interfaces/api/controllers/user_controller.go index 1db2a70..42c8483 100644 --- a/internal/interfaces/api/controllers/user_controller.go +++ b/internal/interfaces/api/controllers/user_controller.go @@ -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") diff --git a/internal/interfaces/api/mapper/response_from_post_getall_result.go b/internal/interfaces/api/mapper/response_from_post_getall_result.go index e2ffcc2..23be1ef 100644 --- a/internal/interfaces/api/mapper/response_from_post_getall_result.go +++ b/internal/interfaces/api/mapper/response_from_post_getall_result.go @@ -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)) diff --git a/internal/interfaces/api/mapper/response_from_user_find_by_id_result.go b/internal/interfaces/api/mapper/response_from_user_find_by_id_result.go index b5d90a1..39a478c 100644 --- a/internal/interfaces/api/mapper/response_from_user_find_by_id_result.go +++ b/internal/interfaces/api/mapper/response_from_user_find_by_id_result.go @@ -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, } } diff --git a/internal/interfaces/api/mapper/response_from_user_find_by_name_result.go b/internal/interfaces/api/mapper/response_from_user_find_by_name_result.go index eff4642..651acd1 100644 --- a/internal/interfaces/api/mapper/response_from_user_find_by_name_result.go +++ b/internal/interfaces/api/mapper/response_from_user_find_by_name_result.go @@ -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, } } diff --git a/internal/interfaces/api/mapper/response_from_user_get_all_result.go b/internal/interfaces/api/mapper/response_from_user_get_all_result.go index 944f5c5..a4d882d 100644 --- a/internal/interfaces/api/mapper/response_from_user_get_all_result.go +++ b/internal/interfaces/api/mapper/response_from_user_get_all_result.go @@ -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)) diff --git a/internal/interfaces/api/mapper/response_from_user_result.go b/internal/interfaces/api/mapper/response_from_user_result.go index 0a2518a..7807d9e 100644 --- a/internal/interfaces/api/mapper/response_from_user_result.go +++ b/internal/interfaces/api/mapper/response_from_user_result.go @@ -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, } } diff --git a/internal/interfaces/api/requests/create_post_request.go b/internal/interfaces/api/requests/create_post_request.go index d933b1a..1afc048 100644 --- a/internal/interfaces/api/requests/create_post_request.go +++ b/internal/interfaces/api/requests/create_post_request.go @@ -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"` } diff --git a/internal/interfaces/api/requests/create_user_request.go b/internal/interfaces/api/requests/create_user_request.go index 99e7b86..f3b500e 100644 --- a/internal/interfaces/api/requests/create_user_request.go +++ b/internal/interfaces/api/requests/create_user_request.go @@ -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"` } diff --git a/internal/interfaces/api/requests/login_user_request.go b/internal/interfaces/api/requests/login_user_request.go index 36b00a9..403b294 100644 --- a/internal/interfaces/api/requests/login_user_request.go +++ b/internal/interfaces/api/requests/login_user_request.go @@ -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"` } diff --git a/internal/interfaces/api/requests/put_user_request.go b/internal/interfaces/api/requests/put_user_request.go index 04d94bb..aadb90c 100644 --- a/internal/interfaces/api/requests/put_user_request.go +++ b/internal/interfaces/api/requests/put_user_request.go @@ -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"` } diff --git a/internal/interfaces/api/responses/get_list_post_response.go b/internal/interfaces/api/responses/get_list_post_response.go index ad3c860..4a1a700 100644 --- a/internal/interfaces/api/responses/get_list_post_response.go +++ b/internal/interfaces/api/responses/get_list_post_response.go @@ -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 diff --git a/internal/interfaces/api/responses/image_get_all.go b/internal/interfaces/api/responses/image_get_all.go new file mode 100644 index 0000000..6e8b10c --- /dev/null +++ b/internal/interfaces/api/responses/image_get_all.go @@ -0,0 +1,4 @@ +package responses + +type GetAllImagesList struct { +} diff --git a/internal/interfaces/api/responses/user_response.go b/internal/interfaces/api/responses/user_response.go index 58e3ee2..b4e6914 100644 --- a/internal/interfaces/api/responses/user_response.go +++ b/internal/interfaces/api/responses/user_response.go @@ -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 diff --git a/internal/interfaces/route.go b/internal/interfaces/route.go index de88e66..d8c33bb 100644 --- a/internal/interfaces/route.go +++ b/internal/interfaces/route.go @@ -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) } diff --git a/internal/utils/error_handler.go b/internal/utils/error_handler.go index f23271b..7a9d49b 100644 --- a/internal/utils/error_handler.go +++ b/internal/utils/error_handler.go @@ -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, ¬FoundErr): 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 } diff --git a/internal/utils/inline_list_validator.go b/internal/utils/inline_list_validator.go new file mode 100644 index 0000000..1ec1fa9 --- /dev/null +++ b/internal/utils/inline_list_validator.go @@ -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 +} diff --git a/migrations/00004_update_users.up.sql b/migrations/00004_update_users.up.sql new file mode 100644 index 0000000..5f70512 --- /dev/null +++ b/migrations/00004_update_users.up.sql @@ -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 '';