Skip to content

Commit

Permalink
이메일로도 사용자 조회할 수 있도록 API 추가 (#18)
Browse files Browse the repository at this point in the history
* add: 서비스 데이터는 public이므로 인증 없이 사용자 조회하도록 반영

* rename: 함수명 변경

* up: token 기반으로 사용자 조회하는 api 복구

* rename: 명확하게 이름 변경

* up: 명확하게 변수명 변경

* up: 중복 코드 함수화

* up: 문서화

* up: 누락된 http status 추가
  • Loading branch information
parkgang committed Nov 20, 2021
1 parent 2d9afa6 commit 1570ea5
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 26 deletions.
46 changes: 45 additions & 1 deletion docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ var doc = `{
"tags": [
"User"
],
"summary": "사용자 정보 조회",
"summary": "Token으로 사용자 정보 조회",
"parameters": [
{
"type": "string",
Expand Down Expand Up @@ -450,6 +450,50 @@ var doc = `{
}
}
},
"/users/{userEmail}": {
"get": {
"description": "사용자 이메일으로 사용자를 조회합니다.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"User"
],
"summary": "Email로 사용자 정보 조회",
"parameters": [
{
"type": "string",
"description": "사용자 Email",
"name": "userEmail",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/models.UserInfo"
}
},
"400": {
"description": ""
},
"404": {
"description": ""
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/models.ErrResponse"
}
}
}
}
},
"/version": {
"get": {
"description": "앱 버전을 응답합니다.",
Expand Down
46 changes: 45 additions & 1 deletion docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
"tags": [
"User"
],
"summary": "사용자 정보 조회",
"summary": "Token으로 사용자 정보 조회",
"parameters": [
{
"type": "string",
Expand Down Expand Up @@ -430,6 +430,50 @@
}
}
},
"/users/{userEmail}": {
"get": {
"description": "사용자 이메일으로 사용자를 조회합니다.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"User"
],
"summary": "Email로 사용자 정보 조회",
"parameters": [
{
"type": "string",
"description": "사용자 Email",
"name": "userEmail",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/models.UserInfo"
}
},
"400": {
"description": ""
},
"404": {
"description": ""
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/models.ErrResponse"
}
}
}
}
},
"/version": {
"get": {
"description": "앱 버전을 응답합니다.",
Expand Down
31 changes: 30 additions & 1 deletion docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,36 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/models.ErrResponse'
summary: 사용자 정보 조회
summary: Token으로 사용자 정보 조회
tags:
- User
/users/{userEmail}:
get:
consumes:
- application/json
description: 사용자 이메일으로 사용자를 조회합니다.
parameters:
- description: 사용자 Email
in: path
name: userEmail
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/models.UserInfo'
"400":
description: ""
"404":
description: ""
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/models.ErrResponse'
summary: Email로 사용자 정보 조회
tags:
- User
/users/login:
Expand Down
56 changes: 35 additions & 21 deletions internal/app/handlers/users.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package handlers

import (
"encoding/base64"
"errors"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -252,7 +251,7 @@ func UserKakaoLoginCallBack(c *gin.Context) {
c.Redirect(http.StatusFound, redUrl)
}

// @Summary 사용자 정보 조회
// @Summary Token으로 사용자 정보 조회
// @Description token 클레임에 있는 id 값으로 사용자를 조회합니다.
// @Tags User
// @Accept json
Expand All @@ -263,7 +262,7 @@ func UserKakaoLoginCallBack(c *gin.Context) {
// @Failure 404
// @Failure 500 {object} models.ErrResponse
// @Router /users [get]
func UserInfo(c *gin.Context) {
func UserInfoTokenQuey(c *gin.Context) {
au, err := auth.ExtractTokenMetadata(c.Request)
if err != nil {
c.JSON(http.StatusUnauthorized, models.ErrResponse{
Expand All @@ -272,10 +271,10 @@ func UserInfo(c *gin.Context) {
return
}

users := entitys.User{
user := entitys.User{
Id: uint(au.UserId),
}
if err := orm.Client.First(&users).Error; err != nil {
if err := orm.Client.First(&user).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.Status(http.StatusNotFound)
return
Expand All @@ -287,26 +286,41 @@ func UserInfo(c *gin.Context) {
return
}

// [base64 encoding for any image](https://freshman.tech/snippets/go/image-to-base64/)
var base64Encoding string
res := models.NewUserInfo(user)
c.JSON(http.StatusOK, res)
}

// 이미지 파일의 콘텐츠 유형에 맞게 적절한 URI 체계 헤더를 추가합니다.
mimeType := http.DetectContentType(users.AvatarImage)
switch mimeType {
case "image/jpeg":
base64Encoding += "data:image/jpeg;base64,"
case "image/png":
base64Encoding += "data:image/png;base64,"
// @Summary Email로 사용자 정보 조회
// @Description 사용자 이메일으로 사용자를 조회합니다.
// @Tags User
// @Accept json
// @Produce json
// @Param userEmail path string true "사용자 Email"
// @Success 200 {object} models.UserInfo
// @Failure 400
// @Failure 404
// @Failure 500 {object} models.ErrResponse
// @Router /users/{userEmail} [get]
func UserInfoEmailQuey(c *gin.Context) {
userEmail := c.Param("userEmail")
if userEmail == "" {
c.Status(http.StatusBadRequest)
return
}

base64Encoding += base64.StdEncoding.EncodeToString(users.AvatarImage)

res := models.UserInfo{
Id: int(users.Id),
Email: users.Email,
Name: users.Name,
AvatarImage: base64Encoding,
user := entitys.User{}
if err := orm.Client.Where("email = ?", userEmail).Find(&user).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.ErrResponse{
Message: err.Error(),
})
return
}
if userEmail != user.Email {
c.Status(http.StatusNotFound)
return
}

res := models.NewUserInfo(user)
c.JSON(http.StatusOK, res)
}

Expand Down
30 changes: 30 additions & 0 deletions internal/app/models/user-info.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,38 @@
package models

import (
"encoding/base64"
"net/http"

"github.com/belf-kr/oauth-server/internal/app/entitys"
)

type UserInfo struct {
Id int `json:"id" binding:"required" example:"1"`
Email string `json:"email" binding:"required" example:"[email protected]"`
Name string `json:"name" binding:"required" example:"사용자01"`
AvatarImage string `json:"avatarImage" binding:"required" example:"base64으로 인코딩된 이미지"`
}

func NewUserInfo(user entitys.User) UserInfo {
// [base64 encoding for any image](https://freshman.tech/snippets/go/image-to-base64/)
var base64Encoding string

// 이미지 파일의 콘텐츠 유형에 맞게 적절한 URI 체계 헤더를 추가합니다.
mimeType := http.DetectContentType(user.AvatarImage)
switch mimeType {
case "image/jpeg":
base64Encoding += "data:image/jpeg;base64,"
case "image/png":
base64Encoding += "data:image/png;base64,"
}

base64Encoding += base64.StdEncoding.EncodeToString(user.AvatarImage)

return UserInfo{
Id: int(user.Id),
Email: user.Email,
Name: user.Name,
AvatarImage: base64Encoding,
}
}
3 changes: 2 additions & 1 deletion internal/app/routers/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ 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.UserInfo)
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)
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/project/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package project

const (
AppName string = "oauth-server"
AppVersion string = "0.2.2"
AppVersion string = "0.3.0"
)

0 comments on commit 1570ea5

Please sign in to comment.