diff --git a/docs/docs.go b/docs/docs.go index 9eb6c5e..38b1f5c 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -151,6 +151,99 @@ var doc = `{ } } }, + "/users/avatar": { + "post": { + "description": "사용자 아바타(프로필) 사진을 업로드 합니다.", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "User" + ], + "summary": "사용자 아바타 사진 업로드", + "parameters": [ + { + "type": "string", + "description": "Bearer {AccessToken}", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "type": "file", + "description": "아바타 사진", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "201": { + "description": "" + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/models.ErrResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.ErrResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/models.ErrResponse" + } + } + } + }, + "delete": { + "description": "사용자 아바타(프로필) 사진을 삭제합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "User" + ], + "summary": "사용자 아바타 사진 삭제", + "parameters": [ + { + "type": "string", + "description": "Bearer {AccessToken}", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "204": { + "description": "" + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.ErrResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/models.ErrResponse" + } + } + } + } + }, "/users/login": { "post": { "description": "로그인을 성공 시 JWT token이 발급됩니다.", diff --git a/docs/swagger.json b/docs/swagger.json index 3b0e1fa..d7e9735 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -131,6 +131,99 @@ } } }, + "/users/avatar": { + "post": { + "description": "사용자 아바타(프로필) 사진을 업로드 합니다.", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "User" + ], + "summary": "사용자 아바타 사진 업로드", + "parameters": [ + { + "type": "string", + "description": "Bearer {AccessToken}", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "type": "file", + "description": "아바타 사진", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "201": { + "description": "" + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/models.ErrResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.ErrResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/models.ErrResponse" + } + } + } + }, + "delete": { + "description": "사용자 아바타(프로필) 사진을 삭제합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "User" + ], + "summary": "사용자 아바타 사진 삭제", + "parameters": [ + { + "type": "string", + "description": "Bearer {AccessToken}", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "204": { + "description": "" + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/models.ErrResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/models.ErrResponse" + } + } + } + } + }, "/users/login": { "post": { "description": "로그인을 성공 시 JWT token이 발급됩니다.", diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 04535bd..213b86a 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -239,6 +239,68 @@ paths: summary: Email로 사용자 정보 조회 tags: - User + /users/avatar: + delete: + consumes: + - application/json + description: 사용자 아바타(프로필) 사진을 삭제합니다. + parameters: + - description: Bearer {AccessToken} + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "204": + description: "" + "401": + description: Unauthorized + schema: + $ref: '#/definitions/models.ErrResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/models.ErrResponse' + summary: 사용자 아바타 사진 삭제 + tags: + - User + post: + consumes: + - multipart/form-data + description: 사용자 아바타(프로필) 사진을 업로드 합니다. + parameters: + - description: Bearer {AccessToken} + in: header + name: Authorization + required: true + type: string + - description: 아바타 사진 + in: formData + name: file + required: true + type: file + produces: + - application/json + responses: + "201": + description: "" + "400": + description: Bad Request + schema: + $ref: '#/definitions/models.ErrResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/models.ErrResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/models.ErrResponse' + summary: 사용자 아바타 사진 업로드 + tags: + - User /users/login: post: consumes: diff --git a/internal/app/handlers/users.go b/internal/app/handlers/users.go index 33ec078..2f341e9 100644 --- a/internal/app/handlers/users.go +++ b/internal/app/handlers/users.go @@ -464,3 +464,88 @@ func UserTokenRefresh(c *gin.Context) { }) } } + +// @Summary 사용자 아바타 사진 업로드 +// @Description 사용자 아바타(프로필) 사진을 업로드 합니다. +// @Tags User +// @Accept mpfd +// @Produce json +// @Param Authorization header string true "Bearer {AccessToken}" +// @Param file formData file true "아바타 사진" +// @Success 201 +// @Failure 400 {object} models.ErrResponse +// @Failure 401 {object} models.ErrResponse +// @Failure 500 {object} models.ErrResponse +// @Router /users/avatar [post] +func UploadAvatar(c *gin.Context) { + au, err := auth.ExtractTokenMetadata(c.Request) + if err != nil { + c.JSON(http.StatusUnauthorized, models.ErrResponse{ + Message: err.Error(), + }) + return + } + + file, err := c.FormFile("file") + if err != nil { + c.JSON(http.StatusBadRequest, models.ErrResponse{ + Message: err.Error(), + }) + return + } + + fileContent, err := file.Open() + if err != nil { + c.JSON(http.StatusInternalServerError, models.ErrResponse{ + Message: err.Error(), + }) + return + } + defer fileContent.Close() + + fileData, err := ioutil.ReadAll(fileContent) + if err != nil { + c.JSON(http.StatusInternalServerError, models.ErrResponse{ + Message: err.Error(), + }) + return + } + + if err := orm.Client.Model(&entitys.User{}).Where("id = ?", au.UserId).Update("AvatarImage", fileData).Error; err != nil { + c.JSON(http.StatusInternalServerError, models.ErrResponse{ + Message: err.Error(), + }) + return + } + + c.Status(http.StatusCreated) +} + +// @Summary 사용자 아바타 사진 삭제 +// @Description 사용자 아바타(프로필) 사진을 삭제합니다. +// @Tags User +// @Accept json +// @Produce json +// @Param Authorization header string true "Bearer {AccessToken}" +// @Success 204 +// @Failure 401 {object} models.ErrResponse +// @Failure 500 {object} models.ErrResponse +// @Router /users/avatar [delete] +func DeleteAvatar(c *gin.Context) { + au, err := auth.ExtractTokenMetadata(c.Request) + if err != nil { + c.JSON(http.StatusUnauthorized, models.ErrResponse{ + Message: err.Error(), + }) + return + } + + if err := orm.Client.Model(&entitys.User{}).Where("id = ?", au.UserId).Update("AvatarImage", nil).Error; err != nil { + c.JSON(http.StatusInternalServerError, models.ErrResponse{ + Message: err.Error(), + }) + return + } + + c.Status(http.StatusNoContent) +} diff --git a/internal/app/routers/router.go b/internal/app/routers/router.go index bd22804..6ff468c 100644 --- a/internal/app/routers/router.go +++ b/internal/app/routers/router.go @@ -16,11 +16,15 @@ func Use(api *gin.RouterGroup) { users.POST("/signup", handlers.UserSignup) users.POST("/login", handlers.UserLogin) users.GET("/login/kakao", handlers.UserKakaoLoginCallBack) - users.GET("", middlewares.TokenAuthMiddleware(), handlers.UserInfoTokenQuey) - users.GET(":userEmail", handlers.UserInfoEmailQuey) users.POST("/logout", middlewares.TokenAuthMiddleware(), handlers.UserLogout) + users.GET("/token/valid", middlewares.TokenAuthMiddleware(), handlers.UserTokenValid) users.POST("/token/refresh", handlers.UserTokenRefresh) + + users.GET("", middlewares.TokenAuthMiddleware(), handlers.UserInfoTokenQuey) + users.GET(":userEmail", handlers.UserInfoEmailQuey) + users.POST("/avatar", middlewares.TokenAuthMiddleware(), handlers.UploadAvatar) + users.DELETE("/avatar", middlewares.TokenAuthMiddleware(), handlers.DeleteAvatar) } configs := api.Group("/configs") {